Sign a request and verify the signature
To ensure the authenticity and integrity of data after transmission, Alipay requires all requests to be signed and the signatures to be verified:
- When calling an API, you must sign the request sent to Alipay and verify the Alipay response signature accordingly. For more information, see Call an API.
- When receiving a notification, you must verify the Alipay request signature. However, you do not need to sign the response for the notification. For more information, see Receive a notification.
Call an API
Prerequisite
To sign a request, generate a pair of asymmetric public and private keys using the RSA2 method. You can download the tool on Alipay Developer Center to get a pair of asymmetric keys.
Figure 1. Set public key section of Alipay Developer Center
The private key is used to generate the signature of a request, and you submit the asymmetric public key in the Set public key section under Integration Settings. Alipay uses the public key to verify your request signature.
Sign a request
The following figure shows how to sign a request:
Figure 2. How to sign a request
Step 1: Construct the content to be signed
The syntax of Content_To_Be_Signed
is as follows:
<HTTP-Method> <HTTP-URI>
<Client-Id>.<Request-Time>.<Request-Body>
HTTP-Method
: POSTHTTP-URI
: For example, if the HTTP URL is https://open-na-global.alipay.com/ams/api/v1/payments/pay, this field is/ams/api/v1/payments/pay
.Client-Id
: Used to identify a client. For example,TEST_5X00000000000000
. You can get this field from the request header.Request-Time
: Specifies the timestamp of when a request is sent. The value of this field must be accurate to milliseconds. For example,1685599933871
. You can get the timestamp from the request header.Request-Body
: The data body of the request. For example:
{
"order":{
"orderId":"OrderID_0101010101",
"orderDescription":"sample_order",
"orderAmount":{
"value":"100",
"currency":"JPY"}
}
}
By complying with the syntax of Content_To_Be_Signed
, the request body above is constructed as follows:
POST /ams/api/v1/payments/pay
TEST_5X00000000000000.2019-05-28T12:12:12+08:00.{
"order":{
"orderId":"OrderID_0101010101",
"orderDescription":"sample_order",
"orderAmount":{
"value":"100",
"currency":"JPY"}
}
}
Step 2: Generate the signature
The syntax of generating the signature is as follows:
generatedSignature=base64UrlEncode(sha256withrsa(<Content_To_Be_Signed>), <privateKey>))
sha256withrsa
: The method to generate a digital signature for the provided contentbase64UrlEncode
: The method to encode the generated digital signatureContent_To_Be_Signed
: The content obtained from Step 1privateKey
: The private key value obtained from Prerequisite
An example of a generated signature is as follows:
KrwDE9tAPJYBb4cUZU6ALJxGIZgwDXn5UkFPMip09n%2FkYKPhEIII%2Fki2rYY2lPtuKVgMNz%2BtuCU%
2FjzRpohDbrOd8zYriiukpGAxBQDIVbatGI7WYOcc9YVQwdCR6ROuRQvr%2FD1AfdhHd6waAASu5Xugow9
w1OW7Ti93LTd0tcyEWQYd2S7c3A73sHOJNYl8DC1PjasiBozZ%2FADgb7ONsqHo%2B8fKHsLygX9cuMkQY
TGIRBQsvfgICnJhh%2BzXV8AQoecJBTrv6p%xxxx
The following code sample shows how to use java to sign a request:
/**
*
* @param requestURI // domain part excluded, sample: /ams/api/v1/payments/pay
* @param clientId
* @param requestTime
* @param privateKey
* @param requestBody
* @return
*/
public static String sign(String requestURI, String clientId, String requestTime,
String privateKey, String requestBody) {
String content = String.format("POST %s\n%s.%s.%s", requestURI, clientId, requestTime,
requestBody);
try {
java.security.Signature signature = java.security.Signature
.getInstance("SHA256withRSA");
PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(
new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey.getBytes("UTF-8"))));
signature.initSign(priKey);
signature.update(content.getBytes("UTF-8"));
byte[] signed = signature.sign();
return URLEncoder.encode(new String(Base64.encodeBase64(signed), "UTF-8"), "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Step 3: Add the generated signature to the request header
- Assemble a signature string based on the following syntax:
'Signature: algorithm=<algorithm>, keyVersion=<key-version>, signature=<generatedSignature>'
algorithm
,keyVersion
: See the header of the Message structure chapter.generatedSignature
: The signature generated in Step 2.
For example:
'Signature: algorithm=RSA256, keyVersion=1, signature=KrwDE9tAPJYBb4cUZU6ALJxGIZgwDXn5UkFPMip09n%2FkYKPhEIII%2Fki2rYY2lPtuKVgMNz%2BtuCU%2FjzRpohDbrOd8zYriiukpGAxBQDIVbatGI7WYOcc9YVQwdCR6ROuRQvr%2FD1AfdhHd6waAASu5Xugow9w1OW7Ti93LTd0tcyEWQYd2S7c3A73sHOJNYl8DC1PjasiBozZ%2FADgb7ONsqHo%2B8fKHsLygX9cuMkQYTGIRBQsvfgICnJhh%2BzXV8AQoecJBTrv6p%****'
- Add the signature string to the request header. For details about the request header, see the Message structure chapter.
Send a request
Construct a request by adding the Client-Id
, Request-Time
, and Signature
properties to the request header. After a request is constructed, you can use common tools, such as cURL or Postman to send the request. In the following example, cURL is used:
curl -X POST \
https://www.example.com/ams/api/v1/payments/pay \
-H 'Content-Type: application/json' \
-H 'Client-Id: TEST_5X00000000000000' \
-H 'Request-Time: 1685599933871' \
-H 'Signature: algorithm=RSA256, keyVersion=0, signature=KrwDE9tAPJYBb4cUZU6ALJxGIZgwDXn5UkFPMip09n%2FkYKPhEIII%2Fki2rYY2lPtuKVgMNz%2BtuCU%2FjzRpohDbrOd8zYriiukpGAxBQDIVbatGI7WYOcc9YVQwdCR6ROuRQvr%2FD1AfdhHd6waAASu5Xugow9w1OW7Ti93LTd0tcyEWQYd2S7c3A73sHOJNYl8DC1PjasiBozZ%2FADgb7ONsqHo%2B8fKHsLygX9cuMkQYTGIRBQsvfgICnJhh%2BzXV8AQoecJBTrv6p%xxxx' \
-d '{
"order":{
"orderId":"OrderID_0101010101",
"orderDescription":"sample_order",
"orderAmount":{
"value":"100",
"currency":"JPY"
}
},
"paymentAmount":{
"value":"100",
"currency":"JPY"
},
"paymentFactor": {
"isInStorePayment": "true"
}
}'
Handle a response
After receiving a response from Alipay, verify the signature of the response. The following figure shows how to verify a signature:
Figure 3. How to verify a signature
A response consists of the response header and the response body. For example:
- Code sample of the response header:
Client-Id: 5X00000000000000
Response-Time: 2019-05-28T12:12:14+08:00
signature: algorithm=RSA256, keyVersion=0, signature=p9T2hXxIjek0UOLw3fwlthNsV6ATaioIvu8X1uFx8a9tE87d2XEhqylnf0KjifJ3WhCoMokl
GwwlDS3tsSenwnL0Ha6BsXbJvUHRC5qcVlNy5Oq%2FpNqx2%2BKdwbw4eY7tZBDQhMKoaMVSbqbCb3eRBX
sw9ZwOO%2FFCyq1zICzllOd4pbhpvES3gcw2X%2B0Ye4hQJBghcLCJxCizSv9lMyTmV%2BYA39B9gRouha
N0dM2aeAXMlVJAWtJdcL%2Bdub%2F3LrzxBnY%****
- Code sample of the response body:
{
"result": {
"resultCode":"SUCCESS",
"resultStatus":"S",
"resultMessage":"success"
}
}
The following steps demonstrate how to handle a response from Alipay by using the examples above.
Step 1: Obtain Alipay public key
Obtain the Alipay public key from Alipay Developer Center. The following figure shows where to obtain the Alipay public key:
Figure 4. Obtain Alipay public key
Note: Only when you upload your asymmetric public key to Alipay Developer Center, can you obtain the Alipay public key used to verify the corresponding response from Alipay.
Step 2: Construct the content to be verified
The syntax of Content_To_Be_Validate
is as follows:
<HTTP-Method> <HTTP-URI>
<Client-Id>.<Response-Time>.<Response-Body>
HTTP-Method
: POSTHTTP-URI
: For example, if the HTTP URL is https://open-na-global.alipay.com/ams/api/v1/payments/pay, this field is/ams/api/v1/payments/pay
.Client-Id
: Used to identify a client. You can get this field from the response header.Response-Time
: Specifies the time when a response is returned, as defined by ISO 8601. This field must be accurate to milliseconds. For example,2019-05-28T12:12:14+08:00
. You can get this field from the response header.Response-Body
: The data body of the response.
By complying with the syntax of Content_To_Be_Validated
, construct the response given above as follows:
POST /ams/api/v1/payments/pay
TEST_5X00000000000000.2019-05-28T12:12:14+08:00.{
"result": {
"resultCode":"SUCCESS",
"resultStatus":"S",
"resultMessage":"success"
}
}
Step 3: Get the signature from the response header
The target signature string (target_signature
) can be extracted from the Signature
header in the response header. For details about the response header, see Message structure.
Code sample of Signature
:
Signature: algorithm=RSA256, signature=<target_signature>
Step 4: Verify the signature
The syntax of validating the signature is as follows:
IS_SIGNATURE_VALID=sha256withrsa_verify(base64UrlDecode(<target_signature>), <Content_To_Be_Validated>, <serverPublicKey>)
sha256withrsa_verify
: The method to verify the signaturebase64UrlDecode
: The method to decode the signaturetarget_signature
: The target signature obtained from step 3content_to_be_verified
: The content to be verified, created from step 2serverPublicKey
: The Alipay public key obtained from step 1IS_SIGNATURE_VALID
: A Boolean value that specifies whether the signature is valid
true
: The signature is valid.false
: The signature is not valid. The cause can be a mismatch between the private key and public key, orContent_To_Be_Validated
is not correctly constructed.
The following sample code shows how to use Java to verify the signature:
/**
*
* @param requestURI // domain part excluded, sample: /ams/api/v1/payments/pay
* @param clientId
* @param reponseTime
* @param alipayPublicKey
* @param responseBody
* @param signatureToBeVerified
* @return
*/
public static boolean verify(String requestURI, String clientId, String reponseTime,
String alipayPublicKey, String responseBody,
String signatureToBeVerified) {
//signatureToBeVerified would not be present in the response when AMS returns a SIGNATURE_INVALID
if (StringUtil.isBlank(signatureToBeVerified)) {
return false;
}
String content = String.format("POST %s\n%s.%s.%s", requestURI, clientId, reponseTime,
responseBody);
try {
java.security.Signature signature = java.security.Signature
.getInstance("SHA256withRSA");
PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(
new X509EncodedKeySpec(Base64.decodeBase64(alipayPublicKey.getBytes("UTF-8"))));
signature.initVerify(pubKey);
signature.update(content.getBytes("UTF-8"));
return signature.verify(Base64.decodeBase64(URLDecoder.decode(signatureToBeVerified,
"UTF-8").getBytes("UTF-8")));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Receive a notification
Handle a request
After receiving a notification from Alipay, verify the signature of the request. The process of verifying the request signature is similar to the process introduced in the Handle a response section. To verify the signature, follow these steps:
- Obtain the Alipay public key for the request to verify the signature.
- Construct the request to be verified by complying with the syntax of
Content_To_Be_Validated
:
<HTTP-METHOD> <Request-URI>
<Client-Id>.<Request-Time>.<Request-Body>
- Get the signature from the request header.
- Verify the signature.