
本文详解如何在 laravel cashier 中集成 stripe 支持的多种支付方式(如信用卡、sepa、paypal 等),通过 setupintent + stripe elements 实现安全、合规的多支付方法添加与管理。
本文详解如何在 laravel cashier 中集成 stripe 支持的多种支付方式(如信用卡、sepa、paypal 等),通过 setupintent + stripe elements 实现安全、合规的多支付方法添加与管理。
Laravel Cashier 默认聚焦于订阅场景下的支付流程,但其底层完全兼容 Stripe 的现代支付能力——包括所有 Stripe 支持的支付方式(如 Card、SEPA Direct Debit、SOFA、iDEAL、PayPal、Link 等)。关键在于:Cashier 并不限制支付方式类型,而是通过 Stripe 的 SetupIntent 机制统一管理客户支付凭据(PaymentMethod),而非仅绑定卡片。
✅ 核心实现逻辑
-
后端生成 SetupIntent
在用户进入支付方式管理页时,调用 createSetupIntent() 获取客户端可使用的 SetupIntent 客户端密钥:
// routes/web.php
Route::get('/payment-methods', function (Request $request) {
return view('payment-methods', [
'setupIntent' => auth()->user()->createSetupIntent(),
]);
});
-
前端初始化 Stripe Elements(支持多方式)
使用 Stripe.js v3+ 的 Elements 实例,并配置 PaymentElement(推荐)或 CardElement + PaymentMethodType 扩展支持:
<!-- resources/views/payment-methods.blade.php -->
<div id="payment-element"></div>
<button id="submit-button">添加支付方式</button>
<script src="https://js.stripe.com/v3/"></script><script>
const stripe = Stripe('{{ config('services.stripe.key') }}');
const elements = stripe.elements({
clientSecret: '{{ $setupIntent->client_secret }}',
// 启用多种支付方式(自动适配用户所在地区)
appearance: { theme: 'stripe' },
});
const paymentElement = elements.create('payment', {
// 可显式指定支持的支付方式(可选)
wallets: { applePay: 'auto', googlePay: 'auto' },
});
paymentElement.mount('#payment-element');
document.getElementById('submit-button').addEventListener('click', async () => {
const { error, setupIntent } = await stripe.confirmSetup({
elements,
redirect: 'if_required', // 对需跳转的方式(如 SOFA、iDEAL)自动处理
confirmParams: {
return_url: '{{ route('payment-methods.success') }}',
},
});
if (error) {
alert(error.message);
} else {
// 成功后,将 PaymentMethod ID 提交至后端绑定
const response = await axios.post('/api/payment-methods', {
payment_method: setupIntent.payment_method,
});
console.log('已成功添加支付方式:', response.data);
}
});
</script>
⚠️ 注意:confirmSetup() 替代了旧版 confirmCardSetup(),它原生支持所有 Stripe 支付方式,无需为每种方式单独编码。
-
后端接收并绑定 PaymentMethod
接收前端传来的 payment_method ID,使用 Cashier 提供的 addPaymentMethod() 方法安全绑定:
// app/Http/Controllers/PaymentMethodController.php
use Illuminate\Http\Request;
public function store(Request $request)
{
$request->validate(['payment_method' => 'required|string']);
$user = auth()->user();
$user->addPaymentMethod($request->input('payment_method'));
return response()->json([
'message' => '支付方式已成功添加',
'payment_method' => $user->paymentMethods()->latest()->first(),
]);
}
✅ 绑定后,该 PaymentMethod 将自动关联到用户,并可用于后续订阅创建($user->newSubscription(...)->create())、一次性收费($user->charge(...))或手动发起支付($user->createCharge(...))。
? 安全与最佳实践
- 始终使用 SetupIntent(而非 Token):Stripe 已弃用 createToken,SetupIntent 是 PCI 合规且支持 SCA(强认证)的唯一推荐方式。
- 避免硬编码密钥:前端仅使用 publishable_key;client_secret 由服务端动态生成并仅传递一次,不可复用。
- 验证 PaymentMethod 状态:可通过 $user->paymentMethods()->where('is_default', true)->first() 获取默认方式;调用 $pm->isVerified() 检查是否已通过验证(如 SEPA 需银行确认)。
- 处理异步验证结果:对需异步确认的方式(如 SOFA、ACH),监听 Stripe Webhook payment_method.attached 或 payment_method.updated 事件更新状态。
? 补充:设置默认支付方式与切换
// 设为默认
$user->updateDefaultPaymentMethod($paymentMethodId);
// 删除某支付方式
$user->deletePaymentMethod($paymentMethodId);
// 获取全部可用方式(含类型标识)
$methods = $user->paymentMethods()->with('asStripePaymentMethod')->get()->map(function ($pm) {
return [
'id' => $pm->id,
'type' => $pm->asStripePaymentMethod()->type, // 'card', 'sepa_debit', 'paypal', etc.
'last4' => $pm->card_last_four ?? null,
'brand' => $pm->card_brand ?? null,
];
});
通过以上方案,你无需绕过 Cashier,即可充分利用 Stripe 全套支付生态——真正实现“一套后端逻辑,多种前端支付体验”。











