laravel-cashier
Auto-invoked skill
Subscription billing with Stripe or Paddle
Trigger Keywords
This skill automatically activates when Claude detects these keywords:
cashier
stripe
subscription
billing
payment
paddle
Overview
The laravel-cashier skill provides expertise for implementing subscription billing in Laravel using Cashier with Stripe or Paddle, including subscriptions, trials, invoices, and webhooks.
What This Skill Provides
- Subscription Management - Create, update, cancel subscriptions
- Payment Methods - Add, update, remove payment methods
- Invoicing - Generate and email invoices
- Webhooks - Handle Stripe/Paddle webhooks
- Checkout - Stripe Checkout integration
- Metered Billing - Usage-based pricing
Quick Start
# Install Cashier for Stripe
composer require laravel/cashier
# Publish migrations
php artisan vendor:publish --tag="cashier-migrations"
php artisan migrate
# Add to .env
STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
Model Setup
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;
final class User extends Authenticatable
{
use Billable;
}
Creating Subscriptions
// Create subscription
$user->newSubscription('default', 'price_monthly')
->create($paymentMethod);
// With trial
$user->newSubscription('default', 'price_monthly')
->trialDays(14)
->create($paymentMethod);
// With coupon
$user->newSubscription('default', 'price_monthly')
->withCoupon('SAVE20')
->create($paymentMethod);
// Multiple plans
$user->newSubscription('default', ['price_monthly', 'price_addon'])
->create($paymentMethod);
Managing Subscriptions
// Check subscription status
if ($user->subscribed('default')) {
// User has active subscription
}
if ($user->subscription('default')?->onTrial()) {
// User is on trial
}
if ($user->subscription('default')?->canceled()) {
// Subscription was canceled
}
// Swap plans
$user->subscription('default')->swap('price_yearly');
// Cancel
$user->subscription('default')->cancel();
// Cancel immediately
$user->subscription('default')->cancelNow();
// Resume
$user->subscription('default')->resume();
Checkout Integration
// Controller
public function checkout(Request $request)
{
return $request->user()
->newSubscription('default', 'price_monthly')
->checkout([
'success_url' => route('dashboard'),
'cancel_url' => route('pricing'),
]);
}
// Blade
<form action="" method="POST">
@csrf
<button type="submit">Subscribe</button>
</form>
Webhooks
// routes/web.php
Route::post('/stripe/webhook', [WebhookController::class, 'handleWebhook']);
// Custom webhook handler
namespace App\Http\Controllers;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class WebhookController extends CashierController
{
protected function handleCustomerSubscriptionCreated(array $payload)
{
// Handle new subscription
parent::handleCustomerSubscriptionCreated($payload);
}
protected function handleInvoicePaymentFailed(array $payload)
{
// Notify user of failed payment
}
}
Common Pitfalls
- Missing webhook endpoint - Configure in Stripe Dashboard
- Not validating webhook signatures - Set
STRIPE_WEBHOOK_SECRET - Forgetting CSRF exception - Exclude webhook route from CSRF
- Not handling failed payments - Implement retry logic
- Testing with live keys - Always use test keys in development
Best Practices
- Use Stripe Checkout for PCI compliance
- Handle all relevant webhook events
- Implement grace periods for failed payments
- Test with Stripe CLI locally
- Use price IDs, not hardcoded amounts
- Queue webhook processing for reliability
Related Skills
- laravel-auth - Authentication
- laravel-queue - Queue processing