如何通过Stripe Subscription(Laravel Cashier)实现额度耗尽后立即扣费?
处理Laravel Cashier(Stripe)中基础套餐额度耗尽的扣费方案
针对你提到的Basic套餐用户月中耗尽额度的场景,结合Laravel Cashier与Stripe Subscription,可通过以下方案实现扣费,核心是先触发额度耗尽的检测逻辑,再根据业务需求选择合适的扣费模式:
一、先实现额度耗尽的触发机制
首先需要在用户消耗额度的环节加入检测,或者通过定时任务监控:
- 实时检测:在用户每次使用额度的业务逻辑中,扣除额度后立即检查剩余额度是否为0,若为0则触发扣费流程。
- 定时监控:通过Laravel调度器(Scheduler)每天/每小时运行Artisan命令,扫描所有Basic套餐用户的额度使用情况,标记已耗尽额度的用户并触发扣费。
二、可选的扣费实现方案
方案1:售卖额外额度包(一次性扣费)
适合用户只需要临时补充少量额度的场景:
- 在Stripe后台创建一次性价格(One-time Price),对应固定额度的收费(例如:50额度收费$X)。
- 当用户额度耗尽时,调用Laravel Cashier的一次性扣费方法:
// 获取当前用户的Basic订阅(可选,关联订阅便于Stripe后台统一管理) $subscription = auth()->user()->subscription('basic'); // 执行一次性扣费,需确保用户有默认支付方式 try { // 按金额扣费,金额为Stripe价格对应的金额(单位:分) $charge = $subscription->charge(500, auth()->user()->defaultPaymentMethod()->id); // 扣费成功后,给用户增加对应额度 auth()->user()->increment('available_quota', 50); } catch (\Stripe\Exception\CardException $e) { // 处理支付失败逻辑,比如通知用户更新支付方式 session()->flash('error', $e->getMessage()); }
方案2:临时升级到Pro套餐(按周期比例扣费)
适合用户需要剩余周期内使用更高额度的场景:
- 在Stripe后台配置Basic和Pro的订阅价格。
- 当用户额度耗尽时,将订阅升级为Pro套餐,Stripe会自动按剩余周期比例计算差价并扣费:
try { // 升级订阅,自动按剩余周期比例收取差价 auth()->user()->subscription('basic')->swap('pro'); // 升级后更新用户可用额度:Pro套餐总200 - 已使用的100 = 100剩余额度 auth()->user()->update(['available_quota' => 100]); } catch (\Stripe\Exception\CardException $e) { // 处理支付失败 }
- 若需要在周期结束后自动换回Basic套餐,可在升级时设置
onGracePeriod或者通过调度器在订阅周期结束时执行降级操作。
方案3:添加订阅附加项(额度包作为订阅附加)
适合用户需要长期固定补充额度的场景:
- 在Stripe后台给Basic套餐创建订阅附加项(Subscription Add-on),对应固定额度的月度收费。
- 当用户额度耗尽时,给当前订阅添加该附加项并立即扣费:
try { // 给Basic订阅添加额度附加项 auth()->user()->subscription('basic')->addItem([ 'price' => 'price_xxxxxx', // Stripe后台附加项的价格ID ])->invoice(); // 立即生成发票并扣费 // 增加对应额度 auth()->user()->increment('available_quota', 100); } catch (\Stripe\Exception\CardException $e) { // 处理支付失败 }
三、注意事项
- 扣费前必须通过邮件/站内信通知用户,明确告知额度即将耗尽及扣费选项,避免纠纷。
- 确保用户已设置默认支付方式,若未设置,引导用户添加支付方式后再执行扣费。
- 所有扣费逻辑需加入异常捕获,处理支付失败、卡片过期等情况,避免业务流程中断。
内容的提问来源于stack exchange,提问作者Mahmud hasan
相关产品推荐
相关产品推荐

