Un paiement réussi qui n'est jamais devenu une réservation
Un client a payé. Razorpay a indiqué un succès. Le webhook a envoyé un HTTP 200. Le paiement a été capturé.
Pourtant, la réservation est restée bloquée sur « en cours de confirmation ».
Aucune erreur n'est apparue. Aucune exception n'a fait planter le code. Aucune alerte ne s'est déclenchée. Chaque métrique indiquait un système sain.
Mais le client n'avait rien reçu. Le créateur n'avait aucune réservation.
Accepter de l'argent est facile. S'assurer que chaque paiement mène à une réservation est le véritable défi.
La plupart des tutoriels suggèrent ce flux :
- Le webhook reçoit l'événement
- Le webhook met à jour la réservation
C'est dangereux. Si la logique métier réside à l'intérieur du webhook, vous dépendez entièrement du succès de la livraison. Les webhooks sont confrontés à des tentatives de réessai, des doublons et des échecs partiels.
Nous avons modifié notre architecture pour séparer ces tâches. Les webhooks ne font désormais qu'enregistrer des événements. Ils n'exécutent pas de logique métier.
Nous avons introduit un registre d'événements avec trois tables :
- payment_orders : la vérité du fournisseur
- payment_events : le registre d'événements immuable
- bookings : la vérité métier
Le webhook n'a désormais qu'une seule mission :
- Vérifier la signature
- Enregistrer l'événement
- Retourner un 200
Cela protège le système. Si le webhook échoue, l'événement est tout de même sauvegardé.
Nous avons également appris que l'état du paiement et l'état de la réservation sont différents. Un paiement capturé est une entrée. Une réservation confirmée est le résultat. Les maintenir séparés permet d'effectuer un rapprochement.
Lors d'une investigation, nous avons trouvé un bug. Les événements existaient dans la base de données. Le processeur était opérationnel. Le webhook était opérationnel.
Mais le processeur ne s'est jamais exécuté. Personne ne déclenchait la fonction pour traiter les événements en attente.
Découpler l'ingestion du traitement est une bonne conception. Mais cela crée une nouvelle exigence : quelque chose doit déclencher le traitement.
Nous avons implémenté un ordonnanceur pour exécuter plusieurs tâches :
- Traiter les événements de paiement
- Récupérer les webhooks manqués
- Valider la cohérence du système
Pour éviter les erreurs lors des tentatives de réessai, nous utilisons cette logique :
- Sélectionner les événements non traités
- Utiliser « SKIP LOCKED » pour permettre plusieurs workers
- S'assurer que les livraisons en double n'aient aucun effet
Un système qui ne fonctionne que lorsque chaque webhook arrive à temps est un système fragile. Si votre file d'attente n'a personne pour la vider, le travail attend indéfiniment.
La fiabilité signifie construire en prévoyant les défaillances.