Le défi
Un SaaS B2B en expansion de l’Amérique du Nord vers l’APAC et l’EMEA avait besoin d’une infrastructure de paiement capable d’encaisser en cinq devises, de gérer la facturation d’abonnements, de traiter les nouvelles tentatives avec élégance et de réussir une revue de sécurité. Il avait dépassé une configuration à processeur unique — les marges de change absorbaient 1,8 % du chiffre d’affaires, le règlement prenait plusieurs jours et son gestionnaire de webhooks perdait des événements sous charge. Le directeur financier voulait Airwallex pour le change et les rails mondiaux ; le directeur technique voulait conserver sa pile FastAPI existante et ne pas faire des paiements un service distinct que l’équipe ne pourrait pas exploiter.
La demande : livrer en un seul trimestre une intégration Airwallex en production sur FastAPI + PostgreSQL, avec une fiabilité des webhooks à toute épreuve, une véritable machine à états d’abonnement, une architecture alignée PCI-DSS et un dispositif d’exploitation clair pour que l’ingénieur d’astreinte à 2 h du matin n’ait pas à appeler le directeur technique.
Notre solution
Nous avons construit une intégration Airwallex ciblée autour de trois idées d’ingénierie : un modèle de domaine de paiement typé, un pipeline de webhooks selon le modèle outbox et une machine à états pour le cycle de vie des abonnements que le reste de l’application peut lire mais que seul le code de paiement peut écrire.
Côté API, toutes les données de carte sont collectées avec les éléments de paiement hébergés d’Airwallex, de sorte que le backend de l’application ne touche jamais un PAN — le périmètre PCI reste au niveau SAQ A. Le service FastAPI expose une petite API de paiements typée (modèles Pydantic v2, documentée OpenAPI) que l’équipe produit consomme ; les appels à l’API Airwallex sont encapsulés dans un client unique avec clés d’idempotence, nouvelles tentatives exponentielles et coupe-circuit.
Côté webhooks, chaque événement Airwallex arrive sur un point de terminaison signé et vérifié qui ne fait qu’une chose : persister l’événement brut dans une table `inbox` au sein d’une seule transaction. Un worker distinct traite l’inbox dans l’ordre, avec une livraison au moins une fois et des gestionnaires idempotents. Ce modèle seul a réglé complètement le problème des événements perdus — même lors d’un pic de trafic multiplié par 4 au lancement.
La machine à états des abonnements gère l’essai, l’actif, l’impayé, la relance, la pause, l’annulation et la réactivation, avec des transitions autorisées explicites et un journal d’audit à chaque changement d’état. Les paiements échoués suivent désormais un calendrier de nouvelles tentatives intelligent (et non le backoff exponentiel par défaut) adapté aux habitudes de jour de facturation du client, ce qui a produit la baisse de 65 % du churn lié aux paiements échoués.
- Éléments de paiement hébergés Airwallex — le backend de l’application ne touche jamais un PAN (PCI SAQ A)
- API de paiements FastAPI typée avec modèle de domaine Pydantic v2 et contrat OpenAPI
- Client Airwallex idempotent avec clés d’idempotence, nouvelles tentatives exponentielles et coupe-circuit
- Pipeline de webhooks selon le modèle inbox — vérification de signature, événement brut persisté, traitement ordonné par un worker
- Machine à états d’abonnement : essai, actif, impayé, relance, pause, annulé, réactivé
- Calendrier de relance intelligent adapté aux habitudes de jour de facturation des clients (pas un backoff naïf)
- Prise en charge multidevise : USD, CAD, GBP, EUR, AUD au lancement — d’autres ajoutées en quelques jours
- Tableaux de bord Datadog pour le retard des webhooks, le taux de nouvelles tentatives, l’entonnoir de relance et l’exposition au change
- Véritable guide d’astreinte couvrant une panne d’Airwallex, un arriéré de webhooks et des événements à signature invalide