微信支付回调后如何验证签名是否合法?

玉轩 阅读 14

我接入了微信H5支付,用户支付完成后微信会跳转回我的return_url,但我不确定怎么验证这个回调是不是真的来自微信,防止伪造请求。官方文档说要用签名验证,但我试了几次总是验签失败。

我用的是微信提供的验签方法,把参数按字典序排序后拼接,再用商户APIv3密钥做HMAC-SHA256。但返回的sign和我算出来的不一样。是不是我漏了什么参数?比如要不要包含sign_type?

这是我的验签代码:

function verifyWechatSignature(params, expectedSign) {
  const { sign, ...rest } = params;
  const sortedKeys = Object.keys(rest).sort();
  const queryString = sortedKeys.map(k => <code>${k}=${rest[k]}</code>).join('&');
  const computedSign = crypto
    .createHmac('sha256', WECHAT_APIV3_KEY)
    .update(queryString)
    .digest('hex')
    .toUpperCase();
  return computedSign === expectedSign;
}

每次算出来的computedSign和params.sign都不一样,到底哪里出错了?

我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
♫雯清
♫雯清 Lv1
你用错密钥了,H5支付回调验签用的是商户APIv2密钥(32位字符串),不是APIv3密钥;而且参数排序后拼接时,不包含 sign 字段,也不包含 sign_type 字段,拼接完再做 HMAC-SHA256。懒人方案直接上代码:

function verifyWechatSignature(params, expectedSign) {
const { sign, sign_type, ...rest } = params;
const sortedKeys = Object.keys(rest).sort();
const queryString = sortedKeys
.map(k => ${k}=${rest[k]})
.join('&');
const computedSign = crypto
.createHmac('sha256', WECHAT_APIV2_KEY)
.update(queryString)
.digest('hex')
.toUpperCase();
return computedSign === expectedSign;
}


记得把 WECHAT_APIV2_KEY 换成你在微信商户平台配置的 APIv2 密钥(不是 APIv3 的那个)。
点赞 1
2026-02-26 18:00