Billing (Stripe)

Stripe via Laravel Cashier 16. Three plans (Free, Pro, Enterprise), monthly/yearly.

Good to know

The billing module is fully optional. If you don't need subscriptions, remove it via npx stacktura init and Stripe will be completely stripped from the codebase.

Stripe Setup Guide

Connect Stripe to your Stacktura project in five steps.

Create a Stripe account

Go to dashboard.stripe.com and sign up. You'll start in test mode by default.

Get your API keys

In the Stripe Dashboard, go to Developers > API keys. Copy both keys into backend/.env:

STRIPE_KEY=pk_test_xxxxxxxxxxxxx
STRIPE_SECRET=sk_test_xxxxxxxxxxxxx

Create your Products and Prices

In the Stripe Dashboard, go to Product catalog > Add product. Create one product per plan (Pro, Enterprise) with both monthly and yearly prices.

Copy each Price ID (price_xxx) into backend/.env:

STRIPE_PRICE_PRO_MONTHLY=price_xxxxxxxxxxxxx
STRIPE_PRICE_PRO_YEARLY=price_xxxxxxxxxxxxx
STRIPE_PRICE_ENTERPRISE_MONTHLY=price_xxxxxxxxxxxxx
STRIPE_PRICE_ENTERPRISE_YEARLY=price_xxxxxxxxxxxxx

Plan names and features are defined in backend/config/plans.php.

Set up webhooks (local development)

Install the Stripe CLI, then forward events to your local backend:

stripe listen --forward-to localhost:8000/api/stripe/webhook

The CLI outputs a whsec_xxx signing secret. Copy it to your .env:

STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxx

Set up webhooks (production)

In the Stripe Dashboard, go to Developers > Webhooks > Add endpoint:

  • URL: https://api.yourdomain.com/api/stripe/webhook
  • Events to listen: customer.subscription.created, updated, deleted, customer.updated, customer.deleted, invoice.payment_action_required, invoice.payment_succeeded, invoice.payment_failed, payment_method.automatically_updated

Copy the Signing secret from the webhook details into your production STRIPE_WEBHOOK_SECRET.


Test Cards

Use these cards in Stripe test mode. Any future date and any 3-digit CVC.

ScenarioCard NumberResult
Successful payment4242 4242 4242 4242Succeeds
3D Secure required4000 0025 0003 1228Requires authentication
Declined4000 0000 0000 0002Card declined
Insufficient funds4000 0000 0000 9995Insufficient funds
Expired card4000 0000 0000 0069Expired card

Going Live

Before you go live

Live and test mode use different API keys, Price IDs, and webhook secrets. You need to re-create everything in live mode.

  1. In the Stripe Dashboard, toggle Test mode off (top right)
  2. Copy your live API keys (pk_live_, sk_live_) into your production .env
  3. Re-create your products/prices in live mode and update the STRIPE_PRICE_* values
  4. Create a live webhook endpoint and update STRIPE_WEBHOOK_SECRET
  5. Make sure your site runs over HTTPS (required by Stripe)

API Endpoints

MethodEndpointDescription
GET/api/billing/plansList plans
GET/api/billing/subscriptionCurrent subscription
POST/api/billing/checkoutCreate Checkout session
POST/api/billing/portalCustomer Portal session
POST/api/billing/subscription/swapSwitch plan
POST/api/billing/subscription/cancelCancel subscription
POST/api/billing/subscription/resumeResume subscription
POST/api/stripe/webhookWebhook handler

Webhook Events (9)

customer.subscription.created, updated, deleted, customer.updated, customer.deleted, payment_method.automatically_updated, invoice.payment_action_required, succeeded, failed.

Authentication Google OAuth

Documentation

Ready to build your SaaS?

Full source code, all modules, lifetime updates.

Get Stacktura — $249