Merchant access identifier assigned by the platform
Signature Authentication
Overview
All API requests must be authenticated and signed to ensure security and integrity.
Authentication
Header Authentication
Each request must include the following headers:
Request signature
Example
POST /api/v2/pay/submit
Content-Type: application/json
x-access-key: MERCHANT_001
signature: a1b2c3d4e5f6...Signature Algorithm
Steps to Calculate the Signature
Step 1: Prepare Parameters
Collect all body parameters and exclude:
- The
signaturefield itself - Parameters whose values are
nullor empty strings
Example body parameters
{
"timestamp": "1742205605123",
"merchantOrderNo": "PHC202604170001",
"orderAmount": "1200",
"payMethod": "MAYA",
"callbackUrl": "https://merchant.example.com/payments/notify",
"redirectUrl": "https://merchant.example.com/payments/return"
}Step 2: Sort Parameters
Sort all parameters by parameter name in alphabetical order (a-z).
Example
After sorting:
callbackUrl, merchantOrderNo, orderAmount, payMethod, redirectUrl, timestampStep 3: Concatenate the String
Concatenate the sorted parameters in key=value format, joined by &. Use the original string values from the request when building the signing string.
Example
callbackUrl=https://merchant.example.com/payments/notify&merchantOrderNo=PHC202604170001&orderAmount=1200&payMethod=MAYA&redirectUrl=https://merchant.example.com/payments/return×tamp=1742205605123Step 4: Append the Secret Key
Append the merchant secret key to the end of the concatenated string.
Example
callbackUrl=https://merchant.example.com/payments/notify&merchantOrderNo=PHC202604170001&orderAmount=1200&payMethod=MAYA&redirectUrl=https://merchant.example.com/payments/return×tamp=1742205605123{SECRET_KEY}Step 5: Calculate the Hash
Use the SHA256 algorithm to calculate the hash.
Step 6: Convert to Lowercase
Convert the hash result to a lowercase hexadecimal string.
Final signature
If the example above uses demo_secret_key_ph as the secret key, the signature result is:
baaa22c91470a152155a34284dbf32d6e21bd761a4067755db3d70e5bad28c30Async callback signature verification follows the same rule. The callback signature field is also signature, and the signature field itself must be excluded during verification.
Signature Example Code
Java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.TreeMap;
public class SignUtil {
public static String sign(Map<String, Object> params, String secretKey) throws NoSuchAlgorithmException {
TreeMap<String, String> sortedParams = new TreeMap<>();
for (Map.Entry<String, Object> entry : params.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value != null && !"".equals(value) && !"signature".equals(key)) {
sortedParams.put(key, value.toString());
}
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(entry.getKey()).append("=").append(entry.getValue());
}
sb.append(secretKey);
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(b & 0xff);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString().toLowerCase();
}
}Node.js
const crypto = require('crypto');
function generateSignature(params, secretKey) {
const filteredParams = {};
for (const [key, value] of Object.entries(params)) {
if (value !== null && value !== '' && key !== 'signature') {
filteredParams[key] = value;
}
}
const sortedKeys = Object.keys(filteredParams).sort();
const signStr = sortedKeys
.map(key => `${key}=${filteredParams[key]}`)
.join('&');
return crypto.createHash('sha256').update(signStr + secretKey).digest('hex').toLowerCase();
}Java Usage Example
Map<String, Object> params = new HashMap<>();
params.put("timestamp", "1742205605123");
params.put("merchantOrderNo", "PHC202604170001");
params.put("orderAmount", "1200");
params.put("payMethod", "MAYA");
params.put("callbackUrl", "https://merchant.example.com/payments/notify");
params.put("redirectUrl", "https://merchant.example.com/payments/return");
String signature = SignUtil.sign(params, "demo_secret_key_ph");
System.out.println(signature);
// baaa22c91470a152155a34284dbf32d6e21bd761a4067755db3d70e5bad28c30Node.js Usage Example
const params = {
timestamp: '1742205605123',
merchantOrderNo: 'PHC202604170001',
orderAmount: '1200',
payMethod: 'MAYA',
callbackUrl: 'https://merchant.example.com/payments/notify',
redirectUrl: 'https://merchant.example.com/payments/return',
};
const signature = generateSignature(params, 'demo_secret_key_ph');
console.log(signature);
// baaa22c91470a152155a34284dbf32d6e21bd761a4067755db3d70e5bad28c30