Skip to content

Laravel Cashier

介绍

Laravel Cashier 提供了一个表达式流畅的接口,用于 Stripe 的订阅计费服务。它处理几乎所有你不想编写的样板订阅计费代码。除了基本的订阅管理,Cashier 还可以处理优惠券、交换订阅、订阅“数量”、取消宽限期,甚至生成发票 PDF。

配置

Composer

首先,将 Cashier 包添加到你的 composer.json 文件中:

php
"laravel/cashier": "~2.0"

服务提供者

接下来,在你的 app 配置文件中注册 Laravel\Cashier\CashierServiceProvider

迁移

在使用 Cashier 之前,我们需要向你的数据库添加几个列。别担心,你可以使用 cashier:table Artisan 命令创建一个迁移来添加必要的列。例如,要向用户表添加列,请使用 php artisan cashier:table users。迁移创建后,只需运行 migrate 命令。

模型设置

接下来,在你的模型定义中添加 BillableTrait 和适当的日期变更器:

php
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 密钥:

php
User::setStripeKey('stripe-key');

订阅计划

一旦你有了模型实例,你可以轻松地将该用户订阅到给定的 Stripe 计划:

php
$user = User::find(1);

$user->subscription('monthly')->create($creditCardToken);

如果你想在创建订阅时应用优惠券,可以使用 withCoupon 方法:

php
$user->subscription('monthly')
     ->withCoupon('code')
     ->create($creditCardToken);

subscription 方法将自动创建 Stripe 订阅,并更新你的数据库以包含 Stripe 客户 ID 和其他相关的计费信息。如果你的计划在 Stripe 中配置了试用期,试用结束日期也会自动设置在用户记录上。

如果你的计划有一个 在 Stripe 中配置的试用期,你必须在订阅后手动设置试用结束日期:

php
$user->trial_ends_at = Carbon::now()->addDays(14);

$user->save();

指定额外的用户详细信息

如果你想指定额外的客户详细信息,可以将它们作为第二个参数传递给 create 方法:

php
$user->subscription('monthly')->create($creditCardToken, [
	'email' => $email, 'description' => '我们的第一位客户'
]);

要了解 Stripe 支持的额外字段,请查看 Stripe 的 客户创建文档

无卡片前期

如果你的应用程序提供无信用卡的免费试用,请将模型上的 cardUpFront 属性设置为 false

php
protected $cardUpFront = false;

在账户创建时,请确保在模型上设置试用结束日期:

php
$user->trial_ends_at = Carbon::now()->addDays(14);

$user->save();

交换订阅

要将用户交换到新订阅,请使用 swap 方法:

php
$user->subscription('premium')->swap();

如果用户正在试用,试用将正常保持。此外,如果订阅存在“数量”,该数量也将保持。

订阅数量

有时订阅会受到“数量”的影响。例如,你的应用程序可能会按每个用户每月收费 10 美元。要轻松增加或减少你的订阅数量,请使用 incrementdecrement 方法:

php
$user = User::find(1);

$user->subscription()->increment();

// 将五个添加到订阅的当前数量...
$user->subscription()->increment(5);

$user->subscription()->decrement();

// 将五个从订阅的当前数量中减去...
$user->subscription()->decrement(5);

取消订阅

取消订阅非常简单:

php
$user->subscription()->cancel();

当订阅被取消时,Cashier 将自动在你的数据库中设置 subscription_ends_at 列。此列用于知道何时 subscribed 方法应开始返回 false。例如,如果客户在 3 月 1 日取消订阅,但订阅原定于 3 月 5 日结束,则 subscribed 方法将在 3 月 5 日之前继续返回 true

恢复订阅

如果用户取消了他们的订阅并且你希望恢复它,请使用 resume 方法:

php
$user->subscription('monthly')->resume($creditCardToken);

如果用户取消了订阅,然后在订阅完全到期之前恢复该订阅,他们将不会立即被收费。他们的订阅将简单地重新激活,并将在原始计费周期上收费。

检查订阅状态

要验证用户是否订阅了你的应用程序,请使用 subscribed 命令:

php
if ($user->subscribed())
{
	//
}

subscribed 方法非常适合用作路由过滤器:

php
Route::filter('subscribed', function()
{
	if (Auth::user() && ! Auth::user()->subscribed())
	{
		return Redirect::to('billing');
	}
});

你还可以使用 onTrial 方法确定用户是否仍在试用期内(如果适用):

php
if ($user->onTrial())
{
	//
}

要确定用户是否曾经是活跃的订阅者,但已取消他们的订阅,可以使用 cancelled 方法:

php
if ($user->cancelled())
{
	//
}

你还可以确定用户是否取消了他们的订阅,但仍在“宽限期”内,直到订阅完全到期。例如,如果用户在 3 月 5 日取消了原定于 3 月 10 日结束的订阅,则用户在 3 月 10 日之前处于“宽限期”。请注意,在此期间,subscribed 方法仍返回 true

php
if ($user->onGracePeriod())
{
	//
}

everSubscribed 方法可用于确定用户是否曾经在你的应用程序中订阅过计划:

php
if ($user->everSubscribed())
{
	//
}

onPlan 方法可用于确定用户是否根据其 ID 订阅了给定计划:

php
if ($user->onPlan('monthly'))
{
	//
}

处理失败的付款

如果客户的信用卡过期怎么办?别担心 - Cashier 包含一个 Webhook 控制器,可以轻松为你取消客户的订阅。只需将路由指向控制器:

php
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 方法。

php
class WebhookController extends Laravel\Cashier\WebhookController {

	public function handleInvoicePaymentSucceeded($payload)
	{
		// 处理事件
	}

}
lightbulb

除了在你的数据库中更新订阅信息外,Webhook 控制器还将通过 Stripe API 取消订阅。

发票

你可以使用 invoices 方法轻松检索用户的发票数组:

php
$invoices = $user->invoices();

在列出客户的发票时,你可以使用这些辅助方法来显示相关的发票信息:

php
{{ $invoice->id }}

{{ $invoice->dateString() }}

{{ $invoice->dollars() }}

使用 downloadInvoice 方法生成发票的 PDF 下载。是的,真的这么简单:

php
return $user->downloadInvoice($invoice->id, [
	'vendor'  => '你的公司',
	'product' => '你的产品',
]);