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

Laravel中如何通过Payment Intent验证Stripe支付的卡余额不足或拒付?

解决方案:Stripe Payment Intent 测试卡错误未触发的问题

你的核心问题在于使用了Stripe已弃用的Token创建流程,且在确认Payment Intent阶段未正确捕获支付失败的同步/异步错误。以下是具体修复步骤:

1. 替换Token创建流程为Stripe Elements(官方推荐)

Stripe不再建议手动创建Token,改用Elements组件(或Payment Element)收集卡信息,既能安全处理敏感数据,也能自动覆盖更多前端验证场景,包括测试卡的错误判断。

Laravel后端调整

移除创建Token的代码,直接生成Payment Intent并返回客户端密钥:

// 创建Payment Intent(仅需设置金额、货币)
$paymentIntent = \Stripe\PaymentIntent::create([
    'amount' => 1000, // 单位:分
    'currency' => 'usd',
    'automatic_payment_methods' => ['enabled' => true],
]);

// 返回客户端密钥给前端用于支付确认
return response()->json(['clientSecret' => $paymentIntent->client_secret]);

2. 前端捕获Payment Intent确认阶段的错误

测试卡的余额不足、挂失等错误,均在确认Payment Intent阶段触发,需在前端支付确认逻辑中捕获并反馈给用户:

前端示例(JavaScript + Stripe.js)

// 初始化Stripe及Elements
const stripe = Stripe('你的Stripe公钥');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');

// 支付提交按钮事件
document.getElementById('submit-payment').addEventListener('click', async () => {
    const { error } = await stripe.confirmCardPayment(
        '后端返回的clientSecret',
        {
            payment_method: {
                card: cardElement,
                billing_details: {
                    name: '用户姓名',
                },
            },
        }
    );

    if (error) {
        // 捕获测试卡错误并提示用户
        alert(error.message);
    } else {
        // 支付成功后跳转或更新页面状态
        window.location.href = '/payment-success';
    }
});

3. 配置Webhook处理异步支付结果

部分测试卡场景(如需要3DS验证的卡)会触发异步支付结果,必须通过Stripe Webhook接收payment_intent.succeeded和payment_intent.payment_failed事件,更新本地订单状态:

Laravel Webhook路由

Route::post('/stripe/webhook', [StripeWebhookController::class, 'handle']);

Webhook控制器逻辑

public function handle(Request $request)
{
    $payload = $request->getContent();
    $sigHeader = $request->header('Stripe-Signature');
    $webhookSecret = config('services.stripe.webhook_secret');

    try {
        $event = \Stripe\Webhook::constructEvent(
            $payload, $sigHeader, $webhookSecret
        );
    } catch (\UnexpectedValueException $e) {
        return response()->json(['error' => '无效请求'], 400);
    } catch (\Stripe\Exception\SignatureVerificationException $e) {
        return response()->json(['error' => '无效签名'], 400);
    }

    // 处理支付成功事件
    if ($event->type === 'payment_intent.succeeded') {
        $paymentIntent = $event->data->object;
        Order::where('stripe_payment_intent_id', $paymentIntent->id)->update(['status' => 'paid']);
    }

    // 处理支付失败事件
    if ($event->type === 'payment_intent.payment_failed') {
        $paymentIntent = $event->data->object;
        Order::where('stripe_payment_intent_id', $paymentIntent->id)->update([
            'status' => 'failed',
            'error_message' => $paymentIntent->last_payment_error->message ?? '支付失败'
        ]);
    }

    return response()->json(['status' => 'success']);
}

4. 测试验证

使用Stripe测试卡验证:

  • 余额不足:4000 0000 0000 0002
  • 挂失卡:4000 0000 0000 0044
  • 需3DS验证:4000 0000 0000 3220

此时前端会在confirmCardPayment时捕获错误提示,后端Webhook也会同步接收失败事件,确保系统正确触发错误反馈并更新订单状态。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:25:37