Skip to content

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:

x-access-keystringRequired

Merchant access identifier assigned by the platform

signaturestringRequired

Request signature

Example

http
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 signature field itself
  • Parameters with null or empty string values

Request Parameter Example

json
{
  "timestamp": "1742205605123",
  "orderAmount": "12000",
  "merchantOrderNo": "BDC202604170001",
  "payMethod": "BKASH",
  "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, timestamp

Step 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=BKASH&timestamp=1742205605123

Step 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=BKASH&timestamp=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:

acfc0c9a2b8538fbad46bb6b09aa902f3378579487a6b95fb7fcdac1fdbd2bc0

Async 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 ​

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 ​

javascript
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 ​

java
Map<String, Object> params = new HashMap<>();
params.put("timestamp", "1742205605123");
params.put("orderAmount", "12000");
params.put("merchantOrderNo", "BDC202604170001");
params.put("payMethod", "BKASH");
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);
// acfc0c9a2b8538fbad46bb6b09aa902f3378579487a6b95fb7fcdac1fdbd2bc0

Node.js Usage Example ​

javascript
const params = {
  timestamp: '1742205605123',
  orderAmount: '12000',
  merchantOrderNo: 'BDC202604170001',
  payMethod: 'BKASH',
  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);
// acfc0c9a2b8538fbad46bb6b09aa902f3378579487a6b95fb7fcdac1fdbd2bc0