案例 微信支付 APIv3 报 401 / SIGN_ERROR:按签名链路逐项排查

2026-09-23 21:02:57

微信支付 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。这三个东西——私钥、mchidserial_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 ...

比对得到的 mchidAuthorization 头里传的 mchid 字段是否一致。

4. nonce_str 与 timestamp 两处必须一致

Authorization 头里的随机字符串 nonce_str 和时间戳 timestamp,必须和计算签名时用的值完全相同。签名用的时间戳、随机字符串,与头里传的 nonce_strtimestamp 是同一份数据,任何一边重新生成一遍都会导致验签失败。

5. 签名串格式

这是出错最多的一类,逐条看:

  1. 计算签名时没有正确处理 \n。签名示例里的 \n 是换行符,不是一个反斜杠加字母 n 的字符。
  2. 第一行的请求方法必须大写,GETPOSTPUT,不能小写。
  3. 生成请求签名共 5 行,每一行都以换行符结尾。如果是 GET 请求,第五行是空行加换行符,不要漏掉这个换行符。
  4. 第二行的 URL 要替换成实际请求的接口 URL,且不带域名,必须写成 /v3/certificates 这种格式,不能写成 https://api.mch.weixin.qq.com/v3/certificates
  5. 检查签名串里没有多余的 /,比如不要出现 //v3/certificates

6. 前面的都对,查代码转义

上面全部确认无误、依然报签名错误,通常就是代码处理环节做了转义。用示例里的密钥和示例请求算一遍签名值,如果代码算出来的结果和示例不一致,就去查代码里的转义问题。

参考:APIv3 错误信息与错误码

微信支付 API v3 用 HTTP 状态码表示请求处理结果:

  • 处理成功且有应答消息体返回 200,无应答消息体返回 204;
  • 已被成功接受待处理的请求返回 202;
  • 请求处理失败(缺少必要入参、余额不足等)返回 4xx;
  • 微信支付侧服务系统错误返回 500 / 501 / 503。

错误响应体的结构化字段:

  • code:错误码,分公共错误码和业务错误码;
  • message:错误描述,同一个 code 可能对应多个 message;
  • detail:当 codePARAM_ERRORINVALID_REQUEST 时返回。其中 field 指示错误参数位置(body 里的 JSON 用 JSON Pointer 路径,如 /amount/currency;URL 或 Query String 用参数变量名),value 是错误的值,issue 是具体原因,locationbody / 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
复制全文 生成海报 微信支付 接口对接 签名 排障

推荐文章

程序员茄子在线接单