ยืนยันหมายเลขโทรศัพท์ด้วยข้อมูลเข้าสู่ระบบดิจิทัล

คู่มือนี้จะอธิบายรายละเอียดวิธีใช้ DigitalCredential API เพื่อรับหมายเลขโทรศัพท์ที่ยืนยันแล้ว สำหรับผู้ใช้ กระบวนการนี้มี 2 ขั้นตอนดังนี้

  1. ขอ TS.43 token: แอปไคลเอ็นต์ ("เครื่องมือยืนยัน") ขอโทเค็น TS.43 ชั่วคราวจากอุปกรณ์ของผู้ใช้ TS.43 token คือ ข้อมูลเข้าสู่ระบบที่ผู้ให้บริการออกให้ซึ่งแสดงถึงตัวตนของผู้ใช้
  2. แลกเปลี่ยนโทเค็นเป็นหมายเลขโทรศัพท์: Backend ของแอปจะแลกเปลี่ยน TS.43 token กับผู้รวบรวมข้อมูลหรือผู้ให้บริการเพื่อรับหมายเลขโทรศัพท์ที่ยืนยันแล้วของผู้ใช้

สิ่งที่ต้องมีก่อน

หากต้องการใช้การยืนยันหมายเลขโทรศัพท์ด้วย DigitalCredential API คุณต้องมี บัญชีกับผู้รวบรวมข้อมูล ผู้รวบรวมจะโต้ตอบกับผู้ให้บริการขนส่งและ จัดเตรียม API ที่จำเป็นสำหรับแอปของคุณ โดยปกติจะเป็นปลายทาง API ของระบบคลาวด์ที่เรียกเก็บเงินได้

นอกจากนี้ คุณยังต้องเพิ่มทรัพยากร Dependency ต่อไปนี้ลงในสคริปต์การสร้าง Gradle ด้วย

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.6.0-alpha05")
    implementation("androidx.credentials:credentials-play-services-auth:1.6.0-alpha05")
}

ดึงดูด

dependencies {
    implementation "androidx.credentials:credentials:1.6.0-alpha05"
    implementation "androidx.credentials:credentials-play-services-auth:1.6.0-alpha05"
}

การใช้งาน

โดยทั่วไปกระบวนการตั้งแต่ต้นจนจบจะมีขั้นตอนดังนี้

  1. ขอพารามิเตอร์ DCQL (ภาษาการค้นหาข้อมูลประจำตัวดิจิทัล) จาก ผู้รวบรวมข้อมูล: โทรหาผู้รวบรวมข้อมูลอย่างน้อย 1 รายและขอชุดพารามิเตอร์ DCQL DCQL ช่วยให้คุณระบุข้อมูลเข้าสู่ระบบดิจิทัลที่แน่นอนซึ่งคุณต้องการจากผู้รวบรวมแต่ละรายได้
  2. สร้างคำขอ OpenID4VP: สร้างคำขอ OpenID4VP จากแบ็กเอนด์ของแอป พร้อมทั้งใส่พารามิเตอร์ DCQL จากผู้รวบรวม จากนั้นส่งคำขอ OpenID4VP ไปยังแอปไคลเอ็นต์

  3. เรียกใช้ Credential Manager API: ในแอปไคลเอ็นต์ ให้ใช้ Credential Manager API เพื่อส่งคำขอ OpenID4VP ไปยังระบบปฏิบัติการ ในการตอบกลับ คุณจะได้รับออบเจ็กต์การตอบกลับ OpenID4VP ที่มี TS.43 Digital Credential ระบบจะเข้ารหัสข้อมูลเข้าสู่ระบบนี้และมีเพียงผู้รวบรวมข้อมูลที่เชื่อมโยงเท่านั้นที่ ถอดรหัสได้ หลังจากได้รับโทเค็นของผู้ให้บริการขนส่งแล้ว ให้ส่งการตอบกลับจากแอปไคลเอ็นต์ไปยังแบ็กเอนด์ของแอป

  4. ตรวจสอบการตอบกลับ: ตรวจสอบการตอบกลับ OpenID4VP ในแบ็กเอนด์ของแอป

  5. แลกเปลี่ยนเป็นหมายเลขโทรศัพท์: จากแบ็กเอนด์ของแอป ให้ส่ง TS.43 Digital Credential ไปยังผู้รวบรวมข้อมูล ผู้รวบรวมจะตรวจสอบความถูกต้องของ ข้อมูลเข้าสู่ระบบและแสดงหมายเลขโทรศัพท์ที่ยืนยันแล้ว

รูปภาพแสดงขั้นตอนของคำขอการยืนยันหมายเลขโทรศัพท์
รูปที่ 1วงจรของคำขอการยืนยันหมายเลขโทรศัพท์ เริ่มจากแบ็กเอนด์ของเครื่องมือยืนยันที่ขอพารามิเตอร์จากผู้รวบรวม และสิ้นสุดด้วยหมายเลขโทรศัพท์ที่ยืนยันแล้วซึ่งส่งคืน

ขอพารามิเตอร์ 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: ค่าที่ไม่ซ้ำกันซึ่งแบ็กเอนด์สร้างขึ้นสำหรับคำขอแต่ละรายการ Nonce ในออบเจ็กต์ข้อมูลเข้าสู่ระบบ DCQL ของผู้รวบรวมต้องตรงกับ Nonce นี้
  • 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)