Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cashier Laravel Package

laravel/cashier

Laravel Cashier adds a fluent Stripe subscription billing layer to Laravel. Manage plans, trials, coupons, quantities, swaps, cancellations with grace periods, and invoicing, including PDF invoice generation, with minimal boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laravel/cashier stripe/stripe-php
    

    Publish the migration and config:

    php artisan vendor:publish --provider="Laravel\Cashier\CashierServiceProvider"
    php artisan migrate
    
  2. Configure Stripe: Add your Stripe API keys to .env:

    STRIPE_KEY=your_stripe_secret_key
    STRIPE_ENDPOINT_SECRET=your_webhook_signing_secret
    
  3. First Use Case: Attach a Stripe customer to a user model:

    use Laravel\Cashier\Billable;
    
    class User extends Authenticatable implements Billable
    {
        use Billable;
    }
    

    Create a subscription in a controller:

    $user->newSubscription('monthly', 'price_123')->create($paymentMethodId);
    

Key Starting Points

  • Webhooks: Set up Stripe\Webhook middleware in routes/web.php:
    Route::post('/stripe/webhook', [WebhookController::class, 'handle'])->middleware('signed');
    
  • Testing: Use Stripe::fake() in tests:
    Stripe::fake();
    $user->newSubscription('basic')->create('token_123');
    

Implementation Patterns

Core Workflows

1. Subscription Management

  • Create/Update:

    // Create a new subscription
    $user->newSubscription('premium', 'price_123')
         ->withEvent('premium_upgrade')
         ->create($paymentMethodId);
    
    // Switch plans
    $user->subscription('premium')->swap('price_456');
    
    // Pause/resume
    $user->subscription('premium')->pause();
    $user->subscription('premium')->resume();
    
  • Cancellation:

    // Cancel immediately
    $user->subscription('premium')->cancel();
    
    // Cancel at end of period
    $user->subscription('premium')->cancelNow(); // Immediate
    $user->subscription('premium')->cancelAtPeriodEnd(); // Grace period
    

2. Payment Handling

  • One-time Payments:

    $user->charge(1000); // $10.00
    $user->charge(1000, ['description' => 'Premium Access']);
    
  • Payment Methods:

    // Add a payment method
    $user->addPaymentMethod($paymentMethodId);
    
    // Set default
    $user->setDefaultPaymentMethod($paymentMethodId);
    
    // Update payment method
    $user->updateDefaultPaymentMethod($newPaymentMethodId);
    

3. Invoices and PDFs

  • Generate Invoices:

    $invoice = $user->invoices()->latest()->first();
    $invoice->download(); // Download PDF
    $invoice->send();     // Email PDF
    
  • Upcoming Invoices:

    $upcomingInvoice = $user->upcomingInvoice();
    

4. Coupons and Trials

  • Apply Coupons:

    $user->newSubscription('basic', 'price_123')
         ->withCoupon('SUMMER20')
         ->create($paymentMethodId);
    
  • Trials:

    $user->newSubscription('basic', 'price_123')
         ->trialDays(7)
         ->create($paymentMethodId);
    

5. Checkout Sessions

  • Stripe Checkout:

    $session = $user->createSetupIntent();
    // Or for subscriptions:
    $session = $user->createSubscription('premium', 'price_123');
    return redirect()->away($session->url);
    
  • Custom Checkout:

    $session = $user->createCheckoutSession([
        'mode' => 'subscription',
        'line_items' => [
            ['price' => 'price_123', 'quantity' => 1],
        ],
        'success_url' => route('checkout.success'),
        'cancel_url' => route('checkout.cancel'),
    ]);
    

Integration Tips

  • Middleware: Use EnsureUserHasValidSubscription to protect routes:

    Route::get('/premium', function () {
        // ...
    })->middleware('subscribed:premium');
    
  • Events: Listen to Cashier events (e.g., SubscriptionCreated):

    event(new SubscriptionCreated($subscription, $user));
    
  • Testing:

    Stripe::fake();
    $user->newSubscription('basic')->create('token_123');
    $this->assertTrue($user->subscribed('basic'));
    
  • Webhooks: Handle Stripe events in WebhookController:

    public function handle(Request $request)
    {
        $payload = $request->getContent();
        \Stripe\Webhook::constructEvent(
            $payload, $request->header('Stripe-Signature'),
            config('cashier.webhook_secret')
        );
        // Handle event (e.g., invoice.paid)
    }
    

Gotchas and Tips

Common Pitfalls

  1. Webhook Signing:

    • Ensure STRIPE_ENDPOINT_SECRET matches your Stripe webhook signing secret.
    • Fix: Verify the secret in .env and regenerate if needed in Stripe Dashboard.
  2. Payment Method Handling:

    • defaultPaymentMethod() may return null if no default is set.
    • Tip: Always check for null before using:
      if ($user->hasPaymentMethod()) {
          $user->defaultPaymentMethod();
      }
      
  3. Subscription Swaps:

    • Swapping plans may fail if the new plan has different billing cycles (e.g., monthly → yearly).
    • Tip: Use prorate: true in the swap method:
      $user->subscription('premium')->swap('price_456', ['prorate' => true]);
      
  4. Invoice Generation:

    • PDF generation requires dompdf or wkhtmltopdf. Install via:
      composer require barryvdh/laravel-dompdf
      
    • Gotcha: Taxes may appear incorrectly if not configured in Stripe. Use tax_rates in Stripe Dashboard.
  5. Testing:

    • Stripe::fake() must be called before any Stripe interaction in tests.
    • Tip: Use Stripe::testTokens() for test payment methods:
      Stripe::fake(['tokens' => ['test_token_123']]);
      
  6. Cancellation Grace Periods:

    • cancelAtPeriodEnd() does not immediately cancel; the subscription remains active until the end of the billing cycle.
    • Tip: Use cancelNow() for immediate cancellation.
  7. Stripe API Limits:

    • Cashier batches webhook processing. For high-volume apps, consider:
      \Laravel\Cashier\Cashier::flushWebhookQueue();
      

Debugging Tips

  • Log Webhook Events: Add logging in WebhookController to debug events:

    \Log::info('Webhook event:', ['event' => $event->type, 'data' => $event->data]);
    
  • Stripe CLI: Use the Stripe CLI to test webhooks locally:

    stripe listen --forward-to localhost:8000/stripe/webhook
    
  • Cashier Logs: Enable debug mode in config/cashier.php:

    'debug' => env('CASHIER_DEBUG', false),
    

Extension Points

  1. Custom Webhook Logic: Extend WebhookController to handle custom events:

    public function handleCustomerSubscriptionDeleted()
    {
        // Custom logic for subscription deletions
    }
    
  2. Custom Invoice Views: Override the invoice PDF template in resources/views/vendor/cashier/invoice.blade.php.

  3. Custom Subscription Logic: Use model observers or accessors to add custom fields:

    public function getCustomSubscriptionAttribute()
    {
        return $this->subscription('premium')->customField;
    }
    
  4. Multi-Currency Support: Cashier supports multiple currencies via Stripe. Configure in config/cashier.php:

    'currency' => 'usd', // Default currency
    
  5. Basil (Connect) Support: For Stripe Connect (payments to connected accounts), use:

    $user->newSubscription('premium', 'price_123')
         ->asStripeCustomer()
         ->create($paymentMethodId);
    

Configuration Quirks

  • Taxes: Ensure `tax_be
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai