laravel 會(huì)計(jì)員(Cashier)
簡(jiǎn)介
Laravel Cashier 提供了一種表現(xiàn)流利的接口來(lái)支持 Stripe 和 Braintree 的計(jì)費(fèi)服務(wù)。它封裝了許多你畏懼編寫(xiě)的認(rèn)購(gòu)計(jì)費(fèi)樣板血公。除了基本的認(rèn)購(gòu)管理,Cashier 還可以處理優(yōu)惠券煞赢、服務(wù)升級(jí)以故、服務(wù)替換屯耸、認(rèn)購(gòu)份額、取消并保留期限內(nèi)可用送丰、甚至是生成 PDF 類(lèi)型的發(fā)票缔俄。
Stripe 配置
Composer
首先,添加 Strpe 的 Cashier 包到你的 composer.json
文件器躏,然后運(yùn)行 composer update
命令:
"laravel/cashier": "~6.0"
服務(wù)提供者
然后在 app
配置文件中注冊(cè) Laravel\Cashier\CashierServiceProvider
服務(wù)提供者俐载。
數(shù)據(jù)庫(kù)遷移
在使用 Cashier 之前,我們也需要去準(zhǔn)備一下數(shù)據(jù)庫(kù)登失。我們需要在 users
表中添加幾列遏佣,并且創(chuàng)建一個(gè)新的 subscriptions
表來(lái)保留客戶(hù)的認(rèn)購(gòu):
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();
});
一旦遷移表創(chuàng)建完畢,你可以通過(guò) artisan 命令 migrate
進(jìn)行遷移操作壁畸。
模型起步
接著贼急,你需要在你的模型定義中添加 Billable
trait:
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}
提供秘鑰
然后你需要在 services.php
配置文件中對(duì)你的 Stripe 進(jìn)行配置:
'stripe' => [
'model' => App\User::class,
'secret' => env('SIRIPE_SECRET'),
];
Braintree 配置
注意事項(xiàng)
對(duì)于大多數(shù)的操作茅茂,Stripe 和 Braintree 在 Cashier 中的方法實(shí)現(xiàn)是相同的,兩種服務(wù)都提供了對(duì)使用信用卡進(jìn)行認(rèn)購(gòu)的計(jì)費(fèi)支持太抓。但是 Braintree 也支持通過(guò) PayPal 的支付方式空闲。Braintree 也相應(yīng)的缺乏一些 Stripe 所支持的特性。你需要根據(jù)自身的需求去對(duì)比選擇使用 Stripe 還是 Braintree走敌。
- Braintree 支持 PayPal 支付碴倾,而 Stripe 不支持。
- Braintree 在認(rèn)購(gòu)時(shí)不支持
increment
和decrement
掉丽,這是 Braintree 自身的限制跌榔,而不是 Cashier 的局限性。 - Braintree 不支持百分比的折扣捶障。這是 Braintree 自身的限制僧须,而不是 Cashier 所限制的。
Composer
首先项炼,你需要在你的 composer.json
文件中進(jìn)行添加 Cashier
的文件包并使用 composer update
命令進(jìn)行安裝:
"laravel/cashier-braintree": "~1.0"
服務(wù)提供者
接著担平,注冊(cè) laravel\Cashier\CashierServiceProvider
服務(wù)提供者到你的 app
配置文件。
安排信用優(yōu)惠
在你使用 Braintree 的 Cashier 之前锭部,你需要先在你的 Braintree 控制面板中定義一個(gè) plan-credit
折扣暂论。這個(gè)折扣會(huì)被用于正確的按比例從年度改為按月計(jì)費(fèi)或者從月到年計(jì)費(fèi)。你可以在控制面板中定義這個(gè)折扣為任意你所希望的值拌禾,Cashier 會(huì)在我們使用優(yōu)惠時(shí)進(jìn)行正確的結(jié)算取胎。
數(shù)據(jù)庫(kù)遷移
在使用 Cashier 之前,我們也需要預(yù)先構(gòu)建好數(shù)據(jù)庫(kù)湃窍。我們需要在 users
表中添加幾列并且創(chuàng)建一個(gè) subscriptions
表來(lái)處理所有的用戶(hù)認(rèn)購(gòu):
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();
});
一旦遷移的表結(jié)構(gòu)構(gòu)建完成闻蛀,你就可以通過(guò) artisan 命令 migrate
運(yùn)行遷移操作。
模型起步
接著坝咐,在你的模型中添加 Billable
trait:
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}
提供配置
然后循榆,你需要在你的 services.php
配置文件中進(jìn)行相關(guān)配置:
'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
服務(wù)提供者的 boot
方法中運(yùn)行下面的 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'));
訂閱/認(rèn)購(gòu)
創(chuàng)建一個(gè)認(rèn)購(gòu)
為了創(chuàng)建一個(gè)認(rèn)購(gòu),你首先需要先從 billable 模型中提取一個(gè)實(shí)例墨坚,通常情況下它是 App\User
的一個(gè)實(shí)例。一旦你擁有了一個(gè)模型的實(shí)例映挂,你就可以使用 newSubscription
方法來(lái)創(chuàng)建一個(gè)該模型的認(rèn)購(gòu):
$user = User::find(1);
$user->newSubscription('main', 'monthly')->create($creditCardToken);
傳遞到 newSubscription
方法的第一個(gè)參數(shù)應(yīng)該是認(rèn)購(gòu)的名稱(chēng)泽篮。如果你的應(yīng)用僅僅只提供一種單一功能的訂閱,你或許可以定義為 main
或者 primary
柑船。而第二個(gè)參數(shù)則是用戶(hù)需要認(rèn)購(gòu)的 Stripe / Braintree 的付費(fèi)計(jì)劃帽撑。這個(gè)值應(yīng)該和你的 Stripe 或者 Braintree 中的計(jì)劃標(biāo)識(shí)相對(duì)應(yīng)。
create
方法會(huì)自動(dòng)的創(chuàng)建一個(gè)認(rèn)購(gòu)鞍时,并且同客戶(hù)的 ID 和 其他賬單相關(guān)的信息更新到數(shù)據(jù)庫(kù)亏拉。
其他用戶(hù)詳細(xì)信息
如果你需要指定添加一些額外的用戶(hù)信息扣蜻,你可以在 create
方法中傳遞第二個(gè)參數(shù):
$user->newSubscription('main', 'monthly')->create($creditCardToken, [
'email' => $email,
]);
你可以查看 Stripe 和 Braintree 的文檔來(lái)獲取其所支持的額外字段。
優(yōu)惠
如果你需要在創(chuàng)建一個(gè)認(rèn)購(gòu)時(shí)使用優(yōu)惠及塘,你可以使用 withCoupon
方法:
$user->newSubscription('main', 'monthly')
->withCoupon('code')
->create($creditCardToken);
檢查認(rèn)購(gòu)狀態(tài)
一旦訂閱了你的應(yīng)用莽使,你可以通過(guò)各種簡(jiǎn)單方便的方法來(lái)檢查他們的認(rèn)購(gòu)狀態(tài)。首先笙僚,你可以通過(guò) subscribed
方法來(lái)檢查用戶(hù)是否激活了認(rèn)購(gòu)芳肌,即使用戶(hù)是在試用期中,該方法也會(huì)返回 true
:
if ($user->subscribed('main')) {
//
}
通過(guò) subscribed
方法肋层,我們可以創(chuàng)建一個(gè)極好的路由中間件亿笤,用來(lái)過(guò)濾只有處于訂閱狀態(tài)的用戶(hù)可以訪問(wèn)路由或者控制器:
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);
}
如果你需要判斷用戶(hù)是不是還在試用期之中,你可以使用 onTrial
方法栋猖,該方法通常是用來(lái)向用戶(hù)提醒其還在試用期之中:
if ($user->subscription('main')->onTrial()) {
//
}
subscribedToPlan
方法用來(lái)判斷用戶(hù)是否訂閱了所給定的 Stripe / Braintree 計(jì)劃净薛。比如,我們需要判斷用戶(hù)的 main
認(rèn)購(gòu)是不是通過(guò) monthly
計(jì)劃來(lái)進(jìn)行付費(fèi)的:
if ($user->subscribedToPlan('monthly', 'main')) {
//
}
取消認(rèn)購(gòu)狀態(tài)
你可以通過(guò) cancelled
方法來(lái)判斷用戶(hù)是否曾經(jīng)進(jìn)行過(guò)認(rèn)購(gòu)蒲拉,但是卻在使用的過(guò)程中取消了繼續(xù)付費(fèi)訂閱:
if ($user->subscription('main')->cancelled()) {
//
}
或許罕拂,你需要判斷一個(gè)用戶(hù)取消了持續(xù)訂閱,但是他的訂閱期還未過(guò)期全陨。比如爆班,一個(gè)用戶(hù)在 3 月 5 號(hào)取消了持續(xù)訂閱,但是他的上次付費(fèi)服務(wù)還可以繼續(xù)使用到 3 月 10 號(hào)辱姨。他還在其可用期內(nèi)柿菩。你應(yīng)該注意只要是在可用期內(nèi),不論是否取消了持續(xù)訂閱或者還是在試用期內(nèi)雨涛,subscribed
方法都會(huì)返回 true
:
if ($user->subscription('main')->onGracePeriod()) {
//
}
改變付費(fèi)計(jì)劃
在用戶(hù)認(rèn)購(gòu)了你的應(yīng)用之后枢舶,有時(shí)候或許他們想要變更付費(fèi)的計(jì)劃。你可以使用 swap
方法來(lái)變更到一個(gè)新的認(rèn)購(gòu)計(jì)劃替久。比如凉泄,我們可以非常簡(jiǎn)單的切換當(dāng)前用戶(hù)到 premium
認(rèn)購(gòu):
$user = App\User::find(1);
$user->subscription('main')->swap('provider-plan-id');
如果用戶(hù)還處于試用期之中,那么即使切換付費(fèi)計(jì)劃蚯根,他們的試用期也是會(huì)被保持后众。還有,如果之前認(rèn)購(gòu)的份數(shù)存在颅拦,相應(yīng)的認(rèn)購(gòu)的飛鼠也會(huì)被保持:
$user->subscription('main')->swap('provider-plan-id');
如果你想要在切換付費(fèi)方案的同時(shí)取消之前的試用期蒂誉,你可以使用 skipTrial
方法:
$user->subscription('main')
->skipTrial()
->swap('provider-plan-id');
認(rèn)購(gòu)份額
注意:認(rèn)購(gòu)份額只支持 Stripe 版本的 Cashier。Braintree 并沒(méi)有 Stripe 份額的概念距帅。
有時(shí)候認(rèn)購(gòu)時(shí)受份額影響的右锨。比如,你的應(yīng)用可能是按照每用戶(hù)每月 $10 來(lái)進(jìn)行計(jì)費(fèi)的碌秸。要輕松的遞增或遞減認(rèn)購(gòu)的數(shù)量绍移,你可以使用 incrementQuantity
和 decrementQuantity
方法:
$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)
另外悄窃,你也可以通過(guò)使用 updateQuantity
放法來(lái)設(shè)置一個(gè)指定的份額:
$user->subscription('main')->updateQuantity(10);
關(guān)于更多的認(rèn)購(gòu)份額信息,請(qǐng)查看 Strpe documentation蹂窖。
認(rèn)購(gòu)稅率
在 Cashier 中轧抗,可以非常簡(jiǎn)單的提供 tax_percent
值到 Stripe / Braintree。為了指定用戶(hù)支付認(rèn)購(gòu)時(shí)的稅率百分比恼策,你需要實(shí)現(xiàn) taxPercentage
方法到你的 billable 模型中鸦致,并且在該方法中返回一個(gè) 0 - 100 的值,該值不應(yīng)該多于 2 個(gè)小數(shù):
public function taxPercentage() {
return 20;
}
這使你可以應(yīng)用在多種模型間計(jì)算不同的稅率,這意味著你可以跨越多個(gè)國(guó)家的用戶(hù)群來(lái)設(shè)置結(jié)算稅率涣楷。
取消訂閱
你可以簡(jiǎn)單的調(diào)用 cancel
方法來(lái)取消用戶(hù)訂閱:
$user->subscription('main')->cancel();
當(dāng)認(rèn)購(gòu)被取消時(shí)分唾,Cashier 會(huì)自動(dòng)的設(shè)置 ends_at
列到數(shù)據(jù)庫(kù)中。該列會(huì)被用來(lái)了解當(dāng)調(diào)用 subscribed
方法時(shí)何時(shí)應(yīng)該返回 false
狮斗。比如绽乔,如果用戶(hù)在 3 月 1 號(hào)取消了認(rèn)購(gòu),但是上一次認(rèn)購(gòu)期應(yīng)該是在 3 月 5 號(hào)結(jié)束碳褒,所以折砸, subscribed
方法會(huì)持續(xù)返回 true
直到 3 月 5 號(hào)。
你可以通過(guò) onGracePeriod
方法來(lái)判斷一個(gè)已經(jīng)取消訂閱的用戶(hù)是否還在其可用期內(nèi):
if ($user->subscription('main')->onGracePeriod()) {
//
}
恢復(fù)訂閱
如果用戶(hù)取消了其訂閱沙峻,并且想要恢復(fù)訂閱睦授,那么你可以使用 resume
方法。用戶(hù)必須是在其可用期內(nèi)才可以恢復(fù)訂閱:
$user->subscription('main')->resume();
如果用戶(hù)取消了訂閱摔寨,并在其可用期內(nèi)恢復(fù)了訂閱去枷,那么認(rèn)購(gòu)不會(huì)立即進(jìn)行計(jì)費(fèi)支付。訂閱只是被重新激活是复,其付費(fèi)周期還是基于原先的計(jì)費(fèi)周期删顶。
試用
提供試用并記錄信用卡信息
如果你想要在提供試用期的同時(shí)還收集支付方式的信息。你應(yīng)該在你創(chuàng)建用戶(hù)認(rèn)購(gòu)時(shí)使用 trialDays
方法:
$user = User::find(1);
$user->newSubscription('main', 'monthly')
->trialDays(10)
->create($creditCardToken);
該方法會(huì)設(shè)置一個(gè)試用結(jié)束日期到數(shù)據(jù)庫(kù)的認(rèn)購(gòu)記錄中淑廊。并且會(huì)通知 Stripe / Braintree 暫不計(jì)費(fèi)逗余,直到超過(guò)了該日期才開(kāi)始進(jìn)行計(jì)費(fèi)。
注意:如果你的客戶(hù)并沒(méi)有在試用期結(jié)束之前取消訂閱季惩,那么他們會(huì)在試用期結(jié)束時(shí)自動(dòng)扣費(fèi)录粱,所以你應(yīng)該在試用期結(jié)束前那天進(jìn)行用戶(hù)通知。
你可以通過(guò)用戶(hù)實(shí)例的 onTrial
方法或者認(rèn)購(gòu)實(shí)例的 onTrial
方法來(lái)判斷用戶(hù)是否在試用期:
if ($user->onTrial('main')) {
//
}
if ($user->subscription('main')->onTrial()) {
//
}
提供試用的同時(shí)不記錄支付信息
如果你想要在提供試用期的同時(shí)而不收集用戶(hù)的支付方法信息蜀备,你可以簡(jiǎn)單的設(shè)置 trial_ends_at
列到你的用戶(hù)記錄中关摇。你應(yīng)該在該列中設(shè)置你所期望的試用結(jié)束的日期。比如碾阁,這一般是用戶(hù)注冊(cè)過(guò)程中的典型做法:
$user = User::create([
// Populate other user properties...
'trial_ends_at' => Carbon::now()->addDays(10),
]);
Cashier 會(huì)認(rèn)為這中類(lèi)型的試用是一種通用的試用期,因?yàn)檫@個(gè)日期并不會(huì)被關(guān)聯(lián)到任何已有的訂閱中些楣。如果當(dāng)前日期并沒(méi)有超過(guò) trial_ends_at
所設(shè)置的值脂凶,在 User
實(shí)例中的 onTrial
方法將會(huì)返回為 true
:
if ($user->onTrial()) {
// User is within their trial period...
}
你也可以通過(guò) onGenericTrial
方法來(lái)判斷用戶(hù)是否還沒(méi)有進(jìn)行任何認(rèn)購(gòu)宪睹,并且還在通用期內(nèi):
if ($user->onGenericTrial()) {
// User is within their 'generic' trial period...
}
一旦你準(zhǔn)備好去創(chuàng)建一個(gè)真實(shí)的認(rèn)購(gòu)到用戶(hù),你通常應(yīng)該使用 newSubscription
方法:
$user = User::find(1);
$user->newSubscription('main', 'monthly')->create($creditCardToken);
處理 Stripe Webhooks
失敗的認(rèn)購(gòu)
如果用戶(hù)的信用卡過(guò)期了怎么辦蚕钦?不用擔(dān)心亭病,Cashier 為你提供了便捷的取消用戶(hù)訂閱的 Webhook 控制器。你只需要將控制器添加到路由就可以了:
Route::post(
'stripe/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
就那么簡(jiǎn)單嘶居!失敗的支付會(huì)在這個(gè)控制器中捕獲和處理罪帖。這個(gè)控制器會(huì)在 Stripe 確定用戶(hù)的訂閱支付失敗時(shí)(通常是在三次支付失敗)取消用戶(hù)的訂閱邮屁。不要忘記在你的 Stripe 控制面板中配置 webhook 的 URI整袁。
因?yàn)?Stripe webhooks 需要穿過(guò) laravel 的 CSRF 中間件,所以你應(yīng)該將你的路由抽離出 web
中間件組佑吝,或者在你的 VerifyCsrfToken
中間件中添加排除的 URI:
protected $except = [
'stripe/*',
];
其他 Webhooks
如果你想要處理額外的 Stripe webhook 事件坐昙,你可以簡(jiǎn)單的繼承 Webhook 控制器。你所繼承的控制器名中的方法名稱(chēng)應(yīng)該與 Cashier 的預(yù)期約定想對(duì)應(yīng)芋忿。特別的炸客,方法名稱(chēng)應(yīng)該有 handle
前綴,并且以大寫(xiě)駝峰的方式命名你所期望捕獲的 Stripe webhook 事件名稱(chēng)戈钢。比如痹仙,你想要處理 invoice.payment_succeeded
webhook, 那么你應(yīng)該在控制器中添加 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
失敗的訂閱
如果用戶(hù)的信用卡過(guò)期了怎么辦?不用擔(dān)心殉了,Cashier 為你提供了便捷的取消用戶(hù)訂閱的 Webhook 控制器开仰。你只需要將控制器添加到路由就可以了:
Route::post(
'braintree/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
就那么簡(jiǎn)單!失敗的支付會(huì)在這個(gè)控制器中捕獲和處理宣渗。這個(gè)控制器會(huì)在 Braintree 確定用戶(hù)的訂閱支付失敗時(shí)(通常是在三次支付失敹端)取消用戶(hù)的訂閱。不要忘記在你的 Braintree 控制面板中配置 webhook 的 URI痕囱。
因?yàn)?Stripe webhooks 需要穿過(guò) laravel 的 CSRF 中間件田轧,所以你應(yīng)該將你的路由抽離出 web
中間件組,或者在你的 VerifyCsrfToken
中間件中添加排除的 URI:
protected $except = [
'braintree/*',
];
其他 Webhooks
如果你想要處理額外的 Braintree webhook 事件鞍恢,你可以簡(jiǎn)單的繼承 Webhook 控制器傻粘。你所繼承的控制器名中的方法名稱(chēng)應(yīng)該與 Cashier 的預(yù)期約定想對(duì)應(yīng)。特別的帮掉,方法名稱(chēng)應(yīng)該有 handle
前綴弦悉,并且以大寫(xiě)駝峰的方式命名你所期望捕獲的 Stripe webhook 事件名稱(chēng)。比如蟆炊,你想要處理 dispute_opened
webhook, 那么你應(yīng)該在控制器中添加 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
}
}
一次性付費(fèi)
簡(jiǎn)單的付費(fèi)
注意:在使用 Stripe 時(shí)稽莉,
charge
方法接收的金額可以是相應(yīng)貨幣的最小單位。而 Braintree涩搓,你應(yīng)該傳遞美元到charge
方法:
如果你想要對(duì)訂閱的用戶(hù)施行一次性付費(fèi)污秆,你可以使用 charge
方法:
// Stripe Accepts Charges In Cents...
$user->charge(100);
// Braintree Accepts Charges In Dollars...
$user->charge(1);
charge
方法也可以接收一個(gè)數(shù)組作為其第二個(gè)參數(shù)劈猪,這個(gè)參數(shù)將傳遞給底層的 Stripe / Braintree 用于支付賬單的創(chuàng)建:
$user->charge(100, [
'custom_option' => $value,
]);
當(dāng)支付失敗時(shí),charge
方法將會(huì)拋出一個(gè)異常良拼,如果支付成功則完整的 Stripe / Braintree 響應(yīng)將會(huì)被返回:
try {
$response = $user->charge(100);
} catch (Exception $e) {
//
}
支付并提供發(fā)票
有時(shí)候战得,你可能需要做一次性的支付,并且也要生成一個(gè)發(fā)票給用戶(hù)庸推。你可以使用 invoiceFor
方法來(lái)生成發(fā)票并提供一個(gè) PDF 的收據(jù)給用戶(hù):
// Stripe Accepts Charges In Cents...
$user->invoiceFor('One Time Fee', 500);
// Braintree Accepts Charges In Dollars...
$user->invoiceFor('One Time Fee', 5);
開(kāi)具發(fā)票會(huì)立即向用戶(hù)的信用卡進(jìn)行收費(fèi)常侦。invoiceFor
方法也接收一個(gè)數(shù)組作為第三個(gè)參數(shù),用于傳遞給底層的 Stripe / Braintree 支付賬單創(chuàng)建時(shí)使用:
$user->invoiceFor('One Time Fee', 500, [
'custom-option' => $value,
]);
注意:
invoiceFor
方法會(huì)創(chuàng)建 Stripe 發(fā)票贬媒,這將重新嘗試失敗的計(jì)費(fèi)聋亡。如果你不希望開(kāi)具發(fā)票的同時(shí)嘗試失敗的支付,你需要使用 Stripe API 在他們首次失敗時(shí)就關(guān)閉這個(gè)支付掖蛤。
發(fā)票
你可以通過(guò)使用 invoices
方法來(lái)檢索一個(gè)可計(jì)費(fèi)模型的發(fā)票數(shù)組:
$invoices = $user->invoices();
當(dāng)你為客戶(hù)列出其發(fā)票時(shí)杀捻,你可以使用 invoice 幫助方法來(lái)顯示相應(yīng)的發(fā)票詳情。比如蚓庭,你想要在表格中列出所有的發(fā)票致讥,從而允許用戶(hù)方便的下載:
<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 類(lèi)型的發(fā)票
你需要安裝 dompdf
PHP 類(lèi)庫(kù)來(lái)生成 PDF:
composer require dompdf/dompdf
在路由或者控制器中,使用 downloadInvoice
方法來(lái)生成一個(gè)供下載的 PDF 類(lèi)型的發(fā)票器赞。該方法會(huì)自動(dòng)的生成正確的下載響應(yīng)到瀏覽器中:
Route::get('user/invoice/{invoice}', function ($invoiceId) {
return Auth::user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
]);
});