常见问题排查
先在下面找和你情况对得上的那条,照着做。还不行的话,把报错原文、请求时间和单号发给顽兔技术支持,注意别把 api_secret 一起发出去。
调接口报 40001(签名错误)
这个错基本都是密钥不对。先检查 api_secret 复制全了没有,有没有多带空格或换行,是不是把 webhook_secret 拿来用了。轮换过密钥的话,旧密钥 7 天后就失效了,报错信息里会写明失效时间,换成新密钥即可。用 SDK 发请求签名不会算错,排除密钥问题就够了。自己拼签名的,对一下签名串:timestamp、nonce、请求体原文三行用换行拼起来,HMAC-SHA256 后转小写 hex。
调接口报 40002(时间戳超窗或重放)
十有八九是服务器时钟不准,和标准时间差 5 分钟以上网关就拒。date 看一眼,配上 NTP 校时就好。另一种情况是同一个请求原封不动又发了一次,网关当重放拦掉了,这是正常的。用 SDK 每次请求都会生成新的 nonce,碰不到这个问题。
调接口报 40003(商户不存在或已禁用)
先核对 merchant_id 有没有抄错、抄漏。没抄错就是商户状态的问题,可能还没启用,也可能被停了,联系顽兔确认。
调接口报 42201(商户未开通支付渠道)
下单传的 channel 不是顽兔给你开的那条渠道。开的是支付宝就传 alipay,开的是银联商务聚合码就传 chinaums。不传等于传 alipay,所以只开了银商的商户一定要显式传。想再开一条渠道,找顽兔商务。
收不到 webhook 回调
按这个顺序查,大多数人卡在前两步:
- 先调查单接口看订单状态。不是
paid就是用户没付成,跟回调没关系 - 回调地址公网能不能访问到。本地开发得走内网穿透,穿透地址一变,到商户后台「接入配置 → 支付回调」改一下再「保存配置」,保存前会先发测试回调,通不通当场知道;平时想自检点地址旁边的「测试地址」
- 防火墙、安全组有没有按来源 IP 拦。网关的出口 IP 不固定,回调端口得对所有来源放开,来源可不可信靠验签判断
- 证书过不过得去。https 加 IP 配自签证书过不了网关的证书校验;测试阶段用 http,或者用有正规证书的域名
- 路径有没有配错。商户后台里配的完整地址得和你的路由一字不差,
/wantu/webhook这一段也算 - 你的接口有没有返回 2xx。网关只看 HTTP 状态码,返回 3xx(跳转不跟随,请直接配最终地址)、4xx、5xx 或者超时都算失败:支付回调那一刻的首投 3 秒超时,之后的重试 10 秒
- 失败了网关会重试,从 1 分钟起,间隔逐步拉长到 12 小时,一共 8 次。配置修好后等下一轮就能收到,不会丢
回调验签失败(WantuWebhookVerifyError)
四个 SDK 里都是验签方法抛的(Node/Python 是 pay.verify_webhook(...),Go 是 pay.VerifyWebhook(...),Java 是 pay.verifyWebhook(...)),原因是一样的。九成是没拿到请求体原文:验签算的是原始字节,Express 这个路由要挂 express.raw(),FastAPI 要用 await request.body(),Go 要先 io.ReadAll(r.Body),Spring 的参数要声明成 @RequestBody byte[]。挂了全局 JSON 中间件提前把 body 读掉,或者先调了 request.json()、ShouldBindJSON、把参数声明成 DTO,签名必然对不上。
剩下两种情况:配了独立的 webhook_secret 但代码里没传,或者反过来,两边得一致;服务器时钟不准,处理办法同 40002。
订单一直是 created
这不是故障,是用户没付完:没扫码、扫了没付、付到一半把页面关了。真付了的话,查单接口会去渠道确认,状态自己会变成 paid;一直不付,超时后订单自动变 closed,默认 15 分钟,让用户重新下单就行。用户明确不付了(取消、换套餐重新下单),调关闭订单把旧单关掉,不用等超时。
支付页打不开 / 500 / 提示系统繁忙
一般是渠道偶尔抖一下,等几分钟再试;订单已经超时就重新下一单。要是反复出现,把发生时间和单号发给顽兔查。
银联商务聚合码:iframe 白屏 / pay_url 浏览器打不开
都不是故障,是用法不对。channel: "chinaums" 时拿到的 pay_url 是二维码的内容,不是一个网页,所以不能放 iframe,要用二维码库画成码图,写法见发起支付的银商一节。电脑浏览器直接打开它会提示不支持,因为这个地址只能在微信、支付宝、云闪付里打开,让用户拿手机扫码图就对了。
另外两个和银商有关的报错:42201「商户未开通支付渠道」看上面那条;50002「银商商户参数未配置」是渠道开了、但顽兔侧还没录入你的银商商户号和终端号,找顽兔补录。
回调收到了两次,会不会重复入账
回调一定会重复送到,重试机制决定的,所以要靠入账 SQL 的条件更新来挡:
想查有没有已经重复入过账的:按 out_trade_no 分组数一下积分流水,哪个单号超过 1 行就是重复了。
金额报错(40004 或 SDK 本地拦截)
金额得是字符串,单位元,最多两位小数:"100.00" 对,100、"1.234" 都不行。不合法的金额 SDK 在本地就拦下了,报错信息里写着原因。