Laravel 5.5 Cashier 如何设置分钟或秒级试用期
结论
Laravel Cashier 5.5 支持通过 trialUntil() 指定试用结束的准确时间,所以在代码中可以设置分钟或秒级的试用期:
use Carbon\Carbon;
$user->newSubscription('main', 'monthly')
->trialUntil(Carbon::now()->addMinutes(10))
->create($creditCardToken);
但 Cashier 最终还是要把试用结束时间提交给支付平台。以 Laravel 5.5 常用的 Stripe 为例,当时的 API 对试用期设有最短时长限制,分钟或秒级的时间可能被 Stripe 拒绝。因此,Cashier 支持这种写法,不等于支付平台一定允许这么短的试用期。
设置分钟或秒级时间
trialDays() 只接收天数。如果需要更精确地控制时间,可以改用 trialUntil(),并传入日期时间对象。
设置 10 分钟:
use Carbon\Carbon;
$user->newSubscription('main', 'monthly')
->trialUntil(Carbon::now()->addMinutes(10))
->create($creditCardToken);
设置 30 秒:
use Carbon\Carbon;
$user->newSubscription('main', 'monthly')
->trialUntil(Carbon::now()->addSeconds(30))
->create($creditCardToken);
也可以先构造具体的结束时间:
use Carbon\Carbon;
$trialEndsAt = Carbon::now()->addHour();
$user->newSubscription('main', 'monthly')
->trialUntil($trialEndsAt)
->create($creditCardToken);
Cashier 会将这个时间转换为支付平台需要的 trial_end 时间戳。
为什么可能无法成功
trialUntil() 解决的是 Cashier 如何表示试用结束时间,订阅本身仍由 Stripe 创建。如果当前 Stripe API 版本要求试用期至少持续若干天,下面这样的请求就会收到 Stripe 返回的参数错误:
->trialUntil(Carbon::now()->addMinutes(5))
限制来自 Stripe,而不是 Carbon 或 Laravel,也不应该通过修改 Cashier 源码来绕过。如果支付平台不接受这个时间,只修改本地数据库中的 trial_ends_at,也无法让 Stripe 提前扣款。
如何测试 recurring payments 和 webhooks
如果 Stripe 不接受分钟或秒级试用期,可以拆开测试:
- 在 Stripe 测试模式下创建订阅。
- 使用支付平台提供的测试功能触发相应的 webhook。
- 将 webhook 请求发送到本地或测试环境,验证签名、路由及业务处理逻辑。
- 为订阅状态变化编写自动化测试,直接构造对应的 webhook payload。
- 如果需要测试完整的试用结束流程,就使用支付平台允许的最短试用时间。
应用内部与试用期有关的判断可以单独测试,不必等待 Stripe 跑完一次完整的计费周期:
$trialEndsAt = Carbon::now()->addMinutes(5);
$this->assertTrue($trialEndsAt->isFuture());
注意事项
不要只更新本地 subscriptions 表中的 trial_ends_at。Cashier 的本地记录必须与 Stripe 的订阅状态保持一致,否则应用可能认为试用已经结束,而 Stripe 仍将订阅视为处于试用期。
分钟或秒级试用期可以通过 trialUntil() 表示,但能否创建成功,取决于当前账户使用的 Stripe API 版本及其试用期限制。
备注:内容仅供参考。
