Skip to content
Back to skills

Laravel Billing

ASecurity

Use when implementing subscriptions, invoices, payment methods, webhooks, or billing portals with Laravel Cashier (Stripe or Paddle).

  • 29 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added February 7, 2026
businessrustphptestinggitapidatabasesecurity

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Pro scans all 20 files and shows the line behind each finding

Scanned September 29, 2026

npx -y skills add fusengine/agents --skill laravel-billing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Laravel Billing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Laravel Billing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/fusengine-laravel-billing/badge)](https://www.skillsdirectory.com/skills/fusengine-laravel-billing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: laravel-billing
description: Use when implementing subscriptions, invoices, payment methods, webhooks, or billing portals with Laravel Cashier (Stripe or Paddle).
versions:
  laravel: "13.0"
  cashier-stripe: "16.x"
  cashier-paddle: "2.x"
  php: "8.3"
user-invocable: true
references: references/stripe.md, references/paddle.md, references/subscriptions.md, references/webhooks.md, references/invoices.md, references/payment-methods.md, references/testing.md, references/checkout.md, references/metered-billing.md, references/team-billing.md, references/dunning.md, references/feature-flags.md, references/templates/UserBillable.php.md, references/templates/SubscriptionController.php.md, references/templates/WebhookController.php.md, references/templates/CheckoutController.php.md, references/templates/InvoiceController.php.md, references/templates/BillingRoutes.php.md, references/templates/SubscriptionTest.php.md, references/templates/MeteredBillingController.php.md, references/templates/TeamBillable.php.md, references/templates/DunningService.php.md, references/templates/FeatureFlags.php.md
related-skills: laravel-auth, laravel-api, fusecore
---

<objective>
Covers Laravel Cashier for Stripe and Paddle: choosing between the two
(payment processor vs merchant-of-record, tax handling, fees), subscription
lifecycle (create, swap, cancel, resume, trials, grace periods), webhooks and
signature verification, invoices, payment methods, checkout/customer portal,
metered/usage-based billing, team/per-seat billing, dunning (failed-payment
recovery), and Pennant-based feature flags per plan. Includes FuseCore
modular-project integration. For multi-vendor/marketplace split payments, see
laravel-stripe-connect instead.
</objective>

# Laravel Billing (Cashier)

## Agent Workflow (MANDATORY)

Before ANY implementation, spawn 3 agents in parallel, one `Agent` call each with a `name`:

1. **fuse-ai-pilot:explore-codebase** - Check existing billing setup, User model
2. **fuse-ai-pilot:research-expert** - Verify latest Cashier docs via Context7
3. **mcp__context7__query-docs** - Query specific patterns (Stripe/Paddle)

After implementation, run **fuse-ai-pilot:sniper** for validation.

---

## Overview

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 |

### Key Difference: MoR vs Payment Processor

| 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) |

---

## Critical Rules

1. **Use webhooks** - Never rely on client-side confirmations
2. **Handle grace periods** - Allow access until subscription ends
3. **Never store card details** - Use payment tokens/methods
4. **Test with test keys** - Always before production
5. **Verify webhook signatures** - Prevent spoofing attacks
6. **Handle incomplete payments** - 3D Secure requires user action

---

## Architecture

```
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)
```

---

## FuseCore Integration

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 Checklist

- [ ] Billing code in `/FuseCore/Billing/` module
- [ ] Billable trait on User model in `/FuseCore/User/`
- [ ] Webhook routes in `/FuseCore/Billing/Routes/web.php`
- [ ] Exclude webhook from CSRF via `preventRequestForgery(except: [...])` (L13 `PreventRequestForgery`)
- [ ] Declare `"User"` dependency in `module.json`

→ See [fusecore skill](../fusecore/SKILL.md) for complete module patterns.

---

## Decision Guide

### Stripe vs Paddle

```
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
```

### Subscription vs One-Time

```
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
```

---

## Key Concepts

| Concept | Description | Reference |
|---------|-------------|-----------|
| **Billable** | Trait that enables billing on a model | [stripe.md](references/stripe.md) |
| **Subscription** | Recurring billing cycle | [subscriptions.md](references/subscriptions.md) |
| **Price ID** | Stripe/Paddle price identifier | [stripe.md](references/stripe.md) |
| **Grace Period** | Time after cancellation with access | [subscriptions.md](references/subscriptions.md) |
| **Webhook** | Server-to-server payment notifications | [webhooks.md](references/webhooks.md) |
| **Customer Portal** | Self-service billing management | [checkout.md](references/checkout.md) |

---

## Reference Guide

### Concepts (WHY & Architecture)

| Topic | Reference | When to Consult |
|-------|-----------|-----------------|
| **Stripe Cashier** | [stripe.md](references/stripe.md) | Stripe setup, configuration |
| **Paddle Cashier** | [paddle.md](references/paddle.md) | Paddle setup, differences |
| **Subscriptions** | [subscriptions.md](references/subscriptions.md) | Create, cancel, swap, pause |
| **Webhooks** | [webhooks.md](references/webhooks.md) | Webhook security, handling |
| **Invoices** | [invoices.md](references/invoices.md) | PDF generation, receipts |
| **Payment Methods** | [payment-methods.md](references/payment-methods.md) | Cards, wallets, updates |
| **Checkout** | [checkout.md](references/checkout.md) | Hosted checkout, portal |
| **Testing** | [testing.md](references/testing.md) | Test cards, webhook testing |

### Advanced SaaS Features

| Topic | Reference | When to Consult |
|-------|-----------|-----------------|
| **Metered Billing** | [metered-billing.md](references/metered-billing.md) | Usage-based pricing (API, storage) |
| **Team Billing** | [team-billing.md](references/team-billing.md) | Organization billing, per-seat |
| **Dunning** | [dunning.md](references/dunning.md) | Failed payment recovery |
| **Feature Flags** | [feature-flags.md](references/feature-flags.md) | Plan-based feature access |

### Templates (Complete Code)

| Template | When to Use |
|----------|-------------|
| [UserBillable.php.md](references/templates/UserBillable.php.md) | User model with Billable trait |
| [SubscriptionController.php.md](references/templates/SubscriptionController.php.md) | CRUD subscription operations |
| [WebhookController.php.md](references/templates/WebhookController.php.md) | Custom webhook handling |
| [CheckoutController.php.md](references/templates/CheckoutController.php.md) | Stripe Checkout + Portal |
| [InvoiceController.php.md](references/templates/InvoiceController.php.md) | Invoice download |
| [BillingRoutes.php.md](references/templates/BillingRoutes.php.md) | Complete route definitions |
| [SubscriptionTest.php.md](references/templates/SubscriptionTest.php.md) | Pest tests for billing |
| [MeteredBillingController.php.md](references/templates/MeteredBillingController.php.md) | Usage tracking and reporting |
| [TeamBillable.php.md](references/templates/TeamBillable.php.md) | Team model with seat management |
| [DunningService.php.md](references/templates/DunningService.php.md) | Payment recovery automation |
| [FeatureFlags.php.md](references/templates/FeatureFlags.php.md) | Laravel Pennant per-plan features |

---

## Quick Reference

### Check Subscription Status

```php
// 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();
```

### Create Subscription

```php
// Simple subscription
$user->newSubscription('default', 'price_monthly')
    ->create($paymentMethodId);

// With trial
$user->newSubscription('default', 'price_monthly')
    ->trialDays(14)
    ->create($paymentMethodId);
```

### Manage Subscription

```php
$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();
```

### Billing Portal

```php
// Redirect to customer portal (Stripe)
return $user->redirectToBillingPortal(route('dashboard'));

// Get portal URL
$url = $user->billingPortalUrl(route('dashboard'));
```

---

## Best Practices

### DO
- Use webhooks for payment confirmation
- Implement grace periods for cancelled subscriptions
- Set up webhook signature verification
- Handle `IncompletePayment` exceptions
- Test with Stripe CLI locally
- Prune old data regularly

### DON'T
- Trust client-side payment confirmations
- Store card numbers (PCI compliance)
- Skip webhook verification
- Ignore failed payment webhooks
- Forget to handle 3D Secure
- Hardcode prices (use env or config)

---

## Laravel 13 Notes

Cashier Stripe 16.x (current 16.8) and Cashier Paddle 2.x (current 2.8) are **Laravel 13 compatible**. Points to watch:

- Webhooks: the new [[laravel-auth]] `PreventRequestForgery` CSRF protection must exclude webhook routes (`stripe/webhook`, `paddle/webhook`) via `preventRequestForgery(except: [...])`
- `cache.serializable_classes` (default `false` in L13): list the classes explicitly if you cache Cashier objects
- PHP: Cashier accepts PHP 8.1+, but Laravel 13 requires PHP 8.3 minimum

```php
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->preventRequestForgery(except: [
        'stripe/*', 'paddle/*',
    ]);
})
```

Files in this skill

  • SKILL.md10.6 KB
  • references/checkout.md4.8 KB
  • references/dunning.md3.4 KB
  • references/feature-flags.md4 KB
  • references/invoices.md4.7 KB
  • references/metered-billing.md3 KB
  • references/paddle.md4 KB
  • references/payment-methods.md4.9 KB
  • references/stripe.md3.4 KB
  • references/subscriptions.md5.1 KB
  • references/team-billing.md3.1 KB
  • references/templates/BillingRoutes.php.md6.2 KB
  • references/templates/CheckoutController.php.md7.4 KB
  • references/templates/DunningService.php.md8.5 KB
  • references/templates/FeatureFlags.php.md7.5 KB
  • references/templates/InvoiceController.php.md7.1 KB
  • references/templates/MeteredBillingController.php.md6.9 KB
  • references/templates/SubscriptionController.php.md8.4 KB
  • references/templates/SubscriptionTest.php.md9.1 KB
  • references/templates/TeamBillable.php.md7.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.