V1(MD5签名)
每个请求都要带签名 sign,平台据此确认请求是你发的、参数没有被改过。平台发给你的支付结果通知也带签名,用同样的方法校验。
签名步骤
- 取出要发送的全部参数,去掉
sign、sign_type和值为空的参数。文档没有列出、但你额外传了的参数,也要参与签名。 - 按参数名的 ASCII 码从小到大排序。
- 把参数按
参数名=参数值的格式用&连接,得到待签名串。参数值用原文,不做 URL 编码。 - 在待签名串末尾直接接上 MD5密钥(中间不加任何字符),计算 MD5,得到的 32 位小写字符串就是
sign。 - 发送时带上
sign,sign_type传MD5(不传也按 MD5 处理)。
sign = md5(待签名串 + MD5密钥)细节规则
- 只有值为空字符串的参数不参与签名,值为
0的参数照常参与。 - 参数名区分大小写,只排除小写的
sign和sign_type。 - 数组形式的参数(如
goods[]=1)不参与签名。 - 参数值原样拼接:不去首尾空格,不转义
&和=,中文按 UTF-8 计算。 - MD5 结果必须是小写,大写的签名校验不通过。
计算示例
下单参数:
pid=1001
type=alipay
out_trade_no=20260927123456
notify_url=https://你的域名/notify
return_url=https://你的域名/return
name=会员充值
money=1.00
sign_type=MD5去掉 sign_type,排序、拼接后的待签名串:
money=1.00&name=会员充值¬ify_url=https://你的域名/notify&out_trade_no=20260927123456&pid=1001&return_url=https://你的域名/return&type=alipayMD5密钥取 你的MD5密钥 这七个字符时,接上密钥计算 MD5 得到:
sign=87b1ef8e501b2dbadb50379631290300用你的程序按同样的参数和密钥计算,结果相同就说明实现正确;正式请求换成你自己的密钥。
PHP 示例
<?php
function zpay_sign(array $params, string $key): string
{
unset($params['sign'], $params['sign_type']);
$params = array_filter($params, function ($value) {
return $value !== '' && $value !== null && !is_array($value);
});
ksort($params);
$pairs = [];
foreach ($params as $name => $value) {
$pairs[] = $name . '=' . $value;
}
return md5(implode('&', $pairs) . $key);
}
$params = [
'pid' => '1001',
'type' => 'alipay',
'out_trade_no' => '20260927123456',
'notify_url' => 'https://你的域名/notify',
'return_url' => 'https://你的域名/return',
'name' => '会员充值',
'money' => '1.00',
];
$params['sign'] = zpay_sign($params, '你的MD5密钥');
$params['sign_type'] = 'MD5';
// 校验收到的支付结果通知
$valid = hash_equals(zpay_sign($_GET, '你的MD5密钥'), $_GET['sign'] ?? '');Python 示例
import hashlib
import hmac
def zpay_sign(params: dict, key: str) -> str:
pairs = sorted(
(name, str(value))
for name, value in params.items()
if name not in ("sign", "sign_type")
and value is not None
and value != ""
and not isinstance(value, (list, tuple, dict))
)
content = "&".join(f"{name}={value}" for name, value in pairs)
return hashlib.md5((content + key).encode("utf-8")).hexdigest()
params = {
"pid": "1001",
"type": "alipay",
"out_trade_no": "20260927123456",
"notify_url": "https://你的域名/notify",
"return_url": "https://你的域名/return",
"name": "会员充值",
"money": "1.00",
}
params["sign"] = zpay_sign(params, "你的MD5密钥")
params["sign_type"] = "MD5"
# 校验收到的支付结果通知(received 为通知参数组成的字典)
def notify_valid(received: dict) -> bool:
return hmac.compare_digest(zpay_sign(received, "你的MD5密钥"), received.get("sign", ""))