小程序支付签名失败,参数都检查过了还是报错?
用微信小程序支付时,签名一直失败返回”签名错误”。已经确认参数(appid、timestamp等)正确,也按文档排序了参数,但依然报错。签名算法用的是HMAC-SHA1,生成的sign和后端返回的一致吗?
代码示例:
const signStr = Object.keys(params).sort().map(k => <code>${k}=${params[k]}</code>).join('&');
const sign = crypto.createHmac('SHA1', '密钥').update(signStr).digest('hex');
后端返回的prepay_id存在,但wx.requestPayment执行时提示”fail sign error”。是不是时间戳或随机字符串格式有问题?或者参数排序需要排除某些字段?
微信支付目前支持的签名类型是 MD5 和 HMAC-SHA256(新版V3接口用RSA),你用的 SHA1 完全不对,签名肯定验不过。
还有一个关键点,前端调起支付
wx.requestPayment的签名参数和后端统一下单的签名参数是两套不同的东西。后端拿到 prepay_id 只是第一步,前端调起支付需要重新生成签名,参数如下:appId、timeStamp、nonceStr、package(值是 prepay_id=xxx)、signType
这五个字段按字典序拼接,最后拼上商户密钥,用 MD5 或 HMAC-SHA256 生成。注意 timeStamp 要求是秒级时间戳,不是毫秒,这个坑很多人踩过。
正确的签名生成逻辑大概是这样:
实际项目中,这个签名强烈建议让后端生成好直接返回给前端,前端不要碰商户密钥,安全风险太大。后端返回 prepay_id 的时候,顺手把 paySign、timeStamp、nonceStr 一起返回,前端只管调接口就行。
总结一下:算法换成 MD5 或 HMAC-SHA256,时间戳用秒级,签名最好后端生成。改完这些基本就能过了。
检查下timestamp是不是秒级的,不是的话除以1000转成秒。再不行就睡一觉明天再调吧,太累了容易出错。