Cashier 交易工具包
Laravel Cashier
- 簡介
- #升級Cashier
- ##設定Braintree
- #貨幣配置
- 恢復訂閱
- 以信用卡訂閱
- #建立客戶
- 更新信用卡
- 刪除信用卡
- ##處理Stripe Webhooks
定義Webhook 事件 - #訂閱失敗
- Webhook 驗簽
- #處理Braintree Webhooks
#定義Webhook 事件- #一次收費
簡介
Laravel Cashier 提供了直覺、流暢的介面來存取 Stripe's 和 Braintree's 的付費訂閱服務。它可以處理幾乎讓您頭痛的付費訂閱代碼。除了提供基本的訂閱管理之外,Cashier 還可以幫您處理優惠券、交換訂閱、訂閱 「數量」、取消寬限期,甚至還可以產生 PDF 發票。
{注意} 如果您只是需要 “一次性” 的收費並且不提供訂閱,就不應該使用 Cashier。建議您使用 Stripe 和 Braintree 的 SDK。
升級Cashier
當您從舊版升級到最新版本的Cashier 前,建議您優先閱讀Cashier 升級指南.
#StripeComposer
composer require laravel/cashier
資料庫遷移在使用Cashier 之前,需要準備資料庫。 Cashier 需要在您的users
表中新增幾個列,並建立一個新的subscriptions 表來保存所有客戶的訂閱:
Schema::table('users', function ($table) { $table->string('stripe_id')->nullable()->collation('utf8mb4_bin'); $table->string('card_brand')->nullable(); $table->string('card_last_four', 4)->nullable(); $table->timestamp('trial_ends_at')->nullable(); }); Schema::create('subscriptions', function ($table) { $table->increments('id'); $table->unsignedInteger('user_id'); $table->string('name'); $table->string('stripe_id')->collation('utf8mb4_bin'); $table->string('stripe_plan'); $table->integer('quantity'); $table->timestamp('trial_ends_at')->nullable(); $table->timestamp('ends_at')->nullable(); $table->timestamps(); });一旦遷移檔案建立好後,執行Artisan 的
Billable 模型
Billable Trait 到您的模型定義。這個Trait 提供了多個方法以便執行常用支付任務,例如建立訂閱、使用優惠券以及更新信用卡資訊:
use Laravel\Cashier\Billable;class User extends Authenticatable{ use Billable; }API Keys最後,在配置檔案
'stripe' => [ 'model' => App\User::class, 'key' => env('STRIPE_KEY'), 'secret' => env('STRIPE_SECRET'), ],############## #######Braintree#########
Braintree 注意事項
在許多情況下,Stripe 和 Braintree 實現 Cashier 的功能都是一樣的,兩者都提供了透過信用卡訂閱付款的功能, Braintree 還額外支援透過 PayPal 付款。但 Braintree 也缺少一些 Stripe 支援的功能,在決定使用 Stripe 或 Braintree 之前,您需要考慮以下幾點:
- Braintree 支援 PayPal 而 Stripe 不支援。
- Braintree 不支援
increment
和decrement
方法,這是 Braintree 的限制,而不是 Cashier 限制。 - Braintree 不支援基於百分比的折扣。這是 Braintree 的限制,而不是 Cashier 限制。
Composer
首先,將Braintree 的Cashier 套件新增到您專案的依賴項:
composer require "laravel/cashier-braintree":"~2.0"
信用卡優惠方案
在使用Cashier 之前,你需要先在Braintree 控制面板中定義一個plan-credit
折扣。這個折扣會根據用戶選擇的付款選項來匹配合適的折扣比例,例如選擇年付或月付。
在 Braintree 控制面板中配置的折扣總額可以隨意填寫,Cashier 會在每次使用優惠券的時候根據您的配置來覆蓋該預設值。由於 Braintree 不支援使用訂閱頻率來匹配折扣比例,所以這個優惠券是必需的。
資料庫遷移
開始使用 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->unsignedInteger('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 模型
然後,加入Billable
Trait 到你的模型定義:
use Laravel\Cashier\Billable; class User extends Authenticatable{ use Billable; }
#API Keys
緊接著,您應該在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(config('services.braintree.environment')); \Braintree_Configuration::merchantId(config('services.braintree.merchant_id')); \Braintree_Configuration::publicKey(config('services.braintree.public_key')); \Braintree_Configuration::privateKey(config('services.braintree.private_key'));##貨幣配置
Cashier 使用美元(USD)作為預設貨幣。您可以透過在服務提供者的
boot 方法中呼叫
Cashier::useCurrency 方法來變更預設的貨幣。這個
useCurrency 方法接受兩個字串參數:貨幣和貨幣符號:
use Laravel\Cashier\Cashier; Cashier::useCurrency('eur', '€');
建立訂閱
建立訂閱,首先需要取得到一個 Billable 模型實例,通常是 App\User
的實例。一旦您取得了模型實例,您可以使用 newSubscription
方法建立模型的訂閱:
$user = User::find(1); $user->newSubscription('main', 'premium')->create($stripeToken);
newSubscription
方法的第一個參數應該是訂閱的名稱。如果您的應用程式只提供一個訂閱,那麼您可以將其設定為 main
或 primary
。第二個參數是用戶訂閱的 Stripe / Braintree 計畫。這個值應該與 Stripe 或 Braintree 中的識別碼對應。
create
方法接受一個 Stripe 信用卡 / 來源令牌,它將開始訂閱,並使用客戶 ID 和其他相關的帳單資訊更新資料庫。
用戶其他的詳細資訊
如果您想要指定用戶其他的詳細信息,您可以透過將它們作為第二個參數傳遞給create
方法:
$user->newSubscription('main', 'monthly')->create($stripeToken, [ 'email' => $email, ]);
要了解更多關於Stripe 或Braintree 支援的額外字段,請查看Stripe 的內容建立客戶文件 或對應的Braintree 文件 。
優惠券
如果您想在建立訂閱時使用優惠券,您可以使用withCoupon
方法:
$user->newSubscription('main', 'monthly') ->withCoupon('code') ->create($stripeToken);
檢查訂閱狀態
一旦用戶在您的應用程式訂閱了,您可以使用各種方便的方法輕鬆地檢查他們的訂閱狀態。首先,如果使用者有一個啟動的訂閱,那麼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()) { // }
基於給定的Stripe / Braintree 計劃ID,可以使用subscribedToPlan
方法來確定使用者是否訂閱了該計劃。在本例中,我們將確定使用者的main
訂閱是否啟動了monthly
計畫:
if ($user->subscribedToPlan('monthly', 'main')) { // }
recurring
方法可用於確定使用者當前是否已訂閱,並且不再處於試用階段:
if ($user->subscription('main')->recurring()) { // }#
取消訂閱狀態
為了確定使用者是否曾經訂閱,但已經取消了他們的訂閱,您可以使用cancelled
方法:
if ($user->subscription('main')->cancelled()) { // }
您也可以確定用戶是否已經取消了訂閱,但仍處於訂閱的「寬限期」,直到訂閱完全過期為止。例如,如果用戶在 3 月 5 日取消了原定於 3 月 10 日到期的訂閱,那麼用戶將在 3 月 10 日之前進行「寬限期」。請注意,在此期間subscribed
方法仍然傳回true
:
if ($user->subscription('main')->onGracePeriod()) { // }
如果要確定使用者取消訂閱的時間是否已不在其「寬限期」 內,可以使用ended
方法:
if ($user->subscription('main')->ended()) { // }
#修改訂閱計劃
用戶在您的應用程式中訂閱了之後,他們可能會偶爾想要更改一個新的訂閱方案。若要將一個使用者切換到一個新的訂閱,需將訂閱方案的識別碼傳遞給 swap
方法:
$user = App\User::find(1); $user->subscription('main')->swap('provider-plan-id');
如果使用者在試用期,試用期的期限會被保留。另外,如果訂閱的數量存在「份額」,那麼該份額也將保持。
如果你想在更改使用者訂閱計畫的時候取消使用者目前訂閱的試用期,可以使用skipTrial
方法:
$user->subscription('main') ->skipTrial() ->swap('provider-plan-id');
訂閱量
{注意} 訂閱量僅由Cashier 的Stripe 支援。 Braintree 沒有一個對應於 Stripe 的「數量」的特性。
有些時候訂閱是會受「數量」影響的。舉個例子,你的應用程式的付費方式可能是每個帳戶 $10 / 月。你可以用incrementQuantity
和 decrementQuantity
方法輕鬆地增加或減少你的訂閱量:
$user = User::find(1); $user->subscription('main')->incrementQuantity(); // 对当前的订阅量加5... $user->subscription('main')->incrementQuantity(5); $user->subscription('main')->decrementQuantity(); // 对当前的订阅量减5... $user->subscription('main')->decrementQuantity(5);
或者,你可以使用updateQuantity
方法設定一個特定的數量:
$user->subscription('main')->updateQuantity(10);
noProrate
方法可用於更新訂閱的數量,而不會對收費進行定價:
$user->subscription('main')->noProrate()->updateQuantity(10);
要獲得更多關於訂閱量的信息,請參考Stripe 文件.
#訂閱稅額
#在計費模式上實作taxPercentage
方法,並且傳回一個0 到100 不超過2 位小數的數字,用來指定使用者在訂閱中支付的稅率百分比。
public function taxPercentage() { return 20; }
taxPercentage
方法讓你能夠在模型的基礎上應用稅率,這對於一個跨越多個國家和稅率的用戶群可能有幫助。
{注意}
taxPercentage
方法只適用於付費訂閱模式。如果你用 charges 來做「一次性」收費,你需要同時手動指定稅率。
同步稅率百分比
當更改 taxPercentage
方法傳回的硬編碼值時,使用者的任何現有訂閱的稅率設定將保持不變。如果要用傳回的taxPercentage
值更新現有訂閱的稅率,則應在使用者的訂閱實例上呼叫syncTaxPercentage
方法:
$user->subscription('main')->syncTaxPercentage();
#訂閱錨定日期
{注意} Cashier 中只有Stripe 支援修改訂閱錨定日期。
預設情況下,計費週期錨定是建立訂閱的日期,如果使用試用期,則是試用結束的日期。如果要修改帳單錨定日期,可以使用anchorBillingCycleOn
方法:
use App\User;use Carbon\Carbon; $user = User::find(1); $anchor = Carbon::parse('first day of next month'); $user->newSubscription('main', 'premium') ->anchorBillingCycleOn($anchor->startOfDay()) ->create($stripeToken);
有關管理訂閱計費週期的詳細信息,請參閱Stripe 計費週期文件
取消訂閱
#在使用者訂閱上呼叫cancel
方法用來取消訂閱:
$user->subscription('main')->cancel();
當一個訂閱被取消時,Cashier 將會自動在你的資料庫中設定 ends_at
欄位。這個欄位經常被用來得知 subscribed
欄位何時應該開始回傳 false
。例如,如果客戶在 3 月 1 日取消訂閱,但訂閱方案直到 3 月 5 日才結束,subscribed
方法將會繼續回傳 true
一直到 3 月 5 日。
你可以使用onGracePeriod
方法來確定使用者是否確定訂閱,但是仍然存在一個「寬限期」:
if ($user->subscription('main')->onGracePeriod()) { // }
如果你想馬上取消訂閱,請在使用者的訂閱中呼叫cancelNow
方法:
$user->subscription('main')->cancelNow();
恢復訂閱
如果一個用已經取消訂閱,你可以在你希望恢復它的時候使用resume
方法。用戶必須 仍然在他們的寬限期內才可以恢復訂閱:
$user->subscription('main')->resume();
如果用戶已取消訂閱,然後在訂閱寬限期前恢復該訂閱,他們將不會被立即計費。相反,他們的訂閱將會被重新激活,需要按照原來的付款流程再次進行付款。
#試用訂閱
#########################以信用卡訂閱
如果你想給你的顧客提供試用期,同時收集支付方法信息,那麼你應該在創建訂閱使用trialDays
方法:
$user = User::find(1);$user->newSubscription('main', 'monthly') ->trialDays(10) ->create($stripeToken);
此方法會在資料庫訂閱記錄上設定訂閱期結束時間,以便告知Sripe / Braintree 在此之前不要計算使用者的帳單資訊。
{注意} 如果顧客沒有在試用期結束前取消訂閱,訂閱會被自動結算,所以你應該確保告知你的用戶他們的試用結束期。
trialUntil
方法允許提供DateTime
# 實例指定試用結束期:
use Carbon\Carbon;$user->newSubscription('main', 'monthly') ->trialUntil(Carbon::now()->addDays(10)) ->create($stripeToken);
你可以使用使用者實例的onTrial
方法或訂閱實例的onTrial
方法判斷使用者是否處於試用期。以下兩個範例等價:
if ($user->onTrial('main')) { // } if ($user->subscription('main')->onTrial()) { // }
#非信用卡訂閱
如果你不想在提供試用期的時候收集用戶付款方式信息,只需設定用戶記錄的trial_ends_at
列為期望的試用期結束日期即可,這通常在用戶註冊期間完成:
$user = User::create([ // Populate other user properties... 'trial_ends_at' => now()->addDays(10), ]);
{注意} 確保已新增
trial_ends_at
日期修改器 到模型定義。
Cashier 把這種類型的引用稱為「一般體驗」,因為它沒有關聯任何已存在的訂閱。如果目前的日期沒有超過 trail_ends_at
值,User
實例的 onTrial
方法將會傳回 true
:
if ($user->onTrial()) { // 用户在他们的试用期内... }
如果你希望明確的知道用戶處於「一般」試用期,並且還未創建實際的訂閱,那麼你可以使用onGenericTrial
方法:
if ($user->onGenericTrial()) { // 用户在他们「一般」试用期... }
如果你準備給用戶創建實際的訂閱,通常你可以使用newSubsription
方法:
$user = User::find(1); $user->newSubscription('main', 'monthly')->create($stripeToken);
客戶
建立客戶
有時,您可能想要在未訂閱的情況下建立Stripe 客戶。您可以使用 createAsStripeCustomer
方法完成此操作:
$user->createAsStripeCustomer();
#一旦在 Stripe 中建立了客戶,您可以稍後開始訂閱。
{提示} 在 Braintree 中建立客戶使用的是
createAsBraintreeCustomer
方法。
金融卡
接收信用卡
可計費模型實例上的cards
方法傳回Laravel\Cashier\Card
實例的集合:
$cards = $user->cards();
要檢索預設卡,可以使用defaultCard
方法;
$card = $user->defaultCard();
確定卡號存檔
您可以使用hasCardOnFile
方法檢查客戶是否在其帳戶上儲存了信用卡:
if ($user->hasCardOnFile()) { // }
更新信用卡
updateCard
方法可用於更新使用者的信用卡信息,該方法接受一個Stripe 令牌並設定一個新的信用卡作為預設支付來源:
$user->updateCard($stripeToken);
將您的卡片資訊與客戶的預設卡片資訊進行Stripe 同步,可以使用updateCardFromStripe
方法:
$user->updateCardFromStripe();
#刪除信用卡
要刪除卡,應先使用cards
方法檢索客戶的卡。然後,可以呼叫要刪除的卡片實例上的delete
方法:
foreach ($user->cards() as $card) { $card->delete(); }
{注意} 如果要刪除預設卡,請確保使用
updateCardFromStripe
方法將新的預設卡與資料庫同步。
deleteCards
方法將刪除應用程式儲存的使用者的所有卡片資訊:
$user->deleteCards();
{注意} 如果使用者已有訂閱,則應考慮阻止他們刪除最後剩餘的付款方式。
處理Stripe Webhooks
Stripe 和Braintree 都可以透過webhook 通知應用各種各樣的事件。要處理 Stripe webhook,需要定義一個 Cashier 的 webhook 控制器的路由。這個控制器可以處理所有進入webhook 的請求並將他們分發到合適的控制器方法中:
Route::post( 'stripe/webhook', '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook' );
{注意} 一旦註冊了路由,確保在您的Stripe 控制面板中配置了webhook URL。
預設情況下,這個控制器將會自動對支付失敗次數過多(這個次數可以在Stripe 設定中定義)的訂閱進行取消;此外,我們很快會發現,你可以擴充這個控制器去處理任何你想要處理的webhook 事件。
{注意} 請確保使用 Cashier 的 webhook 驗簽 中間件來保護傳入請求。
Webhooks & CSRF 保護
因為Stripe webhooks 需要繞過Laraval 的CSRF 保護,請確保在你的VerifyCsrfToken
中間件含有URI ,或將其置於web
中間件組之外:
protected $except = [ 'stripe/*', ];
定義 Webhook 事件處理程序
Cashier 對於失敗支付自動進行取消訂閱,但是如果你有其他的 Stripe webhook 事件希望去處理,可以擴展 Webhook 控制器。你的方法名稱應該與 Cashier 期望的約定相符,更具體的說,你希望處理 Stripe webhook 的方法應該以 handle
和 “駝峰” 名為前綴。舉例來說,如果你希望處理invoice.payment_succeeded
的webhook,你應該在控制器添加handleInvoicePaymentSucceeded
方法:
<?php namespace App\Http\Controllers; use Laravel\Cashier\Http\Controllers\WebhookController as CashierController; class WebhookController extends CashierController{ /** * Handle invoice payment succeeded. * * @param array $payload * @return \Symfony\Component\HttpFoundation\Response */ public function handleInvoicePaymentSucceeded($payload) { // 此处处理事件 } }
接下來,在routes /web.php
檔案中定義Cashier 控制器的路由:
Route::post( 'stripe/webhook', '\App\Http\Controllers\WebhookController@handleWebhook' );
訂閱失敗
##如果用戶的信用卡過期怎麼辦?別擔心 - Cashier 包含了一個 Webhook 控制器可以輕鬆為你取消使用者的訂閱。如上文所述,你需要做的只是將路由指向控制器:Route::post( 'stripe/webhook', '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook' );就是這樣!失敗的付款將會被控制器捕獲並處理,該控制器會在 Stripe 判斷訂閱失敗後(通常嘗試支付失敗 3 次及以上)取消用戶的訂閱。 Webhook 驗簽為了保護Webhook,你需要使用
Stripe 的webhook 簽章 。為了方便起見,Cashier 包含一個中間件,用於驗證傳入 Stripe webhook 的請求是否有效。
如果要啟用 Webhook 驗證,請確保在services 設定檔中設定了
stripe.webhook.secret 的值。 Webhook 的
secret 可以從 Stripe 使用者控制面板中找到。
Route::post( 'braintree/webhook', '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook' );
{注意} 一旦註冊了路由,請確保在Braintree 控制器面板配置了webhook URL 。預設情況下,這個控制器將會自動對支付失敗次數過多(這個次數可以在Braintree 設定中定義)的訂閱進行取消;此外,我們很快會發現,你可以擴充這控制器去處理任何你想要處理的webhook 事件。 Webhooks & CSRF 保護因為Braintree webhooks 需要繞過Laravel 的CSRF 保護,請確保在你的
VerifyCsrfToken 中間件清單中含有URI ,或將其置於
web 中間件組之外:
protected $except = [ 'braintree/*', ];
定義 Webhook 事件處理程序
Cashier 對於失敗支付自動進行取消訂閱,但如果你有其他的 Braintree webhook 事件希望去處理,可以擴充 Webhook 控制器。你的方法名稱應該與 Cashier 期望的約定相符,更具體的說,你希望處理 Braintree webhook 的方法應該以 handle
和“駝峰”名為前綴。舉例來說,如果你希望處理dispute_opened
這個webhook,你應該在控制器裡加入handleDisputeOpened
方法:
<?php namespace App\Http\Controllers; use Braintree\WebhookNotification; use Laravel\Cashier\Http\Controllers\WebhookController as CashierController; class WebhookController extends CashierController{ /** * Handle a new dispute. * * @param \Braintree\WebhookNotification $webhook * @return \Symfony\Component\HttpFoundation\Responses */ public function handleDisputeOpened(WebhookNotification $webhook) { // 此处处理时事件... } }
#訂閱失敗
如果使用者的信用卡過期怎麼辦?別擔心 - Cashier 包含了一個 Webhook 控制器可以輕鬆為你取消使用者的訂閱。只需要將路由指向控制器中:
Route::post( 'braintree/webhook', '\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook' );
就是這樣!失敗的付款將會被控制器捕獲和處理,該控制器會在 Braintree 判斷訂閱失敗後(通常嘗試支付失敗 3 次及以上)取消用戶的訂閱。不要忘記:在你的 Braintree 控制器面板中設定 webhook URI。
# #簡單付款
{注意} 當使用Stripe 時,
charge
方法接收你想支付於應用程式使用的貨幣的最小單位 的金額。然而,當使用Braintree 時,你應該將全部的美元金額傳入charge
方法:
如果你想對訂閱客戶的信用卡收取「一次性」費用,可以在可計費模型實例上使用charge
方法:
// Stripe 接收分为单位的费用... $stripeCharge = $user->charge(100); // Braintree 接收美元为单位的费用... $user->charge(1);
charge
方法接受一個陣列作為它的第二個參數,允許你在建立付款時將任何你想要的選項傳給底層的Stripe / Braintree 。有關在建立付款時可用的選項,請參閱 Stripe 或 Braintree 文件:
$user->charge(100, [ 'custom_option' => $value, ]);
如果付款失敗,charge
方法將會拋出例外。如果付款成功,則方法將會傳回完整的 Stripe / Braintree 回應:
try { $response = $user->charge(100); } catch (Exception $e) { // }
費用與發票
有時你可能需要支付一次性費用同時也需要產生費用發票,以便可以向客戶提供 PDF 文件格式的收據。 invoiceFor
方法可以讓你做到這一點。例如,向客戶開立 5.00 美元的「一次性費用」發票:
// Stripe 接收分为单位的费用... $user->invoiceFor('One Time Fee', 500); // Braintree 接收美元为单位的费用... $user->invoiceFor('One Time Fee', 5);
該發票會立即透過用戶信用卡支付。 invoiceFor
方法接收一個陣列作為第三個參數,讓你在建立付款時將任何你想要的選項傳遞給底層的Stripe / Braintree :
$user->invoiceFor('Stickers', 500, [ 'quantity' => 50, ], [ 'tax_percent' => 21, ]);
如果你使用Braintree 作為你的帳單提供者,你在呼叫invoiceFor
方法時必須包含description
選項:
$user->invoiceFor('One Time Fee', 500, [ 'description' => 'your invoice description here', ]);
{注意}
invoiceFor
方法將會建立Stripe 發票,該發票將會在付款失敗後重試。如果你不想失敗後重試,你需要在第一次付款失敗後呼叫 Stripe API 關閉它。
關於退款
#如果您需要處理退款,您可以使用refund
方法。此方法接受Stripe charge ID 作為其唯一參數:
$stripeCharge = $user->charge(100); $user->refund($stripeCharge->id);
#發票
您可以使用invoices
方法輕鬆取得帳單模型的發票陣列:
$invoices = $user->invoices(); // 结果包含处理中的发票... $invoices = $user->invoicesIncludingPending();
當列出客戶發票清單時,可以使用發票輔助函數來顯示相關的發票資訊。例如,您可能想要在表格中列出每張發票,從而方便客戶下載它們:
<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 發票
在路由或控制器中,使用downloadInvoice
方法產生一個發票的PDF 下載。這個方法會自動為瀏覽器產生適當的 HTTP 下載回應:
use Illuminate\Http\Request; Route::get('user/invoice/{invoice}', function (Request $request, $invoiceId) { return $request->user()->downloadInvoice($invoiceId, [ 'vendor' => 'Your Company', 'product' => 'Your Product', ]); });