遇到“签名错误(SIGN_ERROR)”,多半是这几类坑
微信支付V3报SIGN_ERROR,常见不是“密钥不对”,而是签名串拼错、时间戳不准、证书/商户号用错。我见过一个案例:同一笔查询订单GET请求,开发把URL做了UrlEncode,结果线下全过、线上全挂,返回就是SIGN_ERROR。
密钥与证书:别把“能连上”当“配对了”
先确认你签名用的私钥、商户号、证书序列号是一套的。
- 商户号mchid:特约商户别误用服务商的mchid和证书。
- merchant private key:签名用商户私钥,不是APIv3密钥。
- 证书序列号serial_no:Authorization里带的serial_no要对应当前使用的商户证书。
- APIv3密钥:它用于回调解密/敏感字段,不直接参与签名,但没配好会引发一堆“看起来像签名”的后续问题。
参数拼接:签名串的细节最容易翻车
微信开放社区在2026年给过很明确的提醒,照着排坑:
- timestamp和nonce_str:生成签名和拼Authorization必须用同一组时间戳、随机串,别“签名时生成一次、header里又生成一次”。
- URL别加工:不要ToLowerCase(),不要UrlEncode()。请求的path长什么样,签名串就用什么样。
- GET请求body为空:body是空字符串,但签名串里的换行还得保留;很多库把最后那个“\n”吞了就会错。
- 请求方法要一致:POST写成GET、或反过来,签名串立刻不匹配。
小例子:查单接口是GET,你签名串里method写成POST,即使其它都对,也会100%验签失败。
时间戳校准:服务器快慢几分钟就够你难受
有些环境容器时间漂移,签名里的timestamp偏差过大,微信侧会直接判不可信。
- 把应用服务器接入NTP校时(公司内网也行),保证系统时间稳定。
- 日志里打印本机timestamp、nonce、签名串原文(注意脱敏),对照微信侧报错时间点排查。
可执行建议:拿一笔固定请求(同一URL、同一body),把“签名串原文 + 计算出的签名 + Authorization四要素(timestamp/nonce/serial/signature)”完整落日志;再逐条核对URL是否被编码、GET是否空body、timestamp/nonce是否复用、mchid与证书是否配对。通常10分钟能定位到具体哪一行拼错。