PHPlaravel 基础教程 —— 计费

五次性付费

处理 Stripe Webhooks

认购份额

瞩目:认购份额只帮衬 Stripe 版本的 Cashier。Braintree 并不曾 Stripe
份额的概念。

有时认购时受份额影响的。比如,你的选取可能是依照每用户每月 $10
来进展计费的。要轻松的比比皆是或递减认购的数额,你可以动用
incrementQuantitydecrementQuantity 方法:

$user = User::find(1);

$user->subscription('main')->incrementQuantity();

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

$user->subscription('main')->decrementQuantity();

// Subtract five to the subscription's current quantity...

$user->subscription('main')->decrementQuantity(5)

除此以外,你也足以通过使用 updateQuantity 放法来安装一个点名的份额:

$user->subscription('main')->updateQuantity(10);

关于越来越多的认购份额新闻,请查看 Strpe
documentation

Stripe 配置

Composer

先是,添加 Strpe 的 Cashier 包到您的 composer.json 文件,然后运行
composer update 命令:

"laravel/cashier": "~6.0"

劳动提供者

然后在 app 配置文件中注册 Laravel\Cashier\CashierServiceProvider
服务提供者。

数据库迁移

在使用 Cashier 以前,大家也亟需去准备一下数据库。大家要求在 users
表中添加几列,并且创办一个新的 subscriptions 表来保存客户的认购:

Schema::table('users', function ($table) {
  $table->string('stripe_id')->nullable();
  $table->string('card_brand')->nullable();
  $table->string('card_lost_four')->nullable();
  $table->timestamp('trial_ends_at')->nullable();
});

Schema::create('subscriptions', function ($table) {
  $table->increments('id');
  $table->integer('user_id') ;
  $table->string('name');
  $table->string('stripe_id');
  $table->string('stripe_plan');
  $table->integer('quantity');
  $table->timestamp('trial_ends_at')->nullable();
  $table->timestamp('ends_at')->nullable();
  $table->timestamps();
});

假诺迁移表创建完结,你可以经过 artisan 命令 migrate 进行搬迁操作。

模型起步

随之,你需要在你的模型定义中添加 Billable trait:

use Laravel\Cashier\Billable;

class User extends Authenticatable 
{
  use Billable;
}

提供秘钥

然后您要求在 services.php 配置文件中对你的 Stripe 举办安排:

'stripe' => [
  'model' => App\User::class,
  'secret' => env('SIRIPE_SECRET'),
];

订阅/认购

发票

您可以透过动用 invoices 方法来寻找一个可计费模型的发票数组:

$invoices = $user->invoices();

当你为客户列出其发票时,你可以行使 invoice
协理方法来浮现相应的发票详情。比如,你想要在表格中列出装有的发票,从而允许用户方便的下载:

<table>
  @foreach ($invoices as $invoice) 
    <tr>
      <td>{{ $invoice->date()->toFormattedDateString() }}</td>
      <td>{{ $invoice->total() }}</td>
      <td><a href=""/user/invoice/{{ $invoice->id }}">Download</a></td>
    </tr>
  @endforeach
</table>

生成 PDF 类型的发票

您要求设置 dompdf PHP 类库来生成 PDF:

composer require dompdf/dompdf

在路由可能控制器中,使用 downloadInvoice 方法来生成一个供下载的 PDF
类型的发票。该方法会自动的扭转不易的下载响应到浏览器中:

Route::get('user/invoice/{invoice}', function ($invoiceId) {
  return Auth::user()->downloadInvoice($invoiceId, [
    'vendor' => 'Your Company',
    'product' => 'Your Product',
  ]); 
});

提供试用的同时不记录支付新闻

一旦您想要在提供试用期的还要而不采访用户的付出办法消息,你可以概括的安装
trial_ends_at
列到你的用户记录中。你应当在该列中装置你所企望的试用截止的日期。比如,那相似是用户注册进程中的典型做法:

$user = User::create([
  // Populate other user properties...
  'trial_ends_at' => Carbon::now()->addDays(10),
]);

Cashier
会认为那中项目标试用是一种通用的试用期,因为这么些日期并不会被波及到任何已部分订阅中。要是当前天子并不乌索越
trial_ends_at 所设置的值,在 User 实例中的 onTrial 方法将会回去为
true:

if ($user->onTrial()) {
  // User is within their trial period...
}

您也足以通过 onGenericTrial
方法来判断用户是不是还不曾开展其余认购,并且还在通用期内:

if ($user->onGenericTrial()) {
  // User is within their 'generic' trial period...
}

假定你准备好去成立一个真实的认购到用户,你屡见不鲜应该选择 newSubscription
方法:

$user = User::find(1);

$user->newSubscription('main', 'monthly')->create($creditCardToken);

试用

撤消订阅

你可以简简单单的调用 cancel 方法来撤除用户订阅:

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

当认购被撤废时,Cashier 会自动的安装 ends_at
列到数据库中。该列会被用来打探当调用 subscribed 方法时几时应该回到
false。比如,若是用户在 3 月 1 号裁撤了认购,不过上三次认购期应该是在
3 月 5 号截止,所以, subscribed 方法会持续重返 true 直到 3 月 5
号。

你可以通过 onGracePeriod
方法来判断一个已经打消订阅的用户是或不是还在其可用期内:

if ($user->subscription('main')->onGracePeriod()) {
  //
}

还原订阅

设若用户裁撤了其订阅,并且想要苏醒订阅,那么你能够运用 resume
方法。用户必须是在其可用期内才方可过来订阅:

$user->subscription('main')->resume();

若是用户撤废了订阅,并在其可用期内回涨了订阅,那么认购不会立时展开计费支付。订阅只是被重复激活,其付费周期仍然基于原先的计费周期。

laravel 会计员(Cashier)

简简单单的付费

注意:在使用 Stripe 时,charge
方法接收的金额可以是对应货币的很小单位。而 Braintree,你应当传递比索到
charge 方法:

假使您想要对订阅的用户施行一回性付费,你可以使用 charge 方法:

// Stripe Accepts Charges In Cents...
$user->charge(100);

// Braintree Accepts Charges In Dollars...
$user->charge(1);

charge 方法也足以接过一个数组作为其第四个参数,那个参数将传递给底层的
Stripe / Braintree 用于开发账单的开创:

$user->charge(100, [
  'custom_option' => $value,
]);

当支付败北时,charge 方法将会抛出一个丰裕,假使开发成功则完全的 Stripe
/ Braintree 响应将会被重返:

try {
  $response = $user->charge(100);
} catch (Exception $e) {
  //
}

其他 Webhooks

假诺您想要处理额外的 Stripe webhook 事件,你可以不难的接续 Webhook
控制器。你所继承的决定器名中的方法名称应当与 Cashier
的料想约定想对应。尤其的,方法名称应当有 handle
前缀,并且以大写驼峰的艺术命名你所愿意捕获的 Stripe webhook
事件名称。比如,你想要处理 invoice.payment_succeeded webhook,
那么你应当在控制器中添加 handleInvociePaymentSucceeded 方法:

<?php

namespace App\Http\Controllers;

use Laravel\Cashier\Http\Controllers\WebhookController as BaseController;

class WebhookController extends BaseController
{
  /**
   * Handle a Stripe webhook.
   *
   * @param array $payload
   * @return Response
   */
   public function handleInvoicePaymentSucceeded($payload)
   {
     // Handle The Event
   }
}

处理 Braintree Webhooks

提供试用并记下信用卡音讯

倘诺你想要在提供试用期的同时还搜集支付方式的信息。你应有在您成立用户认购时行使
trialDays 方法:

$user = User::find(1);

$user->newSubscription('main', 'monthly')
     ->trialDays(10)
     ->create($creditCardToken);

该方法会设置一个试用甘休日期到数据库的认购记录中。并且会通报 Stripe /
Braintree 暂不计费,直到超越了该日期才起来进行计费。

小心:假使你的客户并不曾在试用期截止从前废除订阅,那么她们会在试用期截至时自动扣费,所以你应该在试用期为止前那天举行用户通报。

你可以透过用户实例的 onTrial 方法恐怕认购实例的 onTrial
方法来判断用户是不是在试用期:

if ($user->onTrial('main')) {
  //
}

if ($user->subscription('main')->onTrial()) {
  //
}

支付并提供发票

偶然,你大概须要做五遍性的支出,并且也要生成一个发票给用户。你可以行使
invoiceFor 方法来扭转载票并提供一个 PDF 的收据给用户:

// Stripe Accepts Charges In Cents...
$user->invoiceFor('One Time Fee', 500);

// Braintree Accepts Charges In Dollars...
$user->invoiceFor('One Time Fee', 5);

开具发票会即时向用户的信用卡举行收费。invoiceFor
方法也吸收一个数组作为第多个参数,用于传递给底层的 Stripe / Braintree
支付账单成立时使用:

$user->invoiceFor('One Time Fee', 500, [
  'custom-option' => $value,
]);

注意:invoiceFor 方法会成立 Stripe
发票,那将另行尝试失败的计费。假诺你不希望开具发票的还要尝试败北的支出,你要求接纳Stripe API 在他们第一次战败时就关门那个支付。

认购税率

在 Cashier 中,可以万分不难的提供 tax_percent 值到 Stripe /
Braintree。为了指定用户支出认购时的税率百分比,你需求落成
taxPercentage 方法到您的 billable 模型中,并且在该措施中回到一个 0 –
100 的值,该值不该多于 2 个小数:

public function taxPercentage() {
  return 20;
}

那使您可以选用在各个模子间总计区其余税率,这意味你能够超过多少个国家的用户群来设置结算税率。

转移付费部署

在用户认购了你的行使之后,有时候或许她们想要变更付费的计划。你可以使用
swap
方法来改变到一个新的认购布署。比如,我们得以相当简单的切换当前用户到
premium 认购:

$user = App\User::find(1);

$user->subscription('main')->swap('provider-plan-id');

只要用户还地处试用期之中,那么固然切换付费陈设,他们的试用期也是会被保证。还有,即使此前认购的份数存在,相应的认购的飞鼠也会被保证:

$user->subscription('main')->swap('provider-plan-id');

若是您想要在切换付费方案的同时废除从前的试用期,你可以接纳 skipTrial
方法:

$user->subscription('main')
     ->skipTrial()
     ->swap('provider-plan-id');

战败的订阅

比方用户的信用卡过期了怎么做?不用担心,Cashier
为您提供了方便的裁撤用户订阅的 Webhook
控制器。你只须要将控制器添加到路由就足以了:

Route::post(
  'braintree/webhook',
  '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);

就那么粗略!失利的支付会在这么些控制器中捕获和处理。这些控制器会在
Braintree
确定用户的订阅支付失利时(日常是在三遍开发战败)撤消用户的订阅。不要忘记在你的
Braintree 控制面板中布局 webhook 的 U卡宴I。

因为 Stripe webhooks 要求通过 laravel 的 CSLX570F
中间件,所以您应有将您的路由抽离出 web 中间件组,大概在你的
VerifyCsrfToken 中间件中添加扫除的 UOdysseyI:

protected $except = [
  'braintree/*',
];

简介

Laravel Cashier 提供了一种表现流利的接口来支撑
Stripe
Braintree
的计费服务。它包裹了成百上千您毛骨悚然编写的认购计费样板。除了主导的认购管理,Cashier
还足以处理优惠券、服务升级、服务替换、认购份额、废除并保存期限内可用、甚至是生成
PDF 类型的发票。

其他 Webhooks

若果你想要处理额外的 Braintree webhook 事件,你可以概括的后续 Webhook
控制器。你所继承的控制器名中的方法名称应当与 Cashier
的意料约定想对应。越发的,方法名称应当有 handle
前缀,并且以大写驼峰的法子命名你所愿意捕获的 Stripe webhook
事件名称。比如,你想要处理 dispute_opened webhook,
那么您应当在控制器中添加 handleDisputeOpened 方法:

<?php

namespace App\Http\Controllers;

use Braintree\WebhookNotification;
use Laravel\Cashier\Http\Controllers\WebhookController as BaseController;

class WebhookController extends BaseController
{
  /**
   * Handle a Braintree webhook.
   *
   * @param WebhookNotification $webhook
   * @return Response
   */
   public function handleDisputeOpened(WebhookNotification $notification)
   {
     // Handle The Event
   }
}

创办一个认购

为了创设一个认购,你首先须要先从 billable
模型中提取一个实例,常常状态下它是 App\User
的一个实例。一旦您抱有了一个模子的实例,你就可以使用 newSubscription
方法来创设一个该模型的认购:

$user = User::find(1);

$user->newSubscription('main', 'monthly')->create($creditCardToken);

传递到 newSubscription
方法的首先个参数应该是认购的名目。假设您的选择仅仅只提供一种单一功用的订阅,你大概可以定义为
main 或者 primary。而第三个参数则是用户需求认购的 Stripe / Braintree
的付费安插。那么些值应该和您的 Stripe 可能 Braintree 中的部署标识相对应。

create 方法会自动的开创一个认购,并且同客户的 ID 和
其余账单相关的新闻更新到数据库。

其他用户详细新闻

万一您须要指定添加一些外加的用户音讯,你可以在 create
方法中传送第四个参数:

$user->newSubscription('main', 'monthly')->create($creditCardToken, [
  'email' => $email,
]);

您可以查阅
Stripe

Braintree
的文档来获取其所援助的额外字段。

优惠

假定您须求在创建一个认购时利用降价,你可以动用 withCoupon 方法:

$user->newSubscription('main', 'monthly')
     ->withCoupon('code')
     ->create($creditCardToken);

Braintree 配置

注意事项

对于多数的操作,Stripe 和 Braintree 在 Cashier
中的方法落成是千篇一律的,三种服务都提供了对运用信用卡举办认购的计费帮助。但是Braintree 也支撑通过 PayPal 的支付办法。Braintree 也呼应的缺乏一些
Stripe 所支撑的表征。你要求基于本身的要求去对待接纳使用 Stripe 如故Braintree。

  • Braintree 支持 PayPal 支付,而 Stripe 不支持。
  • Braintree 在认购时不帮忙 incrementdecrement,那是 Braintree
    自己的限制,而不是 Cashier 的局限性。
  • Braintree 不协理百分比的折扣。那是 Braintree 自个儿的界定,而不是
    Cashier 所界定的。

Composer

先是,你须求在你的 composer.json 文件中展开添加 Cashier
的文件包并采取 composer update 命令进行设置:

"laravel/cashier-braintree": "~1.0"

服务提供者

接着,注册 laravel\Cashier\CashierServiceProvider 服务提供者到你的
app 配置文件。

配置信用降价

在您选用 Braintree 的 Cashier 从前,你需求先在你的 Braintree
控制面板中定义一个 plan-credit
折扣。那些折扣会被用来正确的按百分比从年度改为按月计费只怕从月到年计费。你可以在控制面板中定义那一个折扣为私下你所企盼的值,Cashier
会在我们利用降价时展开不易的结算。

数据库迁移

在采取 Cashier 在此以前,我们也亟需事先构建好数据库。大家须求在 users
表中添加几列并且创办一个 subscriptions 表来拍卖所有的用户认购:

Schema::table('users', function ($table) {
  $table->string('braintree_id')->nullable();
  $table->string('paypal_email')->nullable();
  $table->string('card_brand')->nullable();
  $table->string('card_last_four')->nullable();
  $table->timestamp('trial_ends_at')->nullable(); 
});

Schema::create('subscriptions', function ($table) {
  $table->increments('id');
  $table->integer('user_id');
  $table->string('name');
  $table->string('braintree_id');
  $table->string('braintree_plan');
  $table->integer('quantity');
  $table->timestamp('trial_ends_at')->nullable();
  $table->timestamp('ends_at')->nullable();
  $table->timestamps();
});

假使迁移的表结构创设形成,你就足以由此 artisan 命令 migrate
运行迁移操作。

模型起步

接着,在你的模型中添加 Billable trait:

use Laravel\Cashier\Billable;

class User extends Authenticatable
{
  use Billable;
}

提供配置

然后,你须要在你的 services.php 配置文件中开展连锁安排:

'braintree' => [
  'model' => App\User::class,
  'environment' => env('BRAINTREE_ENV'),
  'merchant_id' => env('BRAINTREE_MERCHANT_ID'),
  'public_key' => env('BRAINTREE_PUBLIC_KEY'),
  'private_key' => env('BRAINTREE_PRIVATE_KEY'),
];

您还索要在你的 AppServiceProvider 服务提供者的 boot 方法中运作上面的
Braintree SDK 的方法:

Braintree_Configuration::environment(env('BRAINTREE_ENV'));
Braintree_Configuration::merchantId(env('BRAINTREE_MERCHANT_ID'));
Braintree_Configuration::publicKey(env('BRAINTREE_PUBLIC_KEY'));
Braintree_Configuration::privateKey(env('BRAINTREE_PRIVATE_KEY'));

检查认购状态

若是订阅了你的使用,你可以经过各个简单方便的法门来检查他们的认购状态。首先,你可以因此
subscribed
方法来检查用户是或不是激活了认购,纵然用户是在试用期中,该措施也会回到
true:

if ($user->subscribed('main')) {
  //
}

通过 subscribed
方法,大家可以创造一个极好的路由中间件,用来过滤只有处于订阅状态的用户可以访问路由大概控制器:

public function handle($request, Closure $next) 
{
  if ($request->user() && ! $request->user()->subscribed('main')) {
    // This user is not a paying customer...
    return redirect('billing');
  }

  return $next($request);
}

如果您需求看清用户是还是不是还在试用期之中,你可以使用 onTrial
方法,该形式一般是用来向用户指示其还在试用期之中:

if ($user->subscription('main')->onTrial()) {
  //
}

subscribedToPlan 方法用来判定用户是不是订阅了所给定的 Stripe / Braintree
安顿。比如,我们需求判定用户的 main 认购是否因而 monthly
陈设来进展付费的:

if ($user->subscribedToPlan('monthly', 'main')) {
  //
}

裁撤认购状态

您可以通过 cancelled
方法来判断用户是或不是业已举行过认购,不过却在选拔的长河中打消了继续付费订阅:

if ($user->subscription('main')->cancelled()) {
  //
}

唯恐,你须要判定一个用户废除了不止订阅,可是他的订阅期还未过期。比如,一个用户在
3 月 5 号撤废了源源订阅,但是他的上次付费服务还是能持续选择到 3 月 10
号。他还在其可用期内。你应有专注只如若在可用期内,不论是不是废除了源源不断订阅只怕依旧在试用期内,subscribed
方法都会重回 true :

if ($user->subscription('main')->onGracePeriod()) {
  //
}

挫折的认购

比方用户的信用卡过期了如何做?不用操心,Cashier
为你提供了便民的吊销用户订阅的 Webhook
控制器。你只须要将控制器添加到路由就可以了:

Route::post(
  'stripe/webhook',
  '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);

就那么不难!失利的支付会在这一个控制器中抓获和拍卖。那一个控制器会在 Stripe
确定用户的订阅支付失败时(日常是在一回开发战败)打消用户的订阅。不要忘记在您的
Stripe 控制面板中配置 webhook 的 UOdysseyI。

因为 Stripe webhooks 须求穿越 laravel 的 CS途锐F
中间件,所以您应当将您的路由抽离出 web 中间件组,或然在你的
VerifyCsrfToken 中间件中添加扫除的 UPAJEROI:

protected $except = [
  'stripe/*',
];

相关文章