Machines à états
Tout le comportement de paiement est gouverné par deux machines à états : celle d’un leg (une jambe) et celle d’une session. Le statut de la session est déduit de l’état de ses legs.
- Logique des legs :
api/src/domain/session/leg-status.ts - Logique des sessions :
api/src/domain/session/session-status.ts
Machine à états d’un leg gift card
Section intitulée « Machine à états d’un leg gift card »Une carte cadeau est débitée directement (pas de phase « hold » séparée) : un débit réussi la place
en CAPTURED. L’annulation et le remboursement passent par un état transitoire.
stateDiagram-v2 [*] --> PENDING PENDING --> CAPTURED: débit réussi PENDING --> DEBIT_FAILED: débit refusé CAPTURED --> CANCELING: rollback demandé CAPTURED --> REFUNDING: remboursement demandé CANCELING --> CANCELED CANCELING --> CANCEL_FAILED: refus du fournisseur CANCEL_FAILED --> CANCELING: nouvel essai CANCEL_FAILED --> CANCELED: réglé hors E-Pay REFUNDING --> REFUNDED REFUNDING --> REFUND_FAILED: refus du fournisseur REFUND_FAILED --> REFUNDING: nouvel essai REFUND_FAILED --> REFUNDED: réglé hors E-Pay DEBIT_FAILED --> [*] CANCELED --> [*] REFUNDED --> [*]
Machine à états d’un leg PSP
Section intitulée « Machine à états d’un leg PSP »Un PSP suit un cycle autorisation (hold) → capture. Entre les deux, un hold peut être relâché
(void) lors d’un rollback. Le 3DS introduit un état d’attente d’action client.
stateDiagram-v2 [*] --> PENDING PENDING --> HELD: autorisation réussie PENDING --> HOLD_FAILED: autorisation refusée HELD --> CAPTURED: capture réussie HELD --> CAPTURE_FAILED: capture refusée HELD --> RELEASING: rollback (void du hold) RELEASING --> RELEASED CAPTURED --> REFUNDING: remboursement CAPTURED --> REFUNDED: remboursé chez le PSP (dashboard) REFUNDING --> REFUNDED REFUNDING --> REFUND_FAILED: refus du PSP REFUNDED --> REFUND_FAILED: échec annoncé après coup REFUND_FAILED --> REFUNDING: nouvel essai REFUND_FAILED --> REFUNDED: réglé hors E-Pay HOLD_FAILED --> [*] CAPTURE_FAILED --> [*] RELEASED --> [*] REFUNDED --> [*]
Les états terminaux d’un leg sont : DEBIT_FAILED, HOLD_FAILED, CAPTURE_FAILED, CANCELED,
RELEASED, REFUNDED. Une fois là, plus aucune transition n’est possible.
Machine à états d’une session
Section intitulée « Machine à états d’une session »Une session naît en CREATED, collecte ses legs, puis est traitée. Son statut « avancé »
(COMPLETED, ROLLING_BACK, FAILED, remboursements) est déduit de l’état des legs.
stateDiagram-v2 [*] --> CREATED CREATED --> COLLECTING: ajout de legs COLLECTING --> PROCESSING: submit (montant restant = 0) CREATED --> PROCESSING: submit PROCESSING --> COMPLETED: tous les legs actifs CAPTURED PROCESSING --> COLLECTING: autorisation carte refusée (reopenForRetry, cadeaux conservés) PROCESSING --> ROLLING_BACK: échec de capture ROLLING_BACK --> FAILED: compensation terminée (plus rien en vol) COMPLETED --> PARTIALLY_REFUNDED: un leg remboursé COMPLETED --> FULLY_REFUNDED: tous les legs remboursés PARTIALLY_REFUNDED --> FULLY_REFUNDED CREATED --> EXPIRED: TTL dépassé COLLECTING --> EXPIRED: TTL dépassé FAILED --> [*] FULLY_REFUNDED --> [*] EXPIRED --> [*]
Comment le statut de session est calculé
Section intitulée « Comment le statut de session est calculé »deriveSessionStatus applique, en simplifié, cette cascade de règles sur l’ensemble des legs :
EXPIREDest collant : les compensations qui aboutissent après l’expiration ne ressuscitent pas la session- Un leg en cours de rollback (
CANCELING/RELEASING) →ROLLING_BACK - Session
ROLLING_BACKsans plus rien en vol →FAILED(convergence de la compensation) - Tous les legs encore porteurs d’argent
REFUNDED→FULLY_REFUNDED - Au moins un leg
REFUNDED/REFUNDING/REFUND_FAILED, ou un leg encaissé remboursé en partie chez le PSP →PARTIALLY_REFUNDED - Depuis
PROCESSING, tous les legsCAPTURED→COMPLETED - Sinon → statut courant conservé
Un refus d’autorisation ne passe PAS par cette cascade : le worker appelle explicitement
reopenForRetry — la session repasse en COLLECTING, cartes cadeaux conservées (déjà débitées,
elles restent acquises), et le leg carte refusé sera remplacé par setPspLeg au prochain essai.
Les legs inactifs (HOLD_FAILED, CANCELED…) ne comptent plus dans la somme au submit ni pour
conclure la session.
Lien avec l’orchestration
Section intitulée « Lien avec l’orchestration »Ces transitions ne se produisent pas « en direct » dans la requête HTTP : elles sont appliquées par
l’orchestrateur (process-outbox-entry.ts) au fil du traitement asynchrone. Voir
Outbox & orchestration puis L’orchestrateur.
Source de vérité métier complémentaire :
doc/site/content/state-machines.mdx.