If you're building a SaaS with Laravel, sooner or later you’ll need to handle recurring payments. Laravel offers a robust solution for that: Cashier. In this post, I’ll show you how to integrate it with Stripe or Paddle and how to manage subscriptions, plan changes, and cancellations easily.
Using Laravel Cashier with stripe
Install package
composer require laravel/cashier
php artisan vendor:publish --tag="cashier-migrations"
php artisan migrate
In your User
model:
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
use Billable;
}
In your .env
file:
STRIPE_KEY=pk_test_xxx
STRIPE_SECRET=sk_test_xxx
Create a Subscription
$user = User::find(1);
$user->newSubscription('default', 'premium-plan-id')
->create($paymentMethodId);
You can get the paymentMethodId using Stripe Elements.
Canceling and Managing a Subscription
$user->subscription('default')->cancel();
$user->subscription('default')->cancelNow();
Switch Plans
$user->subscription('default')->swap('new-plan-id');
One Time Charge (No subscription)
$user->charge(2500, $paymentMethodId); // $25.00
Using Laravel Cashier with Paddle
To use Paddle, you need a separate package:
Installation
composer require laravel/cashier-paddle
php artisan vendor:publish --tag="cashier-paddle-migrations"
php artisan migrate
In your .env
file:
PADDLE_VENDOR_ID=your_vendor_id
PADDLE_VENDOR_AUTH_CODE=your_auth_code
Creating a Subscription
$user = User::find(1);
return $user->newSubscription('default', 'plan-id')
->checkout([
'success_url' => route('dashboard'),
'cancel_url' => route('checkout.cancelled'),
]);
With Paddle, the checkout is hosted on Paddle's platform.
Canceling a Subscription
$user->subscription('default')->cancel();
Handling Webhooks
Both Stripe and Paddle send webhook events when something happens, such as:
Payment failed
Card expired
Subscription canceled
Subscription created
You can set up webhook routes in Laravel like this:
Route::post('/webhook/stripe', [WebhookController::class, 'handleStripe']);
Route::post('/webhook/paddle', [WebhookController::class, 'handlePaddle']);
Tips
Use jobs to handle webhook events asynchronously
Use middleware to block access to premium features for inactive users
Create artisan commands to check for expired subscriptions
Conclusion
Laravel Cashier removes most of the complexity when dealing with recurring payments and subscriptions. With native support for both Stripe and Paddle, you can choose the provider that fits your business best.
If you're building a SaaS product with Laravel, this is one of the most complete and production-ready solutions available today.
Top comments (0)