В этом руководстве подробно описано, как использовать API DigitalCredential для получения подтвержденных номеров телефонов ваших пользователей. Процесс состоит из двух этапов:
- Запрос
TS.43 token
: Ваше клиентское приложение («верификатор») запрашивает временный токен TS.43 с устройства пользователя.TS.43 token
— это выданные оператором учётные данные, подтверждающие личность пользователя. - Обменять токен на номер телефона : бэкэнд вашего приложения обменивает
TS.43 token
с агрегатором или оператором на подтвержденный номер телефона пользователя.
Предпосылки
Для реализации проверки номера телефона с помощью API DigitalCredential вам потребуется учётная запись у агрегатора. Агрегатор взаимодействует с операторами связи и предоставляет необходимую API-платформу для вашего приложения, обычно в виде платной облачной конечной точки API.
Вам также необходимо добавить следующие зависимости в ваш скрипт сборки Gradle:
Котлин
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" }
Выполнение
Сквозной процесс обычно состоит из следующих этапов:
- Запрос параметров DCQL (язык запросов цифровых учётных данных) у агрегатора : вызовите один или несколько агрегаторов и запросите набор параметров DCQL. DCQL позволяет указать точные цифровые учётные данные, которые вам нужны от каждого агрегатора.
Создайте запрос OpenID4VP : в бэкенде вашего приложения создайте запрос OpenID4VP, включив параметры DCQL из агрегатора. Затем отправьте запрос OpenID4VP в клиентское приложение.
Вызовите API диспетчера учётных данных : в клиентском приложении используйте API диспетчера учётных данных для отправки запроса OpenID4VP операционной системе. В ответ вы получите объект ответа OpenID4VP, содержащий
TS.43 Digital Credential
. Эти учётные данные зашифрованы и могут быть расшифрованы только соответствующим агрегатором. После получения токена оператора отправьте ответ из клиентского приложения в бэкенд приложения.Проверьте ответ : в бэкэнде вашего приложения проверьте ответ OpenID4VP.
Обмен на номер телефона : из бэкенда вашего приложения отправьте
TS.43 Digital Credential
агрегатору. Агрегатор проверит идентификационные данные и вернет подтверждённый номер телефона.
Запрос параметров DCQL у агрегатора
Из бэкенда вашего приложения отправьте агрегатору запрос на объект учётных данных DCQL (Digital Credential Query Language). Обязательно укажите одноразовый код и идентификатор запроса в запросе. Агрегатор вернёт объект учётных данных 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 агрегатора должно совпадать с этим значением. -
dcql_query
: В этом случае используйтеdcql_query
, чтобы указать, что запрашиваютсяTS.43 Digital Credential
. Вы также можете запросить другие цифровые учётные данные здесь.
Затем заключите запрос OpenID4VP в объект запроса API DigitalCredential и отправьте его клиентскому приложению.
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
]
}
В следующем фрагменте показано, как сгенерировать запрос API DigitalCredential:
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
Вызовите API диспетчера учетных данных
В клиентском приложении выполните вызов API диспетчера учетных данных, используя запрос API DigitalCredential, предоставленный бэкэндом вашего приложения.
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)
}
}
Ответ API DigitalCredential содержит ответ OpenID4VP. Типичный JSON-файл с учётными данными из результата DigitalCredential
выглядит следующим образом:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"vp_token": {
"aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
# Credential in an array structure.
}
}
}
Из клиентского приложения отправьте ответ API DigitalCredential обратно на внутренний сервер, где он может быть проверен и использован для обмена подтвержденным номером телефона с агрегатором.
Подтвердите ответ цифрового удостоверения
Ниже приведен пример того, как проанализировать ответ и выполнить шаг проверки на внутреннем сервере вашего приложения:
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)