繁体   English   中英

如何确保在线支付只执行一次?

[英]How to ensure an online payment is executed only once?

我为我的一个有在线支付的客户开发并维护了一个网站。

大多数情况下,它使用客户的墨西哥银行 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 class 添加了一个::after元素,该元素位于所有内容之上,此外我禁用了该按钮。 这是为了确保用户不能再次单击该按钮。 我不确定在这种情况下是否可以双击。

提交后(由于明显的原因减少了代码),我执行以下操作:

$client = new \GuzzleHttp\Client(['base_uri' => 'https://via.banorte.com:443']);

$parametros = [...]; // information required for the payment

$postQuery = http_build_query($parametros);
$contentLength = strlen($postQuery);

$resultadoPago = $client->post('/payw2', [
    'query' => $parametros,
]);
$headersPago = $resultadoPago->getHeaders();

if ($headersPago['RESULTADO_PAYW'][0] == 'A') {
    // This runs if the response is Authorized
    // The first thing I do here is create the new transaction and mark it as paid
    // Then I do some more stuff and finally redirect to a thank you page
}

然后,如果用户访问该产品,我会检查是否已经有具有相同产品的交易,这样我就不允许用户再次尝试购买它。 所以这让我相信双重支付发生在同一个 window 并且在这个过程中失败了。

有没有办法保证我只执行一次? 还是我总是依赖支付网关的响应? 我正在考虑添加与上一段中提到的相同的检查,但不确定页面是否正在刷新或用户是否正在刷新页面。

我会考虑将 true 或 false 添加到数据属性并确保目标是实际表单。 我不相信 e.currentTarget 在 2.5 秒后仍然保持不变

$(document).on("submit", "#card-form", function(e) {
  e.preventDefault();
  if (!$(this).data("cardSubmit")) return ;
  let DOMForm = this;
  $("#process").addClass("loading");
  $("button[type='submit']",this).prop("disabled", true).html("Processing...");
  setTimeout(function() {
    DOMForm.submit();
    $(DOMForm).data("cardSubmit",false); 
  }, 2500);
})

$(document).on("formvalid.zf.abide", "#card-form", function() {
  $(this).data("cardSubmit",true);
})

$(document).on("forminvalid.zf.abide", "#card-form", function() {
  $(this).data("cardSubmit",false);
})

我认为更深层次的问题是您对产品是否已购买的验证。 如果您跟踪数据库中的购买和产品,我看不出双击会使产品被购买两次的原因。

如果您确实管理数据库,您可以自己跟踪购买情况,并在每次调用时根据数据库验证产品是否可用。 如果可用,则处理付款并使用付款服务响应相应地更新您的数据库。 最后,将购买状态返回到您的前端。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM