微信支付 APIv3 报 401 / SIGN_ERROR:按签名链路逐项排查
接口返回 401,或者响应里出现「错误的签名,验签失败」「签名错误,请检查后再试」,方向基本只有一个:签名没算对或没传对。下面按从密钥文件到签名串的顺序逐项确认。
1. 服务商用谁的私钥
服务商模式下,签名必须用服务商的商户 API 私钥,不是子商户的 API 私钥。这一点弄反,后面几步全对也照样报签名错误。
2. 确认拿到的是商户 API 私钥
计算签名用的是商户 API 私钥 apiclient_key.pem。常见错误有两种:
- 用了商户 API 证书
apiclient_cert.pem。这两个文件名非常像,只差几个字符,注意别搞混。 - 用了平台证书
wechatpay.pem的公钥。
3. 私钥、商户号、证书序列号必须一一对应
签名由商户 API 私钥算出来,通过 HTTP Authorization 头传递。Authorization 头里会带商户号 mchid 和商户 API 证书的序列号 serial_no。这三个东西——私钥、mchid、serial_no——必须来自同一套材料。
确认证书和序列号一致
用 openssl 看证书序列号:
$ openssl x509 -in apiclient_cert.pem -noout -serial
比对输出的序列号和 Authorization 头里 serial_no 字段的值是否一致。
确认商户号和证书匹配
openssl x509 -in apiclient_cert.pem -noout -text | grep -o '...=[0-9]*' | sed ...
比对得到的 mchid 和 Authorization 头里传的 mchid 字段是否一致。
4. nonce_str 与 timestamp 两处必须一致
Authorization 头里的随机字符串 nonce_str 和时间戳 timestamp,必须和计算签名时用的值完全相同。签名用的时间戳、随机字符串,与头里传的 nonce_str、timestamp 是同一份数据,任何一边重新生成一遍都会导致验签失败。
5. 签名串格式
这是出错最多的一类,逐条看:
- 计算签名时没有正确处理
\n。签名示例里的\n是换行符,不是一个反斜杠加字母 n 的字符。 - 第一行的请求方法必须大写,
GET、POST、PUT,不能小写。 - 生成请求签名共 5 行,每一行都以换行符结尾。如果是 GET 请求,第五行是空行加换行符,不要漏掉这个换行符。
- 第二行的 URL 要替换成实际请求的接口 URL,且不带域名,必须写成
/v3/certificates这种格式,不能写成https://api.mch.weixin.qq.com/v3/certificates。 - 检查签名串里没有多余的
/,比如不要出现//v3/certificates。
6. 前面的都对,查代码转义
上面全部确认无误、依然报签名错误,通常就是代码处理环节做了转义。用示例里的密钥和示例请求算一遍签名值,如果代码算出来的结果和示例不一致,就去查代码里的转义问题。
参考:APIv3 错误信息与错误码
微信支付 API v3 用 HTTP 状态码表示请求处理结果:
- 处理成功且有应答消息体返回 200,无应答消息体返回 204;
- 已被成功接受待处理的请求返回 202;
- 请求处理失败(缺少必要入参、余额不足等)返回 4xx;
- 微信支付侧服务系统错误返回 500 / 501 / 503。
错误响应体的结构化字段:
code:错误码,分公共错误码和业务错误码;message:错误描述,同一个code可能对应多个 message;detail:当code为PARAM_ERROR或INVALID_REQUEST时返回。其中field指示错误参数位置(body 里的 JSON 用 JSON Pointer 路径,如/amount/currency;URL 或 Query String 用参数变量名),value是错误的值,issue是具体原因,location取body/url/query。
公共错误码:PARAM_ERROR(参数错误)、INVALID_REQUEST(HTTP 请求不符合微信支付 APIv3 接口规则)、SIGN_ERROR(验证不通过)、SYSTEM_ERROR(系统异常)。
业务错误码示例:NO_AUTH(商户无权限)、OUT_TRADE_NO_USED(商户订单号重复)。
User Agent:HTTP 协议要求客户端每次请求都带 User-Agent。微信支付建议使用默认的 User-Agent,或使用自身系统和应用名称、版本组成独有的 User-Agent。微信支付 API v3 很可能会拒绝处理没有 User-Agent 的请求。
参考链接
- 微信支付商户文档中心 401 / 签名报错排查:https://pay.weixin.qq.com/doc/v3/merchant/4012365347
- 基本规则:https://pay.wechatpay.cn/doc/v3/partner/4012081726