Alipay Signature Generation using NodeJS
Learn how to generate the signature required for Alipay Payment APIs using NodeJS.
The first step to integrate Alipay to your application is to figure out how to generate the signature needed for authorisation when calling any Alipay Payment API.
Why is this a difficult task? Isn't it just a signature?
Well trust me, there is no proper documentation out there that explains how to generate this signature accurately.
Note:
Please double-check with the latest documentation if you are viewing this article much later than a year of writing this blog — April 2021.
Alipay Cashier Payment Request — Sample Payload (request.json)
{
"order": {
"orderAmount": {
"currency": "CNY",
"value": "1314"
},
"extendInfo": {
"chinaExtraTransInfo": {
"totalQuantity": "2",
"otherBusinessType": "testBusinessType",
"businessType": "4",
"goodsInfo": "test"
}
},
"orderDescription": "Mika's coffee shop",
"referenceOrderId": "ORDER_20201130113221588",
"env": {
"osType": "ANDROID",
"terminalType": "WEB"
}
},
"paymentAmount": {
"currency": "CNY",
"value": "1314"
},
"paymentMethod": {
"paymentMethodType": "ALIPAY_CN"
},
"settlementStrategy": {
"settlementCurrency": "USD"
},
"paymentNotifyUrl": "https://www.gaga.com/notify",
"paymentRedirectUrl": "https://global.alipay.com/doc/cashierpayment/intro",
"paymentRequestId": "REQUEST_20201130113221588",
"productCode": "CASHIER_PAYMENT"
}
Import crypto and request.json
const crypto = require("crypto");
const request = require("./request.json");// Alipay Payment Request Payload
const requestString = JSON.stringify(request);
console.log(requestString);
Required Functions
- signContent: Function to generate the signature by signing the content using a private key.
- verifySignature: Function to verify the generated signature using a public key.
function signContent(content, privateKey, encoding) {
const sign = crypto.createSign("SHA256");
sign.write(content, encoding);
sign.end();
return sign.sign(privateKey, "base64");
}function verifySignature(content, publicKey, signature, encoding) {
const verify = crypto.createVerify("SHA256");
verify.write(content, encoding);
verify.end();
return verify.verify(publicKey, Buffer.from(signature, "base64"));
}
Helper Functions
3. base64KeyToPEM: Function to convert the private key to PEM format.
4. splitStringIntoChunks: Function to split a string into chunks used while creating the PEM format key.
function base64KeyToPEM(base64Key, keyType) {
return [`-----BEGIN ${keyType} KEY-----`, ...splitStringIntoChunks(base64Key, 64), `-----END ${keyType} KEY-----`].join("\n");
}function splitStringIntoChunks(input, chunkSize) {
const chunkCount = Math.ceil(input.length / chunkSize)
return Array.from( { length: chunkCount } ).map((v, chunkIndex) => input.substr(chunkIndex * chunkSize, chunkSize));
}
Signature Generation
// Generated private & public keys
const privateKey = "XXXX"; // Replace with your private key
const publicKey = "XXXX"; // Replace with your public key// Construct Signature Content
const clientID = "XXXX"; // Replace with your Client IDconst content = `POST /ams/sandbox/api/v1/payments/pay?_output_charset=utf-8&_input_charset=utf-8\n${clientID}.${new Date().toISOString()}.${requestString}`;console.log(content);// Generate signature
const signature = signContent(content, base64KeyToPEM(privateKey, "PRIVATE"), "utf8");// URL-Encode the signature
// Use the url-encoded signature for the Alipay Payment APIsconst urlEncodedSignature = encodeURIComponent(signature);console.log("URL Encoded Signature:", urlEncodedSignature);
Verify the generated signature
// Verify the generated signature
// Use the generated signature without url encoding for verificationconst isSignatureVerified = verifySignature(content, base64KeyToPEM(publicKey, "PUBLIC"), signature, "utf8");console.log("Verify Signature:", isSignatureVerified);
Checkout the entire code here
https://github.com/aswinkumar4018/alipay-signature-calc
That’s it, you’ve got a perfectly working Signature to integrate with Alipay Payment API.
Thank you so much for reading! Please clap 👏 and share if you found this article useful.