Webhooks
Le bundle expose POST /cashier/webhook pour recevoir les événements Stripe.
Configuration
cashier:
webhook:
secret: '%env(STRIPE_WEBHOOK_SECRET)%'
tolerance: 300
events:
- customer.subscription.created
- customer.subscription.updated
- customer.subscription.deleted
- customer.deleted
- invoice.payment_succeeded
- invoice.payment_failed
- checkout.session.completed
- payment_intent.succeeded
- payment_intent.payment_failedRôle des webhooks
Ne limitez pas votre intégration au retour navigateur après paiement.
Les webhooks servent à:
- confirmer le paiement côté serveur
- synchroniser les subscriptions
- archiver les factures
- émettre les événements Symfony du bundle
Handlers intégrés
Le bundle fournit des handlers pour les événements billing principaux, notamment:
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedcustomer.deletedinvoice.payment_succeededinvoice.payment_failedinvoice.payment_action_requiredcheckout.session.completedcheckout.session.expiredpayment_method.updatedpayment_intent.succeededpayment_intent.payment_failed
Handlers placeholder
Certains handlers sont des points d’extension vides — implémenter via un handler custom:
InvoicePaymentActionRequiredHandler— gèreinvoice.payment_action_requiredCheckoutSessionCompletedHandler— gèrecheckout.session.completed
Configuration production
Créer le webhook via CLI:
php bin/console cashier:webhook --url=https://monsite.com/cashier/webhook --show-secretCopier le secret dans STRIPE_WEBHOOK_SECRET.
Vérifier que le path correspond à cashier.path dans cashier.yaml.
Idempotence
Les handlers Stripe peuvent être appelés plusieurs fois avec le même event ID.
Utilisez $event->id comme guard : stockez les IDs traités, rejetez les doublons.
Gestion des exceptions
Si un handler lance une exception, Stripe retentera le webhook (3 jours, intervalles croissants).
Capturez les exceptions métier et retournez 200 si l’événement peut être ignoré:
Handler custom
use CashierBundle\Contract\WebhookHandlerInterface;
use Stripe\Event;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('cashier.webhook_handler')]
final readonly class SyncOrderHandler implements WebhookHandlerInterface
{
public function handles(): array
{
return ['payment_intent.succeeded'];
}
public function handle(Event $event): void
{
$paymentIntent = $event->data->object;
$orderId = $paymentIntent->metadata->app_order_id ?? null;
// votre logique métier
}
}Événements Symfony dispatchés
WebhookReceivedEventWebhookHandledEventSubscriptionCreatedEventSubscriptionUpdatedEventSubscriptionDeletedEventPaymentSucceededEventPaymentFailedEvent
Stripe CLI locale
php bin/console cashier:webhook:listen --forward-to=http://127.0.0.1:8000/cashier/webhookOu avec --base-url pour construire automatiquement l’URL :
php bin/console cashier:webhook:listen --forward-to --base-url http://localhost:8000La commande:
- lance
stripe listen - récupère le
whsec_... - peut mettre à jour vos
.env* - colorise les entrées webhook et les statuts HTTP
Lecture de la sortie console
- événement entrant Stripe: cyan
- réponse
2xx: vert - réponse
4xx: jaune - réponse
5xxet erreurs CLI: rouge