$ lexprog.com

// notes from an old coder -- php, databases, and the occasional rant

[March 31, 2025] Laravel

Laravel Cashier: Subscription Billing

Laravel Cashier: Subscription Billing

────────────────────────────────────────────────────────

Laravel Cashier: Subscription Billing

Tip: Install Cashier

composer require laravel/cashier
php artisan cashier:install

Gotcha: Billable Trait

use Billable;

Add to your User model for subscription management.

Tip: Create Subscription

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

Gotcha: Webhook Handling

Cashier handles Stripe webhooks automatically. Configure the webhook URL in Stripe dashboard.

Tip: Check Subscription

if ($user->subscribed('default')) {
    // User has active subscription
}

Gotcha: Trial Periods

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

Tip: Use route:cache Carefully

php artisan route:cache is fast, but it doesn't work with closure-based routes. Every time you cache routes, Laravel serializes them. If you have Route::redirect() or closure callbacks, the cache breaks. Stick to controller-based routes in production.

Tip: Model APP_KEY Rotation

Rotating APP_KEY invalidates all encrypted data — cookies, encrypted DB columns, and password reset tokens. If you must rotate (e.g., after a leak), plan a migration that re-encrypts existing data with the new key.

Gotcha: Local Scope Leaks

Global scopes defined in booted() apply to ALL queries on that model — including relationships. An innocent User::all() in admin panel might exclude soft-deleted users if a global scope is active.

Senior Insight

Subscription billing is the highest-risk integration in most Laravel applications. I've seen everything from double charges to silently failed renewals. Cashier handles the Laravel side well, but the real complexity is in webhook handling — Stripe sends webhooks for almost every event, and missing one (like invoice.payment_failed) means a customer loses access without warning. I recommend idempotent webhook handlers with comprehensive logging.

Source: Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/laravel), Spatie Blog (https://spatie.be/blog)

────────────────────────────────────────────────────────
<-- back to posts