This API is used to obtain an access token. Each HTTPS request sent to the HUAWEI Wallet server needs to contain an access token, which will be verified by the HUAWEI Wallet server.
Protocol: HTTPS POST
Direction: Third-party management service -> HUAWEI Wallet server
URL: https://oauth-login.cloud.huawei.com/oauth2/v3/token
Data format:
Request: Content-Type: application/x-www-form-urlencoded
Response: Content-Type: application/json;charset=UTF-8
Request Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/x-www-form-urlencoded. |
Request Body
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| grant_type | Yes | String | Permission grant mode. Set this parameter to client_credentials, which indicates the client credential mode. |
| client_id | Yes | String | OAuth 2.0 client ID obtained during app development preparations. For an app created in AppGallery Connect, set this parameter to the value of Client ID. |
| client_secret | Yes | String | Client secret allocated to the client ID created in app development preparations. For an app created in AppGallery Connect, set this parameter to the value of Client Secret. |
grant_type=client_credentials&client_id=<Client ID>&client_secret=<Client secret>
Response Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/json;charset=UTF-8. |
Response Body
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| token_type | Yes | String | Token type. The value is always Bearer. |
| access_token | Yes | String | Access token. |
| expires_in | No | Long | Access token validity period, in seconds. The default value is 3600 seconds (that is, 60 minutes). |
{
"access_token": "<Returned access token>",
"expires_in": 3600,
"token_type": "Bearer"
} public static String getToken(String clientId, String clientSecret) {
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("grant_type", "client_credentials");
map.add("client_id", clientId);
map.add("client_secret", clientSecret);
String tokenUrl = ConfigUtil.instants().getValue("gw.tokenUrl");
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, header);
ResponseEntity<JSONObject> exchange =
REST_TEMPLATE.exchange(tokenUrl, HttpMethod.POST, entity, JSONObject.class);
JSONObject response = exchange.getBody();
if (response == null) {
throw new NullPointerException("Get null token response.");
}
String accessToken = response.getString("access_token");
if (Strings.isEmpty(accessToken)) {
throw new NullPointerException("Get null access token.");
}
return accessToken;
} This API is used to request the third-party management service to authenticate the authorization certificate after pre-personalization. The authentication request is forwarded by the HUAWEI Wallet server and the request body contains the applet's public key and its corresponding digital signature issued by the HUAWEI Wallet server.
Protocol: HTTPS POST
Direction: HUAWEI Wallet server -> Third-party management service
URL: https://{webServiceURL}/v1/passes/registrations
Data format:
Request: Content-Type: application/json;charset=UTF-8
Response: Content-Type: application/json;charset=UTF-8
webServiceURL indicates the domain name of the DK management service.
Request Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/json;charset=UTF-8. |
| Authorization | Yes | String | Token value in the linkDevicePass parameter, used to apply for a key card. The token is used to check whether the request is valid. |
Request Body
| Parent Node Parameter | Subnode Parameter | Type | Mandatory/Optional | Description |
|---|---|---|---|---|
| requestBody | passTypeIdentifier | String | Mandatory | Service ID registered when applying for Wallet Kit in AppGallery Connect. |
| requestBody | serialNumber | String | Mandatory | Number of the car key card on the HUAWEI Wallet server, which is used by the issuer to identify the card. |
| requestBody | passVersion | String | Optional | Version number, which is always 10.0. |
| requestBody | userDeviceId | String | Mandatory | Unique ID of a user device. |
| requestBody | transId | String | Mandatory | Random number. |
| signature | - | String | Mandatory | Signature of the hash value in requestBody, created by using the applet's identity private key. |
| certificate | signature | String | Mandatory | Signature value generated for the public key by the HUAWEI Wallet server using the private key. When receiving the request, the DK management service needs to use the public key provided by the HUAWEI Wallet server to authenticate the signature. |
| certificate | publicKey | String | Mandatory | Identity public key of the applet. |
{
"requestBody": {
"passTypeIdentifier": "Replace with the Service ID you applied on AGC",
"passVersion": "10.0",
"serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"transId": "16198381994485116358",
"userDeviceId": "xxx"
},
"certificate": {
"publicKey": "xxx",
"signature": "xxx"
},
"signature": "xxx"
} Response Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/json;charset=UTF-8. |
Response Body
| Parent Node Parameter | Subnode Parameter | Type | Mandatory/Optional | Description |
|---|---|---|---|---|
| Httpstatus | - | String | Mandatory | HTTP status code. |
| response | certificate | Certificate | Optional | Certificate returned, which is signed by the DK management service using the private key generated in step 5 of applying for Wallet Kit. |
Certificate Parameters
| Certificate Subnode Parameter | Type | Mandatory/Optional | Description |
|---|---|---|---|
| signature | String | Mandatory | Signature value generated for the public key by the HUAWEI Wallet server using the private key. When receiving the request, the DK management service needs to use the public key provided by the HUAWEI Wallet server to authenticate the signature. |
| publicKey | String | Mandatory | Identity public key of the applet. |
{
"httpStatus": "0",
"response": {
"certificate": {
"signature": "xxx",
"publicKey": "xxx"
}
}
} For details about the complete call example, please refer to the sample code in Wallet Kit - Card Activation on the Server.
public RegistrationsResponse dealWithRegisterRequest(String token, RegistrationsRequest request) {
RegistrationsResponse response = new RegistrationsResponse();
if (token == null) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_PARAM_ERROR));
return response;
}
if (!ParamChecker.isValidRegistrationsRequest(request)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_PARAM_ERROR));
return response;
}
Certificate walletCertificate = request.getCertificate();
if (!verifyWalletCert(walletCertificate)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_SIGN_ERROR));
return response;
}
if (!ParamChecker.hashSignatureCheck(request.toJsonString(), request.getSignature(),
appletAuthPublicKey, DataConvertUtil.SIGN_MODE_SHA256_RSA_MGF1)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_SIGN_ERROR));
return response;
}
String userDeviceId = request.getRequestBody().getUserDeviceId();
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_OK));
Response responseBody = new Response();
Certificate serverCert = PassData.getServerCert(appletAuthPublicKey);
responseBody.setCertificate(serverCert);
response.setResponse(responseBody);
deviceIdCertMap.put(userDeviceId, serverCert);
return response;
} This API is used to obtain a personal data token from the third-party management service. The request is forwarded by the HUAWEI Wallet server. The token will be used to calculate the hash value in the personal data request.
Protocol: HTTPS POST
Direction: HUAWEI Wallet server -> Third-party management service
URL: https://{webServiceURL}/v1/passes/requestPersonalizeToken
Data format:
Request: Content-Type: application/json;charset=UTF-8
Response: Content-Type: application/json;charset=UTF-8
Request Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/json;charset=UTF-8. |
| Authorization | Yes | String | Token value in the linkDevicePass parameter, used to apply for a key card. The token is used to check whether the request is valid. |
Request Body
| Parent Node Parameter | Subnode Parameter | Type | Mandatory/Optional | Description |
|---|---|---|---|---|
| requestBody | passTypeIdentifier | String | Mandatory | Service ID registered when applying for Wallet Kit in AppGallery Connect. |
| requestBody | serialNumber | String | Mandatory | Number of the car key card on the HUAWEI Wallet server, which is used by the issuer to identify the card. |
| requestBody | passVersion | String | Optional | Version number, which is always 10.0. |
| requestBody | userDeviceId | String | Mandatory | Unique ID of a user device. |
| requestBody | transId | String | Mandatory | Random number. |
| signature | - | String | Mandatory | Signature of the hash value in requestBody, created by using the applet's identity private key. |
| certificate | signature | String | Mandatory | Signature of the certificate returned by the device authentication API. The DK management service signs the identity public key of the applet using the private key generated in step 5 of applying for Wallet Kit. |
| certificate | publicKey | String | Mandatory | Identity public key of the applet in the certificate returned by the device authentication API. |
{
"requestBody": {
"passTypeIdentifier": "Replace with the Service ID you applied on AGC",
"passVersion": "10.0",
"serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"transId": "16198381994485116358",
"userDeviceId": "xxx"
},
"certificate": {
"publicKey": "xxx",
"signature": "xxx"
},
"signature": "xxx"
} Response Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/json;charset=UTF-8. |
Response Body
| Parent Node Parameter | Subnode Parameter | Type | Mandatory/Optional | Description |
|---|---|---|---|---|
| Httpstatus | - | String | Mandatory | HTTP status code. |
| response | token | String | Mandatory | Personal data token. |
For details about the complete call example, please refer to the sample code in Wallet Kit - Card Activation on the Server.
public RequestTokenResponse dealWithTokenRequest(RequestTokenRequest request) {
RequestTokenResponse response = new RequestTokenResponse();
String userDeviceId = request.getRequestBody().getUserDeviceId();
Certificate spCertFromRequest = request.getCertificate();
if (CommonUtils.isStringEmpty(userDeviceId) || !ParamChecker.checkSpServerCertificate(spCertFromRequest)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_PARAM_ERROR));
return response;
}
Certificate cachedCert = deviceIdCertMap.get(userDeviceId);
if (cachedCert == null) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_SIGN_ERROR));
return response;
}
if (!ParamChecker.hashSignatureCheck(request.toJsonString(), request.getSignature(),
appletAuthPublicKey, DataConvertUtil.SIGN_MODE_SHA256_RSA_MGF1)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_SIGN_ERROR));
return response;
}
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_OK));
Response responseBody = new Response();
String personalizeToken = PassData.getPersonalizeToken();
responseBody.setToken(personalizeToken);
deviceIdTokenMap.put(userDeviceId, personalizeToken);
response.setResponse(responseBody);
return response;
} This API is used to obtain personal data from the third-party management service. The request is forwarded by the HUAWEI Wallet server.
Protocol: HTTPS POST
Direction: HUAWEI Wallet server -> Third-party management service
URL: https://{webServiceURL}/v1/passes/requestPersonalize
Data format:
Request: Content-Type: application/json;charset=UTF-8
Response: Content-Type: application/json;charset=UTF-8
Request Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/json;charset=UTF-8. |
| Authorization | Yes | String | Token value returned by the API for obtaining a personal data token. The token is used to check whether the request is valid. |
Request Body
| Parent Node Parameter | Subnode Parameter | Type | Mandatory/Optional | Description |
|---|---|---|---|---|
| requestBody | cardSEId | String | Mandatory | Unique ID of an applet, which can be used to distribute the car key. |
| requestBody | passTypeIdentifier | String | Mandatory | Service ID registered when applying for Wallet Kit in AppGallery Connect. |
| requestBody | serialNumber | String | Mandatory | Number of the car key card on the HUAWEI Wallet server, which is used by the issuer to identify the card. |
| requestBody | passVersion | String | Optional | Version number, which is always 10.0. |
| requestBody | userDeviceId | String | Mandatory | Unique ID of a user device. |
| requestBody | personalizePublicKey | String | Mandatory | Personal public key of the applet, which is used to encrypt personal data field values. |
| requestBody | personalizeCert | String | Mandatory | Signature of personalizePublicKey, created by using the applet's identity private key. |
| requestBody | personalizeCertType | String | Mandatory | Fixed value. The private-key signature is used by default. |
| requestBody | transPublicKey | String | Mandatory | Transaction public key, which is used to encrypt the returned symmetric key and make a digital envelope for the returned data. |
| requestBody | transId | String | Mandatory | Transaction ID, which is used to combine the returned symmetric key. |
| signature | - | String | Mandatory | Signature of the hash value in requestBody, created by using the applet's identity private key. The token obtained by calling the API for obtaining a personal data token is used as a key value in requestBody for hash value calculation. |
| certificate | signature | String | Mandatory | Signature of the certificate returned by the device authentication API. The DK management service signs the identity public key of the applet using the private key generated in step 5 of applying for Wallet Kit. |
| certificate | publicKey | String | Mandatory | Identity public key of the applet in the certificate returned by the device authentication API. |
{
"requestBody": {
"cardSEId": "xxxxxxxxxxxxxxxx",
"personalizeCert": "xxx",
"personalizeCertType": "",
"personalizePublicKey": "xxx",
"transPublicKey": "xxx",
"passTypeIdentifier": "Replace with the Service ID you applied on AGC",
"passVersion": "10.0",
"serialNumber": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"transId": "858947076d58a5e66ee22b9ed1c43c4d",
"userDeviceId": "xxx"
},
"certificate": {
"publicKey": "xxx",
"signature": "xxx"
},
"signature": "xxx"
} Response Header
| Parameter | Mandatory | Type | Description |
|---|---|---|---|
| Content-Type | Yes | String | Content type. The value is application/json;charset=UTF-8. |
Response Body
| Parent Node Parameter | Subnode Parameter | Type | Mandatory/Optional | Description |
|---|---|---|---|---|
| Httpstatus | - | String | Mandatory | HTTP status code. |
| response | encryptSessionKey | String | Mandatory | Session key encrypted by the DK management service using transPublicKey in the request. The fields involved in encryption using Base64 encoding are described as follows: The AES128 values of aesKey and aesIv are generated by the third-party management service and are used to generate encryptAppletPersonalizeFields and encryptDevicePass after encryption. The values of transId, aesKey, and aesIv are encrypted using transPublicKey in the request and then encoded by Base64 to obtain encryptSessionKey. Encryption algorithm: RSA/ECB/OAEPWithSHA-256AndMGF1Padding. |
| response | encryptDevicePass | String | Optional | Empty string. |
| response | encryptAppletPersonalizeFields | String | Mandatory | Personal data parameter of the applet, used for authentication and data encryption and decryption during Bluetooth/NFC card swiping. The parameter is encrypted by the DK management service using the generated session key. The value is then encoded by Base64. |
| signature | - | String | Mandatory | The DK management service signs the hash value of the response using the private key generated in step 5 of applying for Wallet Kit. |
| encryptAppletPersonalizeFields Subnode Parameter | Type | Mandatory/Optional | Storage Format | Description |
|---|---|---|---|---|
| temp_key | String | Mandatory | - | Plaintext of AES128 key, left padded with a fixed hexadecimal string 34810233 and then encrypted using appletPublicKey. The AES128 key contains 16 bytes and is used to encrypt CardId and cardPrivateInfo. The encryption algorithm is RSA/NONE/OAEPWithSHA1AndMGF1Padding. |
| temp_iv | String | Mandatory | - | AES-128 IV encrypted using appletPublicKey (applet's personal public key), which contains 16 bytes and is used by the applet to decrypt the card data. The encryption algorithm is RSA/NONE/OAEPWithSHA1AndMGF1Padding. |
| card_id | String | Mandatory | 9F3B + Lc + CardId | Unique ID of a card issued by the issuer, which is the same as the value of serialNumber defined when the key card is generated. The ID contains 16 bytes. The card ID is encoded in TLV format, where T=9F3B indicates the data type, Lc=10 specifies the length as 10 bytes, and V represents the card ID. The entire TLV is encrypted using aesKey and aesIv and then converted into a hexadecimal string. The CBC encryption mode is used and the encryption algorithm is AES/CBC/NoPadding. |
| card_key | String | Mandatory | - | Key of a card, which contains 16 bytes and is used to calculate SessionKey. Each card supports one key. The key is left padded with 34010133, and then the entire string is converted into a hexadecimal string and encrypted using appletPublicKey. The encryption algorithm is RSA/NONE/OAEPWithSHA1AndMGF1Padding. |
| card_info | String | Mandatory | 9F05 + Lc + CardInfo1 + 9F31 + Lc + CardAuthParameter | Private information about a card, which can be read before authentication (GetProcessData step) and stored in TLV format (with multiple TLV records combined). The plaintext TLV data is padded with 800...00 to a multiple of 16 bytes. The result is encrypted using aesKey and aesIv, and then converted into a hexadecimal string. The CBC encryption mode is used and the encryption algorithm is AES/CBC/NoPadding. |
| card_privateInfo | String | Mandatory | - | Private information about a card, such as the validity period and permissions. The information is read after authentication (ReadBinary step) and parsed by the third-party management service. The plaintext data is padded with 800...00 to a multiple of 16 bytes. The result is encrypted using aesKey and aesIv, and then converted into a hexadecimal string. The CBC encryption mode is used and the encryption algorithm is AES/CBC/NoPadding. |
| card_key_iv | String | Mandatory | Lc + CardKeyIV | Session key negotiated in the transaction process (which needs to be delivered to the car synchronously). The value contains 16 bytes. If you do not need to use this value, pass zeros for all bytes. |
{
"httpStatus": "0",
"response": {
"encryptDevicePass": "xxx",
"encryptAppletPersonalizeFields": "xxx",
"encryptSessionKey": "xxx"
},
"signature": "xxx"
} For details about the complete call example, please refer to the sample code in Wallet Kit - Card Activation on the Server.
public PersonalizeResponse dealWithPersonalizeDataRequest(String token, PersonalizeRequest request) {
PersonalizeResponse response = new PersonalizeResponse();
RequestBody requestBody = request.getRequestBody();
String userDeviceId = requestBody.getUserDeviceId();
Certificate spCertFromRequest = request.getCertificate();
String cachedToken = deviceIdTokenMap.remove(userDeviceId);
if (cachedToken == null || !cachedToken.equals(token)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_PARAM_ERROR));
return response;
}
if (CommonUtils.isStringEmpty(userDeviceId) || !ParamChecker.checkSpServerCertificate(spCertFromRequest)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_PARAM_ERROR));
return response;
}
Certificate cachedCert = deviceIdCertMap.get(userDeviceId);
if (cachedCert == null) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_PARAM_ERROR));
return response;
}
if (!ParamChecker.hashSignatureCheck(request.toJsonString(token), request.getSignature(),
appletAuthPublicKey, DataConvertUtil.SIGN_MODE_SHA256_RSA_MGF1)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_SIGN_ERROR));
return response;
}
String personalizePKSign = requestBody.getPersonalizeCert();
byte[] srcBytes = DataConvertUtil.base64Decode(requestBody.getPersonalizePublicKey());
if (!DataConvertUtil.checkSign(srcBytes, personalizePKSign,
appletAuthPublicKey, DataConvertUtil.SIGN_MODE_SHA256_RSA_MGF1)) {
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_SIGN_ERROR));
return response;
}
response.setHttpStatus(String.valueOf(Constants.RESULT_CODE_OK));
PassDataResponse passData = getDevicePassData(requestBody);
response.setResponse(passData);
String passDataStr = passData.toJsonString();
String passHashValue = DataConvertUtil.encodeSHA256(passDataStr);
String signature = DataConvertUtil.signData(passHashValue, Constants.SERVER_SECRET_KEY);
response.setSignature(signature);
return response;
}