Integrate Stripe and Paddle payments with Laravel Cashier. Use when implementing subscriptions, invoices, payment methods, or billing portals.
Before ANY implementation, spawn 3 agents in parallel, one Agent call each with a name:
After implementation, run fuse-ai-pilot:sniper for validation.
Laravel Cashier provides subscription billing with Stripe or Paddle. Choose based on your needs:
| Provider | Package | Best For |
|---|---|---|
| Stripe | laravel/cashier |
Full control, high volume, complex billing |
| Paddle | laravel/cashier-paddle |
Tax handling, compliance, global sales |
| Aspect | Stripe | Paddle |
|---|---|---|
| Type | Payment Processor | Merchant of Record |
| Taxes | You manage (or Stripe Tax) | Paddle manages automatically |
| Invoices | Your company name | Paddle + your name |
| Compliance | Your responsibility | Paddle handles |
| Fees | ~2.9% + $0.30 | ~5% + $0.50 (all-inclusive) |
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)
When working in a FuseCore project, billing follows the modular structure:
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/Billing/ module/FuseCore/User//FuseCore/Billing/Routes/web.phpVerifyCsrfToken"User" dependency in module.jsonโ See fusecore skill for complete module patterns.
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
| Concept | Description | Reference |
|---|---|---|
| Billable | Trait that enables billing on a model | stripe.md |
| Subscription | Recurring billing cycle | subscriptions.md |
| Price ID | Stripe/Paddle price identifier | stripe.md |
| Grace Period | Time after cancellation with access | subscriptions.md |
| Webhook | Server-to-server payment notifications | webhooks.md |
| Customer Portal | Self-service billing management | checkout.md |
| Topic | Reference | When to Consult |
|---|---|---|
| Stripe Cashier | stripe.md | Stripe setup, configuration |
| Paddle Cashier | paddle.md | Paddle setup, differences |
| Subscriptions | subscriptions.md | Create, cancel, swap, pause |
| Webhooks | webhooks.md | Webhook security, handling |
| Invoices | invoices.md | PDF generation, receipts |
| Payment Methods | payment-methods.md | Cards, wallets, updates |
| Checkout | checkout.md | Hosted checkout, portal |
| Testing | testing.md | Test cards, webhook testing |
| Topic | Reference | When to Consult |
|---|---|---|
| Metered Billing | metered-billing.md | Usage-based pricing (API, storage) |
| Team Billing | team-billing.md | Organization billing, per-seat |
| Dunning | dunning.md | Failed payment recovery |
| Feature Flags | feature-flags.md | Plan-based feature access |
| Template | When to Use |
|---|---|
| UserBillable.php.md | User model with Billable trait |
| SubscriptionController.php.md | CRUD subscription operations |
| WebhookController.php.md | Custom webhook handling |
| CheckoutController.php.md | Stripe Checkout + Portal |
| InvoiceController.php.md | Invoice download |
| BillingRoutes.php.md | Complete route definitions |
| SubscriptionTest.php.md | Pest tests for billing |
| MeteredBillingController.php.md | Usage tracking and reporting |
| TeamBillable.php.md | Team model with seat management |
| DunningService.php.md | Payment recovery automation |
| FeatureFlags.php.md | Laravel Pennant per-plan features |
// 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'));
IncompletePayment exceptionsCashier Stripe 16.x et Cashier Paddle 2.x sont compatibles Laravel 13. Points d'attention :
PreventRequestForgery doit exclure les routes webhook (stripe/webhook, paddle/webhook) via validateOrigin(except: [...])serializable_classes : whitelister les DTOs Cashier si vous serialize des subscriptions (queue)// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->validateOrigin(except: [
'stripe/*', 'paddle/*',
]);
})