微信支付查单与回调:5 秒内先验签再应答,关单前必须先查单
用户支付成功但商户侧没收到通知,订单就会停在未支付。用户投诉、重复支付基本都由此产生。这份笔记整理微信支付官方《支付回调和查单实现指引(通用规则)》(更新于 2026-10-13)里的处理流程与硬性规则。
文档地址:https://pay.weixin.qq.com/doc/v3/partner/4012082568
整体思路
网络异常或系统波动会让异步支付结果通知丢失,所以订单状态不能只依赖回调,要按下面几层兜住:
- 前端拿到支付返回时,调用商户查单接口确认状态,把结果展示给用户。
- 后台要准确、高效地处理异步支付结果通知,并按接口规范返回处理结果。
- 后台没收到异步通知时,主动调用《微信支付查单接口》同步状态。
- T+1 日拉取 T 日交易账单,与商户系统订单逐笔核对;微信侧成功但商户侧未成功的,补发货或退款。
前端支付返回的处理
公众号、小程序、App 支付
前端返回“用户取消”,订单保持未支付,提示用户支付未完成。前端返回“成功”或“报错”,都要调用商户查单接口确认:
- 查单明确返回支付成功,展示支付成功页;
- 查单返回未支付,提醒用户“稍后进入订单管理页核实订单状态,不要重复发起支付”,同时后台要及时获取、更新状态。用户再次对未支付订单发起支付时,必须用原单号,不要更换支付单号。
H5 支付
返回发起支付页面或指定的 redirect_url 后,页面上要放一个“已完成支付”按钮。用户点击后调用查单接口确认状态,后续判断同上。
NATIVE 支付
展示二维码后,前端定时轮询查单接口确认状态,比如间隔 2 秒查一次、轮询 60 秒(间隔和次数可按业务调整)。轮询到支付成功就展示成功页;超过设定时间仍未成功,退出轮询并提示交易超时。
后端:回调、轮询查单、对账
支付回调
收到异步支付结果通知后,要在 5 秒内先验签再应答。验签不通过时返回 4xx 或 5xx,不得返回 200。
没收到支付成功回调时,先查单,不要更换商户订单号立即重新下单。trade_state 为 NOTPAY 不表示支付失败。
两个前置条件容易漏:商户平台未设置 APIv3 密钥时,微信支付不向 notify_url 推送支付成功回调;防火墙拦截了微信支付回调 IP 段时同样收不到通知,需要放行该 IP 段访问 notify_url 的 443 端口。
另外,《商户订单号查询订单》与《微信支付订单号查询订单》两个查单接口至少要接入一个,两个都不接就无法确认订单支付状态。
定时轮询查单
长时间收不到支付结果通知时,后台定时轮询查单接口核实状态,文档给了两种方案:
- 方案一:以订单下单成功时间为基准(或以前端支付返回成功/报错后第一次查单未成功的时间为基准),按 5 秒 / 30 秒 / 1 分钟 / 3 分钟 / 5 分钟 / 10 分钟 / 30 分钟 的间隔调用查单接口。间隔和次数可按业务调整。
- 方案二:定时任务每 30 秒启动一次,找出最近 10 分钟内创建且未支付的订单,调用查单接口核实;系统记录查询次数,10 次查询之后仍未支付成功,停止后续查询并调用《关单接口》关闭订单。
T+1 对账
T+1 日上午 10 点以后,调用《微信支付对账单下载接口》,或登录微信商户平台手工下载 T 日交易账单,按账单中的订单数据逐笔与商户系统订单核对。核对结果分四种:
- 订单匹配成功,双方状态都是支付成功:正常,对账成功。
- 订单匹配成功,但商户侧状态非支付成功:按自身业务决定,是更新为支付成功并发货,还是给用户退款。
- 订单匹配失败,账单中的单号在商户系统查不到:异常,排查系统是否有数据异常。
- 订单匹配失败,商户系统中成功的订单在账单中找不到:异常,排查订单处理逻辑是否有 bug。
关单前必须先查单
用户取消订单、超过可支付时间仍未支付、或按上面的查单方案达到停止条件时,都先查单,再按 trade_state 处理。没付才关单,已付不关单。
NOTPAY:调用关闭订单。关单成功后本地标为已关闭,不再拉起支付;用户还要购买,用新的商户订单号重新下单。NOTPAY不得直接置为支付失败。SUCCESS:不关单。同一商户订单号已支付成功,不要重复下单,也不要再调用关单;用户要取消这笔已支付订单,走退款。CLOSED:不再调用关闭订单。REFUND:不关单,按已有退款单继续处理。
关单接口返回「订单已支付」(错误码 268449538 / 268498689)时,说明查单之后用户已经付完,重新查单并按 SUCCESS 处理。
关单分支示意(伪代码,仅表达判断顺序):
# 示意:关单前的状态机
state = 查单(out_trade_no)
if state == NOTPAY:
关单(out_trade_no)
if 返回错误码 in (268449538, 268498689):
state = 查单(out_trade_no) # 查单后用户已支付
if state == SUCCESS:
按已支付处理()
else:
本地标为已关闭()
elif state == SUCCESS:
不关单() # 用户取消走退款
elif state == CLOSED:
不再关单()
elif state == REFUND:
按已有退款单继续处理()
常见问题
前端返回怎么区分成功、取消、异常
- 公众号支付看 JSAPI 返回的
res.err_msg:get_brand_wcpay_request:ok为支付成功,get_brand_wcpay_request:cancel为支付中用户取消,get_brand_wcpay_request:fail为支付失败。 - 小程序支付看回调类型:
success/requestPayment:ok为调用支付成功;fail/requestPayment:fail cancel为用户取消;fail/requestPayment:fail (detail message)为调用支付失败,detail message 是后台返回的详细失败原因。 - App 支付看 onResp 的
errCode:0成功;-1错误(可能原因:签名错误、未注册 AppID、项目设置 AppID 不正确、注册的 AppID 与设置的不匹配、其他异常);-2用户取消。
怎么判断订单真的支付成功
收到《微信支付查单接口》响应报文,验签成功,且 trade_state 为 SUCCESS,才认为订单支付成功。上面这些前端返回值只区分前端返回类型,不能单独作为支付成功的依据。
注意事项
- 支付结果以后端查单或支付成功回调为准。
get_brand_wcpay_request:ok只表示用户完成收银台操作,不表示支付成功;更新为已支付并发货,仅当查单或支付成功回调验签通过且trade_state为SUCCESS。 - 回调须在 5 秒内先验签再应答;验签不通过返回 4xx 或 5xx,不得返回 200。
- 防火墙放行微信支付回调 IP 段访问 notify_url 的 443 端口;未设置 APIv3 密钥收不到支付成功回调。
- 两个查单接口至少接一个,不得漏接查单。
- 未收到支付成功回调时先查单,不得更换
out_trade_no再次下单;trade_state为NOTPAY不表示支付失败。