如何使用Stripe防止重复充电?

时间:2017-12-04 13:59:11

标签: node.js stripe-payments

我使用Stripe允许我的客户保存信用卡并支付发票(具有唯一ID)。在付款时,我使用表单将带有卡ID(由条带提供)的POST请求发送到我的服务器,然后控制器对其进行收费。然后我将发票标记为支付给我。

事实证明,如果我足够快地双击我的表单提交按钮,我会发送两个POST请求,并且这些卡最终会被收取两次费用,因为当第二个POST请求到达我的服务器时,POST请求来自我的服务器到条纹API(从第一次点击)尚未完成,因此发票尚未标记为付款。

我考虑在第一次点击后禁用表单提交按钮,但我觉得可能有一种更清洁的方式。

Stripe的一方是否有防止重复收费(可能使用我的发票ID)?如果不是最好的后端方法在我身边做什么呢?

3 个答案:

答案 0 :(得分:6)

首次点击后禁用表单提交绝对是实现此目的的最简单方法。

另一种方法是使用记录为here的幂等请求。我们的想法是在向Stripe的API发出请求时传递唯一标识符,以确保您只能运行此事务一次。如果您使用完全相同的幂等关键字重新运行查询,您将从第一次调用中获得原始响应,这可确保您永远不会为同一个"事务"在您的网站上。

答案 1 :(得分:3)

如其他答案所述,您可以使用Idempotent Requests来防止重复收费。这是我的实现方式:

checkout.php上:

<?php
function rand_string( $length ) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return substr(str_shuffle($chars),0,$length);
}
$idempotency = rand_string(8);
?>
 ...
<form method="post" action="payment.php">
<input type="hidden" name="idempotency" id="idempotency" value="<?=$idempotency?>">
...
</form>
...

payment.php上:

<?php
$idempotency = preg_replace('/[^a-z\d]/im', '', $_POST['idempotency']);
...

try {
    $charge = \Stripe\Charge::create(
        ["amount" => $price,
        "currency" => $currency,
        "description" => $invoiceid,
        "customer" => $customer->id ], 
    ["idempotency_key" => $idempotency,]);
}catch(Exception $e) {
    $api_error = $e->getMessage();
}

答案 2 :(得分:2)

是幂等请求是实现此目的的正确方法。

你可以在这里参考

https://stripe.com/docs/api#idempotent_requests

另一个可以实现的简单解决方案是通过跟踪条带api调用来使用状态机。