悠悠楠杉
支付接口对接教程:处理支付状态不同步与重复回调
支付接口对接做到“能弹出收银台”,还没有完成。用户关闭页面后,支付结果仍可能通过服务端通知送达;通知遇到网络故障,也可能重复发送。接入时,把支付结果确认和业务履约分开处理,才能减少漏发货、重复开通等问题。
请求发出后,为什么还拿不到支付凭证
接入前,确认商户已开通目标支付产品。网页支付与小程序支付的接入条件不同,照搬另一种场景的示例,请求格式即使正确,也可能被拒绝。
请求签名放在服务端生成,商户私钥不进入前端代码。使用渠道官方 SDK 时,对照当前接口版本核对配置,检查应用与商户的关联关系,以及请求地址所属环境。测试环境的凭证混入正式环境,常会表现为鉴权失败。
下单金额从服务端订单读取,不接受前端直接决定应付金额。业务订单在调用支付接口前落库,并保存稳定的商户订单号,后续通知与查单都通过它关联原订单。
若请求超时,保留这笔订单并查询渠道状态。超时只表示本次没有拿到明确响应,贸然换一个订单号重试,可能生成另一笔支付订单。
用户已扣款,订单还停在待支付
前端跳回成功页,或用户展示扣款截图,都不足以直接触发发货。订单状态依据通过校验的服务端通知或主动查单结果更新。
假设一个售卖数字内容的网站出现这样的情况:用户完成付款后关闭页面,订单仍显示待支付。客服收到反馈,后台查单返回支付成功;与此同时,延迟的支付回调也抵达服务器。若两条处理路径都执行“开通内容”,同一笔订单就可能被履约两次。
定位这类问题时,沿同一商户订单号查看通知接收记录和订单更新记录。没有收到通知,检查回调地址的公网可达性;已经收到却未更新,就查看验签结果和数据库错误。日志保留必要的状态与错误信息,不写入私钥或完整敏感支付数据。
收到通知后,按渠道协议验签,再核对通知对应的商户、订单和金额。通知接口被访问过,只能证明收到了一次请求,不能证明款项已经支付成功。
在上述情境中,查单与回调接入同一段状态更新逻辑。数据库通过条件更新,让“待支付转为已支付”只成功一次;只有完成这次转换的处理才创建履约任务。另一条路径发现订单已支付后,保留处理记录,不再重复开通。
支付记录与履约任务在同一事务中写入,避免订单已更新、任务却丢失。任务执行端继续以业务订单号去重,处理任务重试时再次开通的风险。网页随后读取服务端状态;尚未确认时展示“结果确认中”,而不是诱导用户立即重新付款。
上线前,把重复通知和处理中断测出来
联调时,围绕同一笔测试订单重复发送通知,并让查单更新与回调处理同时发生。核对数据库里的支付记录和实际履约次数,接口返回成功并不能替代这些检查。
渠道通知的成功响应,在支付结果可靠落库后按协议返回。若数据库写入失败却提前确认接收,渠道可能停止重试,订单就会继续停在旧状态。发货任务处理较慢时,通知接口只负责保存支付结果和履约任务,不把整个发货过程塞进回调请求。
还要测试进程中断后的恢复:支付记录已保存、履约尚未完成时,恢复后仍能找到待执行任务;任务已经执行过时,重试不会再次发放。
正式环境的回调地址、凭证和权限另行核对,沙箱通过不能替代生产配置验证。上线前补齐未确认订单的查单处理,并把未完成履约任务的恢复路径实际跑通。

