Idempotence et rejeu

Clé orderId, conflit 409, et la règle de l'issue indéterminée.

orderId est la clé, et il n'y en a pas d'autre

L'identification d'une transaction repose entièrement sur l'orderId que vous fournissez. Il n'existe pas de header Idempotency-Key.

  • Unique par organisation — pas globalement. Deux marchands peuvent porter le même orderId sans se gêner.
  • 1 à 100 caractères, ^[A-Za-z0-9_-]+$ : lettres, chiffres, _ et - uniquement.

À vous de le rendre stable et unique. Un compteur séquentiel (order_1, order_2) est un mauvais choix : il est devinable, et le reçu public est adressable par orderId seul. Préférez un identifiant non devinable, par exemple order-<uuid v4>.

Conservez le transactionId (un UUID) renvoyé dans la réponse : c'est la référence de corrélation à citer au support az54.

Rejouer : la règle de l'issue indéterminée

C'est le point qui distingue une intégration robuste d'une intégration qui perd de l'argent.

Un 502 ou un timeout ne vous autorise pas à conclure que le paiement a échoué. Dans ces deux cas, la requête a pu atteindre le PSP et le paiement a pu aboutir. Le statut ne fait pas foi tant que le webhook n'a pas parlé.

La bonne réaction est toujours la même : rejouer strictement la même requête, avec le même orderId et le même corps.

Deux issues possibles :

  • 200 — votre première tentative n'avait rien créé. La demande est maintenant enregistrée.
  • 409 CONFLICT — la transaction existait déjà. data porte { orderId, status } : c'est son état courant. C'est une réponse normale, pas une erreur à remonter. Vous venez d'apprendre ce que vous cherchiez.

Ne changez pas d'orderId au rejeu

Un orderId neuf au rejeu crée une seconde transaction : deux sollicitations, potentiellement deux débits chez le payeur.

Ne modifiez pas non plus les autres champs. Un corps différent peut être rejeté par une validation en amont du contrôle d'unicité — vous recevez alors un 400 qui masque le fait que la transaction existe déjà, et vous concluez à tort à un échec.

Ce qui n'est pas dédupliqué

L'unicité porte sur la création. Les notifications sortantes ne sont pas numérotées : concevez votre handler de webhook comme idempotent, en vous appuyant sur la monotonie des statuts — la première notification terminale fait foi, les suivantes sont sans effet.

On this page