Flux de paiement de bout en bout
Un paiement se découpe en deux phases, plus un canal de retour parallèle dédié à l'expérience utilisateur. Comprendre quelle étape appartient à quelle phase, c'est ce qui sépare une intégration fiable d'une intégration qui « marche à peu près ».
Phase 1 — Initiation (synchrone)
Le client clique sur « Payer par virement bancaire » et se retrouve redirigé vers la page hébergée LodinPay. Tout se déroule au premier plan, dans la session active du client.
| Étape | De | Vers | Action |
|---|---|---|---|
| 1 | Client | Plateforme | Clic sur « Payer par virement bancaire » |
| 2 | Module | BDD commandes | Création de la commande à l'état PENDING |
| 3 | Module | — | Construction du jeton de retour HMAC |
| 4 | Module | Passerelle Lodin | POST /rtp avec les en-têtes signés |
| 5 | Passerelle Lodin | Module | Réponse { url, invoiceId } |
| 6 | Module | BDD commandes | Persistance de l'invoiceId comme référence de la transaction |
| 7 | Module | Client | Redirection HTTP 302 vers la page de paiement hébergée |
| 8 | Client | Passerelle Lodin | Chargement de la page de paiement hébergée |
| 9 | Passerelle Lodin | Banque | Déclenchement de la SCA |
| 10 | Client | Banque | Authentification dans son application bancaire |
À la fin de la phase 1, la commande existe chez vous à l'état PENDING et le client est dans le parcours d'authentification de sa banque.
Phase 2 — Confirmation (asynchrone)
La banque exécute le virement, Lodin constate le règlement, puis la passerelle notifie votre serveur hors-bande. Cette phase s'exécute indépendamment de la session navigateur du client — même si le client ferme son onglet, le webhook arrive quand même.
| Étape | De | Vers | Action |
|---|---|---|---|
| 11 | Banque | Passerelle Lodin | SCT Inst exécuté |
| 12 | Passerelle Lodin | Module | Webhook payment.succeeded (signé) |
| 13 | Module | — | Vérification de la signature HMAC |
| 14 | Module | BDD commandes | État de la commande = PAID (idempotent) |
| 15 | Module | Passerelle Lodin | Réponse HTTP 200 OK |
Le webhook est le canal de confirmation faisant autorité. La phase 2 peut se terminer avant, pendant ou après le retour du client.
En parallèle : retour navigateur (UX uniquement)
En parallèle de la phase 2, Lodin redirige le client vers votre returnUrl. Ce canal existe uniquement pour que le client voie une page de confirmation.
| Étape | De | Vers | Action |
|---|---|---|---|
| 16 | Passerelle Lodin | Client | Redirection navigateur vers returnUrl |
| 17 | Client | Module | GET de la page de retour avec le jeton |
| 18 | Module | — | Vérification du jeton, branchement selon l'état courant |
Le retour navigateur n'est pas fiable : le client peut fermer son onglet, perdre sa connexion ou se laisser distraire. Si l'état de votre commande dépendait de son retour, des paiements échoueraient silencieusement.
Le webhook fait foi, et il fonctionne indépendamment. Le canal de retour n'existe que pour afficher une page de confirmation au client.
Conséquences pour votre implémentation
- L'état de la commande doit être accessible en écriture depuis les deux côtés. Le gestionnaire de webhook (en arrière-plan) et le gestionnaire de retour (au premier plan) peuvent arriver dans n'importe quel ordre. Quel que soit celui qui arrive en premier, l'autre doit voir un état cohérent.
- Le gestionnaire de retour lit l'état, n'écrit jamais l'état du paiement. Son unique rôle est d'afficher la bonne interface en fonction de ce que le gestionnaire de webhook a déjà écrit (ou pas encore).
- Soyez patient sur la page de retour. Si le webhook n'est pas encore arrivé, affichez une page « Traitement en cours… » qui interroge l'état pendant quelques secondes avant de trancher entre confirmation et nouvelle tentative. Ne renvoyez pas une erreur à T+0.
- L'idempotence est obligatoire — voir la Spécification des webhooks.
Voir aussi
- Machine à états des commandes — les états en jeu et leurs transitions.
- Spécification des webhooks — charge utile, vérification de signature, politique de relance.
- Modèle de sécurité — pourquoi le jeton de retour existe alors que le webhook fait foi.