遇到“USERPAYING/系统繁忙”,别急着重下单
微信支付接口返回USERPAYING,通常不是失败,而是用户还在输入密码、指纹确认、或弱网导致支付结果没及时回传。你这边立刻再发起一次支付,很容易把用户绕晕,还可能触发重复扣款的疑虑。
返回系统繁忙(SYSTEMERROR/SYSTEMBUSY)更像“服务器或链路临时抖了一下”。这类情况要做的是重试+核对订单状态,而不是换单号硬冲。
推荐处理:轮询查单 + 退避重试
实操建议这样写(给你一套能直接落地的节奏):
- 收到USERPAYING:不要重新下单,改为调用“支付结果查询”轮询查单
- 轮询频率:前30秒每2秒查一次;还没结果就改为每5秒查一次,最多查到90秒左右
- 系统繁忙:同一个请求参数做重试,建议1s/2s/4s指数退避,控制在3-5次内
- 不管哪种返回,都要以支付通知(notify)+ 查单作为最终结果来源
举个例子:门店扫码支付,用户输密码用了18秒,你这边第6次轮询才查到SUCCESS,这种在高峰期很常见。
超时关单与订单状态核对(避免“卡死单”)
轮询到超时还没成功,别让订单一直挂着。建议你给每笔订单设一个支付有效期,例如5分钟,到点就触发关单(关闭订单接口)。
排查时按这个顺序看,效率最高:
- 你是否对同一个out_trade_no做了幂等(重复请求不会生成新单)
- 是否收到过支付通知,但你服务没正确落库(回调验签、重复通知处理)
- 查单结果是NOTPAY/USERPAYING/SUCCESS/REFUND分别怎么落状态,是否有“中间态”
- 关单后又收到SUCCESS的极端情况:以微信侧最终状态为准,按你的业务做补单/发货校验
给你一份可执行清单(按这个改完就稳很多)
在2026年2月11日 12:00这种高峰期也扛得住的做法:
- 把USERPAYING固定处理成“轮询查单”,不要重新下单
- 把系统繁忙固定处理成“指数退避重试+查单兜底”
- 订单状态机落地:INIT→PAYING→SUCCESS/FAILED/CLOSED,严禁一笔单多终态
- 设置支付有效期(如5分钟)并自动关单,避免库存、优惠券长期占用
你可以先挑一条支付链路做灰度:把轮询上限设成90秒,关单设成5分钟,上线后看“支付成功但超时”的比例,再微调轮询时长和频率。