Skip to content

签名说明 ​

概述 ​

所有 API 请求都必须经过认证和签名,以确保请求的安全性和完整性。

认证方式 ​

Header 认证 ​

每个请求必须在请求头中包含以下字段:

x-access-keystring必选

平台分配的商户访问标识

signaturestring必选

请求签名

示例

http
POST /api/v2/pay/submit
Content-Type: application/json
x-access-key: MERCHANT_001
signature: a1b2c3d4e5f6...

签名算法 ​

签名计算步骤 ​

步骤一:准备参数 ​

收集所有 body 参数,并排除:

  • signature 字段本身
  • 值为 null 或空字符串的参数

请求参数示例

json
{
  "timestamp": "1742205605123",
  "merchantOrderNo": "PHC202604170001",
  "orderAmount": "1200",
  "payMethod": "MAYA",
  "callbackUrl": "https://merchant.example.com/payments/notify",
  "redirectUrl": "https://merchant.example.com/payments/return"
}

步骤二:参数排序 ​

按参数名字母顺序(a-z)对所有参数进行排序。

示例

排序后:
callbackUrl, merchantOrderNo, orderAmount, payMethod, redirectUrl, timestamp

步骤三:拼接字符串 ​

将排序后的参数按 key=value 格式拼接,参数之间用 & 连接。参数值按请求中的原始字符串参与签名。

示例

callbackUrl=https://merchant.example.com/payments/notify&merchantOrderNo=PHC202604170001&orderAmount=1200&payMethod=MAYA&redirectUrl=https://merchant.example.com/payments/return&timestamp=1742205605123

步骤四:追加密钥 ​

将商户密钥(Secret Key)追加到拼接字符串的末尾。

示例

callbackUrl=https://merchant.example.com/payments/notify&merchantOrderNo=PHC202604170001&orderAmount=1200&payMethod=MAYA&redirectUrl=https://merchant.example.com/payments/return&timestamp=1742205605123{SECRET_KEY}

步骤五:计算哈希 ​

使用 SHA256 算法计算哈希值。

步骤六:转小写 ​

将哈希结果转换为小写十六进制字符串。

最终签名

如果以上示例使用的密钥为 demo_secret_key_ph,则签名结果为:

baaa22c91470a152155a34284dbf32d6e21bd761a4067755db3d70e5bad28c30

异步通知的验签规则与以上一致。回调中的签名字段同样为 signature,验签时应排除 signature 字段本身。


签名示例代码 ​

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

javascript
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 调用示例 ​

java
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);
// baaa22c91470a152155a34284dbf32d6e21bd761a4067755db3d70e5bad28c30

Node.js 调用示例 ​

javascript
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