Skip to content

签名算法 ​

所有请求必须携带 signature 参数,用于验证请求合法性。

签名流程 ​

第一步:参数排序与拼接 ​

  1. 筛选所有 非空 且 非 signature 的参数
  2. 按参数名 ASCII 码 从小到大排序(字典序)
  3. 按 key=value 格式拼接,使用 & 连接

第二步:加密生成签名 ​

  1. 在拼接字符串末尾追加 API Token(不加 &)
  2. 对完整字符串进行 MD5 加密
  3. 将结果转为 小写 即为 signature

示例 ​

假设请求参数:

json
{
  "order_id": "20220201030210321",
  "amount": 42,
  "notify_url": "http://example.com/notify",
  "redirect_url": "http://example.com/redirect"
}

假设 API Token 为:your_api_token_here

步骤 1:按字典序排序并拼接

text
amount=42&notify_url=http://example.com/notify&order_id=20220201030210321&redirect_url=http://example.com/redirect

步骤 2:末尾追加 Token,计算 MD5

text
MD5(amount=42&notify_url=http://example.com/notify&order_id=20220201030210321&redirect_url=http://example.com/redirectyour_api_token_here)

得到签名:

text
1cd4b52df5587cfb1968b0c0c6e156cd

规则总结 ​

规则说明
参数名区分大小写Amount 和 amount 是不同参数
空值不参与签名null、""、undefined 均跳过
signature 不参与签名签名本身不算
必须按字典序排序确保双方计算一致
MD5 结果必须小写统一小写字母

PHP 实现 ​

php
function generateSignature(array $params, string $token): string {
    unset($params['signature']);
    $params = array_filter($params, function($v) {
        return $v !== null && $v !== '';
    });

    ksort($params);

    $pairs = [];
    foreach ($params as $k => $v) {
        if (is_bool($v)) $v = $v ? 'true' : 'false';
        $pairs[] = $k . '=' . $v;
    }
    $signStr = implode('&', $pairs) . $token;

    return strtolower(md5($signStr));
}

Python 实现 ​

python
import hashlib

def generate_signature(params: dict, token: str) -> str:
    params = {k: v for k, v in params.items()
              if k != 'signature' and v is not None and v != ''}

    sorted_keys = sorted(params.keys())

    parts = []
    for k in sorted_keys:
        v = params[k]
        if isinstance(v, bool):
            v = 'true' if v else 'false'
        parts.append(f"{k}={v}")
    sign_str = '&'.join(parts) + token

    return hashlib.md5(sign_str.encode('utf-8')).hexdigest().lower()

Node.js 实现 ​

javascript
const crypto = require('crypto');

function generateSignature(params, token) {
  const filtered = {};
  for (const [k, v] of Object.entries(params)) {
    if (k !== 'signature' && v !== null && v !== '' && v !== undefined) {
      filtered[k] = v;
    }
  }
  const sortedKeys = Object.keys(filtered).sort();
  const parts = sortedKeys.map(k => {
    let v = filtered[k];
    if (typeof v === 'boolean') v = v ? 'true' : 'false';
    return `${k}=${v}`;
  });
  const signStr = parts.join('&') + token;
  return crypto.createHash('md5').update(signStr).digest('hex').toLowerCase();
}

XindaPayusdt · 加密货币收款网关