Laravel Cashier

介绍

Laravel Cashier 提供语义化,流畅的接口和 Stripe 的订购管理服务连接。它几乎处理了所有复杂的订购管理相关逻辑。除了基本的订购管理外, Cashier 还可以处理折扣券,订购转换,管理订购「数量」、服务有效期限,甚至产生收据的 PDF 。

配置文件

Composer

首先,把 Cashier 扩展包加到 composer.json

"laravel/cashier": "~2.0"

服务提供者

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

迁移

使用 Cashier 前,我们需要增加几个字段到数据库。别担心,您可以使用 cashier:table Artisan 命令,建立迁移文件来新增必要字段。例如,要增加字段到 users 数据库表,使用 php artisan cashier:table users 。建立完迁移文件后,只要执行 migrate 命令即可。

设定模型

接下来,把 BillableTrait 和日期字段参数加到模型 (model) 里:

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 Key

最后,在起始文件里加入 Stripe key:

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 customer ID 和其他相关帐款信息更新到数据库。如果您的方案有在 Stripe 设定试用期,试用到期时间也会自动记录起来。

如果您的方案有试用期间,但是没有在 Stripe 里设定,您必须在订购后手动储存试用到期时间。

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

$user->save();

自定义额外用户详细数据

如果您想自定义额外的顾客详细数据,您可以将数组作为 create 方法的第二个参数传入:

$user->subscription('monthly')->create($creditCardToken, [
    'email' => $email, 'description' => 'Our First Customer'
]);

想知道更多 Stripe 支持的额外字段,请阅读 Stripe 的线上文件 建立客户.

免信用卡试用

如果您提供免信用卡试用服务,把 cardUpFront 属性设为 false

protected $cardUpFront = false;

建立帐号时,记得把试用到期时间记录起来:

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

$user->save();

订购转换

使用 swap 方法可以把用户转换到新的订购方案:

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

如果用户还在试用期间,试用服务会跟之前一样可用。如果订单有「数量限制」,也会和之前一样。

订购数量

有时候订购行为会跟「数量限制」有关。例如,您的应用程序可能会跟用户每个月收取 $10 元。您可以使用 incrementdecrement 方法简单的调整订购数量:

$user = User::find(1);

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

// Add five to the subscription's current quantity...
$user->subscription()->increment(5);

$user->subscription->decrement();

// Subtract five to the subscription's current quantity...
$user->subscription()->decrement(5);

取消订购

取消订购相当简单:

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

当客户取消订购时, Cashier 会自动更新数据库的 subscription_ends_at 字段。这个字段会被用来判断 subscribed 方法是否该回传 false 。例如,如果顾客在三月一号取消订购,但是服务可以使用到三月五号为止,那么 subscribed 方法在三月五号前都会传回 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())
{
    //
}

您可能想确认用户是否已经取消订单,但是服务还没有到期。例如,如果用户在三月五号取消了订购,但是服务会到三月十号才过期。那么用户到三月十号前都是有效期间。注意, 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)
    {
        // Handle The Event
    }

}

注意 除了更新您数据库里的订购信息以外, Webhook 控制器也可能会经由 Stripe API 取消您的订购。

收据

您可以很简单的经由 invoices 方法拿到客户的收据数组:

$invoices = $user->invoices();

您可以使用这些辅助方法,列出收据的相关信息给客户看:

{{ $invoice->id }}

{{ $invoice->dateString() }}

{{ $invoice->dollars() }}

使用 downloadInvoice 方法产生收据的 PDF 下载。看吧,它的调用是多么的简单:

return $user->downloadInvoice($invoice->id, [
    'vendor'  => 'Your Company',
    'product' => 'Your Product',
]);