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

Laravel电商网站基于Stripe实现类Uber Eats支付方式存储功能咨询

嘿,刚好我之前在Laravel项目里实现过类似Uber Eats的支付方式存储功能,完全基于Stripe的合规方案,不用碰任何敏感银行卡信息,给你梳理下核心思路和具体步骤:

核心原理:Stripe的Customer与PaymentMethod机制

Stripe的Customer对象是实现支付方式存储的核心——我们只需要把用户关联到一个Stripe Customer,然后将用户的支付方式(银行卡、PayPal等)关联到这个Customer上。所有敏感的支付信息都由Stripe托管,我们的数据库只存Stripe返回的payment_method_id和stripe_customer_id,完全符合PCI合规要求,不用自己承担存储风险。

具体实现步骤(Laravel环境)

我假设你已经用Laravel Cashier或者直接集成了Stripe SDK,下面分步骤来:

1. 准备工作:关联用户与Stripe Customer

首先给你的users表加一个字段stripe_customer_id(字符串类型,可为空),用来存储Stripe侧的Customer ID。

然后在用户注册或者首次使用支付功能时,创建Stripe Customer并关联:

// 在User模型里添加方法
public function createStripeCustomer()
{
    if ($this->stripe_customer_id) {
        return $this->stripe_customer_id;
    }

    $customer = \Stripe\Customer::create([
        'email' => $this->email,
        'name' => $this->name,
    ]);

    $this->update(['stripe_customer_id' => $customer->id]);
    return $customer->id;
}

如果你用Laravel Cashier的话更简单,直接调用$user->createAsStripeCustomer()就行,Cashier会自动帮你维护stripe_customer_id字段。

2. 前端收集支付方式(关键:绝不碰原始卡号)

必须用Stripe的前端组件(Elements或者Payment Request Button)来收集支付信息,绝对不能把卡号、CVC等信息传到自己的服务器。

举个简单的前端示例(用Stripe.js v3):

<!-- 加载Stripe.js -->
<script src="https://js.stripe.com/v3/"></script>
<div id="card-element"></div>
<button id="save-payment-method">保存支付方式</button>

<script>
const stripe = Stripe('你的Stripe公钥');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');

// 点击保存按钮时处理
document.getElementById('save-payment-method').addEventListener('click', async () => {
    // 先从后端获取Setup Intent(用来安全初始化支付方式绑定)
    const setupIntentResponse = await fetch('/api/create-setup-intent', { method: 'POST' });
    const setupIntent = await setupIntentResponse.json();

    // 确认Setup Intent,获取PaymentMethod
    const { error, paymentMethod } = await stripe.confirmCardSetup(
        setupIntent.client_secret,
        {
            payment_method: {
                card: cardElement,
                billing_details: { name: '用户姓名' }
            }
        }
    );

    if (error) {
        // 处理错误,比如卡片无效、3DS认证失败等
        alert(error.message);
    } else {
        // 将paymentMethod.id传到后端,关联到用户的Stripe Customer
        await fetch('/api/save-payment-method', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ payment_method_id: paymentMethod.id })
        });
        alert('支付方式已保存');
    }
});
</script>

3. 后端绑定PaymentMethod到Customer

后端接收前端传来的payment_method_id,将其关联到用户的Stripe Customer上:

// 路由:/api/save-payment-method
public function savePaymentMethod(Request $request)
{
    $user = auth()->user();
    // 确保用户已经有Stripe Customer
    $user->createStripeCustomer();

    // 绑定PaymentMethod到Customer
    \Stripe\PaymentMethod::retrieve($request->payment_method_id)->attach([
        'customer' => $user->stripe_customer_id,
    ]);

    // 可选:设置为默认支付方式
    \Stripe\Customer::update($user->stripe_customer_id, [
        'invoice_settings' => [
            'default_payment_method' => $request->payment_method_id,
        ],
    ]);

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

用Cashier的话可以简化成:

$user->addPaymentMethod($request->payment_method_id);
// 设置默认
$user->updateDefaultPaymentMethod($request->payment_method_id);

4. 使用存储的支付方式发起后续支付

当用户下单时,直接用已存储的PaymentMethod发起支付:

// 方式1:使用默认支付方式
$charge = $user->charge(
    1000, // 金额,单位:分(比如10美元就是1000)
    $user->defaultPaymentMethod()->id
);

// 方式2:让用户选择已存储的某个PaymentMethod
$paymentMethods = $user->paymentMethods(); // 获取所有已存储的支付方式
$charge = $user->charge(1000, $selectedPaymentMethodId);

// 检查支付状态
if ($charge->status === 'succeeded') {
    // 处理订单逻辑
}

5. 管理支付方式(查看、删除、设默认)

给用户提供管理支付方式的功能:

// 获取所有已存储的支付方式
$paymentMethods = $user->paymentMethods()->map(function ($method) {
    return [
        'id' => $method->id,
        'brand' => $method->card->brand,
        'last4' => $method->card->last4,
        'exp_month' => $method->card->exp_month,
        'exp_year' => $method->card->exp_year,
        'is_default' => $method->id === $user->defaultPaymentMethod()?->id
    ];
});

// 删除某个支付方式
$user->deletePaymentMethod($paymentMethodId);

// 设置默认支付方式
$user->updateDefaultPaymentMethod($paymentMethodId);
关键注意事项
  • 绝对禁止自己处理原始银行卡信息,所有收集流程必须通过Stripe的前端组件,否则会违反PCI合规
  • 一定要处理Setup Intent和Payment Intent的错误场景,比如3DS认证需要用户额外验证、卡片过期、余额不足等
  • 建议配置Stripe Webhook,监听payment_method.attached、customer.updated等事件,同步支付方式的状态到自己的数据库
  • 测试阶段用Stripe的测试卡号:4242 4242 4242 4242,过期日期填未来的月份/年份,CVC随便填3位数字

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:43:59