Laravel Cashier (Stripe) (Laravel Cashier (Stripe))
- Introduction
- Cashierのアップグレード
- Installation
- Configuration
- Customers
- 支払い方法
- Subscriptions
- サブスクリプショントライアル
- Stripe Webhook の処理
- シングルチャージ
- Checkout
- Invoices
- 失敗した支払いの処理
- 強力な顧客認証 (SCA)
- StripeSDK
- Testing
導入 (Introduction)
Laravel Cashier Stripe は、Stripe の サブスクリプション請求サービスへの表現力豊かで流暢なインターフェイスを提供します。あなたが書くのを恐れている定型的なサブスクリプション請求コードのほぼすべてを処理します。基本的なサブスクリプション管理に加えて、Cashier はクーポン、サブスクリプションの交換、サブスクリプションの「数量」、キャンセル猶予期間を処理し、請求書の PDF を生成することもできます。
Cashierのアップグレード (Upgrading Cashier)
Cashier の新しいバージョンにアップグレードする場合は、アップグレードガイド を注意深く確認することが重要です。
{note} 重大な変更を防ぐため、Cashier は固定の Stripe API バージョンを使用します。 Cashier 13 は、Stripe API バージョン
2020-08-27を利用します。 Stripe API バージョンは、Stripe の新しい機能と改善を利用するためにマイナー リリースで更新されます。
インストール (Installation)
まず、Composer パッケージ マネージャーを使用して Stripe の Cashier パッケージをインストールします。
composer require laravel/cashier
{note} Cashier がすべての Stripe イベントを適切に処理できるようにするには、Cashier の Webhook 処理を設定する を忘れないでください。
データベースの移行
Cashier のサービスプロバイダは独自のデータベース移行ディレクトリを登録するため、パッケージのインストール後にデータベースを移行することを忘れないでください。 Cashier の移行により、users テーブルにいくつかの列が追加され、顧客のすべてのサブスクリプションを保持するための新しい subscriptions テーブルが作成されます。
php artisan migrate
Cashier に同梱されている移行を上書きする必要がある場合は、vendor:publish Artisan コマンドを使用して公開できます。
php artisan vendor:publish --tag="cashier-migrations"
Cashier の移行が完全に実行されないようにする場合は、Cashier が提供する ignoreMigrations メソッドを使用できます。通常、このメソッドは、AppServiceProvider の register メソッドで呼び出す必要があります。
use Laravel\Cashier\Cashier;
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Cashier::ignoreMigrations();
}
{note} Stripe では、Stripe 識別子の格納に使用される列では大文字と小文字を区別することを推奨しています。したがって、MySQL を使用する場合は、
stripe_id列の列照合順序がutf8_binに設定されていることを確認する必要があります。これに関する詳細については、Stripe のドキュメント を参照してください。
構成 (Configuration)
課金対象モデル
Cashier を使用する前に、Billable 特性を請求可能モデル定義に追加します。通常、これは App\Models\User モデルになります。この特性は、サブスクリプションの作成、クーポンの適用、支払い方法情報の更新などの一般的な請求タスクを実行できるようにするさまざまなメソッドを提供します。
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}
Cashier は、請求可能なモデルが Laravel に同梱される App\Models\User クラスであると想定します。これを変更したい場合は、useCustomerModel メソッドで別のモデルを指定できます。このメソッドは通常、AppServiceProvider クラスの boot メソッドで呼び出す必要があります。
use App\Models\Cashier\User;
use Laravel\Cashier\Cashier;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Cashier::useCustomerModel(User::class);
}
{note} Laravel が提供する
App\Models\Userモデル以外のモデルを使用している場合は、提供されている Cashierの移行 を公開し、代替モデルのテーブル名と一致するように変更する必要があります。
APIキー
次に、アプリケーションの .env ファイルで Stripe API キーを構成する必要があります。 Stripe API キーは、Stripe コントロール パネルから取得できます。
STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
通貨構成
デフォルトのCashier通貨は米ドル (USD) です。アプリケーションの .env ファイル内で CASHIER_CURRENCY 環境変数を設定することで、デフォルトの通貨を変更できます。
CASHIER_CURRENCY=eur
レジの通貨を構成することに加えて、請求書に表示する金額の書式を設定するときに使用するロケールを指定することもできます。内部的には、Cashier は PHPのNumberFormatterクラス を使用して通貨ロケールを設定します。
CASHIER_CURRENCY_LOCALE=nl_BE
{note}
en以外のロケールを使用するには、ext-intlPHP 拡張機能がサーバーにインストールされ、構成されていることを確認してください。
税の構成
Stripe税 のおかげで、Stripe によって生成されたすべての請求書の税金を自動的に計算することができます。自動税金計算を有効にするには、アプリケーションの App\Providers\AppServiceProvider クラスの boot メソッドで calculateTaxes メソッドを呼び出します。
use Laravel\Cashier\Cashier;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Cashier::calculateTaxes();
}
税計算が有効になると、新しいサブスクリプションと生成される 1 回限りの請求書で自動的に税計算が行われるようになります。
この機能が適切に動作するには、顧客の名前、住所、納税者番号などの請求詳細が Stripe に同期される必要があります。これを実現するには、Cashier が提供する 顧客データの同期 および 納税者番号 メソッドを使用できます。
{note} 残念ながら、現時点では、単一料金 または シングルチャージチェックアウト に対する税金は計算されません。さらに、Stripe Tax は現在、ベータ期間中は「招待制」です。 Stripe Tax へのアクセスは、Stripe Tax ウェブサイト 経由でリクエストできます。
ロギング
Cashier を使用すると、致命的な Stripe エラーを記録するときに使用するログ チャネルを指定できます。アプリケーションの .env ファイル内で CASHIER_LOGGER 環境変数を定義することで、ログ チャネルを指定できます。
CASHIER_LOGGER=stack
Stripe への API 呼び出しによって生成された例外は、アプリケーションのデフォルトのログ チャネルを通じて記録されます。
カスタムモデルの使用
独自のモデルを定義し、対応する Cashier モデルを拡張することで、Cashier によって内部的に使用されるモデルを自由に拡張できます。
use Laravel\Cashier\Subscription as CashierSubscription;
class Subscription extends CashierSubscription
{
// ...
}
モデルを定義した後、Laravel\Cashier\Cashier クラスを介してカスタム モデルを使用するように Cashier に指示できます。通常、アプリケーションの App\Providers\AppServiceProvider クラスの boot メソッドでカスタム モデルについて Cashier に通知する必要があります。
use App\Models\Cashier\Subscription;
use App\Models\Cashier\SubscriptionItem;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Cashier::useSubscriptionModel(Subscription::class);
Cashier::useSubscriptionItemModel(SubscriptionItem::class);
}
お客様 (Customers)
顧客の取得
Cashier::findBillable メソッドを使用して、Stripe ID によって顧客を取得できます。このメソッドは、課金対象モデルのインスタンスを返します。
use Laravel\Cashier\Cashier;
$user = Cashier::findBillable($stripeId);
顧客の創造
場合によっては、サブスクリプションを開始せずに Stripe 顧客を作成したい場合があります。これは、createAsStripeCustomer メソッドを使用して実行できます。
$stripeCustomer = $user->createAsStripeCustomer();
Stripe で顧客を作成したら、後日サブスクリプションを開始できます。オプションの $options 配列を指定して、追加の Stripe API でサポートされる顧客作成パラメータ を渡すことができます。
$stripeCustomer = $user->createAsStripeCustomer($options);
課金対象モデルの Stripe 顧客オブジェクトを返したい場合は、asStripeCustomer メソッドを使用できます。
$stripeCustomer = $user->asStripeCustomer();
createOrGetStripeCustomer メソッドは、特定の請求可能モデルの Stripe 顧客オブジェクトを取得したいが、請求可能モデルがすでに Stripe 内の顧客であるかどうかが不明な場合に使用できます。このメソッドは、Stripe に新しい顧客がまだ存在しない場合に作成します。
$stripeCustomer = $user->createOrGetStripeCustomer();
顧客の更新
場合によっては、Stripe 顧客に追加情報を直接更新したい場合があります。これは、updateStripeCustomer メソッドを使用して実行できます。このメソッドは、Stripe API でサポートされる顧客更新オプション の配列を受け入れます。
$stripeCustomer = $user->updateStripeCustomer($options);
残高
Stripe では、顧客の「残高」を入金または借方記入することができます。後で、この残高は新しい請求書に記入または借方記入されます。顧客の合計残高を確認するには、請求対象モデルで利用できる balance メソッドを使用できます。 balance メソッドは、顧客の通貨で残高を表すフォーマットされた文字列を返します。
$balance = $user->balance();
顧客の残高を入金するには、applyBalance メソッドに負の値を指定できます。必要に応じて、説明も入力できます。
$user->applyBalance(-500, 'Premium customer top-up.');
applyBalance メソッドに正の値を指定すると、顧客の残高が引き落とされます。
$user->applyBalance(300, 'Bad usage penalty.');
applyBalance メソッドは、顧客の新しい顧客残高トランザクションを作成します。これらのトランザクション レコードは、balanceTransactions メソッドを使用して取得できます。これは、顧客が確認できる貸方と借方のログを提供するのに役立ちます。
// Retrieve all transactions...
$transactions = $user->balanceTransactions();
foreach ($transactions as $transaction) {
// Transaction amount...
$amount = $transaction->amount(); // $2.31
// Retrieve the related invoice when available...
$invoice = $transaction->invoice();
}
納税者番号
Cashier は、顧客の納税者番号を管理する簡単な方法を提供します。たとえば、taxIds メソッドを使用して、顧客に割り当てられたすべての 納税者番号 をコレクションとして取得できます。
$taxIds = $user->taxIds();
顧客の特定の納税者 ID を識別子によって取得することもできます。
$taxId = $user->findTaxId('txi_belgium');
有効な type と値を createTaxId メソッドに指定することで、新しい税 ID を作成できます。
$taxId = $user->createTaxId('eu_vat', 'BE0123456789');
createTaxId メソッドは、顧客のアカウントに VAT ID をすぐに追加します。 VAT ID の検証も Stripe によって行われます;ただし、これは非同期プロセスです。 customer.tax_id.updated Webhook イベントをサブスクライブし、VAT ID verification パラメータ を検査することで、検証の更新の通知を受け取ることができます。 Webhook の処理の詳細については、Webhook ハンドラーの定義に関するドキュメント を参照してください。
deleteTaxId メソッドを使用して納税者 ID を削除できます。
$user->deleteTaxId('txi_belgium');
Stripe と顧客データを同期する
通常、アプリケーションのユーザーが自分の名前、電子メール アドレス、または Stripe によって保存されているその他の情報を更新する場合は、Stripe に更新を通知する必要があります。そうすることで、Stripe の情報のコピーがアプリケーションの情報と同期されます。
これを自動化するには、モデルの updated イベントに反応するイベント リスナを課金対象モデルに定義できます。次に、イベント リスナ内で、モデルに対して syncStripeCustomerDetails メソッドを呼び出すことができます。
use function Illuminate\Events\queueable;
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::updated(queueable(function ($customer) {
if ($customer->hasStripeId()) {
$customer->syncStripeCustomerDetails();
}
}));
}
これで、顧客モデルが更新されるたびに、その情報が Stripe と同期されるようになります。便宜上、Cashier は顧客の最初の作成時に顧客情報を Stripe と自動的に同期します。
Cashier が提供するさまざまなメソッドをオーバーライドすることで、顧客情報を Stripe に同期するために使用される列をカスタマイズできます。たとえば、stripeName メソッドをオーバーライドして、レジ担当者が顧客情報を Stripe に同期するときに顧客の「名前」とみなされる属性をカスタマイズできます。
/**
* Get the customer name that should be synced to Stripe.
*
* @return string|null
*/
public function stripeName()
{
return $this->company_name;
}
同様に、stripeEmail、stripePhone、および stripeAddress メソッドをオーバーライドできます。これらのメソッドは、Stripe 顧客オブジェクトの更新 のときに、対応する顧客パラメータに情報を同期します。顧客情報の同期プロセスを完全に制御したい場合は、syncStripeCustomerDetails メソッドをオーバーライドできます。
請求ポータル
Stripe は、顧客がサブスクリプション、支払い方法を管理し、請求履歴を表示できるように 請求ポータルをセットアップする簡単な方法 を提供します。コントローラまたはルートから課金対象モデルの redirectToBillingPortal メソッドを呼び出すことで、ユーザーを課金ポータルにリダイレクトできます。
use Illuminate\Http\Request;
Route::get('/billing-portal', function (Request $request) {
return $request->user()->redirectToBillingPortal();
});
デフォルトでは、ユーザーはサブスクリプションの管理を終了すると、Stripe 請求ポータル内のリンクを介してアプリケーションの home ルートに戻ることができます。 URL を引数として redirectToBillingPortal メソッドに渡すことで、ユーザーが戻るカスタム URL を指定できます。
use Illuminate\Http\Request;
Route::get('/billing-portal', function (Request $request) {
return $request->user()->redirectToBillingPortal(route('billing'));
});
HTTP リダイレクト応答を生成せずに課金ポータルへの URL を生成したい場合は、billingPortalUrl メソッドを呼び出します。
$url = $request->user()->billingPortalUrl(route('billing'));
支払い方法 (Payment Methods)
支払い方法の保存
Stripe でサブスクリプションを作成したり、「1 回限り」の請求を実行するには、支払い方法を保存し、Stripe からその識別子を取得する必要があります。これを達成するために使用されるアプローチは、サブスクリプションまたは単一料金のどちらの支払い方法を使用する予定であるかによって異なります。そのため、以下では両方について検討します。
定期購読の支払い方法
サブスクリプションで将来使用するために顧客のクレジット カード情報を保存する場合は、Stripe の「Setup Intents」API を使用して顧客の支払い方法の詳細を安全に収集する必要があります。 「セットアップ インテント」は、顧客の支払い方法に請求する意図を Stripe に示します。 Cashier の Billable トレイトには、新しいセットアップ インテントを簡単に作成するための createSetupIntent メソッドが含まれています。このメソッドは、顧客の支払い方法の詳細を収集するフォームをレンダリングするルートまたはコントローラから呼び出す必要があります。
return view('update-payment-method', [
'intent' => $user->createSetupIntent()
]);
Setup Intent を作成してビューに渡した後、支払い方法を収集する要素にそのシークレットを添付する必要があります。たとえば、次の「支払い方法の更新」フォームについて考えてみましょう。
<input id="card-holder-name" type="text">
<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>
<button id="card-button" data-secret="{{ $intent->client_secret }}">
Update Payment Method
</button>
次に、Stripe.js ライブラリを使用して、Stripe要素 をフォームに添付し、顧客の支払い詳細を安全に収集します。
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('stripe-public-key');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
</script>
次に、カードを検証し、Stripe の confirmCardSetup メソッド を使用して Stripe から安全な「支払い方法識別子」を取得できます。
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
cardButton.addEventListener('click', async (e) => {
const { setupIntent, error } = await stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: cardElement,
billing_details: { name: cardHolderName.value }
}
}
);
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
}
});
Stripe によってカードが検証された後、結果の setupIntent.payment_method 識別子を Laravel アプリケーションに渡し、そこで顧客に添付できます。支払い方法は、新しい支払い方法として追加されました または デフォルトの支払い方法を更新するために使用されます のいずれかです。支払い方法識別子をすぐに 新しいサブスクリプションを作成する に使用することもできます。
{tip} セットアップ インテントと顧客の支払い詳細の収集について詳しく知りたい場合は、Stripe が提供するこの概要を確認してください までお問い合わせください。
一括料金の支払い方法
もちろん、顧客の支払い方法に対して 1 回の請求を行う場合、支払い方法識別子を使用する必要があるのは 1 回だけです。 Stripe の制限により、顧客の保存されているデフォルトの支払い方法を 1 回の請求に使用することはできません。 Stripe.js ライブラリを使用して顧客が支払い方法の詳細を入力できるようにする必要があります。たとえば、次の形式を考えてみましょう。
<input id="card-holder-name" type="text">
<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>
<button id="card-button">
Process Payment
</button>
このようなフォームを定義した後、Stripe.js ライブラリを使用して Stripe要素 をフォームに添付し、顧客の支払い詳細を安全に収集できます。
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripe = Stripe('stripe-public-key');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
</script>
次に、カードを検証し、Stripe の createPaymentMethod メソッド を使用して Stripe から安全な「支払い方法識別子」を取得できます。
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', async (e) => {
const { paymentMethod, error } = await stripe.createPaymentMethod(
'card', cardElement, {
billing_details: { name: cardHolderName.value }
}
);
if (error) {
// Display "error.message" to the user...
} else {
// The card has been verified successfully...
}
});
カードが正常に検証された場合は、paymentMethod.id を Laravel アプリケーションに渡し、一回の充電 を処理できます。
支払い方法の取得
課金対象モデル インスタンスの paymentMethods メソッドは、Laravel\Cashier\PaymentMethod インスタンスのコレクションを返します。
$paymentMethods = $user->paymentMethods();
デフォルトでは、このメソッドは card タイプの支払い方法を返します。別のタイプの支払い方法を取得するには、メソッドの引数として type を渡すことができます。
$paymentMethods = $user->paymentMethods('sepa_debit');
顧客のデフォルトの支払い方法を取得するには、defaultPaymentMethod メソッドを使用できます。
$paymentMethod = $user->defaultPaymentMethod();
findPaymentMethod メソッドを使用して、請求可能なモデルに関連付けられている特定の支払い方法を取得できます。
$paymentMethod = $user->findPaymentMethod($paymentMethodId);
ユーザーが支払い方法を持っているかどうかを判断する
請求可能なモデルのアカウントにデフォルトの支払い方法が関連付けられているかどうかを確認するには、hasDefaultPaymentMethod メソッドを呼び出します。
if ($user->hasDefaultPaymentMethod()) {
//
}
hasPaymentMethod メソッドを使用して、請求可能なモデルのアカウントに少なくとも 1 つの支払い方法が関連付けられているかどうかを確認できます。
if ($user->hasPaymentMethod()) {
//
}
このメソッドは、請求可能なモデルに card タイプの支払い方法があるかどうかを判断します。モデルに別のタイプの支払い方法が存在するかどうかを確認するには、メソッドに引数として type を渡すことができます。
if ($user->hasPaymentMethod('sepa_debit')) {
//
}
デフォルトの支払い方法の更新
updateDefaultPaymentMethod メソッドは、顧客のデフォルトの支払い方法情報を更新するために使用できます。このメソッドは、Stripe 支払い方法識別子を受け入れ、新しい支払い方法をデフォルトの請求支払い方法として割り当てます。
$user->updateDefaultPaymentMethod($paymentMethod);
デフォルトの支払い方法情報を Stripe の顧客のデフォルトの支払い方法情報と同期するには、updateDefaultPaymentMethodFromStripe メソッドを使用できます。
$user->updateDefaultPaymentMethodFromStripe();
{note} 顧客のデフォルトの支払い方法は、請求書発行と新しいサブスクリプションの作成にのみ使用できます。 Stripe によって課された制限により、単一のチャージには使用できない場合があります。
支払い方法の追加
新しい支払い方法を追加するには、支払い方法識別子を渡して、請求可能モデルで addPaymentMethod メソッドを呼び出します。
$user->addPaymentMethod($paymentMethod);
{tip} 支払い方法 ID を取得する方法については、支払い方法の保管に関するドキュメント をご覧ください。
支払い方法の削除
支払い方法を削除するには、削除する Laravel\Cashier\PaymentMethod インスタンスで delete メソッドを呼び出します。
$paymentMethod->delete();
deletePaymentMethod メソッドは、請求可能なモデルから特定の支払い方法を削除します。
$user->deletePaymentMethod('pm_visa');
deletePaymentMethods メソッドは、請求可能なモデルのすべての支払い方法情報を削除します。
$user->deletePaymentMethods();
デフォルトでは、このメソッドは card タイプの支払い方法を削除します。別のタイプの支払い方法を削除するには、メソッドの引数として type を渡すことができます。
$user->deletePaymentMethods('sepa_debit');
{note} ユーザーが有効なサブスクリプションを持っている場合、アプリケーションではユーザーがデフォルトの支払い方法を削除できないようにする必要があります。
定期購入 (Subscriptions)
サブスクリプションは、顧客に定期的な支払いを設定する方法を提供します。 Cashier によって管理される Stripe サブスクリプションは、複数のサブスクリプション価格、サブスクリプション数量、トライアルなどのサポートを提供します。
サブスクリプションの作成
サブスクリプションを作成するには、まず課金対象モデルのインスタンスを取得します。これは通常、App\Models\User のインスタンスになります。モデル インスタンスを取得したら、newSubscription メソッドを使用してモデルのサブスクリプションを作成できます。
use Illuminate\Http\Request;
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription(
'default', 'price_monthly'
)->create($request->paymentMethodId);
// ...
});
newSubscription メソッドに渡される最初の引数は、サブスクリプションの内部名である必要があります。アプリケーションが単一のサブスクリプションのみを提供する場合は、これを default または primary と呼びます。このサブスクリプション名はアプリケーション内部でのみ使用され、ユーザーに表示されることを意図したものではありません。また、スペースを含めることはできません。また、サブスクリプションの作成後に変更しないでください。 2 番目の引数は、ユーザーが購読している特定の価格です。この値は、Stripe の価格の識別子に対応する必要があります。
Stripe 支払い方法識別子 または Stripe PaymentMethod オブジェクトを受け入れる create メソッドは、サブスクリプションを開始するだけでなく、課金対象モデルの Stripe 顧客 ID およびその他の関連課金情報でデータベースを更新します。
{note} 支払い方法識別子を
createサブスクリプション メソッドに直接渡すと、ユーザーが保存している支払い方法にも自動的に追加されます。
請求書メールによる定期的な支払いの回収
顧客の定期支払いを自動的に収集する代わりに、定期支払いの期限が来るたびに顧客に請求書を電子メールで送信するように Stripe に指示できます。その後、顧客は請求書を受け取ったら手動で支払うことができます。請求書を通じて定期的な支払いを回収する場合、顧客は前もって支払い方法を指定する必要はありません。
$user->newSubscription('default', 'price_monthly')->createAndSendInvoice();
サブスクリプションがキャンセルされるまでに顧客が請求書を支払う必要がある期間は、Stripeダッシュボード 内のサブスクリプションと請求書の設定によって決まります。
数量
サブスクリプションの作成時に価格に特定の quantity を設定したい場合は、サブスクリプションを作成する前にサブスクリプション ビルダで quantity メソッドを呼び出す必要があります。
$user->newSubscription('default', 'price_monthly')
->quantity(5)
->create($paymentMethod);
追加の詳細
Stripe でサポートされている追加の customer または subscription オプションを指定したい場合は、それらを create メソッドの 2 番目と 3 番目の引数として渡すことで指定できます。
$user->newSubscription('default', 'price_monthly')->create($paymentMethod, [
'email' => $email,
], [
'metadata' => ['note' => 'Some extra information.'],
]);
クーポン
サブスクリプションの作成時にクーポンを適用したい場合は、withCoupon メソッドを使用できます。
$user->newSubscription('default', 'price_monthly')
->withCoupon('code')
->create($paymentMethod);
または、Stripe プロモーション コード を適用したい場合は、withPromotionCode メソッドを使用できます。指定されたプロモーション コード ID は、顧客向けのプロモーション コードではなく、プロモーション コードに割り当てられた Stripe API ID である必要があります。
$user->newSubscription('default', 'price_monthly')
->withPromotionCode('promo_code')
->create($paymentMethod);
サブスクリプションの追加
すでにデフォルトの支払い方法を持っている顧客にサブスクリプションを追加したい場合は、サブスクリプション ビルダで add メソッドを呼び出すことができます。
use App\Models\User;
$user = User::find(1);
$user->newSubscription('default', 'price_monthly')->add();
Stripe ダッシュボードからのサブスクリプションの作成
Stripe ダッシュボード自体からサブスクリプションを作成することもできます。これを行うと、Cashier は新しく追加されたサブスクリプションを同期し、default という名前を割り当てます。ダッシュボードで作成されたサブスクリプションに割り当てられるサブスクリプション名をカスタマイズするには、WebhookController を拡張します を使用して、newSubscriptionName メソッドを上書きします。
さらに、Stripe ダッシュボードから作成できるサブスクリプションは 1 種類のみです。アプリケーションが異なる名前を使用する複数のサブスクリプションを提供する場合、Stripe ダッシュボードから追加できるサブスクリプションのタイプは 1 つだけです。
最後に、アプリケーションによって提供されるサブスクリプションの種類ごとに、アクティブなサブスクリプションを 1 つだけ追加するように常に注意する必要があります。顧客が 2 つの default サブスクリプションを持っている場合、両方がアプリケーションのデータベースと同期される場合でも、最後に追加されたサブスクリプションのみが Cashier によって使用されます。
購読ステータスの確認
顧客がアプリケーションを購読すると、さまざまな便利な方法を使用して顧客の購読ステータスを簡単に確認できます。まず、顧客がアクティブなサブスクリプションを持っている場合、サブスクリプションが現在試用期間内であっても、subscribed メソッドは true を返します。 subscribed メソッドは、サブスクリプションの名前を最初の引数として受け入れます。
if ($user->subscribed('default')) {
//
}
subscribed メソッドも ルートミドルウェア の有力な候補となり、ユーザーのサブスクリプション ステータスに基づいてルートとコントローラへのアクセスをフィルタリングできます。
<?php
namespace App\Http\Middleware;
use Closure;
class EnsureUserIsSubscribed
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->user() && ! $request->user()->subscribed('default')) {
// This user is not a paying customer...
return redirect('billing');
}
return $next($request);
}
}
ユーザーがまだ試用期間内であるかどうかを確認したい場合は、onTrial メソッドを使用できます。このメソッドは、ユーザーがまだ試用期間中であることをユーザーに警告するかどうかを決定するのに役立ちます。
if ($user->subscription('default')->onTrial()) {
//
}
subscribedToProduct メソッドは、特定の Stripe 製品の識別子に基づいて、ユーザーが特定の製品を購読しているかどうかを判断するために使用できます。 Stripe では、製品は価格の集合です。この例では、ユーザーの default サブスクリプションがアプリケーションの「プレミアム」製品にアクティブにサブスクライブされているかどうかを判断します。指定された Stripe 製品 ID は、Stripe ダッシュボード内の製品 ID の 1 つに対応する必要があります。
if ($user->subscribedToProduct('prod_premium', 'default')) {
//
}
配列を subscribedToProduct メソッドに渡すことによって、ユーザーの default サブスクリプションがアプリケーションの「ベーシック」製品または「プレミアム」製品にアクティブにサブスクライブされているかどうかを判断できます。
if ($user->subscribedToProduct(['prod_basic', 'prod_premium'], 'default')) {
//
}
subscribedToPrice メソッドは、顧客のサブスクリプションが特定の価格 ID に対応するかどうかを判断するために使用できます。
if ($user->subscribedToPrice('price_basic_monthly', 'default')) {
//
}
recurring メソッドは、ユーザーが現在購読中であり、試用期間中でないかどうかを判断するために使用できます。
if ($user->subscription('default')->recurring()) {
//
}
{note} ユーザーが同じ名前の 2 つのサブスクリプションを持っている場合、
subscriptionメソッドによって常に最新のサブスクリプションが返されます。たとえば、ユーザーはdefaultという名前の 2 つのサブスクリプション レコードを持っているとします。ただし、サブスクリプションの 1 つは期限切れの古いサブスクリプションであり、もう 1 つは現在のアクティブなサブスクリプションである可能性があります。最新のサブスクリプションは常に返されますが、古いサブスクリプションは履歴レビューのためにデータベースに保存されます。
キャンセルされたサブスクリプションのステータス
ユーザーがかつてはアクティブなサブスクライバだったが、サブスクリプションをキャンセルしたかどうかを確認するには、canceled メソッドを使用できます。
if ($user->subscription('default')->canceled()) {
//
}
また、ユーザーがサブスクリプションをキャンセルしたが、サブスクリプションが完全に期限切れになるまでまだ「猶予期間」中であるかどうかを判断することもできます。たとえば、ユーザーが元々 3 月 10 日に期限切れになる予定だったサブスクリプションを 3 月 5 日にキャンセルした場合、ユーザーは 3 月 10 日まで「猶予期間」に入ります。この間も、subscribed メソッドは true を返すことに注意してください。
if ($user->subscription('default')->onGracePeriod()) {
//
}
ユーザーがサブスクリプションをキャンセルし、「猶予期間」に入っていないかどうかを確認するには、ended メソッドを使用できます。
if ($user->subscription('default')->ended()) {
//
}
未完了および期限超過のステータス
サブスクリプションの作成後に 2 番目の支払いアクションが必要な場合、サブスクリプションは incomplete としてマークされます。サブスクリプションのステータスは、Cashier の subscriptions データベース テーブルの stripe_status 列に保存されます。
同様に、価格を交換するときに 2 番目の支払いアクションが必要な場合、サブスクリプションは past_due としてマークされます。サブスクリプションがこれらの状態のいずれかにある場合、顧客が支払いを確認するまでアクティブになりません。サブスクリプションに支払いが完了していないかどうかを判断するには、請求可能モデルまたはサブスクリプション インスタンスで hasIncompletePayment メソッドを使用します。
if ($user->hasIncompletePayment('default')) {
//
}
if ($user->subscription('default')->hasIncompletePayment()) {
//
}
サブスクリプションの支払いが完了していない場合は、latestPayment 識別子を渡して、ユーザーをCashierの支払い確認ページに誘導する必要があります。サブスクリプション インスタンスで利用可能な latestPayment メソッドを使用して、この識別子を取得できます。
<a href="{{ route('cashier.payment', $subscription->latestPayment()->id) }}">
Please confirm your payment.
</a>
サブスクリプションが past_due 状態にあるときにもアクティブであると見なされたい場合は、Cashier が提供する keepPastDueSubscriptionsActive メソッドを使用できます。通常、このメソッドは、App\Providers\AppServiceProvider の register メソッドで呼び出す必要があります。
use Laravel\Cashier\Cashier;
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Cashier::keepPastDueSubscriptionsActive();
}
{note} サブスクリプションが
incomplete状態にある場合、支払いが確認されるまで変更することはできません。したがって、サブスクリプションがincomplete状態にある場合、swapメソッドとupdateQuantityメソッドは例外をスローします。
サブスクリプションの範囲
ほとんどのサブスクリプション状態はクエリ スコープとしても使用できるため、特定の状態にあるサブスクリプションについてデータベースを簡単にクエリできます。
// Get all active subscriptions...
$subscriptions = Subscription::query()->active()->get();
// Get all of the canceled subscriptions for a user...
$subscriptions = $user->subscriptions()->canceled()->get();
利用可能なスコープの完全なリストは以下で入手できます。
Subscription::query()->active();
Subscription::query()->canceled();
Subscription::query()->ended();
Subscription::query()->incomplete();
Subscription::query()->notCanceled();
Subscription::query()->notOnGracePeriod();
Subscription::query()->notOnTrial();
Subscription::query()->onGracePeriod();
Subscription::query()->onTrial();
Subscription::query()->pastDue();
Subscription::query()->recurring();
価格の変更
顧客がアプリケーションをサブスクライブした後、新しいサブスクリプション価格への変更を希望する場合があります。顧客を新しい価格に切り替えるには、Stripe 価格の識別子を swap メソッドに渡します。価格を交換するときは、ユーザーが以前にサブスクリプションをキャンセルした場合にそのサブスクリプションを再アクティブ化したいと考えていると想定されます。指定された価格識別子は、Stripe ダッシュボードで使用可能な Stripe 価格識別子に対応する必要があります。
use App\Models\User;
$user = App\Models\User::find(1);
$user->subscription('default')->swap('price_yearly');
お客様が試用中の場合、試用期間は維持されます。さらに、サブスクリプションに「数量」が存在する場合、その数量も維持されます。
価格を交換し、顧客が現在参加している試用期間をキャンセルしたい場合は、skipTrial メソッドを呼び出すことができます。
$user->subscription('default')
->skipTrial()
->swap('price_yearly');
価格を交換して、次の請求サイクルを待たずにすぐに顧客に請求したい場合は、swapAndInvoice メソッドを使用できます。
$user = User::find(1);
$user->subscription('default')->swapAndInvoice('price_yearly');
按分
デフォルトでは、Stripe は価格を切り替えるときに料金を日割り計算します。 noProrate メソッドを使用すると、料金を日割り計算せずにサブスクリプションの価格を更新できます。
$user->subscription('default')->noProrate()->swap('price_yearly');
サブスクリプションの日割り計算の詳細については、Stripe のドキュメント を参照してください。
{note}
swapAndInvoiceメソッドの前にnoProrateメソッドを実行しても、比例配分には影響しません。請求書は必ず発行されます。
購読数量
サブスクリプションは「数量」の影響を受ける場合があります。たとえば、プロジェクト管理アプリケーションでは、プロジェクトごとに月額 10 ドルを請求する場合があります。 incrementQuantity および decrementQuantity メソッドを使用して、サブスクリプション数量を簡単に増減できます。
use App\Models\User;
$user = User::find(1);
$user->subscription('default')->incrementQuantity();
// Add five to the subscription's current quantity...
$user->subscription('default')->incrementQuantity(5);
$user->subscription('default')->decrementQuantity();
// Subtract five from the subscription's current quantity...
$user->subscription('default')->decrementQuantity(5);
あるいは、updateQuantity メソッドを使用して特定の数量を設定することもできます。
$user->subscription('default')->updateQuantity(10);
noProrate メソッドを使用すると、料金を日割り計算せずにサブスクリプションの数量を更新できます。
$user->subscription('default')->noProrate()->updateQuantity(10);
サブスクリプション数量の詳細については、Stripe のドキュメント を参照してください。
複数価格のサブスクリプション数量
サブスクリプションが マルチプライスサブスクリプション の場合は、増分または減分する数量の価格の名前を 2 番目の引数として増分 / 減分メソッドに渡す必要があります。
$user->subscription('default')->incrementQuantity(1, 'price_chat');
複数価格のサブスクリプション
複数価格のサブスクリプション を使用すると、単一のサブスクリプションに複数の請求価格を割り当てることができます。たとえば、基本サブスクリプション価格が月額 10 ドルであるが、ライブ チャットのアドオン価格を追加で月額 15 ドルで提供するカスタマー サービスの「ヘルプデスク」アプリケーションを構築していると想像してください。マルチプライスのサブスクリプション情報は、Cashier の subscription_items データベース テーブルに保存されます。
価格の配列を newSubscription メソッドの 2 番目の引数として渡すことで、特定のサブスクリプションに複数の価格を指定できます。
use Illuminate\Http\Request;
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription('default', [
'price_monthly',
'price_chat',
])->create($request->paymentMethodId);
// ...
});
上の例では、顧客は default サブスクリプションに 2 つの価格を設定します。どちらの価格も、それぞれの請求間隔で請求されます。必要に応じて、quantity メソッドを使用して、各価格の特定の数量を指定できます。
$user = User::find(1);
$user->newSubscription('default', ['price_monthly', 'price_chat'])
->quantity(5, 'price_chat')
->create($paymentMethod);
既存のサブスクリプションに別の価格を追加したい場合は、サブスクリプションの addPrice メソッドを呼び出します。
$user = User::find(1);
$user->subscription('default')->addPrice('price_chat');
上記の例では、新しい価格が追加され、顧客は次の請求サイクルでその料金を請求されます。顧客にすぐに請求したい場合は、addPriceAndInvoice メソッドを使用できます。
$user->subscription('default')->addPriceAndInvoice('price_chat');
特定の数量を含む価格を追加したい場合は、addPrice メソッドまたは addPriceAndInvoice メソッドの 2 番目の引数として数量を渡すことができます。
$user = User::find(1);
$user->subscription('default')->addPrice('price_chat', 5);
removePrice メソッドを使用して、サブスクリプションから価格を削除できます。
$user->subscription('default')->removePrice('price_chat');
{note} サブスクリプションの最後の価格を削除することはできません。代わりに、サブスクリプションをキャンセルするだけです。
スワッピング価格
マルチプライスのサブスクリプションに関連付けられている価格を変更することもできます。たとえば、顧客が price_chat アドオン価格の price_basic サブスクリプションを持っており、顧客を price_basic から price_pro 価格にアップグレードしたいとします。
use App\Models\User;
$user = User::find(1);
$user->subscription('default')->swap(['price_pro', 'price_chat']);
上記の例を実行すると、price_basic を持つ基になるサブスクリプション アイテムが削除され、price_chat を持つサブスクリプション アイテムは保持されます。さらに、price_pro の新しいサブスクリプション アイテムが作成されます。
キーと値のペアの配列を swap メソッドに渡すことで、サブスクリプション項目オプションを指定することもできます。たとえば、サブスクリプション価格の数量を指定する必要がある場合があります。
$user = User::find(1);
$user->subscription('default')->swap([
'price_pro' => ['quantity' => 5],
'price_chat'
]);
サブスクリプションの単一の価格を交換したい場合は、サブスクリプション項目自体で swap メソッドを使用して行うことができます。このアプローチは、サブスクリプションの他の価格に関する既存のメタデータをすべて保持したい場合に特に便利です。
$user = User::find(1);
$user->subscription('default')
->findItemOrFail('price_basic')
->swap('price_pro');
日割り
デフォルトでは、Stripe は複数価格サブスクリプションに価格を追加または削除するときに料金を日割り計算します。日割りなしで価格調整を行いたい場合は、価格操作に noProrate メソッドをチェーンする必要があります。
$user->subscription('default')->noProrate()->removePrice('price_chat');
数量
個々のサブスクリプション価格の数量を更新したい場合は、既存の数量メソッド を使用して価格の名前を追加の引数としてメソッドに渡します。
$user = User::find(1);
$user->subscription('default')->incrementQuantity(5, 'price_chat');
$user->subscription('default')->decrementQuantity(3, 'price_chat');
$user->subscription('default')->updateQuantity(10, 'price_chat');
{note} サブスクリプションに複数の価格がある場合、
Subscriptionモデルのstripe_price属性とquantity属性はnullになります。個々の価格属性にアクセスするには、Subscriptionモデルで使用可能なitems関係を使用する必要があります。
定期購入アイテム
サブスクリプションに複数の価格がある場合、データベースの subscription_items テーブルに複数のサブスクリプション「アイテム」が保存されます。これらには、サブスクリプションの items 関係を介してアクセスできます。
use App\Models\User;
$user = User::find(1);
$subscriptionItem = $user->subscription('default')->items->first();
// Retrieve the Stripe price and quantity for a specific item...
$stripePrice = $subscriptionItem->stripe_price;
$quantity = $subscriptionItem->quantity;
findItemOrFail メソッドを使用して特定の価格を取得することもできます。
$user = User::find(1);
$subscriptionItem = $user->subscription('default')->findItemOrFail('price_chat');
従量制課金
従量制課金 を使用すると、請求サイクル中の製品の使用量に基づいて顧客に請求できます。たとえば、顧客が毎月送信するテキスト メッセージや電子メールの数に基づいて顧客に請求できます。
従量課金の使用を開始するには、まず、Stripe ダッシュボードで従量制価格の新しい製品を作成する必要があります。次に、meteredPrice を使用して、従量制価格 ID を顧客のサブスクリプションに追加します。
use Illuminate\Http\Request;
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription('default')
->meteredPrice('price_metered')
->create($request->paymentMethodId);
// ...
});
Stripeチェックアウト 経由で従量制サブスクリプションを開始することもできます。
$checkout = Auth::user()
->newSubscription('default', [])
->meteredPrice('price_metered')
->checkout();
return view('your-checkout-view', [
'checkout' => $checkout,
]);
使用状況のレポート
顧客がアプリケーションを使用すると、正確に請求できるように、その使用状況を Stripe に報告します。従量制サブスクリプションの使用量を増やすには、reportUsage メソッドを使用できます。
$user = User::find(1);
$user->subscription('default')->reportUsage();
デフォルトでは、「使用数量」1 が請求期間に追加されます。あるいは、特定の「使用量」を渡して、請求期間中の顧客の使用量に追加することもできます。
$user = User::find(1);
$user->subscription('default')->reportUsage(15);
アプリケーションが 1 つのサブスクリプションで複数の価格を提供する場合は、reportUsageFor メソッドを使用して、使用量をレポートする従量制価格を指定する必要があります。
$user = User::find(1);
$user->subscription('default')->reportUsageFor('price_metered', 15);
場合によっては、以前に報告した使用状況を更新する必要がある場合があります。これを実現するには、タイムスタンプまたは DateTimeInterface インスタンスを 2 番目のパラメータとして reportUsage に渡すことができます。これを行うと、Stripe はその時点で報告された使用状況を更新します。指定された日時はまだ現在の請求期間内であるため、以前の使用記録を引き続き更新できます。
$user = User::find(1);
$user->subscription('default')->reportUsage(5, $timestamp);
使用記録の取得
顧客の過去の使用状況を取得するには、サブスクリプション インスタンスの usageRecords メソッドを使用できます。
$user = User::find(1);
$usageRecords = $user->subscription('default')->usageRecords();
アプリケーションが 1 つのサブスクリプションで複数の価格を提供している場合は、usageRecordsFor メソッドを使用して、使用状況レコードを取得する従量制価格を指定できます。
$user = User::find(1);
$usageRecords = $user->subscription('default')->usageRecordsFor('price_metered');
usageRecords メソッドと usageRecordsFor メソッドは、使用状況レコードの連想配列を含む Collection インスタンスを返します。この配列を反復処理して、顧客の合計使用量を表示できます。
@foreach ($usageRecords as $usageRecord)
- 開始期間: {{ $usageRecord['period']['start'] }}
- 期間終了: {{ $usageRecord['period']['end'] }}
- 合計使用量: {{ $usageRecord['total_usage'] }}
@endforeach
返されるすべての使用状況データの完全なリファレンスと、Stripe のカーソル ベースのページネーションの使用方法については、公式の Stripe API ドキュメント を参照してください。
購読税
{note} 税率を手動で計算する代わりに、Stripe Tax を使用して税金を自動計算する を使用できます。
ユーザーがサブスクリプションに対して支払う税率を指定するには、請求可能モデルに taxRates メソッドを実装し、Stripe 税率 ID を含む配列を返す必要があります。これらの税率は Stripe ダッシュボード で定義できます。
/**
* The tax rates that should apply to the customer's subscriptions.
*
* @return array
*/
public function taxRates()
{
return ['txr_id'];
}
taxRates メソッドを使用すると、顧客ごとに税率を適用できます。これは、複数の国や税率にまたがるユーザー ベースに役立つ場合があります。
複数価格のサブスクリプションを提供している場合は、請求可能モデルに priceTaxRates メソッドを実装することで、価格ごとに異なる税率を定義できます。
/**
* The tax rates that should apply to the customer's subscriptions.
*
* @return array
*/
public function priceTaxRates()
{
return [
'price_monthly' => ['txr_id'],
];
}
{note}
taxRatesメソッドは、サブスクリプション料金にのみ適用されます。 Cashier を使用して「1 回限り」の請求を行う場合は、その時点で税率を手動で指定する必要があります。
税率の同期
taxRates メソッドによって返されるハードコードされた税率 ID を変更する場合、ユーザーの既存のサブスクリプションの税金設定は同じままになります。既存のサブスクリプションの税額を新しい taxRates 値で更新する場合は、ユーザーのサブスクリプション インスタンスで syncTaxRates メソッドを呼び出す必要があります。
$user->subscription('default')->syncTaxRates();
これにより、複数価格のサブスクリプション商品の税率も同期されます。アプリケーションが複数価格のサブスクリプションを提供している場合は、課金対象モデルが priceTaxRates メソッド 上で議論した を実装していることを確認する必要があります。
免税
Cashier は、顧客が非課税かどうかを判断するための isNotTaxExempt、isTaxExempt、および reverseChargeApplies メソッドも提供します。これらのメソッドは、Stripe API を呼び出して、顧客の免税ステータスを判断します。
use App\Models\User;
$user = User::find(1);
$user->isTaxExempt();
$user->isNotTaxExempt();
$user->reverseChargeApplies();
{note} これらのメソッドは、あらゆる
Laravel\Cashier\Invoiceオブジェクトでも使用できます。ただし、Invoiceオブジェクトで呼び出された場合、メソッドは請求書の作成時の免除ステータスを決定します。
サブスクリプションアンカー日
デフォルトでは、請求サイクルアンカーはサブスクリプションが作成された日付、または試用期間が使用されている場合は試用が終了する日付です。請求アンカー日を変更したい場合は、anchorBillingCycleOn メソッドを使用できます。
use Illuminate\Http\Request;
Route::post('/user/subscribe', function (Request $request) {
$anchor = Carbon::parse('first day of next month');
$request->user()->newSubscription('default', 'price_monthly')
->anchorBillingCycleOn($anchor->startOfDay())
->create($request->paymentMethodId);
// ...
});
サブスクリプションの請求サイクルの管理の詳細については、Stripe の請求サイクルに関するドキュメント を参照してください。
定期購入のキャンセル
サブスクリプションをキャンセルするには、ユーザーのサブスクリプションで cancel メソッドを呼び出します。
$user->subscription('default')->cancel();
サブスクリプションがキャンセルされると、Cashier は subscriptions データベース テーブルに ends_at 列を自動的に設定します。この列は、subscribed メソッドが false を返し始める時期を知るために使用されます。
たとえば、顧客が 3 月 1 日にサブスクリプションをキャンセルしたが、そのサブスクリプションが 3 月 5 日まで終了する予定ではなかった場合、subscribed メソッドは 3 月 5 日まで true を返し続けます。これは、ユーザーが通常、請求サイクルが終了するまでアプリケーションを使用し続けることが許可されているために行われます。
onGracePeriod メソッドを使用して、ユーザーがサブスクリプションをキャンセルしたがまだ「猶予期間」中であるかどうかを確認できます。
if ($user->subscription('default')->onGracePeriod()) {
//
}
サブスクリプションをすぐにキャンセルしたい場合は、ユーザーのサブスクリプションで cancelNow メソッドを呼び出します。
$user->subscription('default')->cancelNow();
サブスクリプションをすぐにキャンセルし、残りの未請求の従量制使用量または新規/保留中の日割り請求書アイテムを請求したい場合は、ユーザーのサブスクリプションで cancelNowAndInvoice メソッドを呼び出します。
$user->subscription('default')->cancelNowAndInvoice();
特定の時点でサブスクリプションをキャンセルすることもできます。
$user->subscription('default')->cancelAt(
now()->addDays(10)
);
サブスクリプションの再開
顧客がサブスクリプションをキャンセルし、それを再開したい場合は、サブスクリプションで resume メソッドを呼び出すことができます。顧客がサブスクリプションを再開するには、「猶予期間」内である必要があります。
$user->subscription('default')->resume();
顧客がサブスクリプションをキャンセルし、サブスクリプションの有効期限が完全に切れる前にそのサブスクリプションを再開した場合、顧客にはすぐには請求されません。代わりに、サブスクリプションが再度アクティブ化され、元の請求サイクルで請求されます。
サブスクリプショントライアル (Subscription Trials)
支払い方法を前払いする場合
支払い方法情報を事前に収集しながら顧客に試用期間を提供したい場合は、サブスクリプションの作成時に trialDays メソッドを使用する必要があります。
use Illuminate\Http\Request;
Route::post('/user/subscribe', function (Request $request) {
$request->user()->newSubscription('default', 'price_monthly')
->trialDays(10)
->create($request->paymentMethodId);
// ...
});
このメソッドは、データベース内のサブスクリプション レコードに試用期間の終了日を設定し、この日以降になるまで顧客への請求を開始しないように Stripe に指示します。 trialDays メソッドを使用すると、Cashier は Stripe の価格に設定されたデフォルトの試用期間を上書きします。
{note} 試用期間の終了日までに顧客のサブスクリプションがキャンセルされなかった場合、試用期間が終了するとすぐに料金が請求されるため、ユーザーに試用期間の終了日を必ず通知する必要があります。
trialUntil メソッドを使用すると、試用期間の終了時期を指定する DateTime インスタンスを提供できます。
use Carbon\Carbon;
$user->newSubscription('default', 'price_monthly')
->trialUntil(Carbon::now()->addDays(10))
->create($paymentMethod);
ユーザー インスタンスの onTrial メソッドまたはサブスクリプション インスタンスの onTrial メソッドを使用して、ユーザーが試用期間内かどうかを判断できます。以下の 2 つの例は同等です。
if ($user->onTrial('default')) {
//
}
if ($user->subscription('default')->onTrial()) {
//
}
endTrial メソッドを使用して、サブスクリプションのトライアルをすぐに終了できます。
$user->subscription('default')->endTrial();
Stripe / Cashier での試用日の定義
Stripe ダッシュボードで価格を受け取るトライアル日数を定義するか、Cashier を使用して常に明示的に渡すかを選択できます。 Stripe で価格の試用期間を定義することを選択した場合は、明示的に skipTrial() メソッドを呼び出さない限り、過去にサブスクリプションを持っていた顧客の新規サブスクリプションを含む、新しいサブスクリプションには常に試用期間が設定されることに注意する必要があります。
前払いの支払い方法なし
ユーザーの支払い方法情報を事前に収集せずに試用期間を提供したい場合は、ユーザー レコードの trial_ends_at 列を希望する試用終了日に設定できます。これは通常、ユーザー登録時に行われます。
use App\Models\User;
$user = User::create([
// ...
'trial_ends_at' => now()->addDays(10),
]);
{note} 課金対象モデルのクラス定義内の
trial_ends_at属性に 日付キャスト を必ず追加してください。
既存のサブスクリプションに関連付けられていないため、Cashier はこのタイプのトライアルを「一般トライアル」と呼びます。現在の日付が trial_ends_at の値を超えていない場合、請求可能モデル インスタンスの onTrial メソッドは true を返します。
if ($user->onTrial()) {
// User is within their trial period...
}
ユーザーの実際のサブスクリプションを作成する準備ができたら、通常どおり newSubscription メソッドを使用できます。
$user = User::find(1);
$user->newSubscription('default', 'price_monthly')->create($paymentMethod);
ユーザーの試用終了日を取得するには、trialEndsAt メソッドを使用できます。このメソッドは、ユーザーが試用中の場合は Carbon date インスタンスを返し、試用中でない場合は null を返します。デフォルト以外の特定のサブスクリプションの試用終了日を取得したい場合は、オプションのサブスクリプション名パラメーターを渡すこともできます。
if ($user->onTrial()) {
$trialEndsAt = $user->trialEndsAt('main');
}
ユーザーが「一般的な」試用期間内であり、実際のサブスクリプションをまだ作成していないことを具体的に知りたい場合は、onGenericTrial メソッドを使用することもできます。
if ($user->onGenericTrial()) {
// User is within their "generic" trial period...
}
トライアルの延長
extendTrial メソッドを使用すると、サブスクリプションの作成後にサブスクリプションの試用期間を延長できます。トライアルの有効期限がすでに切れており、顧客にサブスクリプションの料金がすでに請求されている場合でも、延長トライアルを提供できます。試用期間内に費やした時間は、お客様の次回の請求書から差し引かれます。
use App\Models\User;
$subscription = User::find(1)->subscription('default');
// End the trial 7 days from now...
$subscription->extendTrial(
now()->addDays(7)
);
// Add an additional 5 days to the trial...
$subscription->extendTrial(
$subscription->trial_ends_at->addDays(5)
);
Stripe Webhook の処理 (Handling Stripe Webhooks)
{tip} Stripe CLI を使用すると、ローカル開発中に Webhook をテストできます。
Stripe は、Webhook 経由でさまざまなイベントをアプリケーションに通知できます。デフォルトでは、Cashier の Webhook コントローラを指すルートは、Cashier サービスプロバイダによって自動的に登録されます。このコントローラは、受信したすべての Webhook リクエストを処理します。
デフォルトでは、Cashier Webhook コントローラは、失敗した請求 (Stripe 設定で定義されている) が多すぎるサブスクリプションのキャンセル、顧客の更新、顧客の削除、サブスクリプションの更新、支払い方法の変更を自動的に処理します。ただし、すぐにわかりますが、このコントローラを拡張して、任意の Stripe Webhook イベントを処理できます。
アプリケーションが Stripe Webhook を処理できるようにするには、Stripe コントロール パネルで Webhook URL を構成してください。デフォルトでは、Cashier の Webhook コントローラは /stripe/webhook URL パスに応答します。 Stripe コントロール パネルで有効にする必要があるすべての Webhook の完全なリストは次のとおりです。
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedcustomer.updatedcustomer.deletedinvoice.payment_action_required
便宜上、Cashier には cashier:webhook Artisan コマンドが含まれています。このコマンドは、Cashier が必要とするすべてのイベントをリッスンする Webhook を Stripe に作成します。
php artisan cashier:webhook
デフォルトでは、作成された Webhook は、APP_URL 環境変数によって定義された URL と、Cashier に含まれる cashier.webhook ルートを指します。別の URL を使用したい場合は、コマンドを呼び出すときに --url オプションを指定できます。
php artisan cashier:webhook --url "https://example.com/stripe/webhook"
作成される Webhook は、Cashier のバージョンと互換性のある Stripe API バージョンを使用します。別の Stripe バージョンを使用したい場合は、--api-version オプションを指定できます。
php artisan cashier:webhook --api-version="2019-12-03"
作成後、Webhook はすぐにアクティブになります。 Webhook を作成したいが、準備が完了するまで無効にしておく場合は、コマンドを呼び出すときに --disabled オプションを指定できます。
php artisan cashier:webhook --disabled
{note} Cashier に含まれる Webhook 署名の検証 ミドルウェアを使用して、受信した Stripe Webhook リクエストを必ず保護してください。
Webhook と CSRF 保護
Stripe Webhook は Laravel の CSRF保護 をバイパスする必要があるため、必ずアプリケーションの App\Http\Middleware\VerifyCsrfToken ミドルウェアの例外として URI をリストするか、web ミドルウェア グループの外部にルートをリストしてください。
protected $except = [
'stripe/*',
];
Webhook イベント ハンドラーの定義
Cashier は、失敗した請求やその他の一般的な Stripe Webhook イベントによるサブスクリプションのキャンセルを自動的に処理します。ただし、追加の Webhook イベントを処理したい場合は、Cashier によって送出される次のイベントをリッスンすることで処理できます。
Laravel\Cashier\Events\WebhookReceivedLaravel\Cashier\Events\WebhookHandled
どちらのイベントにも、Stripe Webhook の完全なペイロードが含まれています。たとえば、invoice.payment_succeeded Webhook を処理したい場合は、イベントを処理する listener を登録できます。
<?php
namespace App\Listeners;
use Laravel\Cashier\Events\WebhookReceived;
class StripeEventListener
{
/**
* Handle received Stripe webhooks.
*
* @param \Laravel\Cashier\Events\WebhookReceived $event
* @return void
*/
public function handle(WebhookReceived $event)
{
if ($event->payload['type'] === 'invoice.payment_succeeded') {
// Handle the incoming event...
}
}
}
リスナを定義したら、アプリケーションの EventServiceProvider 内にリスナを登録できます。
<?php
namespace App\Providers;
use App\Listeners\StripeEventListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Laravel\Cashier\Events\WebhookReceived;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
WebhookReceived::class => [
StripeEventListener::class,
],
];
}
Webhook 署名の検証
Webhook を保護するには、Stripe の Webhook 署名 を使用できます。便宜上、Cashier には、受信した Stripe Webhook リクエストが有効であることを検証するミドルウェアが自動的に組み込まれています。
Webhook 検証を有効にするには、アプリケーションの .env ファイルに STRIPE_WEBHOOK_SECRET 環境変数が設定されていることを確認してください。 Webhook secret は、Stripe アカウントのダッシュボードから取得できます。
シングルチャージ (Single Charges)
かんたんチャージ
{note}
chargeメソッドは、アプリケーションで使用される通貨の最小分母で請求する金額を受け入れます。たとえば、米ドルを使用する場合は、金額をペニー単位で指定する必要があります。
顧客に対して 1 回限りの請求を行う場合は、請求可能モデル インスタンスで charge メソッドを使用できます。 charge メソッドの 2 番目の引数として 支払い方法識別子を提供する を指定する必要があります。
use Illuminate\Http\Request;
Route::post('/purchase', function (Request $request) {
$stripeCharge = $request->user()->charge(
100, $request->paymentMethodId
);
// ...
});
charge メソッドは 3 番目の引数として配列を受け入れ、基になる Stripe チャージ作成に必要なオプションを渡すことができます。料金作成時に利用できるオプションの詳細については、Stripe のドキュメント を参照してください。
$user->charge(100, $paymentMethod, [
'custom_option' => $value,
]);
基になる顧客またはユーザーなしで charge メソッドを使用することもできます。これを実現するには、アプリケーションの課金対象モデルの新しいインスタンスで charge メソッドを呼び出します。
use App\Models\User;
$stripeCharge = (new User)->charge(100, $paymentMethod);
充電が失敗すると、charge メソッドは例外をスローします。チャージが成功すると、Laravel\Cashier\Payment のインスタンスがメソッドから返されます。
try {
$payment = $user->charge(100, $paymentMethod);
} catch (Exception $e) {
//
}
請求書による請求
場合によっては、1 回限りの請求を行って、PDF の領収書を顧客に提供する必要がある場合があります。 invoicePrice メソッドを使用すると、まさにそれが可能になります。たとえば、顧客に新しいシャツ 5 枚の請求書を発行してみましょう。
$user->invoicePrice('price_tshirt', 5);
請求書は、ユーザーのデフォルトの支払い方法に対して直ちに請求されます。 invoicePrice メソッドは、3 番目の引数として配列も受け入れます。この配列には、請求書アイテムの請求オプションが含まれています。このメソッドで受け入れられる 4 番目の引数も、請求書自体の請求オプションを含む配列です。
$user->invoicePrice('price_tshirt', 5, [
'discounts' => [
['coupon' => 'SUMMER21SALE']
],
], [
'default_tax_rates' => ['txr_id'],
]);
あるいは、invoiceFor メソッドを使用して、顧客のデフォルトの支払い方法に対して「1 回限り」の請求を行うこともできます。
$user->invoiceFor('One Time Fee', 500);
invoiceFor メソッドを使用することもできますが、事前定義された価格で invoicePrice メソッドを使用することをお勧めします。そうすることで、Stripe ダッシュボード内で製品ごとの売上に関するより優れた分析とデータにアクセスできるようになります。
{note}
invoicePriceメソッドとinvoiceForメソッドは、失敗した請求を再試行する Stripe 請求書を作成します。失敗した請求書を再試行したくない場合は、最初の請求失敗後に Stripe API を使用して請求書を閉じる必要があります。
払戻手数料
Stripe 料金を返金する必要がある場合は、refund メソッドを使用できます。このメソッドは、最初の引数として Stripe 支払い意図 ID を受け入れます。
$payment = $user->charge(100, $paymentMethodId);
$user->refund($payment->id);
請求書 (Invoices)
請求書の取得
invoices メソッドを使用すると、請求可能なモデルの請求書の配列を簡単に取得できます。 invoices メソッドは、Laravel\Cashier\Invoice インスタンスのコレクションを返します。
$invoices = $user->invoices();
結果に保留中の請求書を含めたい場合は、invoicesIncludingPending メソッドを使用できます。
$invoices = $user->invoicesIncludingPending();
findInvoice メソッドを使用して、ID で特定の請求書を取得できます。
$invoice = $user->findInvoice($invoiceId);
請求書情報の表示
顧客の請求書をリストする場合、請求書のメソッドを使用して、関連する請求書情報を表示できます。たとえば、すべての請求書を表にリストして、ユーザーが請求書を簡単にダウンロードできるようにしたい場合があります。
<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>
今後の請求書
顧客の今後の請求書を取得するには、upcomingInvoice メソッドを使用できます。
$invoice = $user->upcomingInvoice();
同様に、顧客が複数のサブスクリプションを持っている場合は、特定のサブスクリプションの今後の請求書を取得することもできます。
$invoice = $user->subscription('default')->upcomingInvoice();
サブスクリプション請求書のプレビュー
previewInvoice メソッドを使用すると、価格を変更する前に請求書をプレビューできます。これにより、特定の価格変更が行われたときに顧客の請求書がどのようになるかを判断できます。
$invoice = $user->subscription('default')->previewInvoice('price_yearly');
複数の新しい価格で請求書をプレビューするために、価格の配列を previewInvoice メソッドに渡すことができます。
$invoice = $user->subscription('default')->previewInvoice(['price_yearly', 'price_metered']);
請求書 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',
]);
});
デフォルトでは、請求書のすべてのデータは、Stripe に保存されている顧客データと請求書のデータから取得されます。ただし、downloadInvoice メソッドの 2 番目の引数として配列を指定することで、このデータの一部をカスタマイズできます。この配列を使用すると、会社や製品の詳細などの情報をカスタマイズできます。
return $request->user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
'street' => 'Main Str. 1',
'location' => '2000 Antwerp, Belgium',
'phone' => '+32 499 00 00 00',
'url' => 'https://example.com',
'vendorVat' => 'BE123456789',
], 'my-invoice');
downloadInvoice メソッドでは、3 番目の引数を使用してカスタム ファイル名を指定することもできます。このファイル名には、自動的に .pdf という接尾辞が付けられます。
return $request->user()->downloadInvoice($invoiceId, [], 'my-invoice');
カスタム請求書レンダラー
Cashier では、カスタムの請求書レンダラーを使用することもできます。デフォルトでは、Cashier は DompdfInvoiceRenderer 実装を使用します。これは、dompdf PHP ライブラリを利用して Cashier の請求書を生成します。ただし、Laravel\Cashier\Contracts\InvoiceRenderer インターフェイスを実装することで、任意のレンダラーを使用できます。たとえば、サードパーティの PDF レンダリング サービスへの API 呼び出しを使用して、請求書の PDF をレンダリングしたい場合があります。
use Illuminate\Support\Facades\Http;
use Laravel\Cashier\Contracts\InvoiceRenderer;
use Laravel\Cashier\Invoice;
class ApiInvoiceRenderer implements InvoiceRenderer
{
/**
* Render the given invoice and return the raw PDF bytes.
*
* @param \Laravel\Cashier\Invoice. $invoice
* @param array $data
* @param array $options
* @return string
*/
public function render(Invoice $invoice, array $data = [], array $options = []): string
{
$html = $invoice->view($data)->render();
return Http::get('https://example.com/html-to-pdf', ['html' => $html])->get()->body();
}
}
請求書レンダラー コントラクトを実装したら、アプリケーションの config/cashier.php 構成ファイル内の cashier.invoices.renderer 構成値を更新する必要があります。この構成値は、カスタム レンダラー実装のクラス名に設定する必要があります。
チェックアウト (Checkout)
Cashier Stripe は、Stripeチェックアウト のサポートも提供します。 Stripe Checkout は、事前に構築されたホストされた支払いページを提供することで、支払いを受け入れるためのカスタム ページを実装する手間を省きます。
次のドキュメントには、Cashier で Stripe Checkout の使用を開始する方法に関する情報が含まれています。 Stripe Checkout について詳しく知りたい場合は、Checkout に関する Stripe 独自のドキュメント を確認することも検討してください。
製品チェックアウト
課金対象モデルで checkout メソッドを使用して、Stripe ダッシュボード内で作成された既存の製品のチェックアウトを実行できます。 checkout メソッドは、新しい Stripe Checkout セッションを開始します。デフォルトでは、Stripe Price ID を渡す必要があります。
use Illuminate\Http\Request;
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout('price_tshirt');
});
必要に応じて、製品の数量を指定することもできます。
use Illuminate\Http\Request;
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout(['price_tshirt' => 15]);
});
顧客がこのルートを訪問すると、Stripe のチェックアウト ページにリダイレクトされます。デフォルトでは、ユーザーが購入を正常に完了またはキャンセルすると、home ルートの場所にリダイレクトされますが、success_url および cancel_url オプションを使用してカスタム コールバック URL を指定することもできます。
use Illuminate\Http\Request;
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout(['price_tshirt' => 1], [
'success_url' => route('your-success-route'),
'cancel_url' => route('your-cancel-route'),
]);
});
success_url チェックアウト オプションを定義するときに、URL を呼び出すときにチェックアウト セッション ID をクエリ文字列パラメータとして追加するように Stripe に指示できます。これを行うには、リテラル文字列 {CHECKOUT_SESSION_ID} を success_url クエリ文字列に追加します。 Stripe は、このプレースホルダーを実際のチェックアウト セッション ID に置き換えます。
use Illuminate\Http\Request;
use Stripe\Checkout\Session;
use Stripe\Customer;
Route::get('/product-checkout', function (Request $request) {
return $request->user()->checkout(['price_tshirt' => 1], [
'success_url' => route('checkout-success') . '?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('checkout-cancel'),
]);
});
Route::get('/checkout-success', function (Request $request) {
$checkoutSession = $request->user()->stripe()->checkout->sessions->retrieve($request->get('session_id'));
return view('checkout.success', ['checkoutSession' => $checkoutSession]);
})->name('checkout-success');
プロモーションコード
デフォルトでは、Stripe Checkout は ユーザーが引き換え可能なプロモーション コード を許可しません。幸いなことに、チェックアウト ページでこれらを有効にする簡単な方法があります。これを行うには、allowPromotionCodes メソッドを呼び出します。
use Illuminate\Http\Request;
Route::get('/product-checkout', function (Request $request) {
return $request->user()
->allowPromotionCodes()
->checkout('price_tshirt');
});
シングルチャージチェックアウト
Stripe ダッシュボードで作成されていないアドホック製品に対して簡単な課金を実行することもできます。これを行うには、請求可能なモデルで checkoutCharge メソッドを使用し、請求可能な金額、製品名、およびオプションの数量を渡します。顧客がこのルートにアクセスすると、Stripe のチェックアウト ページにリダイレクトされます。
use Illuminate\Http\Request;
Route::get('/charge-checkout', function (Request $request) {
return $request->user()->checkoutCharge(1200, 'T-Shirt', 5);
});
{note} When using the
checkoutChargemethod, Stripe will always create a new product and price in your Stripe dashboard.したがって、Stripe ダッシュボードで事前に製品を作成し、代わりにcheckoutメソッドを使用することをお勧めします。
サブスクリプションのチェックアウト
{note} サブスクリプションに Stripe Checkout を使用するには、Stripe ダッシュボードで
customer.subscription.createdWebhook を有効にする必要があります。この Webhook は、データベースにサブスクリプション レコードを作成し、関連するすべてのサブスクリプション アイテムを保存します。
Stripe Checkout を使用してサブスクリプションを開始することもできます。 Cashier のサブスクリプション ビルダ メソッドを使用してサブスクリプションを定義した後、checkout メソッドを呼び出すことができます。顧客がこのルートにアクセスすると、Stripe のチェックアウト ページにリダイレクトされます。
use Illuminate\Http\Request;
Route::get('/subscription-checkout', function (Request $request) {
return $request->user()
->newSubscription('default', 'price_monthly')
->checkout();
});
製品のチェックアウトと同様に、成功 URL とキャンセル URL をカスタマイズできます。
use Illuminate\Http\Request;
Route::get('/subscription-checkout', function (Request $request) {
return $request->user()
->newSubscription('default', 'price_monthly')
->checkout([
'success_url' => route('your-success-route'),
'cancel_url' => route('your-cancel-route'),
]);
});
もちろん、サブスクリプションのチェックアウト用のプロモーション コードを有効にすることもできます。
use Illuminate\Http\Request;
Route::get('/subscription-checkout', function (Request $request) {
return $request->user()
->newSubscription('default', 'price_monthly')
->allowPromotionCodes()
->checkout();
});
{note} 残念ながら、Stripe Checkout は、サブスクリプションの開始時にすべてのサブスクリプション請求オプションをサポートしているわけではありません。サブスクリプションビルダでの
anchorBillingCycleOnメソッドの使用、比例配分動作の設定、または支払い動作の設定は、Stripe Checkout セッション中には影響しません。使用可能なパラメータを確認するには、Stripe チェックアウト セッション API ドキュメント を参照してください。
Stripe チェックアウトと試用期間
もちろん、Stripe Checkout を使用して完了するサブスクリプションを構築するときに、試用期間を定義できます。
$checkout = Auth::user()->newSubscription('default', 'price_monthly')
->trialDays(3)
->checkout();
ただし、試用期間は少なくとも 48 時間である必要があります。これは、Stripe Checkout でサポートされる最小試用時間です。
サブスクリプションとWebhook
Stripe と Cashier は Webhook 経由でサブスクリプションのステータスを更新するため、顧客が支払い情報を入力した後にアプリケーションに戻った時点では、サブスクリプションがまだ有効になっていない可能性があることに注意してください。このシナリオに対処するには、支払いまたはサブスクリプションが保留中であることをユーザーに通知するメッセージを表示することができます。
納税者番号の収集
Checkout では、顧客の納税者 ID の収集もサポートされています。チェックアウト セッションでこれを有効にするには、セッションの作成時に collectTaxIds メソッドを呼び出します。
$checkout = $user->collectTaxIds()->checkout('price_tshirt');
このメソッドを呼び出すと、顧客は会社として購入するかどうかを示す新しいチェックボックスが利用できるようになります。その場合、納税者 ID 番号を提供する機会が得られます。
{note} アプリケーションのサービスプロバイダで 自動税徴収 をすでに構成している場合、この機能は自動的に有効になるため、
collectTaxIdsメソッドを呼び出す必要はありません。
失敗した支払いの処理 (Handling Failed Payments)
場合によっては、サブスクリプションまたは単一料金の支払いが失敗することがあります。これが発生すると、Cashier はこれが発生したことを通知する Laravel\Cashier\Exceptions\IncompletePayment 例外をスローします。この例外をキャッチした後、続行する方法には 2 つのオプションがあります。
まず、顧客を Cashier に含まれる専用の支払い確認ページにリダイレクトできます。このページには、Cashier のサービスプロバイダを介して登録された、関連付けられた名前付きルートがすでに存在します。したがって、IncompletePayment 例外をキャッチして、ユーザーを支払い確認ページにリダイレクトできます。
use Laravel\Cashier\Exceptions\IncompletePayment;
try {
$subscription = $user->newSubscription('default', 'price_monthly')
->create($paymentMethod);
} catch (IncompletePayment $exception) {
return redirect()->route(
'cashier.payment',
[$exception->payment->id, 'redirect' => route('home')]
);
}
支払い確認ページで、顧客はクレジット カード情報を再度入力し、「3D セキュア」確認など、Stripe で必要な追加のアクションを実行するよう求められます。支払いを確認した後、ユーザーは上で指定した redirect パラメータで指定された URL にリダイレクトされます。リダイレクト時に、message (文字列) および success (整数) クエリ文字列変数が URL に追加されます。支払いページでは現在、次のタイプの支払い方法がサポートされています。
- クレジットカード
- アリペイ
- バンコンタクト
- BECS 口座振替
- EPS
- ギロペイ
- 理想的
- SEPA 口座振替
あるいは、Stripe が支払い確認を処理できるようにすることもできます。この場合、支払い確認ページにリダイレクトする代わりに、Stripe ダッシュボードで Stripe の自動請求メールを設定する を実行できます。ただし、IncompletePayment 例外がキャッチされた場合でも、支払い確認の手順が記載された電子メールを受け取ることをユーザーに通知する必要があります。
支払い例外は、Billable トレイトを使用するモデルの charge、invoiceFor、および invoice のメソッドに対してスローされる可能性があります。サブスクリプションを操作するとき、SubscriptionBuilder の create メソッド、および Subscription および SubscriptionItem モデルの incrementAndInvoice および swapAndInvoice メソッドは、不完全な支払い例外をスローする場合があります。
既存のサブスクリプションに支払いが完了していないかどうかを判断するには、請求可能モデルまたはサブスクリプション インスタンスで hasIncompletePayment メソッドを使用します。
if ($user->hasIncompletePayment('default')) {
//
}
if ($user->subscription('default')->hasIncompletePayment()) {
//
}
例外インスタンスの payment プロパティを検査することで、未完了の支払いの特定のステータスを取得できます。
use Laravel\Cashier\Exceptions\IncompletePayment;
try {
$user->charge(1000, 'pm_card_threeDSecure2Required');
} catch (IncompletePayment $exception) {
// Get the payment intent status...
$exception->payment->status;
// Check specific conditions...
if ($exception->payment->requiresPaymentMethod()) {
// ...
} elseif ($exception->payment->requiresConfirmation()) {
// ...
}
}
強力な顧客認証 (Strong Customer Authentication)
あなたのビジネスまたは顧客のいずれかがヨーロッパに拠点を置いている場合は、EU の強力な顧客認証 (SCA) 規制に従う必要があります。これらの規制は、支払い詐欺を防止するために 2019 年 9 月に欧州連合によって課されました。幸いなことに、Stripe と Cashier は SCA 準拠のアプリケーションを構築する準備ができています。
{note} 始める前に、PSD2 と SCA に関する Stripe のガイド と 新しい SCA API に関するドキュメント を確認してください。
追加の確認が必要な支払い
SCA 規制では、支払いを確認して処理するために追加の検証が必要になることがよくあります。これが発生すると、Cashier は追加の検証が必要であることを通知する Laravel\Cashier\Exceptions\IncompletePayment 例外をスローします。これらの例外を処理する方法の詳細については、失敗した支払いの処理 のドキュメントを参照してください。
Stripe または Cashier によって表示される支払い確認画面は、特定の銀行またはカード発行会社の支払いフローに合わせて調整することができ、追加のカード確認、一時的な少額請求、個別のデバイス認証、またはその他の形式の確認を含めることができます。
未完了および期限超過の状態
支払いに追加の確認が必要な場合、サブスクリプションは、stripe_status データベース列で示されるように、incomplete または past_due 状態のままになります。支払い確認が完了し、Stripe から Webhook 経由でアプリケーションに完了が通知されると、Cashier は顧客のサブスクリプションを自動的にアクティブ化します。
incomplete および past_due 状態の詳細については、これらの状態に関する追加のドキュメント を参照してください。
オフセッション支払い通知
SCA 規制により、顧客はサブスクリプションがアクティブな間でも支払いの詳細を時折確認する必要があるため、セッション外の支払い確認が必要な場合、Cashierは顧客に通知を送信できます。たとえば、これはサブスクリプションの更新時に発生する可能性があります。Cashierの支払い通知は、CASHIER_PAYMENT_NOTIFICATION 環境変数を通知クラスに設定することで有効にできます。デフォルトでは、この通知は無効になっています。もちろん、Cashier にはこの目的に使用できる通知クラスが含まれていますが、必要に応じて独自の通知クラスを自由に提供できます。
CASHIER_PAYMENT_NOTIFICATION=Laravel\Cashier\Notifications\ConfirmPayment
セッション外の支払い確認通知が確実に配信されるようにするには、アプリケーションの Stripe Webhook が設定されている と invoice.payment_action_required Webhook が Stripe ダッシュボードで有効になっていることを確認してください。さらに、Billable モデルは Laravel の Illuminate\Notifications\Notifiable トレイトも使用する必要があります。
{note} 追加の確認が必要な支払いを顧客が手動で行っている場合でも、通知は送信されます。残念ながら、Stripe には支払いが手動で行われたのか、または「オフセッション」で行われたのかを知る方法がありません。ただし、顧客が支払いを確認した後に支払いページにアクセスすると、単に「支払いが成功しました」というメッセージが表示されます。顧客が誤って同じ支払いを 2 回確認して、誤って 2 回目の請求が発生することは許されません。
StripeSDK (Stripe SDK)
Cashier のオブジェクトの多くは、Stripe SDK オブジェクトのラッパーです。 Stripe オブジェクトを直接操作したい場合は、asStripe メソッドを使用してオブジェクトを簡単に取得できます。
$stripeSubscription = $subscription->asStripeSubscription();
$stripeSubscription->application_fee_percent = 5;
$stripeSubscription->save();
updateStripeSubscription メソッドを使用して、Stripe サブスクリプションを直接更新することもできます。
$subscription->updateStripeSubscription(['application_fee_percent' => 5]);
Stripe\StripeClient クライアントを直接使用したい場合は、Cashier クラスの stripe メソッドを呼び出すことができます。たとえば、このメソッドを使用して StripeClient インスタンスにアクセスし、Stripe アカウントから価格のリストを取得できます。
use Laravel\Cashier\Cashier;
$prices = Cashier::stripe()->prices->all();
テスト (Testing)
Cashier を使用するアプリケーションをテストする場合、Stripe API への実際の HTTP リクエストをモックすることができます。ただし、これには、Cashier 自体の動作を部分的に再実装する必要があります。したがって、テストが実際の Stripe API にアクセスできるようにすることをお勧めします。これは遅くなりますが、アプリケーションが期待どおりに動作しているという信頼性が高まり、遅いテストは独自の PHPUnit テスト グループ内に配置される可能性があります。
テストするときは、Cashier 自体に優れたテスト スイートがすでに用意されているため、基礎となる Cashier の動作をすべてテストするのではなく、独自のアプリケーションのサブスクリプションと支払いフローのテストにのみ重点を置く必要があることに注意してください。
まず、テスト バージョンの Stripe シークレットを phpunit.xml ファイルに追加します。
<env name="STRIPE_SECRET" value="sk_test_<your-key>"/>
これで、テスト中に Cashier と対話するたびに、実際の API リクエストが Stripe テスト環境に送信されます。便宜上、Stripe テスト アカウントにテスト中に使用するサブスクリプション/価格を事前に入力しておく必要があります。
{tip} クレジット カードの拒否や失敗など、さまざまな請求シナリオをテストするには、Stripe が提供する幅広い カード番号とトークンのテスト を使用できます。