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 Paddle Laravel Package

laravel/cashier-paddle

Laravel Cashier Paddle adds a fluent Laravel interface for Paddle subscriptions, handling common billing boilerplate like subscription creation and management, plan swaps, quantities, pauses, cancellations, and grace periods.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laravel/cashier-paddle
    

    Publish the config file:

    php artisan vendor:publish --provider="Laravel\CashierPaddle\CashierPaddleServiceProvider"
    
  2. Configuration:

    • Set your Paddle API keys in .env:
      PADDLE_VENDOR_ID=your_vendor_id
      PADDLE_VENDOR_AUTH_CODE=your_auth_code
      PADDLE_WEBHOOK_SECRET=your_webhook_secret
      
    • Configure config/cashier-paddle.php (e.g., webhook URL, default currency).
  3. First Use Case:

    • Create a Subscription:
      use Laravel\CashierPaddle\Facades\CashierPaddle;
      
      $user->newSubscription('main', 'product_id')
           ->create($paymentMethodId);
      
    • Verify Webhook (via Paddle dashboard): Ensure your app’s webhook URL (e.g., https://your-app.com/paddle-webhook) is registered in Paddle’s developer portal.

Implementation Patterns

Core Workflows

  1. Subscription Management:

    • Create/Update:
      $user->newSubscription('main', 'product_id')
           ->quantity(2) // For metered billing
           ->price('custom_price_id') // Override default
           ->create($paymentMethodId);
      
    • Swap Plans:
      $user->subscription('main')->swap('new_product_id');
      
    • Pause/Resume:
      $user->subscription('main')->pause();
      $user->subscription('main')->resume();
      
  2. Webhooks:

    • Handle events in routes/web.php:
      Route::post('/paddle-webhook', [PaddleWebhookController::class, 'handle']);
      
    • Validate signatures in PaddleWebhookController:
      use Laravel\CashierPaddle\Events\WebhookReceived;
      
      public function handle(Request $request) {
          if (!WebhookReceived::validate($request)) {
              abort(403);
          }
          // Process event...
      }
      
  3. Billing Portal:

    • Redirect users to Paddle’s hosted portal:
      return $user->subscription('main')->billable()->paddlePortal();
      
  4. Invoices & Payments:

    • List invoices:
      $user->invoices()->latest()->get();
      
    • Cancel subscription:
      $user->subscription('main')->cancel();
      

Integration Tips

  • Sync with Paddle: Use php artisan paddle:sync to reconcile local subscriptions with Paddle’s data.
  • Testing: Use Paddle’s sandbox environment (configured in .env) and mock webhooks:
    $this->post('/paddle-webhook', $payload)
         ->assertOk();
    
  • Custom Fields: Attach metadata to subscriptions:
    $user->subscription('main')->updateCustomFields(['tier' => 'premium']);
    

Gotchas and Tips

Pitfalls

  1. Webhook Validation:

    • Always validate signatures (WebhookReceived::validate()). Paddle sends events with a Paddle-Signature header.
    • Debugging: Log raw payloads during development:
      \Log::debug('Webhook payload:', $request->all());
      
  2. Idempotency:

    • Paddle’s webhooks may retry failed deliveries. Design handlers to be idempotent (e.g., check event.data.object.id before processing).
  3. Subscription States:

    • Cashier Paddle uses Paddle’s states (active, canceled, paused). Avoid assuming local DB state matches Paddle’s—always fetch fresh data via:
      $user->subscription('main')->fresh();
      
  4. Quantities & Add-ons:

    • For metered billing, ensure quantity matches Paddle’s product setup. Mismatches may cause failed charges.
  5. Webhook URL:

    • Use HTTPS. Paddle rejects HTTP endpoints in production.

Debugging

  • Failed Payments: Check Paddle’s dashboard for charge.failed events. Retry with:
    $user->subscription('main')->resume();
    
  • Missing Events: Verify webhook URL is whitelisted in Paddle’s developer portal and no firewall blocks requests.

Config Quirks

  • Currency: Defaults to USD. Override per subscription:
    ->price('price_id')->currency('EUR')
    
  • Grace Periods: Paddle’s grace periods are handled automatically, but test cancellation flows to confirm behavior.

Extension Points

  1. Custom Events: Listen to Cashier events (e.g., subscription.created):
    use Laravel\CashierPaddle\Events\SubscriptionCreated;
    
    event(new SubscriptionCreated($user, $subscription));
    
  2. Middleware: Protect subscription routes:
    Route::middleware(['auth', 'subscribed'])->group(function () {
        // Protected routes
    });
    
  3. API Extensions: Use Paddle’s raw API via Paddle facade:
    use Laravel\CashierPaddle\Facades\Paddle;
    
    $customers = Paddle::customers()->all();
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport