คู่มือนี้จะอธิบายรายละเอียดวิธีใช้ DigitalCredential API เพื่อรับหมายเลขโทรศัพท์ที่ยืนยันแล้ว สำหรับผู้ใช้ กระบวนการนี้มี 2 ขั้นตอนดังนี้
- ขอ
TS.43 token: แอปไคลเอ็นต์ ("เครื่องมือยืนยัน") ขอโทเค็น TS.43 ชั่วคราวจากอุปกรณ์ของผู้ใช้TS.43 tokenคือ ข้อมูลเข้าสู่ระบบที่ผู้ให้บริการออกให้ซึ่งแสดงถึงตัวตนของผู้ใช้ - แลกเปลี่ยนโทเค็นเป็นหมายเลขโทรศัพท์: Backend ของแอปจะแลกเปลี่ยน
TS.43 tokenกับผู้รวบรวมข้อมูลหรือผู้ให้บริการเพื่อรับหมายเลขโทรศัพท์ที่ยืนยันแล้วของผู้ใช้
ความเข้ากันได้กับเวอร์ชัน Android
API การยืนยันหมายเลขโทรศัพท์รองรับใน Android 10 (API ระดับ 29) ขึ้นไป
สิ่งที่ต้องมีก่อน
หากต้องการใช้การยืนยันหมายเลขโทรศัพท์ด้วย DigitalCredential API คุณต้องมี บัญชีกับผู้รวบรวมข้อมูล ผู้รวบรวมจะโต้ตอบกับผู้ให้บริการขนส่งและ จัดเตรียม API Surface ที่จำเป็นสำหรับแอปของคุณ โดยปกติจะเป็นปลายทาง API ของระบบคลาวด์ที่เรียกเก็บเงินได้
นอกจากนี้ คุณยังต้องเพิ่มทรัพยากร Dependency ต่อไปนี้ลงในสคริปต์การสร้าง Gradle ด้วย
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.6.0-rc02") implementation("androidx.credentials:credentials-play-services-auth:1.6.0-rc02") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.6.0-rc02" implementation "androidx.credentials:credentials-play-services-auth:1.6.0-rc02" }
การใช้งาน
โดยทั่วไปกระบวนการตั้งแต่ต้นจนจบจะมีขั้นตอนดังนี้
- ขอพารามิเตอร์ DCQL (ภาษาการค้นหาข้อมูลประจำตัวดิจิทัล) จากผู้รวบรวมข้อมูล: เรียกใช้ผู้รวบรวมข้อมูลอย่างน้อย 1 รายและขอชุดพารามิเตอร์ DCQL DCQL ช่วยให้คุณระบุข้อมูลเข้าสู่ระบบดิจิทัลที่แน่นอนซึ่งคุณต้องการจากผู้รวบรวมแต่ละรายได้
สร้างคำขอ OpenID4VP: สร้างคำขอ OpenID4VP จากแบ็กเอนด์ของแอป พร้อมทั้งใส่พารามิเตอร์ DCQL จากผู้รวบรวม จากนั้นส่งคำขอ OpenID4VP ไปยังแอปไคลเอ็นต์
เรียกใช้ Credential Manager API: ในแอปไคลเอ็นต์ ให้ใช้ Credential Manager API เพื่อส่งคำขอ OpenID4VP ไปยังระบบปฏิบัติการ ในการตอบกลับ คุณจะได้รับออบเจ็กต์การตอบกลับ OpenID4VP ที่มี
TS.43 Digital Credentialข้อมูลเข้าสู่ระบบนี้ได้รับการเข้ารหัสและถอดรหัสได้โดยผู้รวบรวมที่เชื่อมโยงเท่านั้น หลังจากได้รับโทเค็นของผู้ให้บริการขนส่งแล้ว ให้ส่งการตอบกลับจากแอปไคลเอ็นต์ไปยังแบ็กเอนด์ของแอปตรวจสอบการตอบกลับ: ตรวจสอบการตอบกลับ OpenID4VP ในแบ็กเอนด์ของแอป
แลกเปลี่ยนเป็นหมายเลขโทรศัพท์: จากแบ็กเอนด์ของแอป ให้ส่ง
TS.43 Digital Credentialไปยังผู้รวบรวมข้อมูล ผู้รวบรวมจะตรวจสอบความถูกต้องของ ข้อมูลเข้าสู่ระบบและแสดงหมายเลขโทรศัพท์ที่ยืนยันแล้ว
ขอพารามิเตอร์ DCQL จากผู้รวบรวมข้อมูล
จากแบ็กเอนด์ของแอป ให้ส่งคำขอไปยังผู้รวบรวมเพื่อขอออบเจ็กต์ข้อมูลเข้าสู่ระบบ Digital Credential Query Language (DCQL) โปรดระบุ Nonce และรหัสคำขอในคำขอ ผู้รวบรวมจะแสดงผลออบเจ็กต์ข้อมูลเข้าสู่ระบบ DCQL ซึ่งมีโครงสร้างคล้ายกับต่อไปนี้
{
// The credential ID is mapped to the request ID that is sent in your request to the aggregator.
"id": "aggregator1",
"format": "dc-authorization+sd-jwt",
"meta": {
"vct_values": [
"number-verification/device-phone-number/ts43"
],
"credential_authorization_jwt": "..."
},
"claims": [
{
"path": ["subscription_hint"],
"values": [1]
},
{
"path": ["phone_number_hint"],
"values": ["+14155552671"]
}
]
}
สร้างคำขอ OpenID4VP
ก่อนอื่น ให้สร้างออบเจ็กต์ dcql_query จากแบ็กเอนด์ของแอปโดยวางออบเจ็กต์ข้อมูลเข้าสู่ระบบ DCQL
ไว้ในอาร์เรย์ credentials ที่ซ้อนอยู่ในออบเจ็กต์ dcql_query
ดังที่แสดงในตัวอย่างต่อไปนี้
"dcql_query": {
"credentials": [
"id": "aggregator1",
"format": "dc-authorization+sd-jwt",
"meta": {
"vct_values": [
"number-verification/device-phone-number/ts43"
],
"credential_authorization_jwt": "..."
},
"claims": [
{
"path": ["subscription_hint"],
"values": [1]
},
{
"path": ["phone_number_hint"],
"values": ["+14155552671"]
}
]
]
}
จากนั้นสร้างคำขอ OpenID4VP ที่มีโครงสร้างต่อไปนี้
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
protocol: ต้องตั้งค่าเป็นopenid4vp-v1-unsignedสำหรับคำขอการยืนยันหมายเลขโทรศัพท์response_typeและresponse_mode: ค่าคงที่ที่ระบุรูปแบบของคำขอที่มีค่าคงที่vp_tokenและdc_apiตามลำดับnonce: ค่าที่ไม่ซ้ำกันซึ่งแบ็กเอนด์สร้างขึ้นสำหรับคำขอแต่ละรายการ Nonc ในออบเจ็กต์ข้อมูลเข้าสู่ระบบ DCQL ของผู้รวบรวมต้องตรงกับ Nonc นี้dcql_query: ในกรณีนี้ ให้ใช้dcql_queryเพื่อระบุว่ามีการขอTS.43 Digital Credentialนอกจากนี้ คุณยังขอข้อมูลประจำตัวดิจิทัลอื่นๆ ได้ที่นี่
จากนั้น ให้รวมคำขอ OpenID4VP ไว้ในออบเจ็กต์คำขอ DigitalCredential API แล้ว ส่งไปยังแอปไคลเอ็นต์
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
]
}
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างคำขอ DigitalCredential API
def GenerateDCRequest():
credentials = []
aggregator1_dcql = call_aggregator_endpoint(nonce, "aggregator1", additional_params)
credentials.append(aggregator1_dcql) # You can optionally work with multiple
# aggregators, or request other types of credentials
val dc_request =
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": {"credentials": credentials}
}
}
]
}
return dc_request
เรียกใช้ Credential Manager API
ในแอปไคลเอ็นต์ ให้เรียกใช้ Credential Manager API โดยมีคำขอ DigitalCredential API ที่แบ็กเอนด์ของแอปให้ไว้
val requestJson = generateTs43DigitalCredentialRequestFromServer()
val digiCredOption = GetDigitalCredentialOption(requestJson = requestJson)
val getCredRequest = GetCredentialRequest(
listOf(digiCredOption)
)
coroutineScope.launch {
try {
val response = credentialManager.getCredential(
context = activityContext,
request = getCredRequest
)
val credential = response.credential
when (credential) {
is DigitalCredential -> {
val responseJson = credential.credentialJson
validateResponseOnServer(responseJson)
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential ${credential.type}")
}
}
} catch (e : GetCredentialException) {
// If user cancels the operation, the feature isn't available, or the
// SIM doesn't support the feature, a GetCredentialCancellationException
// will be returned. Otherwise, a GetCredentialUnsupportedException will
// be returned with details in the exception message.
handleFailure(e)
}
}
การตอบกลับ DigitalCredential API มีการตอบกลับ OpenID4VP โดยทั่วไปแล้ว
ไฟล์ JSON ของข้อมูลเข้าสู่ระบบจากผลลัพธ์ของ DigitalCredential จะมีลักษณะดังนี้
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"vp_token": {
"aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
# Credential in an array structure.
}
}
}
จากแอปไคลเอ็นต์ ให้ส่งการตอบกลับของ DigitalCredential API กลับไปยัง เซิร์ฟเวอร์แบ็กเอนด์ ซึ่งสามารถตรวจสอบและใช้เพื่อแลกเปลี่ยนเป็นหมายเลขโทรศัพท์ที่ยืนยันแล้ว กับผู้รวบรวมข้อมูลได้
ตรวจสอบการตอบกลับของข้อมูลเข้าสู่ระบบดิจิทัล
ตัวอย่างต่อไปนี้แสดงวิธีแยกวิเคราะห์การตอบกลับและทำขั้นตอนการตรวจสอบในแบ็กเอนด์ของแอป
def processDigitalCredentialsResponse(response):
# Step 1: Parse out the TS.43 Digital Credential from the response
openId4VpResponse = response['data']
ts43_digital_credential = response['vp_token']["aggregator1"][0]
# Step 2: Perform response validation
verifyResponse(ts43_digital_credential)
def verifyResponse(ts43_digital_credential):
# The returned ts43_digital_credential is an SD-JWT-based Verifiable Credentials
# (SD-JWT VC) as defined in this IETF spec. The section 3.4 of the specification
# outlines how to validate the credential. At a high level, the steps involves
# validating (1) the nonce in the response credential matches the one in the
# request, (2) the integrity of the credential by checking the credential is
# signed by the trusted issuer Android Telephony, and (3) other validity
# properties associated with this credential, such as issue time and expiration
# time
# In most cases, you can use an SD-JWT VC library to perform these validations.
# Some aggregators may also perform the validation logic for you. Check with your
# aggregator to decide the exact scope of the validation required.
แลกเปลี่ยนหมายเลขโทรศัพท์
จากแบ็กเอนด์ของแอป ให้ส่ง TS.43 Digital Credential ที่ตรวจสอบแล้วไปยัง
ปลายทางของตัวรวบรวมเพื่อตรวจสอบข้อมูลเข้าสู่ระบบและรับหมายเลขโทรศัพท์ที่ยืนยันแล้ว
def processDigitalCredentialsResponse(response):
# ... prior steps
# Step 3: Call aggregator endpoint to exchange the verified phone number
callAggregatorPnvEndpoint(ts43_digital_credential)