คู่มือนี้อธิบายวิธีที่ Relying Party (RP) สามารถผสานรวม Digital Credentials API ในทางเทคนิคเพื่อขอและตรวจสอบใบขับขี่ดิจิทัล (mDL) และบัตรประจำตัวจาก Google Wallet ในแอป Android และเว็บ
กระบวนการลงทะเบียนและข้อกำหนดเบื้องต้น
ก่อนที่จะเผยแพร่แอปพลิเคชัน Relying Party ในเวอร์ชันที่ใช้งานจริง คุณต้องลงทะเบียนแอปพลิเคชันอย่างเป็นทางการกับ Google
- ทดสอบใน Sandbox: คุณสามารถเริ่มพัฒนาได้ทันทีโดยใช้ สภาพแวดล้อม Sandbox และ สร้างรหัสทดสอบ ไม่จำเป็นต้องยอมรับข้อกำหนดในการให้บริการสำหรับการทดสอบ
- ส่งแบบฟอร์มการเริ่มต้นใช้งาน: กรอกข้อมูลในแบบฟอร์มการเริ่มต้นใช้งาน RP โดยปกติแล้ว การเริ่มต้นใช้งานจะใช้เวลา 3-5 วันทำการ ชื่อผลิตภัณฑ์และโลโก้ของคุณจะแสดงบนหน้าจอขอความยินยอมที่ผู้ใช้เห็นเพื่อช่วยให้ผู้ใช้ระบุได้ว่าใครเป็นผู้ขอข้อมูล
- ยอมรับข้อกำหนดในการให้บริการ: คุณต้องลงชื่อในข้อกำหนดในการให้บริการก่อนที่จะเผยแพร่
หากมีคำถามเกี่ยวกับการติดตามแอปพลิเคชันหรือการทดสอบจากภูมิภาคที่ไม่รองรับ โปรดดูที่ คำถามที่พบบ่อย
รูปแบบและความสามารถที่รองรับ
Google Wallet รองรับบัตรประจำตัวดิจิทัลตาม ISO mdoc
- ข้อมูลเข้าสู่ระบบที่รองรับ: คุณสามารถดูข้อมูลเข้าสู่ระบบและแอตทริบิวต์ที่รองรับได้
- โปรโตคอลที่รองรับ: OpenID4VP (เวอร์ชัน 1.0)
- Android SDK ขั้นต่ำ: Android 9 (ระดับ API 28) ขึ้นไป
- การรองรับเบราว์เซอร์: โปรดดูรายการเบราว์เซอร์ทั้งหมดที่รองรับ Digital Credentials API ได้ที่หน้าการรองรับระบบนิเวศ
- คำถามที่พบบ่อย: หากมีคำถามเกี่ยวกับการรองรับประเทศและไทม์ไลน์สำหรับภูมิภาคใหม่ โปรดดูคำถามที่พบบ่อยเกี่ยวกับข้อมูลเข้าสู่ระบบและข้อมูล
จัดรูปแบบคำขอ
หากต้องการขอข้อมูลเข้าสู่ระบบจากกระเป๋าเงินใดก็ตาม คุณต้องจัดรูปแบบคำขอโดยใช้ OpenID4VP คุณสามารถขอข้อมูลเข้าสู่ระบบที่เฉพาะเจาะจงหรือข้อมูลเข้าสู่ระบบหลายรายการในออบเจ็กต์ dcql_query เดียว
ตัวอย่างคำขอ JSON
ต่อไปนี้คือตัวอย่างคำขอ requestJson mdoc เพื่อรับข้อมูลเข้าสู่ระบบจากกระเป๋าเงินใดก็ตามในอุปกรณ์ Android หรือเว็บ
{
"requests" : [
{
"protocol": "openid4vp-v1-signed",
"data": {<signed_credential_request>} // This is an object, shouldn't be a string.
}
]
}
การเข้ารหัสคำขอ
client_metadata มีคีย์สาธารณะสำหรับการเข้ารหัสสำหรับคำขอแต่ละรายการ
คุณจะต้องจัดเก็บคีย์ส่วนตัวสำหรับคำขอแต่ละรายการและใช้คีย์ดังกล่าวเพื่อตรวจสอบสิทธิ์และให้สิทธิ์โทเค็นที่คุณได้รับจากแอปกระเป๋าเงิน
พารามิเตอร์ credential_request ใน requestJson มีฟิลด์ต่อไปนี้
ข้อมูลเข้าสู่ระบบที่เฉพาะเจาะจง
{
"response_type": "vp_token",
"response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
"nonce": "1234",
"dcql_query": {
"credentials": [
{
"id": "cred1",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL" // this is for mDL. Use com.google.wallet.idcard.1 for ID pass
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
],
"intent_to_retain": false
}
]
}
]
},
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
"kty": "EC",
"crv": "P-256",
"x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
"y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
"use": "enc",
"kid" : "1", // This is required
"alg" : "ECDH-ES", // This is required
}
]
},
"vp_formats_supported": {
"mso_mdoc": {
"deviceauth_alg_values": [
-7
],
"issuerauth_alg_values": [
-7
]
}
}
}
}
ข้อมูลเข้าสู่ระบบที่มีสิทธิ์
ต่อไปนี้คือตัวอย่างคำขอสำหรับทั้งใบขับขี่ดิจิทัลและ ID พาส ผู้ใช้สามารถดำเนินการต่อด้วยรายการใดรายการหนึ่ง
{
"response_type": "vp_token",
"response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
"nonce": "1234",
"dcql_query": {
"credentials": [
{
"id": "mdl-request",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
],
"intent_to_retain": false
}
]
},
{ // Credential type 2
"id": "id_pass-request",
"format": "mso_mdoc",
"meta": {
"doctype_value": "com.google.wallet.idcard.1"
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
],
"intent_to_retain": false
}
]
}
]
credential_sets : [
{
"options": [
[ "mdl-request" ],
[ "id_pass-request" ]
]
}
]
},
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
"kty": "EC",
"crv": "P-256",
"x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
"y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
"use": "enc",
"kid" : "1", // This is required
"alg" : "ECDH-ES", // This is required
}
]
},
"vp_formats_supported": {
"mso_mdoc": {
"deviceauth_alg_values": [
-7
],
"isserauth_alg_values": [
-7
]
}
}
}
}
คุณสามารถขอแอตทริบิวต์ที่รองรับ จำนวนเท่าใดก็ได้จากข้อมูลเข้าสู่ระบบที่จัดเก็บไว้ใน Google Wallet
คำขอที่ลงชื่อ
คำขอที่ลงชื่อ (คำขอการให้สิทธิ์ที่ปลอดภัยด้วย JWT) จะห่อหุ้ม คำขอการนำเสนอที่ตรวจสอบได้ไว้ภายใน JSON Web Token (JWT) ที่ลงชื่อแบบเข้ารหัสโดยใช้โครงสร้างพื้นฐาน PKI ของคุณ ซึ่งช่วยให้มั่นใจได้ถึงความสมบูรณ์ของคำขอและพิสูจน์ตัวตนของคุณต่อ Google Wallet
ข้อกำหนดเบื้องต้น
ก่อนที่จะนำการเปลี่ยนแปลงโค้ดสำหรับคำขอที่ลงชื่อไปใช้ โปรดตรวจสอบว่าคุณมีสิ่งต่อไปนี้
- คีย์ส่วนตัว: คุณต้องมีคีย์ส่วนตัว (เช่น
ES256แบบ Elliptic Curve) เพื่อลงชื่อคำขอที่จัดการในเซิร์ฟเวอร์ - ใบรับรอง: คุณต้องมีใบรับรอง X.509 มาตรฐานที่ได้จากคู่คีย์
- การลงทะเบียน: ตรวจสอบว่าใบรับรองสาธารณะของคุณได้ลงทะเบียนกับ Google Wallet แล้ว โปรดติดต่อทีมสนับสนุนที่
wallet-identity-rp-support@google.com
ตรรกะการสร้างคำขอ
หากต้องการสร้างคำขอ คุณต้องใช้คีย์ส่วนตัวและห่อหุ้มเพย์โหลดใน JWS
def construct_openid4vp_request(
doctypes: list[str],
requested_fields: list[dict],
nonce_base64: str,
jwe_encryption_public_jwk: jwk.JWK,
is_zkp_request: bool,
is_signed_request: bool,
state: dict,
origin: str
) -> dict:
# ... [Existing logic to build 'presentation_definition' and basic 'request_payload'] ...
# ------------------------------------------------------------------
# SIGNED REQUEST IMPLEMENTATION (JAR)
# ------------------------------------------------------------------
if is_signed_request:
try:
# 1. Load the Verifier's Certificate
# We must load the PEM string into a cryptography x509 object
verifier_cert_obj = x509.load_pem_x509_certificate(
CERTIFICATE.encode('utf-8'),
backend=default_backend()
)
# 2. Calculate Client ID (x509_hash)
# We calculate the SHA-256 hash of the DER-encoded certificate.
cert_der = verifier_cert_obj.public_bytes(serialization.Encoding.DER)
verifier_fingerprint_bytes = hashlib.sha256(cert_der).digest()
# Create a URL-safe Base64 hash (removing padding '=')
verifier_fingerprint_b64 = base64.urlsafe_b64encode(verifier_fingerprint_bytes).decode('utf-8').rstrip("=")
# Format the client_id as required by the spec
client_id = f'x509_hash:{verifier_fingerprint_b64}'
# 3. Update Request Payload with JAR specific fields
request_payload["client_id"] = client_id
# Explicitly set expected origins to prevent relay attacks
# Format for android origin: origin = android:apk-key-hash:<base64SHA256_ofAppSigningCert>
# Format for web origin: origin = <origin_url>
if origin:
request_payload["expected_origins"] = [origin]
# 4. Create Signed JWT (JWS)
# Load the signing private key
signing_key = jwk.JWK.from_pem(PRIVATE_KEY.encode('utf-8'))
# Initialize JWS with the JSON payload
jws_token = jws.JWS(json.dumps(request_payload).encode('utf-8'))
# Construct the JOSE Header
# 'x5c' (X.509 Certificate Chain) is critical: it allows the wallet
# to validate your key against the one registered in the console.
x5c_value = base64.b64encode(cert_der).decode('utf-8')
protected_header = {
"alg": "ES256", # Algorithm (e.g., ES256 or RS256)
"typ": "oauth-authz-req+jwt", # Standard type for JAR
"kid": "1", # Key ID
"x5c": [x5c_value] # Embed the certificate
}
# Sign the token
jws_token.add_signature(
key=signing_key,
alg=None,
protected=json_encode(protected_header)
)
# 5. Return the Request Object
# Instead of returning the raw JSON, we return the signed JWT string
# under the 'request' key.
return {"request": jws_token.serialize(compact=True)}
except Exception as e:
print(f"Error signing OpenID4VP request: {e}")
return None
# ... [Fallback for unsigned requests] ...
return request_payload
ทริกเกอร์ API
ระบบควรสร้างคำขอ API ทั้งหมดฝั่งเซิร์ฟเวอร์ คุณจะส่ง JSON ที่สร้างขึ้นไปยัง API ดั้งเดิม ทั้งนี้ขึ้นอยู่กับแพลตฟอร์ม
ในแอป (Android)
หากต้องการขอข้อมูลเข้าสู่ระบบจากแอป Android ให้ทำตามขั้นตอนต่อไปนี้
อัปเดตทรัพยากร Dependency
ใน build.gradle ของโปรเจ็กต์ ให้อัปเดตทรัพยากร Dependency เพื่อ ใช้ Credential Manager (เบต้า) ดังนี้
dependencies {
implementation("androidx.credentials:credentials:1.5.0-beta01")
implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}
กำหนดค่า Credential Manager
หากต้องการกำหนดค่าและเริ่มต้นใช้งานออบเจ็กต์ CredentialManager ให้เพิ่มตรรกะที่คล้ายกับตรรกะต่อไปนี้
// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)
ขอแอตทริบิวต์ข้อมูลประจำตัว
แทนที่จะระบุพารามิเตอร์แต่ละรายการสำหรับคำขอข้อมูลประจำตัว แอปจะระบุพารามิเตอร์ทั้งหมดด้วยกันเป็นสตริง JSON ภายใน CredentialOption
Credential Manager จะส่งสตริง JSON นี้ไปยังกระเป๋าเงินดิจิทัลที่พร้อมใช้งานโดยไม่ตรวจสอบเนื้อหา จากนั้นกระเป๋าเงินแต่ละใบจะมีหน้าที่:
- แยกวิเคราะห์สตริง JSON เพื่อทำความเข้าใจคำขอข้อมูลประจำตัว
- กำหนดว่าข้อมูลเข้าสู่ระบบที่จัดเก็บไว้รายการใด (หากมี) ที่ตรงตามคำขอ
เราขอแนะนำให้พาร์ทเนอร์สร้างคำขอในเซิร์ฟเวอร์แม้สำหรับการผสานรวมแอป Android
คุณจะใช้ requestJson จาก รูปแบบคำขอ
เป็น request ในการเรียกใช้ฟังก์ชัน GetDigitalCredentialOption()
// The request in the JSON format to conform with
// the JSON-ified Digital Credentials API request definition.
val requestJson = generateRequestFromServer()
val digitalCredentialOption =
GetDigitalCredentialOption(requestJson = requestJson)
// Use the option from the previous step to build the `GetCredentialRequest`.
val getCredRequest = GetCredentialRequest(
listOf(digitalCredentialOption)
)
coroutineScope.launch {
try {
val result = credentialManager.getCredential(
context = activityContext,
request = getCredRequest
)
verifyResult(result)
} catch (e : GetCredentialException) {
handleFailure(e)
}
}
จัดการการตอบกลับข้อมูลเข้าสู่ระบบ
เมื่อได้รับการตอบกลับจากกระเป๋าเงินแล้ว คุณจะตรวจสอบว่าการตอบกลับสำเร็จและมีคำตอบ credentialJson หรือไม่
// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
val credential = result.credential
when (credential) {
is DigitalCredential -> {
val responseJson = credential.credentialJson
validateResponseOnServer(responseJson) // make a server call to validate the response
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential ${credential.type}")
}
}
}
// Handle failure.
fun handleFailure(e: GetCredentialException) {
when (e) {
is GetCredentialCancellationException -> {
// The user intentionally canceled the operation and chose not
// to share the credential.
}
is GetCredentialInterruptedException -> {
// Retry-able error. Consider retrying the call.
}
is NoCredentialException -> {
// No credential was available.
}
else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
}
}
การตอบกลับ credentialJson มี identityToken (JWT) ที่เข้ารหัส ซึ่งกำหนดโดย W3C แอปกระเป๋าเงินมีหน้าที่สร้างการตอบกลับนี้
ตัวอย่าง
{
"protocol" : "openid4vp-v1-signed",
"data" : {
<encrpted_response>
}
}
คุณจะส่งการตอบกลับนี้กลับไปยังเซิร์ฟเวอร์เพื่อตรวจสอบความถูกต้อง ดูขั้นตอนในการตรวจสอบการตอบกลับข้อมูลเข้าสู่ระบบ
เว็บ
หากต้องการขอข้อมูลเข้าสู่ระบบโดยใช้ Digital Credentials API ใน Chrome หรือเบราว์เซอร์อื่นๆ ที่รองรับ ให้ส่งคำขอต่อไปนี้
const credentialResponse = await navigator.credentials.get({
digital : {
requests : [
{
protocol: "openid4vp-v1-signed",
data: {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
})
ส่งการตอบกลับจาก API นี้กลับไปยังเซิร์ฟเวอร์เพื่อตรวจสอบข้อมูลเข้าสู่ระบบ
ตรวจสอบการตอบกลับ
เมื่อกระเป๋าเงินส่ง identityToken (JWT) ที่เข้ารหัสกลับมา คุณต้องทำการตรวจสอบฝั่งเซิร์ฟเวอร์อย่างเข้มงวดก่อนที่จะเชื่อถือข้อมูล
ถอดรหัสการตอบกลับ
ใช้คีย์ส่วนตัวที่ตรงกับคีย์สาธารณะที่ส่งใน client_metadata ของคำขอเพื่อถอดรหัส JWE ซึ่งจะให้ vp_token
ตัวอย่าง Python
from jwcrypto import jwe, jwk
# Retrieve the Private Key from Datastore
reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str)
# Save public key thumbprint for session transcript
encryption_public_jwk_thumbprint = reader_private_jwk.thumbprint()
# Decrypt the JWE encrypted response from Google Wallet
jwe_object = jwe.JWE()
jwe_object.deserialize(encrypted_jwe_response_from_wallet)
jwe_object.decrypt(reader_private_jwk)
decrypted_payload_bytes = jwe_object.payload
decrypted_data = json.loads(decrypted_payload_bytes)
decrypted_data จะส่งผลให้เกิด JSON vp_token ที่มีข้อมูลเข้าสู่ระบบ
{
"vp_token":
{
"cred1": ["<base64UrlNoPadding_encoded_credential>"] // This applies to OpenID4VP 1.0 spec.
}
}
สร้างข้อความถอดเสียงของเซสชัน
ขั้นตอนถัดไปคือการสร้าง SessionTranscript จาก ISO/IEC 18013-5:2021 ด้วยโครงสร้างการส่งต่อที่เฉพาะเจาะจงสำหรับ Android หรือเว็บ
SessionTranscript = [ null, // DeviceEngagementBytes not available null, // EReaderKeyBytes not available [ "OpenID4VPDCAPIHandover", AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web ] ]สำหรับการส่งต่อทั้ง Android และเว็บ คุณจะต้องใช้ Nonce เดียวกันกับที่ใช้สร้าง
credential_requestการส่งต่อ Android
AndroidHandoverData = [ origin, // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>", nonce, // nonce that was used to generate credential request, encryption_public_jwk_thumbprint, // Encryption public key (JWK) Thumbprint ] AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
การส่งต่อเบราว์เซอร์
BrowserHandoverData =[ origin, // Origin URL nonce, // nonce that was used to generate credential request encryption_public_jwk_thumbprint, // Encryption public key (JWK) Thumbprint ] BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
การตอบกลับของอุปกรณ์ต้องได้รับการตรวจสอบตามข้อ 9 ของ ISO/IEC 18013-5:2021 โดยใช้
SessionTranscriptการตรวจสอบนี้มีหลายขั้นตอน ดังนี้
ตรวจสอบใบรับรองของผู้ออกใบรับรอง: แยกวิเคราะห์เชนใบรับรองการลงชื่อของผู้ออกใบรับรองจาก
issuerAuthและตรวจสอบกับใบรับรองรูท IACA ที่เชื่อถือได้ โปรดดูใบรับรอง IACA ของผู้ออกใบรับรองที่รองรับยืนยันลายเซ็น MSO (ส่วนที่ 9.1.2 ของ 18013-5)
คำนวณและตรวจสอบ
ValueDigestsสำหรับองค์ประกอบข้อมูล (ส่วนที่ 9.1.2 ของ 18013-5)ยืนยันลายเซ็น
deviceSignature(ส่วนที่ 9.1.3 ของ 18013-5)
{
"version": "1.0",
"documents": [
{
"docType": "org.iso.18013.5.1.mDL",
"issuerSigned": {
"nameSpaces": {...}, // contains data elements
"issuerAuth": [...] // COSE_Sign1 w/ issuer PK, mso + sig
},
"deviceSigned": {
"nameSpaces": 24(<< {} >>), // empty
"deviceAuth": {
"deviceSignature": [...] // COSE_Sign1 w/ device signature
}
}
}
],
"status": 0
}
การยืนยันอายุที่รักษาความเป็นส่วนตัว (ZKP)
หากต้องการรองรับ Zero-Knowledge Proofs (เช่น การยืนยันว่าผู้ใช้มีอายุมากกว่า 18 ปีโดยไม่ต้องดูวันเกิดที่แน่นอน) ให้เปลี่ยนรูปแบบคำขอเป็น mso_mdoc_zk และระบุการกำหนดค่า zk_system_type ที่จำเป็น
ดูภาพรวมระดับสูงเกี่ยวกับ ZKP และความสามารถของ ZKP ได้ที่ คำถามที่พบบ่อย
...
"dcql_query": {
"credentials": [{
"id": "cred1",
"format": "mso_mdoc_zk",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
"zk_system_type": [
{
"system": "longfellow-libzk-v1",
"circuit_hash": "f88a39e561ec0be02bb3dfe38fb609ad154e98decbbe632887d850fc612fea6f", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 5,
"block_enc_hash": 4096,
"block_enc_sig": 2945,
}
{
"system": "longfellow-libzk-v1",
"circuit_hash": "137e5a75ce72735a37c8a72da1a8a0a5df8d13365c2ae3d2c2bd6a0e7197c7c6", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 6,
"block_enc_hash": 4096,
"block_enc_sig": 2945,
}
],
"verifier_message": "challenge"
},
"claims": [{
...
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
...
คุณจะได้รับ Zero-Knowledge Proof ที่เข้ารหัสกลับมาจากกระเป๋าเงิน คุณสามารถ ตรวจสอบ Proof นี้กับใบรับรอง IACA ของผู้ออกใบรับรองได้โดยใช้ ไลบรารี longfellow-zk ของ Google
verifier-service มีเซิร์ฟเวอร์ที่พร้อมใช้งานจริงและใช้ Docker ซึ่งช่วยให้คุณตรวจสอบ การตอบกลับกับใบรับรอง IACA ของผู้ออกใบรับรองบางรายได้
คุณสามารถแก้ไข certs.pem เพื่อจัดการ ใบรับรอง IACA ของผู้ออกใบรับรอง ที่คุณต้องการเชื่อถือ
แหล่งข้อมูลและการสนับสนุน
- คำถามที่พบบ่อย: หากมีคำถามที่พบบ่อยเกี่ยวกับการผสานรวมทางเทคนิค โปรดดูคำถามที่พบบ่อยเกี่ยวกับข้อมูลประจำตัวและข้อมูลเข้าสู่ระบบดิจิทัล
- การติดตั้งใช้งานอ้างอิง: ดู การติดตั้งใช้งานอ้างอิงของผู้ตรวจสอบข้อมูลประจำตัว ใน GitHub
- เว็บไซต์ทดสอบ: ลองใช้โฟลว์แบบครบวงจรที่ verifier.multipaz.org
- ข้อกำหนด OpenID4VP: ดูข้อกำหนดทางเทคนิคสำหรับ openID4VP
- การสนับสนุน: หากต้องการความช่วยเหลือในการแก้ไขข้อบกพร่องหรือมีคำถามระหว่างการผสานรวม โปรดติดต่อ
wallet-identity-rp-support@google.com