Z tego przewodnika dowiesz się, jak bezpośrednie strony zależne – indywidualni sprzedawcy, firmy i deweloperzy aplikacji – integrują interfejs Digital Credentials API, aby żądać cyfrowych danych uwierzytelniających i je weryfikować w aplikacjach na Androida i w internecie.
Wybierz ścieżkę RP, Verifier Registrar lub stacjonarnie
Jak działa integracja z aplikacją lub usługą zależną
Każda integracja z usługą Relying Party składa się z 4 kroków. Kroki A i C są wykonywane na serwerze, a krok B – w aplikacji na Androida lub w przeglądarce. Wybierz dowolny krok, aby przejść do szczegółów jego implementacji:

Obsługiwane formaty, dane logowania i możliwości
Portfel Google obsługuje cyfrowe dokumenty tożsamości oparte na ISO mdoc przez OpenID4VP (wersja 1.0) na Androidzie 9 (poziom interfejsu API 28) i nowszych wersjach oraz w obsługiwanych przeglądarkach.
Obsługiwane dane uwierzytelniające i atrybuty
Sprawdź identyfikatory doctype_value (mDL, cyfrowy dokument tożsamości, dokument tożsamości ze zdjęciem) i ścieżki deklaracji atrybutów, o które możesz poprosić w Portfelu Google.
Obsługiwani wydawcy i certyfikaty IACA
Pobierz oficjalne certyfikaty główne IACA dla stanów USA, wydawców międzynarodowych i wydawcy Sandbox Utopia, aby zweryfikować issuerAuth.
Krok A. Sformatuj i podpisz żądanie (po stronie serwera)
Aby poprosić o dane uwierzytelniające z dowolnego portfela, musisz sformatować żądanie za pomocą OpenID4VP na serwerze. Możesz poprosić o konkretne dane logowania lub o kilka rodzajów danych logowania w jednym obiekcie dcql_query.
Przykładowe żądanie JSON
Oto przykładowe żądanie mdoc requestJson dotyczące uzyskania danych uwierzytelniających tożsamość z dowolnego portfela na urządzeniu z Androidem lub w internecie.
{
"requests" : [
{
"protocol": "openid4vp-v1-signed",
"data": {<signed_credential_request>} // This is an object, shouldn't be a string.
}
]
}
Szyfrowanie żądań
Parametr client_metadata zawiera klucz publiczny szyfrowania dla każdego żądania.
Musisz przechowywać klucze prywatne dla każdego żądania i używać ich do uwierzytelniania i autoryzowania tokena otrzymanego z aplikacji portfela.
Zintegrowane metadane OpenID4VP
Podczas formatowania żądania danych logowania musisz uwzględnić pole gw_rp_metadata_bytes w obiekcie client_metadata (jak pokazano w przykładowym kodzie żądania poniżej). To pole zawiera metadane strony uzależnionej zakodowane w formacie Base64URL, które są wymagane przez Portfel Google do zweryfikowania Twojej tożsamości i wyświetlenia użytkownikowi Twojej marki.
Ładunek żądania danych logowania
Parametr credential_request w requestJson zawiera te pola.
Konkretne dane logowania
{
"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": {
// Use org.iso.18013.5.1.mDL for mDL,
// com.google.wallet.idcard.1 for ID pass, or
// org.iso.23220.photoid.1 for ID pass (using photo ID document type)
"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
}
]
}
]
},
"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
]
}
},
"gw_rp_metadata_bytes": "<base64url encoded metadata string>"
}
}
Dowolne kwalifikujące się dane logowania
Oto przykładowe żądanie dotyczące mDL, cyfrowego dokumentu tożsamości i cyfrowego dokumentu tożsamości (z użyciem typu dokumentu tożsamości ze zdjęciem). Użytkownik może wybrać dowolną z nich.
{
"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 pass
"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 type 3: ID pass (using photo ID document type)
"id": "photo_id-request",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.23220.photoid.1"
},
"claims": [
{
"path": [
"org.iso.23220.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.23220.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.23220.1",
"age_over_18"
],
"intent_to_retain": false
}
]
}
]
credential_sets : [
{
"options": [
[ "mdl-request" ],
[ "id_pass-request" ],
[ "photo_id-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
],
"issuerauth_alg_values": [
-7
]
}
},
"gw_rp_metadata_bytes": "<base64url encoded metadata string>"
}
}
Możesz poprosić o dowolną liczbę obsługiwanych atrybutów z dowolnego dokumentu tożsamości zapisanego w Portfelu Google.
Podpisane żądania
Podpisane żądania (żądania autoryzacji zabezpieczone tokenem JWT) zawierają żądanie weryfikowalnej prezentacji w kryptograficznie podpisanym tokenie sieciowym JSON (JWT) przy użyciu infrastruktury PKI, co zapewnia integralność żądania i potwierdza tożsamość w Portfelu Google.
Wymagania wstępne
Zanim wprowadzisz zmiany w kodzie dotyczące podpisanych żądań, upewnij się, że masz:
- Klucz prywatny: do podpisania żądania potrzebujesz klucza prywatnego (np. krzywej eliptycznej
ES256) zarządzanego na serwerze. Do testowania w piaskownicy jako strona uzależniona użyj klucza prywatnego do testowania w piaskownicy. - Certyfikat: potrzebujesz standardowego certyfikatu X.509 pochodzącego z pary kluczy.
- Rejestracja: upewnij się, że Twój certyfikat publiczny (lub główny urząd certyfikacji w przypadku rejestratorów weryfikatorów) jest zaufany przez Portfel Google.
Logika tworzenia żądań
Podczas tworzenia i podpisywania żądania OpenID4VP zwróć szczególną uwagę na dokładny format kodowania oczekiwany w przypadku każdego pola. Pomylenie base64 i base64url lub dopełnienia (=) spowoduje niepowodzenie weryfikacji podpisu lub pochodzenia:
| Pole | Wymagane kodowanie / format | Znaki i dopełnienie |
|---|---|---|
client_id (x509_hash:<hash>) |
base64url bez dopełnienia, | Używa alfabetu bezpiecznego dla adresów URL (-, _); usuwa końcowe znaki = |
expected_origins (android:apk-key-hash:<hash>) |
Standard base64 bez dopełnienia | Używa standardowego alfabetu (+, /); usuwa końcowe znaki = |
expected_origins (https://...) |
Adres URL zapisany małymi literami bez ukośników na końcu. | Przykład: https://example.com (bez końcowego znaku /) |
Nagłówek JWS x5c |
Standardowy base64 z dopełnieniem | Używa standardowego alfabetu (+, /); zachowaj końcowe dopełnienie = |
Aby utworzyć żądanie, użyj klucza prywatnego i umieść ładunek w 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()
# Important: Use URL-safe Base64 (base64url: '-', '_') without padding ('=') for client_id
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
# Important: Use standard Base64 (not URL-safe) without padding for android:apk-key-hash:
# origin = f"android:apk-key-hash:{base64.b64encode(apk_cert_hash).decode('utf-8').rstrip('=')}"
# Format for web origin (lowercase URL without trailing slash): origin = "https://example.com"
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.
# Important: Use standard Base64 ('+', '/') WITH padding ('=') for x5c
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
Krok B. Wywołaj interfejs API (po stronie klienta)
Całe żądanie do interfejsu API powinno być generowane po stronie serwera. W zależności od platformy przekaż wygenerowany kod JSON do interfejsów API platformy.
W aplikacji (Android)
Aby poprosić o dokumenty tożsamości z aplikacji na Androida, wykonaj te czynności:
Zaktualizuj zależności
W pliku build.gradle projektu zaktualizuj zależności, aby używać Menedżera danych logowania (beta):
dependencies {
implementation("androidx.credentials:credentials:1.5.0-beta01")
implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}
Konfigurowanie Credential Manager
Aby skonfigurować i zainicjować obiekt CredentialManager, dodaj logikę podobną do tej:
// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)
Atrybuty tożsamości żądania
Zamiast określać poszczególne parametry żądań tożsamości, aplikacja udostępnia je wszystkie razem jako ciąg JSON w parametrze CredentialOption.
Credential Manager przekazuje ten ciąg znaków JSON do dostępnych portfeli cyfrowych bez sprawdzania jego zawartości. Każdy portfel odpowiada za:
- analizowanie ciągu JSON w celu zrozumienia żądania tożsamości;
- określenie, które z zapisanych danych logowania (jeśli takie istnieją) spełniają wymagania żądania;
Zalecamy, aby partnerzy tworzyli żądania na serwerze nawet w przypadku integracji aplikacji na Androida.
Użyjesz requestJson z sekcji Formatowanie i podpisywanie żądania jako request w wywołaniu funkcji 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)
}
}
Obsługa odpowiedzi z danymi logowania
Gdy otrzymasz odpowiedź z portfela, sprawdź, czy jest ona prawidłowa i zawiera odpowiedź 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}")
}
}
Odpowiedź credentialJson zawiera zaszyfrowany token identityToken (JWT) zdefiniowany przez W3C. Za utworzenie tej odpowiedzi odpowiada aplikacja Portfel.
Przykład:
{
"protocol" : "openid4vp-v1-signed",
"data" : {
<encrypted_response>
}
}
Przekaż tę odpowiedź z powrotem do serwera, aby zweryfikować jej autentyczność. Zobacz Odszyfrowywanie i weryfikowanie odpowiedzi.
Sieć
Aby poprosić o dokumenty tożsamości za pomocą interfejsu Digital Credentials API w Chrome lub innych obsługiwanych przeglądarkach, wyślij to żądanie:
const credentialResponse = await navigator.credentials.get({
digital : {
requests : [
{
protocol: "openid4vp-v1-signed",
data: {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
})
Wyślij odpowiedź z tego interfejsu API z powrotem na serwer, aby zweryfikować odpowiedź dotyczącą danych logowania.
Krok C. Odszyfrowanie i zweryfikowanie odpowiedzi (po stronie serwera)
Gdy portfel zwróci zaszyfrowany token identityToken (JWT), musisz przeprowadzić rygorystyczną weryfikację po stronie serwera, zanim zaufasz danym.
Odszyfrowanie odpowiedzi
Aby odszyfrować JWE, użyj klucza prywatnego odpowiadającego kluczowi publicznemu wysłanemu w żądaniu client_metadata. Daje to vp_token.
Przykład w Pythonie:
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 spowoduje zwrócenie obiektu JSON vp_token zawierającego dane logowania:
{
"vp_token":
{
"cred1": ["<base64UrlNoPadding_encoded_credential>"] // This applies to OpenID4VP 1.0 spec.
}
}
Odtwarzanie SessionTranscript i weryfikowanie DeviceResponse
- Utwórz obiekt SessionTranscript z normy ISO/IEC 18013-5:2021 ze strukturą przekazywania danych na Androida lub do internetu:
SessionTranscript = [
null, // DeviceEngagementBytes not available
null, // EReaderKeyBytes not available
[
"OpenID4VPDCAPIHandover",
AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web
]
]
W przypadku przekazywania na Androidzie i w przeglądarce użyj tego samego parametru nonce, który został użyty do wygenerowania parametru credential_request.
Przekazywanie Androida
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()
Przekazywanie przeglądarki
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()
W przypadku korzystania z SessionTranscript odpowiedź urządzenia musi zostać zweryfikowana zgodnie z normą ISO/IEC 18013-5:2021, klauzula 9.
Weryfikacja obejmuje 4 testy:
- Sprawdź certyfikat wydawcy: wyodrębnij łańcuch certyfikatów podpisu wydawcy z
issuerAuthi zweryfikuj go pod kątem zaufanych certyfikatów głównych IACA. Zapoznaj się z artykułem Obsługiwani wydawcy i certyfikaty IACA (i dodaj certyfikat Utopia Sandbox podczas testowania za pomocą testowego dokumentu tożsamości w piaskownicy). - Weryfikacja podpisu MSO (ISO/IEC 18013-5, sekcja 9.1.2).
- Oblicz i sprawdź
ValueDigestspod kątem elementów danych (ISO/IEC 18013-5, sekcja 9.1.2). - Weryfikacja podpisu
deviceSignature(ISO/IEC 18013-5, sekcja 9.1.3).
{
"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
}
Krok D (opcjonalny): weryfikacja wieku chroniąca prywatność (ZKP)
Aby obsługiwać dowody z wiedzą zerową (np. weryfikację, czy użytkownik ma ukończone 18 lat, bez wyświetlania dokładnej daty urodzenia), zmień format żądania na mso_mdoc_zk i podaj wymaganą konfigurację zk_system_type.
Ogólne omówienie tego, czym jest ZKP i jakie ma możliwości, znajdziesz w Najczęstszych pytaniach.
...
"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
{
...
Z portfela otrzymasz zaszyfrowany dowód z wiedzą zerową. Możesz sprawdzić to potwierdzenie pod kątem certyfikatów IACA wydawcy, korzystając z biblioteki longfellow-zk Google.
verifier-service zawiera gotowy do wdrożenia serwer oparty na Dockerze, który umożliwia weryfikację odpowiedzi na podstawie certyfikatów IACA wydawcy.
Możesz zmodyfikować plik certs.pem, aby zarządzać certyfikatami wystawcy IACA, którym chcesz ufać.
Pakiety SDK, przykładowe implementacje i pomoc
Aby przyspieszyć implementację, skorzystaj z naszych bibliotek open source, serwera referencyjnego i narzędzia do weryfikacji stron internetowych:
| Zasób / biblioteka | Co zapewnia | Link |
|---|---|---|
| Identity Verifiers Reference Implementation | Przykładowy serwer i klient demonstrujący generowanie żądań OpenID4VP, podpisywanie JWS, odszyfrowywanie JWE i weryfikację odpowiedzi mdoc. | Repozytorium GitHub |
| Multipaz SDK | Biblioteka open source (OpenWallet Foundation), w tym DeviceResponseParser do dekodowania CBOR, rekonstrukcji SessionTranscript i weryfikacji podpisu ISO/IEC 18013-5/7. |
openwallet-foundation/multipaz |
| Longfellow ZKP Library & Verifier Service | Biblioteka open source i serwer oparty na Dockerze do weryfikacji wieku i atrybutów za pomocą dowodu z wiedzą zerową (mso_mdoc_zk). |
google/longfellow-zk |
| Interactive Web Verifier Tool | Hostowany weryfikator internetowy do testowania żądań interfejsu W3C Digital Credentials API / OpenID4VP w Portfelu Google. | verifier.multipaz.org |
| Specyfikacja OpenID4VP 1.0 | Oficjalna specyfikacja protokołu OpenID for Verifiable Presentations 1.0. | Specyfikacja OpenID4VP |
| Najczęstsze pytania i pomoc dla deweloperów | Odpowiedzi na najczęstsze pytania dotyczące integracji technicznej. Możesz też wysłać e-maila na adres wallet-identity-rp-support@google.com, aby uzyskać pomoc w debugowaniu. |
Najczęstsze pytania dotyczące integracji technicznej |