Laravel 7.x Laravel Cashier

イントロダクション

Laravel CashierはStripeによるサブスクリプション(定期課金)サービスの読みやすく、スラスラと記述できるインターフェイスを提供します。これにより書くのが恐ろしくなるような、サブスクリプション支払いのための決まりきったコードのほとんどが処理できます。基本的なサブスクリプション管理に加え、Cashierはクーポン、サブスクリプションの変更、サブスクリプション数、キャンセル猶予期間、さらにインボイスのPDF発行まで行います。

Cashierのアップデート

新しいバージョンのCashierへアップグレードする場合は、アップグレードガイドを注意深く確認することが重要です。

Note: ブレーキングチェンジを防ぐために、CashierではStripeの固定APIバージョンを使用しています。Cashier12では、Stripeの2020-03-02付けAPIバージョンを使用しています。Stripeの新機能や機能向上を利用するため、マイナーリリースでもStripe APIのバージョンを更新することがあります。

インストール

はじめに、Stripe向けCashierパッケージをComposerでインストールしてください。

composer require laravel/cashier

Note: Stripeの全イベントをCashierで確実に処理するために、CashierのWebhook処理の準備を行なってください。

データベースマイグレーション

CashierサービスプロバーダでCashierのデータベースマイグレーションを登録しています。ですから、パッケージをインストールしたら、データベースのマイグレーションを忘れず実行してください。Cashierマイグレーションはusersテーブルにいくつものカラムを追加し、顧客のサブスクリプションをすべて保持するために新しいsubscriptionsテーブルを作成します。

php artisan migrate

Cashierパッケージに始めから含まれているマイグレーションをオーバーライトしたい場合は、vendor:publish Artisanコマンドを使用しリソース公開できます。

php artisan vendor:publish --tag="cashier-migrations"

Cashierのマイグレーション実行を完全に防ぎたい場合は、Cashierが提供しているignoreMigrationsを使います。通常、このメソッドはAppServiceProviderregisterメソッドの中で実行すべきです。

use Laravel\Cashier\Cashier;

Cashier::ignoreMigrations();

Note: StripeはStripeの識別子を保存しておくカラムはケースセンシティブ(大文字小文字区別)にするべきだと勧めています。そのためstripe_idカラムには、たとえばMySQLではutf8_binのように、適切なカラムコレーションを確実に指定してください。詳しい情報は、Stripeのドキュメントをお読みください。

設定

Billableモデル

Cashierを使い始める前に、モデル定義にBillableトレイトを追加します。このトレイトはサブスクリプションの作成やクーポンの適用、支払い情報の更新などのような、共通の支払いタスク実行を提供する数多くのメソッドを提供しています。

use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;
}

CashierはLaravelに含まれているApp\UserクラスがBillableモデルであると仮定しています。これを変更する場合は、.envファイルでモデルを指定してください。

CASHIER_MODEL=App\User

Note: Laravelの提供するApp\Userモデル以外のモデルを使用する場合は、提供しているマイグレーションをリソース公開し、モデルのテーブル名に一致するように変更する必要があります。

APIキー

次に、.envファイルの中のStripeキーを設定する必要があります。Stripe APIキーは、Stripeのコントロールパネルから取得できます。

STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret

通貨設定

Cashierのデフォルト通貨は米ドル(USD)です。CASHIER_CURRENCY環境変数の指定で、デフォルト通貨を変更可能です。

CASHIER_CURRENCY=eur

Caishierの通貨設定に付け加え、インボイスで表示する金額のフォーマットをローケルを使い指定することも可能です。Cashierは内部で、通貨のローケルを指定するために、PHPのNumberFormatterクラスを利用しています。

CASHIER_CURRENCY_LOCALE=nl_BE

Note: en以外のローケルを指定する場合は、サーバ設定でext-intl PHP拡張がインストールされているのを確認してください。

ログ

Stripeに関連する例外をすべてログする時に使用できるログチャンネルをCashierでは指定できます。CASHIER_LOGGER環境変数を使用し、ログチャンネルを指定します。

CASHIER_LOGGER=stack

顧客

顧客の取得

Cashier::findBillableメソッドによりStripe IDで顧客を取得できます。Billableモデルのインスタンスを返します。

use Laravel\Cashier\Cashier;

$user = Cashier::findBillable($stripeId);

顧客の生成

サブスクリプションを開始しなくてもStripeで顧客を作成したい場合が、ときどき起きるでしょう。createAsStripeCustomerを使い、作成できます。

$stripeCustomer = $user->createAsStripeCustomer();

一度顧客をStripe上に作成しておき、後日サブスクリプションを開始することもできます。また、Stripe APIが提供するオプション($options)を配列として、追加引数に渡すことも可能です。

$stripeCustomer = $user->createAsStripeCustomer($options);

BillableなエンティティがすでにStripeの顧客である場合に顧客オブジェクトを返したい場合は、asStripeCustomerメソッドを使用できます。

$stripeCustomer = $user->asStripeCustomer();

createOrGetStripeCustomerメソッドは、顧客オブジェクトを返したいがBillableなエンティティがすでにStripeの顧客であるかどうかわからない場合に使用します。このメソッドは、まだ存在していない場合、Stripeに新しい顧客を作成します。

$stripeCustomer = $user->createOrGetStripeCustomer();

顧客の更新

まれに、Stripeの顧客を追加情報と一緒に直接更新したい状況もあります。updateStripeCustomerメソッドを使用してください。

$stripeCustomer = $user->updateStripeCustomer($options);

支払いポータル

顧客がサブスクリプションや支払い方法を管理したり、履歴を確認したりを簡単にできるよう、Stripeは支払いポータルを用意しています。コントローラやルートでredirectToBillingPortalメソッドを使えば、ユーザーを支払いポータルへリダイレクトできます。

use Illuminate\Http\Request;

public function billingPortal(Request $request)
{
    return $request->user()->redirectToBillingPortal();
}

サブスクリプションの管理を終えたユーザーは、アプリケーションのhomeルートへ戻されるのがデフォルトです。redirectToBillingPortalメソッドの引数としてユーザーの戻りURLを指定し、カスタマイズ可能です。

use Illuminate\Http\Request;

public function billingPortal(Request $request)
{
    return $request->user()->redirectToBillingPortal(
        route('billing')
    );
}

支払いポータルへのURLを生成のみしたい場合はbillingPortalUrlメソッドを使用してください。

$url = $user->billingPortalUrl(route('billing'));

支払い方法

支払い方法の保存

Stripeでサブスクリプションを生成するか「一度だけ」の課金を実行するためには、支払い方法を登録し、IDを取得する必要があります。サブスクリプションのための支払いメソッドか、一回だけの課金ためかによりアプローチが異なるため、以下で両方共にみていきましょう。

サブスクリプションの支払い方法

将来の仕様に備えて、顧客のクレジットカードを登録する場合、顧客の支払いメソッドの詳細を安全に集めるためにStripe Setup Intents APIを使う必要があります。"Setup Intent(意図)"は、Stripeに対し顧客の支払いメソッドを登録する意図を示しています。CashierのBillableトレイトは、新しいSetup Intentを簡単に作成できるcreateSetupIntentを含んでいます。顧客の支払いメソッドの詳細情報を集めるフォームをレンダーしたいルートやコントローラから、このメソッドを呼び出してください。

return view('update-payment-method', [
    'intent' => $user->createSetupIntent()
]);

Setup Intentを作成したらそれをビューに渡し、支払い方法を集める要素にsecretを付け加える必要があります。たとえば、このような「支払い方法更新」フォームを考えてください。

<input id="card-holder-name" type="text">

<!-- Stripe要素のプレースホルダ -->
<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) {
        // ユーザーに"error.message"を表示する…
    } else {
        // カードの検証に成功した…
    }
});

Stripeによりカードが検証されたら、顧客に付け加えたsetupIntent.payment_methodの結果をLaravelアプリケーションへ渡すことができます。支払い方法は新しい支払い方法を追加するのと、デフォルトの支払い方法を使用する、どちらかが選べます。新しい支払い方法を追加の支払いメソッド識別子を即時に使用することもできます。

Tip!! Setup Intentsと顧客支払いの詳細情報の収集に関するより詳しい情報は、Stripeが提供している概要をご覧ください。

一回のみの課金に対する支払い方法

顧客の支払いメソッドに対し一回のみの課金を作成する場合、ワンタイムの支払いメソッド識別子を使う必要があるだけで済みます。Stripeの制限により、保存されている顧客のデフォルト支払い方法は使用できません。Stripe.jsライブラリを使用し、顧客に支払い方法の詳細を入力してもらえるようにする必要があります。例として、以降のフォームを考えてみましょう。

<input id="card-holder-name" type="text">

<!-- Stripe要素のプレースホルダ -->
<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によりカードが検証し、安全な「支払い方法識別子」をSrtipeから取得します。

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) {
        // ユーザーに"error.message"を表示する…
    } else {
        // カードの検証に成功した…
    }
});

カードの検証が成功すれば、paymentMethod.idをLaravelアプリケーションに渡し、1回限りの支払いを処理できます。

支払い方法の取得

BillableモデルインスタンスのpaymentMethodsメソッドは、Laravel\Cashier\PaymentMethodインスタンスのコレクションを返します。

$paymentMethods = $user->paymentMethods();

デフォルト支払いメソッドを取得する場合は、defaultPaymentMethodメソッドを使用してください。

$paymentMethod = $user->defaultPaymentMethod();

findPaymentMethodメソッドを使用し、そのBillableモデルが持っている特定の支払いメソッドを取得することもできます。

$paymentMethod = $user->findPaymentMethod($paymentMethodId);

ユーザーが支払い方法を持っているかの判定

Billableモデルが自身のアカウントに付加されているデフォルト支払いメソッドを持っているかを判定するには、hasDefaultPaymentMethodメソッドを使用します。

if ($user->hasDefaultPaymentMethod()) {
    //
}

Billableモデルが自身のアカウントに付加されている支払いメソッドを最低1つ持っているかを判定するには、hasPaymentMethodメソッドを使用します。

if ($user->hasPaymentMethod()) {
    //
}

デフォルト支払い方法の更新

updateDefaultPaymentMethodメソッドは顧客のデフォルト支払い方法の情報を更新するために使用します。このメソッドはStripe支払いメソッド識別子を引数に取り、その新しい支払い方法がデフォルト支払い方法として設定されます。

$user->updateDefaultPaymentMethod($paymentMethod);

その顧客のデフォルト支払い方法情報をStripeの情報と同期したい場合は、updateDefaultPaymentMethodFromStripeメソッドを使用してください。

$user->updateDefaultPaymentMethodFromStripe();

Note: 顧客のデフォルト支払い方法は、インボイス発行処理と新しいサブスクリプションの生成にだけ使用されます。Stripeの制限により、一回だけの課金には使用されません。

支払い方法の追加

新しい支払い方法を追加するには、Billableのユーザーに対し、addPaymentMethodを呼び出します。支払いメソッド識別子を渡してください。

$user->addPaymentMethod($paymentMethod);

Tip!! 支払い方法の識別子の取得方法を学ぶには、支払い方法保持のドキュメントを確認してください。

支払い方法の削除

支払い方法を削除するには、削除したいLaravel\Cashier\PaymentMethodインスタンス上のdeleteメソッドを呼び出します。

$paymentMethod->delete();

deletePaymentMethodsメソッドは、そのBillableモデルの全支払いメソッド情報を削除します。

$user->deletePaymentMethods();

Note: アクティブなサブスクリプションがあるユーザーでは、デフォルト支払いメソッドが削除されないようにする必要があるでしょう。

サブスクリプション

サブスクリプション作成

サブスクリプションを作成するには最初にbillableなモデルのインスタンスを取得しますが、通常はApp\Userのインスタンスでしょう。モデルインスタンスが獲得できたら、モデルのサブスクリプションを作成するために、newSubscriptionメソッドを使います。

$user = User::find(1);

$user->newSubscription('default', 'price_premium')->create($paymentMethod);

newSubscriptionメソッドの最初の引数は、サブスクリプションの名前です。アプリケーションでサブスクリプションを一つしか取り扱わない場合、defaultprimaryと名づけましょう。2つ目の引数はユーザーが購入しようとしているサブスクリプションのプランを指定します。この値はStripeのプランの価格識別子に対応させる必要があります。

createメソッドはStripeの支払い方法識別子、もしくはPaymentMethodオブジェクトを引数に取り、サブスクリプションを開始するのと同時に、データベースの顧客IDと他の関連する支払い情報を更新します。

Note: サブスクリプションのcreate()へ支払いメソッド識別子を直接渡すと、ユーザーの保存済み支払いメソッドへ自動的に追加します。

注文数

サブスクリプションの作成時に注文数を指定する場合は、quantityメソッドを使います。

$user->newSubscription('default', 'price_monthly')
     ->quantity(5)
     ->create($paymentMethod);

詳細情報の指定

ユーザーとサブスクリプションに関する詳細情報を追加したい場合は、createメソッドの第2引数と第3引数へ渡すことができます。

$user->newSubscription('default', 'price_monthly')->create($paymentMethod, [
    'email' => $email,
], [
    'metadata' => ['note' => 'Some extra information.'],
]);

Stripeがサポートしている追加のフィールドについてのさらなる情報は、Stripeの顧客の作成サブスクリプションの作成ドキュメントを確認してください。

クーポン

サブスクリプションの作成時に、クーポンを適用したい場合は、withCouponメソッドを使用してください。

$user->newSubscription('default', 'price_monthly')
     ->withCoupon('code')
     ->create($paymentMethod);

サブスクリプションの追加

デフォルトの支払い方法を設定済みユーザーへサブスクリプションを追加する場合は、newSubscriptionメソッド使用時にaddメソッドが使えます。

$user = User::find(1);

$user->newSubscription('default', 'price_premium')->add();

サブスクリプション状態の確認

ユーザーがアプリケーションで何かを購入したら、バラエティー豊かで便利なメソッドでサブスクリプション状況を簡単にチェックできます。まず初めにsubscribedメソッドがtrueを返したら、サブスクリプションが現在試用期間であるにしても、そのユーザーはアクティブなサブスクリプションを持っています。

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

subscribedメソッドはルートミドルウェアで使用しても大変役に立つでしょう。ユーザーのサブスクリプション状況に基づいてルートやコントローラへのアクセスをフィルタリングできます。

public function handle($request, Closure $next)
{
    if ($request->user() && ! $request->user()->subscribed('default')) {
        // このユーザーは支払っていない顧客
        return redirect('billing');
    }

    return $next($request);
}

ユーザーがまだ試用期間であるかを調べるには、onTrialメソッドを使用します。このメソッドはまだ使用期間中であるとユーザーに警告を表示するために便利です。

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

subscribedToPlanメソッドは、そのユーザーがStripeの価格IDで指定したプランを購入しているかを確認します。以下の例では、ユーザーのdefaultサブスクリプションが、購入され有効なmonthlyプランであるかを確認しています。

if ($user->subscribedToPlan('price_monthly', 'default')) {
    //
}

subscribedToPlanメソッドに配列を渡せば、ユーザーのdefaultサブスクリプションが、購入され有効なmonthlyyearlyプランであるかを判定できます。

if ($user->subscribedToPlan(['price_monthly', 'price_yearly'], 'default')) {
    //
}

recurringメソッドはユーザーが現在サブスクリプションを購入中で、試用期間を過ぎていることを判断するために使用します。

if ($user->subscription('default')->recurring()) {
    //
}

キャンセルしたサブスクリプションの状態

ユーザーが一度アクティブな購入者になってから、サブスクリプションをキャンセルしたことを調べるには、cancelledメソッドを使用します。

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

また、ユーザーがサブスクリプションをキャンセルしているが、まだ完全に期限が切れる前の「猶予期間」中であるかを調べることもできます。たとえば、ユーザーが3月5日にサブスクリプションをキャンセルし、3月10日で無効になる場合、そのユーザーは3月10日までは「猶予期間」中です。subscribedメソッドは、この期間中、まだtrueを返すことに注目してください。

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

ユーザーがサブスクリプションをキャンセルし、「猶予期間」を過ぎていることを調べるには、endedメソッドを使ってください。

if ($user->subscription('default')->ended()) {
    //
}

サブスクリプションスコープ

特定状態のサブスクリプションをデータベースから簡単にクエリできるよう、ほとんどのサブスクリプション状態はクエリスコープとしても利用できます。

// アクティブサブスクリプションをすべて取得
$subscriptions = Subscription::query()->active()->get();

// 特定ユーザーのキャンセル済みサブスクリプションをすべて取得
$subscriptions = $user->subscriptions()->cancelled()->get();

以下に利用可能なサブスクリプションスコープをリストします。

Subscription::query()->active();
Subscription::query()->cancelled();
Subscription::query()->ended();
Subscription::query()->incomplete();
Subscription::query()->notCancelled();
Subscription::query()->notOnGracePeriod();
Subscription::query()->notOnTrial();
Subscription::query()->onGracePeriod();
Subscription::query()->onTrial();
Subscription::query()->pastDue();
Subscription::query()->recurring();

不十分と期日超過の状態

サブスクリプション作成後、そのサブクリプションが2つ目の支払いアクションを要求している場合、incomplete(不十分)として印がつけられます。サブスクリプションの状態は、Cashierのsubscriptionsデータベーステーブルのstripe_statusカラムに保存されます。

同様に、サブスクリプションの変更時に第2の支払いアクションが要求されている場合は、past_due(期日超過)として印がつけられます。サブスクリプションが2つのどちらかである時、顧客が支払いを受領するまで状態は有効になりません。あるサブクリプションに不十分な支払いがあるかを確認する場合は、Billableモデルかサブクリプションインスタンス上の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メソッドを使用します。通常このメソッドは、AppServiceProviderregisterメソッドの中で呼び出すべきです。

use Laravel\Cashier\Cashier;

/**
 * 全アプリケーションサービスの登録
 *
 * @return void
 */
public function register()
{
    Cashier::keepPastDueSubscriptionsActive();
}

Note: あるサブクリプションにincomplete状態がある場合、支払いを確認するまでは変更できません。そのためサブクリプションがincomplete状態では、swapupdateQuantityメソッドは例外を投げます。

プラン変更

アプリケーションの購入済みユーザーが新しいサブスクリプションプランへ変更したくなるのはよくあるでしょう。ユーザーを新しいサブスクリプションに変更するには、swapメソッドへプランの価格識別子を渡します。

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

$user->subscription('default')->swap('provider-price-id');

ユーザーが試用期間中の場合、試用期間は継続します。また、そのプランに「購入数」が存在している場合、購入個数も継続します。

プランを変更し、ユーザーの現プランの試用期間をキャンセルする場合は、skipTrialメソッドを使用します。

$user->subscription('default')
        ->skipTrial()
        ->swap('provider-price-id');

次の支払いサイクルまで待つ代わりに、プランを変更時即時にインボイスを発行したい場合は、swapAndInvoiceメソッドを使用します。

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

$user->subscription('default')->swapAndInvoice('provider-price-id');

按分課金

デフォルトでStripeはプランの変更時に按分課金(日割り計算:prorate)を行います。noProrateメソッドは按分課金を行わずにサブスクリプションの更新を指定するために使用します。

$user->subscription('default')->noProrate()->swap('provider-price-id');

サブスクリプションの按分課金についての情報は、Stripeドキュメントで確認してください。

Note: swapAndInvoiceメソッドの前にnoProrateメソッドを実行しても按分課金には影響しません。インボイスは常に発行されます。

購入数

購入数はサブスクリプションに影響をあたえることがあります。たとえば、あるアプリケーションで「ユーザーごと」に毎月10ドル課金している場合です。購入数を簡単に上げ下げするには、incrementQuantitydecrementQuantityメソッドを使います。

$user = User::find(1);

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

// 現在の購入数を5個増やす
$user->subscription('default')->incrementQuantity(5);

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

// 現在の購入数を5個減らす
$user->subscription('default')->decrementQuantity(5);

もしくは特定の数量を設置するには、updateQuantityメソッドを使ってください。

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

noProrateメソッドは、按分課金を行わずにサブスクリプションの購入数を更新するために使用します。

$user->subscription('default')->noProrate()->updateQuantity(10);

サブスクリプション数の詳細については、Stripeドキュメントを読んでください。

Note: マルチプランサブスクリプションを使用する場合、上記の数量メソッドには追加の「プラン」パラメーターが必要です。

複数のサブスクリプション

複数のサブスクリプションでは、1つのサブスクリプションに複数の請求プランを割り当てられます。たとえば、月額10ドルの基本サブスクリプションがあり、さらに月額16ドルのライブチャットアドオンプランを提供する、カスタマーサービスの「ヘルプデスク」アプリケーションを構築していると想像してください。

$user = User::find(1);

$user->newSubscription('default', [
    'price_monthly',
    'chat-plan',
])->create($paymentMethod);

これにより、顧客は新しいデフォルト(default)サブスクリプションを購入できました。両プランともそれぞれの課金期間に応じ、課金されます。各プランの購入数を指定するためにquantityメソッドも使えます。

$user = User::find(1);

$user->newSubscription('default', ['price_monthly', 'chat-plan'])
    ->quantity(5, 'chat-plan')
    ->create($paymentMethod);

もしくはplanメソッドで、追加のプランと購入数を動的に指定できます。

$user = User::find(1);

$user->newSubscription('default', 'price_monthly')
    ->plan('chat-plan', 5)
    ->create($paymentMethod);

他の方法として、既存のサブスクリプションへ後から、新しいプランを追加できます。

$user = User::find(1);

$user->subscription('default')->addPlan('chat-plan');

上記の例では新しいプランが追加され、次の請求サイクルで顧客へ請求されます。すぐに顧客に請求したい場合は、addPlanAndInvoiceメソッドを使用します。

$user->subscription('default')->addPlanAndInvoice('chat-plan');

プラン追加と同時に購入数を指定したい場合は、addPlanaddPlanAndInvoiceメソッドの第2引数へ購入数を渡してください。

$user = User::find(1);

$user->subscription('default')->addPlan('chat-plan', 5);

サブスクリプションからプランを削除したい場合は、removePlanメソッドを使用します。

$user->subscription('default')->removePlan('chat-plan');

Note: サブスクリプションの最後のプランは削除できません。その代わりにサブスクリプションをシンプルにキャンセルしてください。

プラン切り替え

複数のサブスクリプションに紐付いているプランを変更することもできます。たとえば、chat-planアドオンを含むbasic-planサブスクリプションを利用していて、pro-planプランにアップグレードしたいとします。

$user = User::find(1);

$user->subscription('default')->swap(['pro-plan', 'chat-plan']);

上記のコードを実行すると、basic-planを含む基になるサブスクリプションアイテムが削除され、chat-planを含むものが保持されます。さらに、新しいpro-planのために新しいサブスクリプションアイテムが作成されます。

サブスクリプションアイテムのオプションを指定することもできます。たとえば、プランの購入数を指定する必要が起きる場合もあるでしょう。

$user = User::find(1);

$user->subscription('default')->swap([
    'pro-plan' => ['quantity' => 5],
    'chat-plan'
]);

サブスクリプション上のプランをひとつだけ切り替える場合は、サブスクリプションアイテム自体に対してswapメソッドを使用してください。このアプローチは、たとえばサブスクリプションアイテムの既存のメタデータをすべて保持したい場合に役立ちます。

$user = User::find(1);

$user->subscription('default')
        ->findItemOrFail('basic-plan')
        ->swap('pro-plan');

按分課金

Stripeはサブスクリプションのプランを追加または削除する場合、デフォルトで料金を按分課金(日割り計算:prorate)します。按分課金を行わずにプランを調整する場合は、noProrateメソッドをプラン操作へチェーンしてください。

$user->subscription('default')->noProrate()->removePlan('chat-plan');

購入数

個々のサブスクリプションプランの購入数を更新する場合は、既存の購入数メソッドをつかい、メソッドの追加の引数としてプラン名を渡してください。

$user = User::find(1);

$user->subscription('default')->incrementQuantity(5, 'chat-plan');

$user->subscription('default')->decrementQuantity(3, 'chat-plan');

$user->subscription('default')->updateQuantity(10, 'chat-plan');

Note: サブスクリプションに複数のプランを設定している場合、Subscriptionモデルのstripe_planおよびquantity属性はnullになります。個々のプランにアクセスするには、Subscriptionモデルで利用可能なitemsリレーションを使用する必要があります。

サブスクリプションアイテム

サブスクリプションに複数のプランがある場合、データベースのsubscription_itemsテーブルに複数のサブスクリプション「アイテム」が保存されます。サブスクリプションのitemsリレーションを介してこれらにアクセスできます:

$user = User::find(1);

$subscriptionItem = $user->subscription('default')->items->first();

// Retrieve the Stripe plan and quantity for a specific item...
$stripePlan = $subscriptionItem->stripe_plan;
$quantity = $subscriptionItem->quantity;

findItemOrFailメソッドを使用し、特定のプランを取得することも可能です。

$user = User::find(1);

$subscriptionItem = $user->subscription('default')->findItemOrFail('chat-plan');

サブスクリプションの税金

ユーザーがサブスクリプションに対して支払う税率を指定するには、BillableモデルにtaxRatesメソッドを実装し、税率IDを含む配列を返してください。これらの税率は、[Stripeダッシュボード](https://dashboard.stripe.com/test/tax-rates)で定義できます。

public function taxRates()
{
    return ['tax-rate-id'];
}

taxRatesメソッドを使用すると、モデルごとに税率を適用できます。これは、複数の国や税率にまたがるユーザー向けサービスで役立つでしょう。マルチプランサブスクリプションを使用している場合は、BillableモデルにplanTaxRatesメソッドを実装することで、プランごとに異なる税率を定義できます。

public function planTaxRates()
{
    return [
        'plan-id' => ['tax-rate-id'],
    ];
}

Note: taxRatesメソッドはサブスクリプション料金にのみ適用されます。Cashierを使用して「1回限り」の請求を行う場合は、その時点で税率を手動で指定する必要があります。

税率の同期

taxRatesメソッドが返すハードコードされた税率IDを変更しても、ユーザーの既存サブスクリプションの税率設定は同じままです。返されたtaxTaxRates値で既存サブスクリプションの税率を更新する場合は、ユーザーのサブスクリプションインスタンスに対し、syncTaxRatesメソッドを呼び出す必要があります。

$user->subscription('default')->syncTaxRates();

これはサブスクリプションアイテムの税率も同期するため、planTaxRatesメソッドも適切に変更してください。

非課税

キャッシャーは、Stripe APIを呼び出して顧客が非課税かを判断するメソッドも提供します。isNotTaxExemptおよびisTaxExemptreverseChargeAppliesメソッドはBillableモデルで使用できます。

$user = User::find(1);

$user->isTaxExempt();
$user->isNotTaxExempt();
$user->reverseChargeApplies();

これらのメソッドは、任意の Laravel\Cashier\Invoiceオブジェクトでも使用できます。ただし、Invoiceオブジェクトでこれらのメソッドを呼び出すと、メソッドはインボイス作成時の非課税状態であると判断します。

サブスクリプション課金日付け

デフォルトで課金日はサブスクリプションが生成された日付け、もしくは使用期間を使っている場合は、使用期間の終了日です。課金日付を変更したい場合は、anchorBillingCycleOnメソッドを使用します。

use App\User;
use Carbon\Carbon;

$user = User::find(1);

$anchor = Carbon::parse('first day of next month');

$user->newSubscription('default', 'price_premium')
            ->anchorBillingCycleOn($anchor->startOfDay())
            ->create($paymentMethod);

サブスクリプションの課金間隔を管理する情報は、Stripeの課金サイクルのドキュメントをお読みください。

サブスクリプションキャンセル

サブスクリプションをキャンセルするにはcancelメソッドをユーザーのサブスクリプションに対して使ってください。

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

サブスクリプションがキャンセルされるとCashierは自動的に、データベースのends_atカラムをセットします。このカラムはいつからsubscribedメソッドがfalseを返し始めればよいのか、判定するために使用されています。たとえば、顧客が3月1日にキャンセルしたが、そのサブスクリプションが3月5日に終了するようにスケジュールされていれば、subscribedメソッドは3月5日になるまでtrueを返し続けます。

ユーザーがサブスクリプションをキャンセルしたが、まだ「猶予期間」が残っているかどうかを調べるにはonGracePeriodメソッドを使います。

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

サブスクリプションを即時キャンセルしたい場合は、ユーザーのサブスクリプションに対し、cancelNowメソッドを呼び出してください。

$user->subscription('default')->cancelNow();

サブスクリプション再開

ユーザーがキャンセルしたサブスクリプションを、再開したいときには、resumeメソッドを使用してください。サブスクリプションを再開するには、そのユーザーに有効期間が残っている必要があります

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

ユーザーがサブスクリプションをキャンセルし、それからそのサブスクリプションを再開する場合、そのサブスクリプションの有効期日が完全に切れていなければすぐに課金されません。そのサブスクリプションはシンプルに再度有効になり、元々の支払いサイクルにより課金されます。

サブスクリプションのトレイト

支払いの事前登録あり

顧客へ試用期間を提供し、支払情報を事前に登録してもらう場合、サブスクリプションを作成するときにtrialDaysメソッドを使ってください。

$user = User::find(1);

$user->newSubscription('default', 'price_monthly')
            ->trialDays(10)
            ->create($paymentMethod);

このメソッドはデータベースのサブスクリプションレコードへ、試用期間の終了日を設定すると同時に、Stripeへこの期日が過ぎるまで、顧客へ課金を始めないように指示します。trialDaysメソッドを使用する場合、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()) {
    //
}

Stripe/Cashierで使用期間を定義する

Stripeダッシュボードによりプランで受け入れる試用日数を定義するか、Cashierを使用して常に明示的に引数で渡すか選んでください。Stripeでプランの試用日数を定義することを選択する場合、過去にサブスクリプションを購入した顧客の新規サブスクリプションも含め、新規サブスクリプションは明示的にtrialDays(0)を呼び出さない限り、常に試用期間を受け取ることに注意してください。

支払いの事前登録なし

事前にユーザーの支払い方法の情報を登録してもらうことなく、試用期間を提供する場合は、そのユーザーのレコードのtrial_ends_atに、試用の最終日を設定するだけです。典型的な使い方は、ユーザー登録時に設定する方法でしょう。

$user = User::create([
    // 他のユーザープロパティの設定…
    'trial_ends_at' => now()->addDays(10),
]);

Note: モデル定義のtrial_ends_atに対する、日付ミューテタを付け加えるのを忘れないでください。

既存のサブスクリプションと関連付けが行われていないので、Cashierでは、このタイプの試用を「包括的な試用(generic trial)」と呼んでいます。Userインスタンスに対し、onTrialメソッドがtrueを返す場合、現在の日付はtrial_ends_atの値を過ぎていません。

if ($user->onTrial()) {
    // ユーザーは試用期間中
}

とくに、ユーザーが「包括的な試用」期間中であり、まだサブスクリプションが作成されていないことを調べたい場合は、onGenericTrialメソッドが使用できます。

if ($user->onGenericTrial()) {
    // ユーザーは「包括的」な試用期間中
}

ユーザーに実際のサブスクリプションを作成する準備ができたら、通常はnewSubscriptionメソッドを使います。

$user = User::find(1);

$user->newSubscription('default', 'price_monthly')->create($paymentMethod);

試用期限の延長

一度作成したあとに、サブスクリプションの試用期間を延長したい場合は、extendTrialメソッドを使用します。

// 今から7日後に試用期限を終える
$subscription->extendTrial(
    now()->addDays(7)
);

// 使用期限を5日間延長する
$subscription->extendTrial(
    $subscription->trial_ends_at->addDays(5)
);

試用期間が過ぎ、顧客がサブスクリプションをすでに購入している場合でも、追加の試用期限を与えられます。試用期間で費やされた時間は、その顧客の次回のインボイスから差し引かれます。

StripeのWebフック処理

Tip!! ローカル環境でWebhooksのテストするには、Stripe CLIが役立つでしょう。

StripeはWebフックにより、アプリケーションへさまざまなイベントを通知できます。デフォルトで、CashierのWebhookを処理するルートのコントローラは、Cashierのサービスプロバイダで設定されています。このコントローラはWebhookの受信リクエストをすべて処理します。

デフォルトでこのコントローラは、課金に多く失敗し続ける(Stripeの設定で定義している回数)、顧客の更新、顧客の削除、サブスクリプションの変更、支払い方法の変更があると、自動的にサブスクリプションをキャンセル処理します。しかしながら、すぐに見つけることができるようにこのコントローラを拡張し、どんなWebhookイベントでもお好きに処理できます

アプリケーションでStripeのWebhookを処理するためには、StripeのコントロールパネルでWebhook URLを確実に設定してください。CashierのWebhookのデフォルトコントローラは、/stripe/webhookのURIをリッスンしています。Stripeのコントロールパネルで設定する必要のあるWebhookの全リストは、以下のとおりです。

Note: Cashierに含まれる、Webフック署名の確認ミドルウェアを使用し、受信リクエストを確実に保護してください。

WebフックとCSRF保護

StripeのWebフックでは、Laravelの CSRFバリデーションをバイパスする必要があるため、VerifyCsrfTokenミドルウェアのURIを例外としてリストしておくか、ルート定義をwebミドルウェアグループのリストから外しておきましょう。

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

Webフックハンドラの定義

Cashierは課金の失敗時に、サブスクリプションを自動的にキャンセル処理しますが、他のWebフックイベントを処理したい場合は、Webフックコントローラを拡張します。メソッド名はCashierが期待する命名規則に沿う必要があります。とくにメソッドはhandleのプレフィックスで始まり、処理したいStripeのWebフックの名前を「キャメルケース」にします。たとえば、invoice.payment_succeeded Webフックを処理する場合は、handleInvoicePaymentSucceededメソッドをコントローラに追加します。

<?php

namespace App\Http\Controllers;

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

class WebhookController extends CashierController
{
    /**
     * インボイス支払い成功時の処理
     *
     * @param  array  $payload
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function handleInvoicePaymentSucceeded($payload)
    {
        // イベントの処理…
    }
}

次に、routes/web.phpの中で、キャッシャーコントローラへのルートを定義します。これにより、デフォルトのルートが上書きされます。

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

CashierはWebhookを受け取ると、Laravel\Cashier\Events\WebhookReceivedイベントを発行します。そして、WebhookがCashierにより処理されると、Laravel\Cashier\Events\WebhookHandledイベントを発行します。両方のイベント共にStripeのWebhookの完全なペイロードを持っています。

サブスクリプション不可

顧客のクレジットカードが有効期限切れだったら? 心配いりません。CashierのWebhookコントローラが顧客のサブスクリプションをキャンセルします。失敗した支払いは自動的に捉えられ、コントローラにより処理されます。このコントローラはStripeがサブスクリプションに失敗したと判断した場合、顧客のサブスクリプションを取り消します。(通常、3回の課金失敗)

Webフック署名の確認

Webフックを安全にするため、StripeのWebフック署名が利用できます。便利に利用できるよう、Cashierは送信されてきたWebフックリクエストが有効なものか確認するミドルウェアをあらかじめ用意しています。

Webhookの確認を有効にするには、.envファイル中のSTRIPE_WEBHOOK_SECRET環境変数を確実に設定してください。Stripeアカウントのダッシュボードから取得される、Webhookのsecretを指定します。

一回だけの課金

課金のみ

Note: chargeメソッドにはアプリケーションで使用している通貨の最低単位で金額を指定します。

サブスクリプションを購入している顧客の支払いメソッドに対して、「一回だけ」の課金を行いたい場合は、Billableモデルインスタンス上のchargeメソッドを使用します。第2引数に支払い方法識別子を渡してください。

// Stripeはセント単位で課金する
$stripeCharge = $user->charge(100, $paymentMethod);

chargeメソッドは第3引数に配列を受け付け、裏で動いているStripeの課金作成に対するオプションを指定できます。課金作成時に使用できるオプションについては、Stripeのドキュメントを参照してください。

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

裏で動作する顧客やユーザーがなくても、chargeメソッドは使用できます。

use App\User;

$stripeCharge = (new User)->charge(100, $paymentMethod);

課金に失敗すると、chargeメソッドは例外を投げます。課金に成功すれば、メソッドはLaravel\Cashier\Paymentのインスタンスを返します。

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

インボイス付き課金

一回だけ課金をしつつ、顧客へ発行するPDFのレシートとしてインボイスも生成したいことがあります。invoiceForメソッドは、まさにそのために存在しています。例として、「一回だけ」の料金を5ドル課金してみましょう。

// Stripeはセント単位で課金する
$user->invoiceFor('One Time Fee', 500);

金額は即時にユーザーのデフォルト支払い方法へ課金されます。invoiceForメソッドは第3引数に配列を受け付けます。この配列はインボイスアイテムへの支払いオプションを含みます。第4引数も配列で、インボイス自身に対する支払いオプションを指定します。

$user->invoiceFor('Stickers', 500, [
    'quantity' => 50,
], [
    'default_tax_rates' => ['tax-rate-id'],
]);

Note: invoiceForメソッドは、課金失敗時にリトライするStripeインボイスを生成します。リトライをしてほしくない場合は、最初に課金に失敗した時点で、Stripe APIを使用し、生成したインボイスを閉じる必要があります。

払い戻し

Stripeでの課金を払い戻す必要がある場合は、refundメソッドを使用します。このメソッドの第1引数は、Stripe Payment Intent IDです。

$payment = $user->charge(100, $paymentMethod);

$user->refund($payment->id);

インボイス

インボイス取得

invoicesメソッドにより、billableモデルのインボイスの配列を簡単に取得できます。

$invoices = $user->invoices();

// 結果にペンディング中のインボイスも含める
$invoices = $user->invoicesIncludingPending();

指定したインボイスを取得する、findInvoiceメソッドも使用できます。

$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>

インボイスPDF生成

ルートやコントローラの中でdownloadInvoiceメソッドを使うと、そのインボイスのPDFダウンロードを生成できます。このメソッドはブラウザへダウンロードのHTTPレスポンスを正しく行う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',
    ]);
});

downloadInvoiceメソッドでは、3番目の引数としてオプションのカスタムファイル名も指定できます。このファイル名は自動的に".pdf"のサフィックスが付けられます。

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

課金失敗の処理

サブスクリプションへの支払い、もしくは一回のみの課金は失敗することがあります。これが発生したことを知らせるため、CashierはIncompletePayment例外を投げます。この例外を補足した後の処理方法は、2つの選択肢があります。

最初の方法は、その顧客をCashierに含まれている支払い確認専門ページへリダイレクトする方法です。このページに紐つけたルートは、Cashierのサービスプロバイダで登録済みです。IncompletePayment例外を捉えたら、支払い確認ページへリダイレクトします。

use Laravel\Cashier\Exceptions\IncompletePayment;

try {
    $subscription = $user->newSubscription('default', $planId)
                            ->create($paymentMethod);
} catch (IncompletePayment $exception) {
    return redirect()->route(
        'cashier.payment',
        [$exception->payment->id, 'redirect' => route('home')]
    );
}

支払い確認ページで顧客はクレジットカード情報の入力を再度促され、「3Dセキュア」のような追加のアクションがStripeにより実行されます。支払いが確認されたら、上記のようにredirect引数で指定されたURLへユーザーはリダイレクトされます。支払いを確認したら、そのユーザーは上記のようにredirectパラメータで指定されたURLへリダイレクトされます。リダイレクトにはURLへmessage(文字列)とsuccess(整数)クエリ文字列値が追加されます。

別の方法として、Stripeに支払いの処理を任せることもできます。この場合、支払い確認ページへリダイレクトする代わりに、StripeダッシュボードでStripeの自動支払いメールを瀬一定する必要があります。しかしながら、IncompletePayment例外を捉えたら、支払い確認方法の詳細がメールで送られることをユーザーへ知らせる必要があります。

不完全な支払いの例外は、Billableのユーザーに対するchargeinvoiceForinvoiceメソッドで投げられる可能性があります。スクリプションが処理される時、SubscriptionBuildercreateメソッドと、SubscriptionモデルのincrementAndInvoiceswapAndInvoiceメソッドは、例外を発生させる可能性があります。

IncompletePaymentを拡張している支払い例外は現在2タイプ存在します。必要に応じユーザーエクスペリエンスをカスタマイズするために、これらを別々に補足できます。

  • PaymentActionRequired: これはStripeが支払いの確認と処理のために、追加の確認を要求していることを示します。
  • PaymentFailure: これは利用可能な資金が無いなど、様々な理由で支払いが失敗したことを示します。

堅牢な顧客認証 (SCA)

皆さんのビジネスがヨーロッパを基盤とするものであるなら、堅牢な顧客認証 (SCA)規制を守る必要があります。これらのレギュレーションは支払い詐欺を防ぐためにEUにより2019年9月に課せられたものです。幸運なことに、StripeとCashierはSCA準拠のアプリケーション構築のために準備をしてきました。

Note: 始める前に、StripeのPSD2とSCAのガイドと、新SCA APIのドキュメントを確認してください。

支払い要求の追加確認

SCA規制は支払いの確認と処理を行うため、頻繁に追加の検証を要求しています。これが起きるとCashierはPaymentActionRequired例外を投げ、この追加の検証が必要であるとあなたに知らせます。この例外をどのように処理するかは、失敗した支払いの処理方法のセクションをお読みください。

不十分と期日超過の状態

支払いが追加の確認を必要とする場合そのサブクリプションは、stripe_statusデータベースカラムにより表されるincompletepast_due状態になります。Cashierは支払いの確認が完了するとすぐに、Webhookによりその顧客のサブスクリプションを自動的に有効にします。

incompletepast_due状態の詳細は、追加のドキュメントを参照してください。

非セッション確立時の支払い通知

SCA規制は、サブスクリプションが有効なときにも、ときどき支払いの詳細を確認することを顧客に求めています。Cashierではセッションが確立していない時に支払いの確認が要求された場合に、顧客へ支払いの通知を送ることができます。たとえば、サブスクリプションを更新する時にこれが起きます。Cashierの支払い通知はCASHIER_PAYMENT_NOTIFICATION環境変数へ通知クラスをセットすることで有効になります。デフォルトでは、この通知は無効です。もちろん、Cashierにはこの目的に使うための通知クラスが含まれていますが、必要であれば自作の通知クラスを自由に指定できます。

CASHIER_PAYMENT_NOTIFICATION=Laravel\Cashier\Notifications\ConfirmPayment

非セッション時の支払い確認通知が確実に届くよう、StripeのWebhookが設定されており、Stripeのダッシュボードでinvoice.payment_action_required Webhookが有効になっていることを確認してください。さらに、BillableモデルがLaravelのIlluminate\Notifications\Notifiableトレイトを使用していることも確認してください。

Note: 定期課金でなく、顧客が自分で支払った場合でも追加の確認が要求された場合は、その顧客に通知が送られます。残念ながら、Stripeはその支払いが手動や「非セッション時」であることを知る方法がありません。しかし、顧客は支払いを確認した後に支払いページを閲覧したら、「支払いが完了しました」メッセージを確認できます。その顧客は同じ支払いを2度行い、二重に課金されるアクシデントに陥ることを防ぐことができるでしょう。

Stripe SDK

CashierのオブジェクトはStripe SDKオブジェクト上にラップされています。Stripe SDKオブジェクトを直接操作したい場合は、asStripeメソッドを使い簡単に取得できます。

$stripeSubscription = $subscription->asStripeSubscription();

$stripeSubscription->application_fee_percent = 5;

$stripeSubscription->save();

Stripeのサブスクリプションを直接更新するために、updateStripeSubscriptionも使用できます。

$subscription->updateStripeSubscription(['application_fee_percent' => 5]);

テスト

Cashierを使用するアプリケーションをテストする場合、Stripe APIに対する実際のHTTPリクエストをモックしたいことがあります。しかしながら、これはCashier自身の動作を部分的に再実装する必要があります。そのためテストでは実際のStripe APIへアクセスすることを勧めます。この方法は低速ですが、アプリケーションが期待どおりに動作していることをより確信できます。そして遅いテストは独自のPHPUnitテストグループに配置できます。

Cashier自身はすでに十分なテストスーツを持っているため、Cashierの裏で実行されているすべての振る舞いをテストする必要がないことを思い出してください。自分のアプリケーションにおけるサブスクリプションと支払いのフローをテストすることだけに集中すべきでしょう。

使用開始する前に、phpunit.xmlファイルへtestingバージョンのStripeシークレットを追加します。

<env name="STRIPE_SECRET" value="sk_test_<your-key>"/>

これで、常にテスト中のCashierとのやり取りは、Stripeテスト環境へ実際のAPIリクエストが送信されます。便宜上、Stripeテストアカウントで、テスト中に使用するサブスクリプション/プランを事前に入力しておく必要があります。

Tip!! クレジットカードの拒否や失敗など、さまざまな請求シナリオをテストするために、Stripeが提供しているさまざまなテストカード番号とトークンを使用できます。

ドキュメント章別ページ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる