如何确保在线支付仅执行一次?Banorte网关重复支付问题咨询
支付重复执行问题排查与解决方案咨询
我为客户开发维护了一个带在线支付功能的网站,核心使用墨西哥Banorte银行提供的支付网关。目前遇到棘手问题:部分场景下支付会被执行两次,不确定是用户双击提交还是流程其他环节导致,最近一次重复支付的时间间隔约2分钟。另外,该产品是活动准入权限,规则上每人限购1份。
前端实现(Foundation 6)
我设计了收集银行卡信息的表单,前端通过以下逻辑防止重复提交:
var cardSubmit = false; $(document).on("submit", "#card-form", function(e) { e.preventDefault(); if(cardSubmit) { $("#process").addClass("loading"); $("#card-form button[type='submit']").prop("disabled", true).html("Processing..."); setTimeout(function() { e.currentTarget.submit(); }, 2500); } }) $(document).on("formvalid.zf.abide", "#card-form", function() { cardSubmit = true; }) $(document).on("forminvalid.zf.abide", "#card-form", function() { cardSubmit = false; })
.loading类会添加一个::after元素覆盖整个页面,同时禁用提交按钮,但不确定这种方式是否能完全杜绝双击或其他场景下的重复提交。
后端支付请求(PHP + GuzzleHttp)
表单提交后,后端通过GuzzleHttp发起支付请求(代码已简化):
$client = new \GuzzleHttp\Client(['base_uri' => 'https://via.banorte.com:443']); $parametros = [...]; // 支付所需的必要参数信息 $postQuery = http_build_query($parametros); $contentLength = strlen($postQuery); $resultadoPago = $client->post('/payw2', [ 'query' => $parametros, ]); $headersPago = $resultadoPago->getHeaders(); if ($headersPago['RESULTADO_PAYW'][0] == 'A') { // 支付网关返回授权通过时执行 // 第一步是创建新交易记录并标记为已支付 // 后续完成其他业务操作,最后跳转至感谢页面 }
现有限制与疑问
目前用户再次访问产品页面时,系统会检查该用户是否已有该产品的交易记录,从而禁止再次购买。由此推测重复支付可能发生在同一窗口内,是流程中某环节出现了问题。
想请教几个问题:
- 有没有可靠的方法能保证支付仅执行一次?
- 是否必须始终依赖支付网关的响应来做最终判断?
- 考虑在发起支付请求前添加用户限购检查,但不确定是否是页面刷新导致的重复支付问题。
内容的提问来源于stack exchange,提问作者Mihail Minkov
相关产品推荐
相关产品推荐

