Laravel Cashier : gérer les abonnements et paiements avec Stripe
Gérer les paiements récurrents et les abonnements représente un défi technique majeur. Laravel Cashier élimine cette complexité en proposant une interface fluide et expressive pour Stripe. Le package officiel gère tout : abonnements, périodes d’essai, coupons, factures PDF et webhooks.
Qu’est-ce que Laravel Cashier ?
Laravel Cashier Stripe est le package officiel de Laravel pour intégrer les services de facturation par abonnement de Stripe. Plutôt que d’écrire des centaines de lignes de code pour gérer les paiements récurrents, Cashier fournit une API élégante qui s’intègre naturellement avec Eloquent.
Le package prend en charge :
- La gestion complète des abonnements (création, modification, annulation)
- Les périodes d’essai avec ou sans carte bancaire
- Les coupons et codes promotionnels
- La génération automatique de factures PDF
- La facturation à l’usage (metered billing)
- Les webhooks Stripe avec vérification de signature
- Le portail client Stripe Checkout
Installation et configuration
L’installation se fait en quelques commandes Composer et Artisan :
# Installation du package
composer require laravel/cashier
# Publication des migrations
php artisan vendor:publish --tag="cashier-migrations"
# Exécution des migrations
php artisan migrate
Cashier ajoute plusieurs colonnes à la table users et crée les tables subscriptions et subscription_items.
Configurez ensuite vos clés API Stripe dans le fichier .env :
STRIPE_KEY=pk_test_votre_cle_publique
STRIPE_SECRET=sk_test_votre_cle_secrete
STRIPE_WEBHOOK_SECRET=whsec_votre_secret_webhook
Ajoutez le trait Billable à votre modèle User :
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Cashier\Billable;
class User extends Authenticatable
{
// Trait qui ajoute toutes les méthodes de facturation
use Billable;
}
Ce trait injecte automatiquement les méthodes subscribe(), subscribed(), charge(), invoices() et des dizaines d’autres sur votre modèle.
Créer un abonnement
La création d’un abonnement s’effectue via la méthode newSubscription(). Vous devez au préalable créer vos produits et prix dans le dashboard Stripe.
<?php
use Illuminate\Http\Request;
Route::post('/subscribe', function (Request $request) {
// Création de l'abonnement avec le moyen de paiement fourni
$request->user()->newSubscription('default', 'price_basic_monthly')
->create($request->paymentMethodId);
return redirect('/dashboard')->with('success', 'Abonnement activé !');
});
Le premier argument 'default' représente le type d’abonnement (utile si un utilisateur peut avoir plusieurs abonnements). Le second correspond à l’identifiant du prix Stripe.
Pour ajouter une période d’essai :
<?php
// Abonnement avec 14 jours d'essai gratuit
$user->newSubscription('default', 'price_pro_monthly')
->trialDays(14)
->create($paymentMethodId);
Utiliser Stripe Checkout
Stripe Checkout offre une page de paiement hébergée, sécurisée et optimisée pour la conversion. Cashier s’intègre parfaitement avec cette solution :
<?php
use Illuminate\Http\Request;
Route::get('/checkout', function (Request $request) {
// Redirection vers la page Stripe Checkout
return $request->user()
->newSubscription('default', 'price_premium_yearly')
->trialDays(7)
->allowPromotionCodes() // Autorise les codes promo
->checkout([
'success_url' => route('subscription.success'),
'cancel_url' => route('subscription.cancel'),
]);
});
L’utilisateur est redirigé vers Stripe, effectue son paiement, puis revient sur votre application. Les webhooks Stripe synchronisent automatiquement l’état de l’abonnement.
Vérifier le statut d’un abonnement
Cashier propose plusieurs méthodes pour vérifier l’état des abonnements :
<?php
// Vérifie si l'utilisateur a un abonnement actif
if ($user->subscribed('default')) {
// Accès aux fonctionnalités premium
}
// Vérifie l'abonnement à un produit spécifique
if ($user->subscribedToProduct('prod_premium')) {
// L'utilisateur a le produit Premium
}
// Vérifie si l'utilisateur est en période d'essai
if ($user->subscription('default')->onTrial()) {
// Afficher un message sur les jours restants
}
// Vérifie si l'abonnement est annulé mais encore actif (période de grâce)
if ($user->subscription('default')->onGracePeriod()) {
// L'utilisateur peut encore utiliser le service
}
Ces méthodes permettent de créer facilement un middleware pour protéger les routes premium :
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureUserIsSubscribed
{
public function handle(Request $request, Closure $next): Response
{
// Redirige les non-abonnés vers la page de tarification
if (! $request->user()?->subscribed('default')) {
return redirect('/pricing');
}
return $next($request);
}
}
Gérer les paiements uniques
Cashier gère également les paiements ponctuels sans abonnement :
<?php
use Illuminate\Http\Request;
Route::post('/purchase', function (Request $request) {
// Paiement unique de 50€ (montant en centimes)
$payment = $request->user()->charge(
5000,
$request->paymentMethodId
);
return response()->json(['success' => true]);
});
// Paiement avec génération automatique d'une facture
Route::post('/invoice-purchase', function (Request $request) {
// Facture pour 3 articles à un prix défini dans Stripe
$request->user()->invoicePrice('price_tshirt', 3);
return redirect('/orders');
});
Portail de facturation client
Stripe propose un portail client hébergé où les utilisateurs peuvent gérer leurs abonnements, moyens de paiement et télécharger leurs factures. Cashier l’intègre en une ligne :
<?php
use Illuminate\Http\Request;
Route::get('/billing', function (Request $request) {
// Redirige vers le portail Stripe Customer Portal
return $request->user()->redirectToBillingPortal(
route('dashboard') // URL de retour après gestion
);
})->middleware('auth')->name('billing');
Vos utilisateurs peuvent ainsi modifier leur abonnement, changer de formule ou annuler leur souscription sans que vous n’ayez à développer d’interface.
Configurer les webhooks
Les webhooks sont essentiels pour synchroniser votre base de données avec Stripe. Cashier enregistre automatiquement une route /stripe/webhook.
Créez le webhook dans Stripe via Artisan :
php artisan cashier:webhook
N’oubliez pas d’exclure cette route de la protection CSRF dans bootstrap/app.php :
<?php
->withMiddleware(function (Middleware $middleware): void {
$middleware->validateCsrfTokens(except: [
'stripe/*', // Exclut les webhooks Stripe de la vérification CSRF
]);
})
Pour réagir à des événements Stripe personnalisés, écoutez les événements Cashier :
<?php
namespace App\Listeners;
use Laravel\Cashier\Events\WebhookReceived;
class HandleStripeWebhook
{
public function handle(WebhookReceived $event): void
{
// Traitement personnalisé selon le type d'événement
if ($event->payload['type'] === 'invoice.payment_succeeded') {
$customerId = $event->payload['data']['object']['customer'];
// Envoyer un email de remerciement, mettre à jour des statistiques...
}
}
}
Points d’attention
- Collation MySQL : utilisez
utf8_binpour la colonnestripe_idafin de respecter la casse des identifiants Stripe - Webhooks obligatoires : configurez au minimum
customer.subscription.created,customer.subscription.updatedetinvoice.payment_succeeded - Montants en centimes : la méthode
charge()attend les montants en centimes (100 = 1€) - Tests : utilisez les clés de test Stripe et les numéros de carte de test (
4242424242424242) - Mise à jour : consultez toujours le guide de migration avant de mettre à jour Cashier
Stripe vs Paddle : quel choix ?
Laravel propose deux packages Cashier : un pour Stripe et un pour Paddle. Stripe offre plus de contrôle et de fonctionnalités, mais vous devez gérer la TVA vous-même (sauf avec Stripe Tax). Paddle gère automatiquement la TVA mondiale, ce qui simplifie la conformité fiscale pour les entreprises vendant en Europe mais la tarification sur les transactions est quasiment double par rapport à Paddle.
Récapitulatif
Laravel Cashier transforme l’intégration des paiements Stripe & Paddle en une expérience fluide. Le package gère la complexité des abonnements récurrents, des webhooks et de la synchronisation des données. Quelques lignes de code suffisent pour proposer des formules d’abonnement professionnelles avec périodes d’essai, coupons et facturation automatique.
Ressources
À propos de Laravel Actu
Développeur passionné par Laravel et son écosystème.
Voir tous les articles