Stripe webhooks (entrants)
StormeoOS reçoit les events Stripe pour synchroniser abonnements, paiements et statuts client. Cette doc est utile pour comprendre quels events sont consommés — vous n'avez pas besoin de coder de receveur, c'est interne.
Source : server/routes/stripeWebhooks.ts + server/services/stripeService.ts.
Endpoint
POST https://beta.stormeo.io/api/stripe/webhookConfiguré côté Stripe Dashboard → Developers → Webhooks → Add endpoint.
Sécurité
- Vérification de signature obligatoire :
Stripe-Signatureheader validé avecSTRIPE_WEBHOOK_SECRETenv var - Fail-closed : si
STRIPE_SECRET_KEYest défini en prod sansSTRIPE_WEBHOOK_SECRET, le serveur refuse de démarrer (exit 1). Voir server/index.ts (security audit batch 3). - Body raw obligatoire :
express.raw({ type: 'application/json' })est appliqué uniquement sur cette route (pas leexpress.jsonglobal) pour préserver l'octet brut nécessaire à la signature.
Events consommés
| Event Stripe | Action StormeoOS |
|---|---|
customer.subscription.created | Créer / lier subscription côté agence |
customer.subscription.updated | Mettre à jour quantity/items/status |
customer.subscription.deleted | Marquer subscription.status='canceled' |
invoice.paid | Marquer la facture interne associée comme payée → émet webhook invoice.paid Public API |
invoice.payment_failed | Déclencher dunning workflow (relances automatiques) |
invoice.upcoming | Notification interne 7 jours avant prélèvement |
payment_intent.succeeded | Si paiement one-shot (sans subscription) → marquer payé |
payment_intent.payment_failed | Log + email d'alerte agence |
customer.updated | Sync customer.email/name côté clients interne |
charge.refunded | Mettre à jour facture (refundedAt, refundedAmount) |
payout.paid | Sync compte connect (multi-agence avec Stripe Connect) |
Réconciliation avec la Public API
Quand Stripe envoie invoice.paid à StormeoOS, le serveur :
- Met à jour la facture interne (
status='paid') - Émet un webhook
invoice.paidsur la Public API si vous avez souscrit (voir public-api-webhooks.md)
→ Côté votre app, vous écoutez le webhook public invoice.paid (pas le Stripe direct). Avantages :
- Authentifié par votre
signingSecret - Format unifié avec les autres events StormeoOS
- Filtré par votre agence uniquement
Idempotence
Stripe envoie un id unique par event (evt_...). StormeoOS stocke chaque id dans stripe_event_logs pour dédupliquer les retries Stripe (en cas de timeout côté StormeoOS).
Configuration Stripe Dashboard
Pour intégrer Stripe à votre agence :
- Compte → Intégrations → Stripe → Connecter
- OAuth flow Stripe Connect → token stocké chiffré côté StormeoOS
- Webhook automatiquement créé Stripe Dashboard sur
https://beta.stormeo.io/api/stripe/webhook STRIPE_WEBHOOK_SECRETest généré et lié à votre agence (multi-tenant)
Logs
Tous les events reçus sont loggés dans stripe_event_logs :
eventId,eventType,agencyIdreceivedAt,processedAt,processedStatuserrorMessagesi échec de traitement
Consultable côté admin agence (Compte → Intégrations → Stripe → Logs webhook).
Dunning workflow
Sur invoice.payment_failed, StormeoOS déclenche un workflow de relance :
| Jour | Action |
|---|---|
| J+0 | Email "Échec de paiement" au client |
| J+3 | Relance email douce |
| J+7 | Relance email ferme + alerte agence |
| J+14 | Suspension du service automatique (configurable) |
Configurable dans Compte → Facturation → Dunning.
Références
- Stripe Webhooks docs
- Stripe events reference
- Code interne :
server/routes/stripeWebhooks.ts