Laravel Cashier
介绍
Laravel Cashier 提供了一个表达式流畅的接口,用于 Stripe 的订阅计费服务。它处理几乎所有你不想编写的样板订阅计费代码。除了基本的订阅管理,Cashier 还可以处理优惠券、交换订阅、订阅“数量”、取消宽限期,甚至生成发票 PDF。
配置
Composer
首先,将 Cashier 包添加到你的 composer.json
文件中:
"laravel/cashier": "~2.0"
服务提供者
接下来,在你的 app
配置文件中注册 Laravel\Cashier\CashierServiceProvider
。
迁移
在使用 Cashier 之前,我们需要向你的数据库添加几个列。别担心,你可以使用 cashier:table
Artisan 命令创建一个迁移来添加必要的列。例如,要向用户表添加列,请使用 php artisan cashier:table users
。迁移创建后,只需运行 migrate
命令。
模型设置
接下来,在你的模型定义中添加 BillableTrait 和适当的日期变更器:
use Laravel\Cashier\BillableTrait;
use Laravel\Cashier\BillableInterface;
class User extends Eloquent implements BillableInterface {
use BillableTrait;
protected $dates = ['trial_ends_at', 'subscription_ends_at'];
}
Stripe 密钥
最后,在你的一个引导文件中设置你的 Stripe 密钥:
User::setStripeKey('stripe-key');
订阅计划
一旦你有了模型实例,你可以轻松地将该用户订阅到给定的 Stripe 计划:
$user = User::find(1);
$user->subscription('monthly')->create($creditCardToken);
如果你想在创建订阅时应用优惠券,可以使用 withCoupon
方法:
$user->subscription('monthly')
->withCoupon('code')
->create($creditCardToken);
subscription
方法将自动创建 Stripe 订阅,并更新你的数据库以包含 Stripe 客户 ID 和其他相关的计费信息。如果你的计划在 Stripe 中配置了试用期,试用结束日期也会自动设置在用户记录上。
如果你的计划有一个 未 在 Stripe 中配置的试用期,你必须在订阅后手动设置试用结束日期:
$user->trial_ends_at = Carbon::now()->addDays(14);
$user->save();
指定额外的用户详细信息
如果你想指定额外的客户详细信息,可以将它们作为第二个参数传递给 create
方法:
$user->subscription('monthly')->create($creditCardToken, [
'email' => $email, 'description' => '我们的第一位客户'
]);
要了解 Stripe 支持的额外字段,请查看 Stripe 的 客户创建文档。
无卡片前期
如果你的应用程序提供无信用卡的免费试用,请将模型上的 cardUpFront
属性设置为 false
:
protected $cardUpFront = false;
在账户创建时,请确保在模型上设置试用结束日期:
$user->trial_ends_at = Carbon::now()->addDays(14);
$user->save();
交换订阅
要将用户交换到新订阅,请使用 swap
方法:
$user->subscription('premium')->swap();
如果用户正在试用,试用将正常保持。此外,如果订阅存在“数量”,该数量也将保持。
订阅数量
有时订阅会受到“数量”的影响。例如,你的应用程序可能会按每个用户每月收费 10 美元。要轻松增加或减少你的订阅数量,请使用 increment
和 decrement
方法:
$user = User::find(1);
$user->subscription()->increment();
// 将五个添加到订阅的当前数量...
$user->subscription()->increment(5);
$user->subscription()->decrement();
// 将五个从订阅的当前数量中减去...
$user->subscription()->decrement(5);
取消订阅
取消订阅非常简单:
$user->subscription()->cancel();
当订阅被取消时,Cashier 将自动在你的数据库中设置 subscription_ends_at
列。此列用于知道何时 subscribed
方法应开始返回 false
。例如,如果客户在 3 月 1 日取消订阅,但订阅原定于 3 月 5 日结束,则 subscribed
方法将在 3 月 5 日之前继续返回 true
。
恢复订阅
如果用户取消了他们的订阅并且你希望恢复它,请使用 resume
方法:
$user->subscription('monthly')->resume($creditCardToken);
如果用户取消了订阅,然后在订阅完全到期之前恢复该订阅,他们将不会立即被收费。他们的订阅将简单地重新激活,并将在原始计费周期上收费。
检查订阅状态
要验证用户是否订阅了你的应用程序,请使用 subscribed
命令:
if ($user->subscribed())
{
//
}
subscribed
方法非常适合用作路由过滤器:
Route::filter('subscribed', function()
{
if (Auth::user() && ! Auth::user()->subscribed())
{
return Redirect::to('billing');
}
});
你还可以使用 onTrial
方法确定用户是否仍在试用期内(如果适用):
if ($user->onTrial())
{
//
}
要确定用户是否曾经是活跃的订阅者,但已取消他们的订阅,可以使用 cancelled
方法:
if ($user->cancelled())
{
//
}
你还可以确定用户是否取消了他们的订阅,但仍在“宽限期”内,直到订阅完全到期。例如,如果用户在 3 月 5 日取消了原定于 3 月 10 日结束的订阅,则用户在 3 月 10 日之前处于“宽限期”。请注意,在此期间,subscribed
方法仍返回 true
。
if ($user->onGracePeriod())
{
//
}
everSubscribed
方法可用于确定用户是否曾经在你的应用程序中订阅过计划:
if ($user->everSubscribed())
{
//
}
onPlan
方法可用于确定用户是否根据其 ID 订阅了给定计划:
if ($user->onPlan('monthly'))
{
//
}
处理失败的付款
如果客户的信用卡过期怎么办?别担心 - Cashier 包含一个 Webhook 控制器,可以轻松为你取消客户的订阅。只需将路由指向控制器:
Route::post('stripe/webhook', 'Laravel\Cashier\WebhookController@handleWebhook');
就这样!失败的付款将由控制器捕获和处理。控制器将在三次失败的付款尝试后取消客户的订阅。此示例中的 stripe/webhook
URI 仅供参考。你需要在 Stripe 设置中配置该 URI。
处理其他 Stripe Webhooks
如果你有其他 Stripe webhook 事件想要处理,只需扩展 Webhook 控制器。你的方法名称应与 Cashier 的预期约定相对应,具体来说,方法应以 handle
和你希望处理的 Stripe webhook 的名称为前缀。例如,如果你希望处理 invoice.payment_succeeded
webhook,你应该在控制器中添加一个 handleInvoicePaymentSucceeded
方法。
class WebhookController extends Laravel\Cashier\WebhookController {
public function handleInvoicePaymentSucceeded($payload)
{
// 处理事件
}
}
除了在你的数据库中更新订阅信息外,Webhook 控制器还将通过 Stripe API 取消订阅。
发票
你可以使用 invoices
方法轻松检索用户的发票数组:
$invoices = $user->invoices();
在列出客户的发票时,你可以使用这些辅助方法来显示相关的发票信息:
{{ $invoice->id }}
{{ $invoice->dateString() }}
{{ $invoice->dollars() }}
使用 downloadInvoice
方法生成发票的 PDF 下载。是的,真的这么简单:
return $user->downloadInvoice($invoice->id, [
'vendor' => '你的公司',
'product' => '你的产品',
]);