Appearance
签名算法
所有请求必须携带 signature 参数,用于验证请求合法性。
签名流程
第一步:参数排序与拼接
- 筛选所有 非空 且 非 signature 的参数
- 按参数名 ASCII 码 从小到大排序(字典序)
- 按
key=value格式拼接,使用&连接
第二步:加密生成签名
- 在拼接字符串末尾追加 API Token(不加
&) - 对完整字符串进行 MD5 加密
- 将结果转为 小写 即为
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¬ify_url=http://example.com/notify&order_id=20220201030210321&redirect_url=http://example.com/redirect步骤 2:末尾追加 Token,计算 MD5
text
MD5(amount=42¬ify_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();
}