メインコンテンツへスキップ

概要

Laravel Cashier (Stripe) は、Stripe の課金機能を Laravel から扱うための公式パッケージです。あなたは Subscription の作成・状態確認・キャンセル、1回払い、請求書のダウンロード、Webhook 処理を統一された API で実装できます。

インストールと設定

まず Cashier をインストールし、必要なテーブルを作成してください。
composer require laravel/cashier
php artisan vendor:publish --tag="cashier-migrations"
php artisan migrate
次に、App\Models\User などの課金対象モデルに Billable トレイトを追加します。
<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;
}
.env に Stripe のキーを設定します。
STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret

顧客管理

Stripe Customer をまだ作成していない可能性がある場合は、createOrGetStripeCustomer() を使います。
$stripeCustomer = $user->createOrGetStripeCustomer();
明示的に作成するなら createAsStripeCustomer() を使います。
$stripeCustomer = $user->createAsStripeCustomer();

Subscription

新規作成

newSubscription()create() で Subscription を開始します。 $paymentMethodId には Stripe.js などで取得した Payment Method ID を渡します。
$user->newSubscription('default', 'price_monthly')
    ->create($paymentMethodId);
price_monthly は例です。実装時は Stripe ダッシュボードで作成した実際の Price ID を指定してください。

状態確認

subscribed() で有効な Subscription かどうかを確認できます。
if ($user->subscribed('default')) {
    // Active subscription...
}

キャンセルと再開

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

if ($user->subscription('default')->onGracePeriod()) {
    // The user is on the grace period...
}

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

1回払い (Charge)

charge() で 1 回だけ課金できます。金額は通貨の最小単位で渡してください(例: USD なら 100$1.00)。 ここでも $paymentMethodId には Stripe で作成した Payment Method ID を使います。
$payment = $user->charge(100, $paymentMethodId);
課金に失敗した場合、charge() は例外をスローします。

Payment Element

Stripe の Payment Element を使うと、カード・Apple Pay・Google Pay・iDEAL など複数の決済手段を統一的に扱えます。

Subscription での利用

Setup Intent を作成してビューに渡します。
return view('subscribe', [
    'intent' => $user->createSetupIntent()
]);
Blade ビューで Payment Element をマウントし、Setup Intent の client_secret を渡します。
<div id="payment-element"></div>
<button id="submit">Subscribe</button>

<script src="https://js.stripe.com/v3/"></script>
<script>
    const stripe = Stripe('stripe-public-key');

    const elements = stripe.elements({
        clientSecret: '{{ $intent->client_secret }}'
    });

    const paymentElement = elements.create('payment');

    paymentElement.mount('#payment-element');

    document.getElementById('submit').addEventListener('click', async () => {
        const { error } = await stripe.confirmSetup({
            elements,
            confirmParams: {
                return_url: '{{ route("subscription.complete") }}',
            },
        });

        if (error) {
            // エラーメッセージをユーザーに表示...
        }
    });
</script>
Stripe のリダイレクト先 URL には setup_intent パラメータが付与されます。これを使って Payment Method ID を取得し、Subscription を作成します。
use Illuminate\Http\Request;

Route::get('/subscription/complete', function (Request $request) {
    $setupIntent = $request->user()->findSetupIntent(
        $request->setup_intent
    );

    $paymentMethod = $setupIntent->payment_method;

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

    return redirect('/dashboard');
})->name('subscription.complete');

1回払いでの利用

1 回払いでは pay() で Payment Intent を作成します。Order モデルには user_idamountstatusstripe_payment_intent_id カラムが必要です。
use App\Models\Order;
use Illuminate\Http\Request;

Route::post('/pay', function (Request $request) {
    $amount = 1000;

    $payment = $request->user()->pay($amount);

    $order = Order::create([
        'user_id' => $request->user()->id,
        'amount' => $amount,
        'status' => 'pending',
        'stripe_payment_intent_id' => $payment->id,
    ]);

    return view('checkout', [
        'clientSecret' => $payment->client_secret,
        'order' => $order,
    ]);
});
Payment Element をマウントして決済を確定します。
<div id="payment-element"></div>
<button id="submit">Pay Now</button>

<script src="https://js.stripe.com/v3/"></script>
<script>
    const stripe = Stripe('stripe-public-key');

    const elements = stripe.elements({
        clientSecret: '{{ $clientSecret }}'
    });

    const paymentElement = elements.create('payment');

    paymentElement.mount('#payment-element');

    document.getElementById('submit').addEventListener('click', async () => {
        const { error } = await stripe.confirmPayment({
            elements,
            confirmParams: {
                return_url: '{{ route("payment.complete") }}',
            },
        });

        if (error) {
            // エラーメッセージをユーザーに表示...
        }
    });
</script>
リダイレクト後は payment_intent パラメータで Order を検索し、Payment Intent が認証済みユーザーのものであり succeeded ステータスであることを確認してから注文を確定します。
use App\Models\Order;
use Illuminate\Http\Request;

Route::get('/payment/complete', function (Request $request) {
    $order = Order::where('user_id', $request->user()->id)
        ->where('stripe_payment_intent_id', $request->payment_intent)
        ->firstOrFail();

    $paymentIntent = $request->user()
        ->stripe()
        ->paymentIntents
        ->retrieve($request->payment_intent);

    if ($paymentIntent->customer === $request->user()->stripe_id &&
        $paymentIntent->status === 'succeeded') {
        $order->update(['status' => 'paid']);

        // 注文を確定する処理...
    }

    return redirect('/dashboard');
})->name('payment.complete');

請求書

請求書一覧は invoices() で取得できます。
$invoices = $user->invoices();
PDF ダウンロードには dompdf/dompdf をインストールし、downloadInvoice() を使います。$invoiceId には invoices() で取得した請求書 ID を渡してください。
composer require dompdf/dompdf
return $user->downloadInvoice($invoiceId);

Webhook の設定

Cashier は Stripe Webhook 用のルートを自動登録し、デフォルトで /stripe/webhook を使います。Stripe ダッシュボードにこの URL を設定してください。 Webhook の作成は cashier:webhook で実行できます。
php artisan cashier:webhook
CSRF 保護から stripe/* を除外してください。
->withMiddleware(function (Middleware $middleware): void {
    $middleware->preventRequestForgery(except: [
        'stripe/*',
    ]);
})
STRIPE_WEBHOOK_SECRET.env に設定すると、Cashier の署名検証ミドルウェアで Webhook リクエストを検証できます。
最終更新日 2026年7月4日