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

如何高效处理Stripe待处理/失败支付的自动重试?

Stripe支付重试与订单处理方案

一、核心原则:复用原Payment Intent而非新建

不要创建新的Payment Intent,直接重试原交易即可——原Intent已关联客户、支付方式、订单元数据等关键信息,复用能保证数据一致性,也符合Stripe的最佳实践。

二、具体实现步骤

1. 订单状态追踪与队列触发

  • 给订单表新增字段:stripe_payment_intent_id(存储Stripe返回的Intent ID)、payment_status(枚举值:pending/failed/succeeded)、retry_count(记录重试次数,默认0)、created_at(订单创建时间)。
  • 配置定时任务(比如Cron或框架自带的任务调度,如Laravel Scheduler),每1分钟扫描订单表,筛选出以下订单加入重试队列:
    • payment_status为pending或failed
    • 订单创建时间超过5分钟
    • retry_count未达上限(建议设为3次,避免无限重试)

2. 队列任务的重试逻辑

队列任务核心是调用Stripe的confirm接口重试原Payment Intent,PHP代码示例:

// 从队列获取订单信息
$order = getTargetOrder($queueItem);

try {
    $stripe = new \Stripe\StripeClient('你的Stripe密钥');
    // 重试原Payment Intent
    $paymentIntent = $stripe->paymentIntents->confirm(
        $order->stripe_payment_intent_id,
        [
            'payment_method' => $order->stripe_payment_method_id, // 需提前将支付方式ID存到订单表
            'error_on_requires_action' => true, // 直接返回错误,跳过需用户交互的场景
            'metadata' => ['retry_attempt' => $order->retry_count + 1]
        ]
    );

    // 根据返回状态处理订单
    if ($paymentIntent->status === 'succeeded') {
        // 标记订单完成,触发后续流程(如发货)
        updateOrderStatus($order->id, 'completed');
    } elseif (in_array($paymentIntent->status, ['requires_payment_method', 'failed'])) {
        $order->retry_count += 1;
        $order->payment_status = 'failed';
        $order->save();

        // 达到重试上限则通知用户更换卡片
        if ($order->retry_count >= 3) {
            notifyUser($order->user_id, '订单支付失败,请更换支付卡片');
        }
    }
} catch (\Stripe\Exception\ApiErrorException $e) {
    // 捕获Stripe接口错误(如卡片拒付、网络问题)
    $order->retry_count += 1;
    $order->payment_status = 'failed';
    $order->error_msg = $e->getError()->message;
    $order->save();

    if ($order->retry_count >= 3) {
        notifyUser($order->user_id, '订单支付多次失败,请更换支付卡片');
    }
}

3. 关键注意事项

  • 存储支付方式ID:现有代码未保存payment_method_id,建议在创建Payment Intent后,将该字段存入订单表,否则重试时无法指定原支付方式。
  • 递增重试间隔:可设置递增的重试间隔(如第一次5分钟后,第二次15分钟后,第三次30分钟后),避免频繁重试影响用户体验。
  • Webhook兜底:仍需配置Stripe Webhook监听payment_intent.succeeded和payment_intent.failed事件,覆盖用户手动在Stripe后台完成支付的场景。
  • 幂等性保障:队列任务要保证幂等,可通过「订单ID+重试次数」作为唯一标识,避免同一订单被重复处理。

三、现有创建Payment Intent代码的优化

补充存储关键字段,可选启用自动支付方式配置:

if($params['payment_method'] == 'stripe') {
    $paymentIntent = $stripe->paymentIntents->create([
        'shipping' => [
            "name" => $uModel->full_name,
            "phone" => $params['billing_phone'],
            "address" => [
                "city" => $params['billing_city'],
                "country" => $params['billing_country'],
                "line1" => $params['billing_address_1'],
                "line2" => $params['billing_address_2'],
                "postal_code" => $params['billing_postcode'],
                "state" => $params['billing_state']
            ]
        ],
        'amount' => $params['total_price']*100,
        'currency' => 'usd',
        'payment_method_types' => ['card'],
        'metadata' => ['order_id' => $params['order_id']],
        'customer' => $customer,
        'description' => 'Company - orderid #'.$params['order_id'],
        'automatic_payment_methods' => ['enabled' => true] // 可选:启用Stripe自动支付方式处理
    ]);

    // 保存关键信息到订单表
    saveOrderStripeData($params['order_id'], $paymentIntent->id, $params['payment_method_id']);

    $res['clientSecret'] = $paymentIntent->client_secret;
    $res['payment_method'] = "stripe";
}

内容的提问来源于stack exchange,提问作者Sheryar Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 14:53:11