悠悠楠杉
微信支付异步通知到了,订单为什么还没更新?
微信支付异步通知,是微信支付在交易状态变化后向商户通知地址发送的请求。它与用户付款后返回商户页面是两条路径:用户看到“支付成功”,不代表商户服务器已经收到通知;页面没有跳回来,也不能据此认定付款失败。
用户已付款,商户订单仍是待支付
先看商户服务器有没有收到请求。完全没有访问记录时,检查下单时提交的通知地址是否正确、服务是否能从公网访问,以及网关有没有拦截请求。若已有请求进入,排查范围就转到响应记录和处理日志,不必反复让用户付款。
假设一个订单在微信支付侧已显示成功,商户后台却一直是待支付。服务日志里能找到通知请求,但记录停在验签环节。开发人员保存这次请求的原始报文和相关请求头,按当前接入的证书或公钥方案核对验签材料,发现程序在验签前重新序列化了请求体。字段内容看似没变,字节却与收到的原文不同,签名因此无法通过。调整后,程序用收到的原始请求体参与验签,再解密通知中的交易信息。
这类问题处理时,不宜为了尽快更新订单而跳过验签。通知地址对外开放,仅凭请求体里写着“支付成功”就改状态,商户无法确认消息来源。验签通过后,还要核对商户订单号、商户号和支付金额,并确认交易状态与准备执行的业务动作一致。订单金额来自本地已创建的订单记录,不能由通知内容替它决定。
上述订单即使修复了代码,也不会因为重新部署就自动更新。开发人员还需查询该笔交易的微信支付状态,将查询结果与本地订单核对;原先失败的通知是否再次到达,则留在后续日志里确认。
通知重复到达,业务动作却不能重复做
异步通知可能重复送达。服务处理成功后返回成功响应,只表示商户已接收并处理这次通知;它不是向微信支付发起付款,也不保证网络中的每一方都同步看到了这次响应。若数据库已提交,响应却在返回途中中断,后面仍可能收到同一笔交易的通知。
因此,处理通知时要用商户订单号定位订单,并把“待支付改为已支付”做成可重复执行的操作。订单已经是已支付状态,再来的相同通知可以直接确认处理结果,不再重复发放权益。若更新订单后还要发消息或开通服务,相关任务也要有去重依据;否则订单表只更新一次,下游动作仍可能执行多次。
成功响应的时机同样影响结果。程序刚解密就返回成功,随后写库失败,用户的钱已付,商户订单却没有落下状态。把订单更新与必要的后续任务可靠地记录下来,再返回成功响应;遇到数据库不可用等暂时故障,保留失败记录,待通知重试或主动查询后补齐。已经落库但返回失败的请求,则按重复通知处理。
等不到通知时,查询交易状态
通知适合推动订单及时更新,但不能把它当作唯一的付款凭据。用户长时间停在待支付页面,客服或系统应按商户订单号查询微信支付交易状态,再对照本地记录。查询显示支付成功而本地仍待支付,才进入补单处理;查询结果未确定时,页面不要凭一次超时直接改成支付失败,更不要提示用户立即重付同一订单。
排查记录保留商户订单号、通知接收时间、验签结果和订单更新结果即可,避免在日志中完整输出敏感报文。下一次遇到“已付款、未更新”,先确认通知有没有进服务;请求已到,再定位它停在验签、核对交易信息,还是写入订单的环节。

