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": "PKC202604170001",
"payMethod": "JAZZCASH",
"customerName": "Ali Khan",
"customerPhone": "3123456789",
"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=Ali Khan&customerPhone=3123456789&merchantOrderNo=PKC202604170001&orderAmount=12000&payMethod=JAZZCASH×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=Ali Khan&customerPhone=3123456789&merchantOrderNo=PKC202604170001&orderAmount=12000&payMethod=JAZZCASH×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_pk as the secret key, the signature result is:
acfc0c9a2b8538fbad46bb6b09aa902f3378579487a6b95fb7fcdac1fdbd2bc0Async 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", "PKC202604170001");
params.put("payMethod", "JAZZCASH");
params.put("customerName", "Ali Khan");
params.put("customerPhone", "3123456789");
params.put("customerEmail", "pkbuyer@gmail.com");
params.put("callbackUrl", "https://merchant.example.com/payments/notify");
String signature = SignUtil.sign(params, "demo_secret_key_pk");
System.out.println(signature);
// acfc0c9a2b8538fbad46bb6b09aa902f3378579487a6b95fb7fcdac1fdbd2bc0Node.js Usage Example
const params = {
timestamp: '1742205605123',
orderAmount: '12000',
merchantOrderNo: 'PKC202604170001',
payMethod: 'JAZZCASH',
customerName: 'Ali Khan',
customerPhone: '3123456789',
customerEmail: 'pkbuyer@gmail.com',
callbackUrl: 'https://merchant.example.com/payments/notify',
};
const signature = generateSignature(params, 'demo_secret_key_pk');
console.log(signature);
// acfc0c9a2b8538fbad46bb6b09aa902f3378579487a6b95fb7fcdac1fdbd2bc0