laravel-billing について
StripeまたはPaddleを使った課金実装を扱う、Laravel Cashier向けのスキルです。サブスクリプション、決済フロー、安全対策、SaaS課金パターンに加え、FuseCoreとの連携も説明します。
主な機能
- 01StripeとPaddleの選択指針
- 02サブスクリプションのライフサイクルとトライアル
- 03Webhook処理と署名検証
- 04チェックアウト、請求書、支払い方法
- 05従量課金、チーム課金、プラン別課金
- 06FuseCore連携の参考資料とテンプレート
活用シーン
- 01Laravelアプリへのサブスクリプション導入
- 02決済Webhookの安全な処理
- 03従量課金または座席単位課金の追加
- 04支払い失敗への対応とプラン別機能制御
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ fusengine/ agents --skill laravel-billingインストール後、Claude Code で/laravel-billingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/checkout.mddunning.mdfeature-flags.mdinvoices.mdmetered-billing.mdpaddle.mdpayment-methods.mdstripe.mdsubscriptions.mdteam-billing.mdtesting.mdwebhooks.mdreferences/templates/BillingRoutes.php.mdCheckoutController.php.mdDunningService.php.mdFeatureFlags.php.mdInvoiceController.php.mdMeteredBillingController.php.mdSubscriptionController.php.mdSubscriptionTest.php.mdTeamBillable.php.mdUserBillable.php.mdWebhookController.php.md詳細
Stripe と Paddle 向けの Laravel Cashier を解説します。両者の選択(決済プロセッサーと Merchant of Record、税務処理、手数料)、サブスクリプションのライフサイクル(作成、プラン変更、キャンセル、再開、トライアル、猶予期間)、Webhook と署名検証、請求書、支払い方法、チェックアウト/カスタマーポータル、従量課金、チーム/ユーザー単位の課金、督促(支払い失敗からの回復)、プランごとの Pennant ベースの機能フラグが含まれます。FuseCore のモジュール型プロジェクトとの統合にも対応しています。複数ベンダー/マーケットプレイスの分割決済については、代わりに laravel-stripe-connect をご覧ください。
Laravel Billing(Cashier)
エージェントのワークフロー(必須)
実装の前に、必ず 3 つのエージェントを並行して起動します。それぞれ name を指定して Agent を 1 回呼び出してください。
- fuse-ai-pilot:explore-codebase - 既存の課金設定と User モデルを確認します
- fuse-ai-pilot:research-expert - Context7 経由で最新の Cashier ドキュメントを確認します
- mcp__context7__query-docs - 特定のパターン(Stripe/Paddle)を照会します
実装後、検証のために fuse-ai-pilot:sniper を実行します。
概要
Laravel Cashier は、Stripe または Paddle を使ったサブスクリプション課金を提供します。ニーズに応じて選択してください。
| プロバイダー | パッケージ | 最適な用途 |
|---|---|---|
| Stripe | laravel/cashier | 高い制御性、大量処理、複雑な課金 |
| Paddle | laravel/cashier-paddle | 税務処理、コンプライアンス、グローバル販売 |
主な違い:MoR と決済プロセッサー
| 項目 | Stripe | Paddle |
|---|---|---|
| 種類 | 決済プロセッサー | Merchant of Record |
| 税金 | 自社で管理(または Stripe Tax) | Paddle が自動管理 |
| 請求書 | 自社の会社名 | Paddle と自社の名前 |
| コンプライアンス | 自社の責任 | Paddle が対応 |
| 手数料 | 約 2.9% + $0.30 | 約 5% + $0.50(すべて込み) |
重要なルール
- Webhook を使用する - クライアント側の確認に依存しないでください
- 猶予期間を処理する - サブスクリプションが終了するまではアクセスを許可してください
- カード情報を保存しない - 支払いトークン/支払い方法を使用してください
- テストキーでテストする - 本番環境に移行する前に必ずテストしてください
- Webhook の署名を検証する - なりすまし攻撃を防止します
- 未完了の支払いを処理する - 3D セキュアではユーザーの操作が必要です
アーキテクチャ
app/
├── Http/
│ ├── Controllers/
│ │ └── Billing/ ← Billing controllers
│ │ ├── SubscriptionController.php
│ │ ├── CheckoutController.php
│ │ └── InvoiceController.php
│ └── Middleware/
│ └── EnsureSubscribed.php ← Subscription check
├── Models/
│ └── User.php ← Billable trait
├── Listeners/
│ └── StripeEventListener.php ← Webhook handling
└── Services/
└── BillingService.php ← Business logic
config/
├── cashier.php ← Stripe/Paddle config
└── services.php ← API keys
routes/
└── web.php ← Webhook routes (excluded from CSRF)
FuseCore との統合
FuseCore プロジェクトで作業する場合、課金処理はモジュール構成に従います。
FuseCore/
├── Core/ # Infrastructure (priority 0)
│ └── App/Contracts/
│ └── BillingServiceInterface.php ← Billing contract
│
├── User/ # Auth module (existing)
│ └── App/Models/User.php ← Add Billable trait here
│
├── Billing/ # Billing module (new)
│ ├── App/
│ │ ├── Http/
│ │ │ ├── Controllers/
│ │ │ │ ├── SubscriptionController.php
│ │ │ │ ├── CheckoutController.php
│ │ │ │ └── WebhookController.php
│ │ │ └── Middleware/
│ │ │ └── EnsureSubscribed.php
│ │ ├── Listeners/
│ │ │ └── HandleWebhookEvents.php
│ │ └── Services/
│ │ └── BillingService.php
│ ├── Config/
│ │ └── cashier.php ← Module-level config
│ ├── Database/Migrations/
│ ├── Routes/
│ │ ├── web.php ← Webhooks (no CSRF)
│ │ └── api.php ← Subscription management
│ └── module.json # dependencies: ["User"]
FuseCore の課金チェックリスト
- 課金コードを
/FuseCore/Billing/モジュールに配置する -
/FuseCore/User/の User モデルに Billable トレイトを追加する - Webhook のルートを
/FuseCore/Billing/Routes/web.phpに配置する -
preventRequestForgery(except: [...])を使って CSRF から Webhook を除外する(L13PreventRequestForgery) -
module.jsonで"User"依存関係を宣言する
→ モジュールのパターンについて詳しくは、fusecore skill をご覧ください。
選択ガイド
Stripe と Paddle の比較
Selling to businesses (B2B)? → Stripe
├── Need OAuth for third-party apps? → Stripe Connect
└── Selling to consumers (B2C) globally?
├── Want to handle taxes yourself? → Stripe + Stripe Tax
└── Want tax compliance handled? → Paddle
サブスクリプションと単発決済
Recurring revenue? → Subscription
├── Fixed plans? → Single-price subscription
└── Usage-based? → Metered billing (Stripe) or quantity-based
Single purchase? → One-time charge
├── Digital product? → Checkout session
└── Service fee? → Direct charge
主な概念
| 概念 | 説明 | 参照先 |
|---|---|---|
| Billable | モデルで課金を有効にするトレイト | stripe.md |
| サブスクリプション | 定期的な課金サイクル | subscriptions.md |
| Price ID | Stripe/Paddle の価格識別子 | stripe.md |
| 猶予期間 | キャンセル後もアクセスできる期間 | subscriptions.md |
| Webhook | サーバー間の支払い通知 | webhooks.md |
| カスタマーポータル | セルフサービスでの課金管理 | checkout.md |
リファレンスガイド
概念(理由とアーキテクチャ)
| トピック | リファレンス | 参照するタイミング |
|---|---|---|
| Stripe Cashier | stripe.md | Stripe のセットアップ、設定 |
| Paddle Cashier | paddle.md | Paddle のセットアップ、相違点 |
| サブスクリプション | subscriptions.md | 作成、キャンセル、プラン変更、一時停止 |
| Webhook | webhooks.md | Webhook のセキュリティ、処理 |
| 請求書 | invoices.md | PDF の生成、領収書 |
| 支払い方法 | payment-methods.md | カード、ウォレット、更新 |
| チェックアウト | checkout.md | ホスト型チェックアウト、ポータル |
| テスト | testing.md | テストカード、Webhook のテスト |
高度な SaaS 機能
| トピック | リファレンス | 参照するタイミング |
|---|---|---|
| 従量課金 | metered-billing.md | 使用量ベースの料金設定(API、ストレージ) |
| チーム課金 | team-billing.md | 組織の課金、ユーザーごとの料金設定 |
| 督促 | dunning.md | 失敗した支払いの回収 |
| 機能フラグ | feature-flags.md | プランに応じた機能アクセス |
テンプレート(完全なコード)
| テンプレート | 使用するタイミング |
|---|---|
| UserBillable.php.md | Billable トレイトを持つユーザーモデル |
| SubscriptionController.php.md | サブスクリプションの CRUD 操作 |
| WebhookController.php.md | カスタム Webhook の処理 |
| CheckoutController.php.md | Stripe Checkout + Portal |
| InvoiceController.php.md | 請求書のダウンロード |
| BillingRoutes.php.md | ルート定義一式 |
| SubscriptionTest.php.md | 課金の Pest テスト |
| MeteredBillingController.php.md | 使用量の追跡とレポート |
| TeamBillable.php.md | シート管理機能を持つチームモデル |
| DunningService.php.md | 支払い回収の自動化 |
| FeatureFlags.php.md | プランごとの Laravel Pennant 機能 |
クイックリファレンス
サブスクリプションのステータスを確認する
// Has active subscription?
$user->subscribed('default');
// Subscribed to specific price?
$user->subscribedToPrice('price_premium', 'default');
// On trial?
$user->onTrial('default');
// Cancelled but still active?
$user->subscription('default')->onGracePeriod();
サブスクリプションを作成する
// Simple subscription
$user->newSubscription('default', 'price_monthly')
->create($paymentMethodId);
// With trial
$user->newSubscription('default', 'price_monthly')
->trialDays(14)
->create($paymentMethodId);
サブスクリプションを管理する
$subscription = $user->subscription('default');
// Change plan
$subscription->swap('price_yearly');
// Cancel at period end
$subscription->cancel();
// Cancel immediately
$subscription->cancelNow();
// Resume cancelled subscription
$subscription->resume();
課金ポータル
// Redirect to customer portal (Stripe)
return $user->redirectToBillingPortal(route('dashboard'));
// Get portal URL
$url = $user->billingPortalUrl(route('dashboard'));
ベストプラクティス
推奨事項
- 支払いの確認には Webhook を使用する
- キャンセルされたサブスクリプションには猶予期間を設ける
- Webhook 署名の検証を設定する
IncompletePayment例外を処理する- ローカル環境で Stripe CLI を使ってテストする
- 古いデータを定期的に削除する
禁止事項
- クライアント側の支払い確認を信用しない
- カード番号を保存しない(PCI 準拠)
- Webhook の検証を省略しない
- 支払い失敗の Webhook を無視しない
- 3D Secure の処理を忘れない
- 価格をハードコードしない(env または設定を使用する)
Laravel 13 に関する注意点
Cashier Stripe 16.x(現行バージョンは 16.8)および Cashier Paddle 2.x(現行バージョンは 2.8)はLaravel 13 に対応しています。次の点に注意してください。
- Webhook:新しい [[laravel-auth]]
PreventRequestForgeryCSRF 保護では、preventRequestForgery(except: [...])を使って Webhook ルート(stripe/webhook、paddle/webhook)を除外する必要があります cache.serializable_classes(L13 ではデフォルトでfalse):Cashier オブジェクトをキャッシュする場合は、クラスを明示的に列挙します- PHP:Cashier は PHP 8.1 以降を受け入れますが、Laravel 13 には PHP 8.3 以降が必要です
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->preventRequestForgery(except: [
'stripe/*', 'paddle/*',
]);
})
コメント
Markdown 対応