Laravel Cashier(Stripe)
はじめに
Laravel Cashier Stripe は、Stripe のサブスクリプション課金サービスに対して表現豊かで流暢なインターフェースを提供します。あなたが書くのをためらっているボイラープレートのサブスクリプション課金コードのほとんどを処理します。基本的なサブスクリプション管理に加えて、Cashier はクーポン、サブスクリプションの切り替え、サブスクリプションの「数量」、キャンセル猶予期間、さらには請求書の PDF の生成さえも処理できます。
Cashier のアップグレード
新しいバージョンの Cashier にアップグレードする際には、アップグレードガイド を注意深く確認することが重要です。
互換性のない変更を防ぐために、Cashier は固定された Stripe API バージョンを使用しています。Cashier 15 は Stripe API バージョン 2023-10-16
を利用しています。新しい Stripe の機能や改善を活用するために、Stripe API バージョンはマイナーリリースで更新されます。
インストール
まず、Composer パッケージマネージャを使用して Stripe のための Cashier パッケージをインストールします:
composer require laravel/cashier
パッケージをインストールした後、vendor:publish
Artisan コマンドを使用して Cashier のマイグレーションを公開します:
php artisan vendor:publish --tag="cashier-migrations"
その後、データベースをマイグレーションします:
php artisan migrate
Cashier のマイグレーションは、users
テーブルにいくつかの列を追加します。また、すべての顧客のサブスクリプションを保持する subscriptions
テーブルと、複数の価格を持つサブスクリプション用の subscription_items
テーブルを作成します。
必要であれば、vendor:publish
Artisan コマンドを使用して Cashier の設定ファイルを公開することもできます:
php artisan vendor:publish --tag="cashier-config"
最後に、Stripe イベン トを適切に処理するために、Cashier のウェブフック処理を設定 することを忘れないでください。
Stripe は、Stripe 識別子を保存するために使用される任意の列は大文字と小文字を区別する必要があると推奨しています。そのため、MySQL を使用する場合は stripe_id
列の列照合を utf8_bin
に設定する必要があります。これに関する詳細情報は、Stripe のドキュメント で確認できます。
設定
請求可能なモデル
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.
*/
public function boot(): void
{
Cashier::useCustomerModel(User::class);
}
Laravelの提供するApp\Models\User
モデル以外のモデルを使用している場合は、Cashier migrationsを公開して変更し、代替モデルのテーブル名に一致するようにする必要があります。
APIキー
次に、アプリケーションの.env
ファイルでStripeのAPIキーを設定する必要があります。StripeのコントロールパネルからStripeのAPIキーを取得できます:
STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret
アプリケーションの.env
ファイルでSTRIPE_WEBHOOK_SECRET
環境変数が定義されていることを確認する必要があります。この変数は、着信ウェブフックが実際にStripeからのものであることを確認するために使用されます。
通貨の設定
デフォルトのCashier通貨は米ドル(USD)です。アプリケーションの.env
ファイル内でCASHIER_CURRENCY
環境変数を設定することで、デフォルトの通貨を変更できます:
CASHIER_CURRENCY=eur
Cashierの通貨を設定するだけでなく、請求書上の金額を表示する際に使用されるロケールを指定することもできます。内部的には、CashierはPHPのNumberFormatter
クラスを使用して通貨のロケールを設定しています:
CASHIER_CURRENCY_LOCALE=nl_BE
en
以外のロケールを使用するには、サーバーにext-intl
PHP拡張機能がインストールおよび構成されていることを確認してください。
税金の設定
Stripe Taxのおかげで、Stripeが生成するすべての請求書の税金を自動的に計算することが可能です。App\Providers\AppServiceProvider
クラスのboot
メソッドでcalculateTaxes
メソッドを呼び出すことで、自動税金計算を有効にすることができます:
use Laravel\Cashier\Cashier;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Cashier::calculateTaxes();
}
税金の計算が有効になると、新しいサブスクリプションおよび生成される一時的な請求書に自動税金計算が適用されます。
この機能を正しく動作させるためには、顧客の請求先詳細(顧客の名前、住所、税IDなど)をStripeに同期する必要があります。これを達成するために、Cashierが提供する顧客データの同期およびTax IDメソッドを使用できます。
単発請求や単発請求チェックアウトには税金が計算されません。
ロギング
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.
*/
public function boot(): void
{
Cashier::useSubscriptionModel(Subscription::class);
Cashier::useSubscriptionItemModel(SubscriptionItem::class);
}
クイックスタート
製品の販売
Stripe Checkoutを利用する前に、Stripeダッシュボードで固定価格の製品を定義する必要があります。さらに、Cashierのウェブフック処理を設定する必要があります。
アプリケーションを介して製品やサブスクリプションの請求を提供することは、初めは難しいかもしれません。しかし、CashierとStripe Checkoutのおかげで、現代的で堅牢な支払い統合を簡単に構築することができます。
非繰り返しの単発製品に対して顧客に料金を請求するために、Cashierを使用して顧客をStripe Checkoutに誘導し、そこで支払い情報を提供し購入を確認します。支払いがCheckout経由で行われると、顧客はアプリケーション内で選択した成功URLにリダイレクトされます:
use Illuminate\Http\Request;
Route::get('/checkout', function (Request $request) {
$stripePriceId = 'price_deluxe_album';
$quantity = 1;
return $request->user()->checkout([$stripePriceId => $quantity], [
'success_url' => route('checkout-success'),
'cancel_url' => route('checkout-cancel'),
]);
})->name('checkout');
Route::view('/checkout/success', 'checkout.success')->name('checkout-success');
Route::view('/checkout/cancel', 'checkout.cancel')->name('checkout-cancel');
上記の例で示されているように、指定された「価格識別子」に対してCashierが提供するcheckout
メソッドを使用して、顧客をStripe Checkoutに誘導します。Stripeを使用する際、「価格」とは、特定の製品の定義された価格を指します。
必要に応じて、checkout
メソッドは自動的にStripeに顧客を作成し、そのStripe顧客レコードをアプリケーションのデータベース内の対応するユーザーに接続します。チェックアウトセッションを完了した後、顧客は専用の成功またはキャンセルページにリダイレクトさ れ、そこで顧客に情報メッセージを表示することができます。
Stripe Checkoutへのメタデータの提供
製品を販売する際、独自のアプリケーションで定義されたCart
およびOrder
モデルを使用して、完了した注文や購入した製品を追跡することが一般的です。購入を完了するために顧客をStripe Checkoutにリダイレクトする際、完了した購入を対応する注文に関連付けるために既存の注文識別子を提供する必要があるかもしれません。
これを達成するために、checkout
メソッドに metadata
の配列を提供することができます。ユーザーがチェックアウトプロセスを開始すると、当社のアプリケーション内で保留中の Order
が作成されると想像してみましょう。この例では、Cart
と Order
モデルは Cashier によって提供されていないため、自分のアプリケーションのニーズに基づいてこれらの概念を実装することができます:
use App\Models\Cart;
use App\Models\Order;
use Illuminate\Http\Request;
Route::get('/cart/{cart}/checkout', function (Request $request, Cart $cart) {
$order = Order::create([
'cart_id' => $cart->id,
'price_ids' => $cart->price_ids,
'status' => 'incomplete',
]);
return $request->user()->checkout($order->price_ids, [
'success_url' => route('checkout-success').'?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('checkout-cancel'),
'metadata' => ['order_id' => $order->id],
]);
})->name('checkout');
上記の例でわかるように、ユーザーがチェックアウトプロセスを開始すると、checkout
メソッドにカート/注文に関連付けられたすべての Stripe 価格識別子を提供します。もちろん、お客様がそれらを追加するときにこれらのアイテムを「ショッピングカート」または注文に関連付ける責任は、あなたのアプリケーションにあります。また、metadata
配列を介して注文の ID を Stripe Checkout セッションに提供します。最後に、Stripe が顧客をアプリケーションにリダイレクトする際に、Checkout 成功ルートに CHECKOUT_SESSION_ID
テンプレート変数を追加しました。Stripe が顧客をアプリケーションにリダイレクトする際に、このテンプレート変数は自動的に Checkout セッション ID で埋められます。
次に、Checkout 成功ルートを構築しましょう。これは、Stripe Checkout を介して購入が完了した後にユーザーがリダイレクトされるルートです。このルート内で、Stripe Checkout セッション ID と関連する Stripe Checkout インスタンスを取得 して、提供されたメタデータにアクセスし、顧客の注文を適切に更新することができます:
use App\Models\Order;
use Illuminate\Http\Request;
use Laravel\Cashier\Cashier;
Route::get('/checkout/success', function (Request $request) {
$sessionId = $request->get('session_id');
if ($sessionId === null) {
return;
}
$session = Cashier::stripe()->checkout->sessions->retrieve($sessionId);
if ($session->payment_status !== 'paid') {
return;
}
$orderId = $session['metadata']['order_id'] ?? null;
$order = Order::findOrFail($orderId);
$order->update(['status' => 'completed']);
return view('checkout-success', ['order' => $order]);
})->name('checkout-success');
Stripe のCheckout セッションオブジェクトに含まれるデータについての詳細は、Stripe のドキュメントを参照してください。