Laravel Cashier + Stripe setup for SaaS billing (complete guide)
A practical guide to setting up Laravel Cashier with Stripe for SaaS billing, including products, prices, checkout, webhooks, trials, and production reliability.
Quick Answer
Quick answer: Laravel Cashier + Stripe setup for SaaS billing (complete guide)
A practical guide to setting up Laravel Cashier with Stripe for SaaS billing, including products, prices, checkout, webhooks, trials, and production reliability.
See supporting documentationLaravel Cashier + Stripe setup for SaaS billing (complete guide)
If you are building a Laravel SaaS, Stripe + Laravel Cashier is one of the fastest paths to production billing. The key is not only getting checkout working, but also making subscription lifecycle events reliable in production.
This guide walks through the full setup: plans, checkout, webhooks, trials, portal access, and common failure points.
Quick answer: how do you set up Stripe billing in Laravel?
At a high level:
- Configure Stripe keys and install Cashier
- Create products and prices in Stripe
- Map plan IDs in your app config
- Create checkout/subscription flows
- Process Stripe webhooks reliably
- Gate product access by subscription state
If each of these is implemented cleanly, you can run SaaS billing with predictable behavior and fewer support incidents.
What Laravel Cashier handles well
Laravel Cashier gives you a practical abstraction for:
- creating and managing subscriptions
- handling trial periods
- swapping plans
- canceling/reactivating subscriptions
- opening Stripe customer portal sessions
Use it as your billing workflow layer, while Stripe remains the source of truth for charges and invoices.
Step 1: Install and configure Cashier
Use this as your baseline setup sequence.
1) Install the package and run migrations
composer require laravel/cashier
php artisan vendor:publish --tag="cashier-migrations"
php artisan migrateThis creates Cashier billing tables (subscriptions, subscription items, etc.).
2) Add Stripe and billing env variables
STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
# optional but common
CASHIER_CURRENCY=usd
CASHIER_CURRENCY_LOCALE=enKeep test and live keys strictly separated by environment.
3) Make your billable model use Cashier
In most Laravel SaaS apps, User is the billable model. Add Billable:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}If your billing entity is a workspace/team model, add Billable there instead and keep subscription checks workspace-scoped.
4) Ensure webhook endpoint is reachable and CSRF-safe
Cashier expects Stripe webhooks at:
/stripe/webhookMake sure your app allows Stripe to post to this endpoint without CSRF blocking, then configure the same endpoint URL in Stripe Dashboard for each environment.
5) Sanity-check with a test subscription
Before building full UI flows:
- create one Stripe test product/price
- create a test checkout/subscription in app code
- confirm subscription rows are created/updated locally
- send a Stripe test webhook and confirm processing succeeds
Implementation notes:
- keep billing config centralized (config file or billing service)
- ensure your billable model relationship is stable and tested
- avoid scattering Stripe price IDs across controllers
Step 2: Create Stripe products and prices intentionally
In Stripe, create products and the exact price models you need:
- monthly and yearly prices
- optional trials
- seat-based price variants (if team billing)
Keep IDs explicit and environment-specific (test vs live).
Recommended pattern:
- define plan keys in app config (for example
starter_monthly,pro_yearly) - map plan keys to Stripe price IDs in env/config
- use plan keys in your application logic instead of hardcoding price IDs directly
Step 3: Build checkout and subscription creation flows
A reliable SaaS flow usually looks like this:
- user/workspace selects a plan
- app creates Stripe checkout session (or direct subscription flow)
- user completes payment in Stripe
- webhook confirms subscription state
- app enables paid access based on confirmed state
Important rule: do not trust browser redirect alone as billing truth.
Use webhooks as the system of record for final subscription state.
Step 4: Webhooks are where billing reliability is won
Your webhook handler should be:
- signature-verified
- idempotent
- order-tolerant
- observable (logs + alerts)
Core events to handle for SaaS lifecycle:
- subscription created/updated/canceled
- invoice payment succeeded/failed
- trial ending (if used)
Operational checklist:
- store processed event IDs to prevent duplicate side effects
- make access updates retry-safe
- alert on repeated webhook failures
- keep manual replay runbook ready
Step 5: Gate access with subscription state, not assumptions
Your app should check subscription status in one centralized layer (policy/middleware/service), then enforce feature access consistently.
At minimum, define behavior for:
- active subscription
- trialing
- past_due
- canceled but still in grace period
- fully ended access
This prevents inconsistent behavior between dashboard pages, APIs, and background jobs.
Step 6: Add trials, upgrades, downgrades, and cancellation paths
For production-ready SaaS billing, implement lifecycle flows clearly:
- start trial from selected plan
- upgrade immediately when user picks higher tier
- downgrade with predictable effective date
- cancel with clear access end date and reactivation option
User confusion here creates support load. Keep billing status and next charge date visible in your UI.
Step 7: Support team and seat-based billing (if applicable)
If your product is workspace/team-based:
- map Stripe quantity to seat count
- sync quantity when seats change
- avoid race conditions during invite/remove member events
A robust approach is to centralize seat sync in one domain service and queue updates safely.
For a deeper implementation model, see: How to build a SaaS app with Laravel in 2026
Step 8: Test mode and production cutover
Before going live:
- test all checkout outcomes in Stripe test mode
- simulate webhook retries and duplicate delivery
- test failed payment and recovery paths
- validate cancellation and grace-period behavior
- verify billing portal round-trips
For live cutover, use a checklist and keep rollback options documented.
Common mistakes to avoid
- relying on redirect success pages as payment truth
- no idempotency in webhook processing
- hardcoding Stripe price IDs in multiple places
- mixing billing logic into unrelated controllers
- no support visibility for current subscription state
Practical architecture recommendation
Use this split:
- Stripe: payment execution and invoice source of truth
- Cashier: Laravel-native billing workflow abstraction
- Your app: feature gating and product-specific access rules
This keeps the system understandable as you scale plan complexity.
Final takeaway
Laravel Cashier + Stripe is a strong default for SaaS billing if you prioritize webhook reliability, centralized access gating, and clean plan mapping from day one.
If you want to skip most of the setup and start from a production-ready baseline, explore:
Ready to ship faster?
Build your SaaS with a production-ready foundation
Launch with authentication, billing, tenancy, and team workflows already in place, then focus on the features that make your product unique.
Related posts
How to build seat-based pricing in Laravel with Stripe (step-by-step, 2026)
A practical step-by-step guide to implementing seat-based SaaS pricing in Laravel using Stripe, including quantity sync, edge cases, and webhook safety.
How to implement seat-based pricing in Laravel SaaS apps
A practical guide to seat-based pricing in Laravel SaaS apps, including data model design, Stripe quantity sync, billing edge cases, and reliable production workflows.
Authentication, social login, and team invites in Laravel SaaS: the complete guide
How to build a complete auth system for Laravel SaaS products, covering registration, social login with Google and GitHub, email verification, team invitations, and role-based workspace access.