Merchant access identifier assigned by the platform
Signature Authentication
Overview
All API requests must be authenticated and signed to ensure request security and integrity.
Authentication Method
Header Authentication
Each request must include the following fields in the request header:
Request signature
Example
POST /api/v2/pay/submit
Content-Type: application/json
x-access-key: MERCHANT_001
signature: a1b2c3d4e5f6...Signature Algorithm
Signature Calculation Steps
Step 1: Prepare Parameters
Collect all body parameters and exclude:
- The
signaturefield itself - Parameters with
nullor empty string values
Request Parameter Example
{
"timestamp": "1742205605123",
"orderAmount": "12000",
"merchantOrderNo": "BDC202604170001",
"payMethod": "KBZPAY",
"customerName": "Rahim",
"customerPhone": "01712345678",
"customerEmail": "pkbuyer@gmail.com",
"callbackUrl": "https://merchant.example.com/payments/notify"
}Step 2: Sort Parameters
Sort all parameters alphabetically by parameter name (a-z).
Example
After sorting:
callbackUrl, customerEmail, customerName, customerPhone, merchantOrderNo, orderAmount, payMethod, timestampStep 3: Concatenate 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&customerEmail=pkbuyer@gmail.com&customerName=Rahim&customerPhone=01712345678&merchantOrderNo=BDC202604170001&orderAmount=12000&payMethod=KBZPAY×tamp=1742205605123Step 4: Append Secret Key
Append the merchant's Secret Key to the end of the concatenated string.
Example
callbackUrl=https://merchant.example.com/payments/notify&customerEmail=pkbuyer@gmail.com&customerName=Rahim&customerPhone=01712345678&merchantOrderNo=BDC202604170001&orderAmount=12000&payMethod=KBZPAY×tamp=1742205605123{SECRET_KEY}Step 5: Calculate Hash
Use the SHA256 algorithm to calculate the hash value.
Step 6: Convert to Lowercase
Convert the hash result to a lowercase hexadecimal string.
Final Signature
If the example above uses demo_secret_key_bd as the secret key, the signature result is:
9819cec934445dbf9a810941a63e563fd7f3f2c2d0e33359103b644d47c3863cAsync callback signature verification follows the same rule above. The callback signature field is also named 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 {
// 1. Use TreeMap for alphabetical sorting, filter empty values and signature field
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());
}
}
// 2. Concatenate parameters in key=value&key=value format
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());
}
// 3. Append secret key
sb.append(secretKey);
// 4. Calculate SHA256
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
// 5. Convert to lowercase hexadecimal
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) {
// 1. Filter empty values and signature field
const filteredParams = {};
for (const [key, value] of Object.entries(params)) {
if (value !== null && value !== '' && key !== 'signature') {
filteredParams[key] = value;
}
}
// 2. Sort alphabetically
const sortedKeys = Object.keys(filteredParams).sort();
// 3. Concatenate parameters
const signStr = sortedKeys
.map(key => `${key}=${filteredParams[key]}`)
.join('&');
// 4. Append secret key and calculate SHA256
const finalStr = signStr + secretKey;
return crypto.createHash('sha256').update(finalStr).digest('hex').toLowerCase();
}Java Usage Example
Map<String, Object> params = new HashMap<>();
params.put("timestamp", "1742205605123");
params.put("orderAmount", "12000");
params.put("merchantOrderNo", "BDC202604170001");
params.put("payMethod", "KBZPAY");
params.put("customerName", "Rahim");
params.put("customerPhone", "01712345678");
params.put("customerEmail", "pkbuyer@gmail.com");
params.put("callbackUrl", "https://merchant.example.com/payments/notify");
String signature = SignUtil.sign(params, "demo_secret_key_bd");
System.out.println(signature);
// 9819cec934445dbf9a810941a63e563fd7f3f2c2d0e33359103b644d47c3863cNode.js Usage Example
const params = {
timestamp: '1742205605123',
orderAmount: '12000',
merchantOrderNo: 'BDC202604170001',
payMethod: 'KBZPAY',
customerName: 'Rahim',
customerPhone: '01712345678',
customerEmail: 'pkbuyer@gmail.com',
callbackUrl: 'https://merchant.example.com/payments/notify',
};
const signature = generateSignature(params, 'demo_secret_key_bd');
console.log(signature);
// 9819cec934445dbf9a810941a63e563fd7f3f2c2d0e33359103b644d47c3863c