Does Laravel Work With Paddle?
Laravel and Paddle integrate seamlessly for SaaS billing, with community packages and webhooks handling subscriptions, invoicing, and tax compliance out of the box.
Quick Facts
How Laravel Works With Paddle
Laravel works excellently with Paddle through Laravel Cashier, a first-party package that abstracts Paddle's API into an elegant, Laravel-native interface. Cashier handles subscription management, billing portal integration, and webhook processing with minimal boilerplate. The integration is HTTP-based—Paddle sends webhook events to your Laravel application, which Cashier automatically verifies using Ed25519 signatures and dispatches as Laravel events. Developers define billable models, attach subscription plans, and manage customer details through fluent, expressive methods. Paddle's merchant-of-record model means tax compliance is handled server-side; Laravel simply orchestrates the billing workflow. The architecture scales well because webhooks are queued jobs, preventing payment processing from blocking request handling. One key consideration: Paddle uses subscription UUIDs rather than sequential IDs, so your database schema needs UUIDs for subscription tracking. Most gotchas involve webhook verification misconfiguration or timezone mismatches between Paddle's UTC timestamps and application logic.
Best Use Cases
Quick Setup
composer require laravel/cashier-paddle<?php
// config/cashier.php
return [
'cashier' => 'paddle',
'paddle' => [
'public_key' => env('PADDLE_PUBLIC_KEY'),
'secret_key' => env('PADDLE_SECRET_KEY'),
],
];
// app/Models/User.php
use Laravel\Cashier\Billable;
class User extends Model
{
use Billable;
}
// In your controller
$user = User::find(1);
$checkout = $user->checkout('pri_123456')
->returnTo(route('billing'))
->create();
return redirect($checkout->url);
// Handle webhooks automatically via routes/api.php
Route::post('/paddle/webhook', '\Laravel\\Cashier\\Http\\Controllers\\WebhookController@handle');Known Issues & Gotchas
Webhook signature verification fails due to environment mismatch
Fix: Ensure PADDLE_PUBLIC_KEY in .env matches your Paddle environment (sandbox vs. production). Use php artisan tinker to verify key format and test webhook signatures locally with Paddle's CLI tool.
Subscription state mismatches between Paddle and Laravel
Fix: Always sync subscription state via webhooks; don't assume local state is authoritative. Use Cashier's sync methods or implement a reconciliation command for recovery.
Timezone issues with renewal dates and billing periods
Fix: Store all Paddle timestamps in UTC in your database. Convert to user timezone only in views using Laravel's Carbon library.
Rate limiting on Paddle API calls during bulk operations
Fix: Batch API requests and use queued jobs. Paddle allows 30 requests/second; queue heavy operations with exponential backoff.
Alternatives
- •Stripe with Laravel Cashier—more payment methods but higher complexity for tax compliance
- •Lemonsqueezy with Laravel—newer alternative with built-in affiliate support and simpler setup
- •Chargify with custom Laravel integration—more flexibility but requires manual webhook handling
Resources
Related Compatibility Guides
Explore more compatibility guides