You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何确保在线支付仅执行一次?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 00:46:09