Cascade et repli
Ce qui parcourt la liste des candidats, ce qui l'arrête et ce qui retire une route.
La cascade parcourt une seule fois la liste classée des candidats pendant l'appel
POST /payments/{id}, alors que votre requête est encore ouverte. Ce n'est ni une politique de
nouvelle tentative ni une tâche en arrière-plan. Lorsqu'elle se termine, la réponse HTTP est déjà
en route vers vous.
Vous ne pouvez configurer aucune chaîne de repli. Cette chaîne correspond à la liste de candidats construite par Orchestration des paiements. Cette page explique jusqu'où le moteur la parcourt avant d'abandonner.
Ce qui fait avancer la cascade
Une seule situation la fait avancer : le prestataire a échoué d'une manière qui ne dit rien sur le payeur. En pratique, le driver rencontre une erreur réseau ou renvoie un échec qu'il juge utile de réessayer ailleurs.
| Comportement de la connexion | Étape suivante |
|---|---|
| Elle a levé une erreur avant de recevoir une réponse : connexion refusée, échec DNS, expiration du socket | Le candidat suivant est essayé |
Elle a répondu 5xx, 408 ou 429 | Le candidat suivant est essayé |
| Elle a répondu d'une manière que son propre driver juge utile de réessayer ailleurs | Le candidat suivant est essayé |
Chacun de ces cas marque la tentative comme échouée, associe l'échec à cette route et descend d'une ligne. Le payeur n'est informé de rien, car rien ne s'est encore passé de son côté.
La dernière ligne dépend de l'évaluation du prestataire et varie selon celui-ci. Un prestataire qui répond sans référence permettant de suivre le débit est inutilisable pour ce paiement, mais peut fonctionner pour le suivant. Son driver transmet donc le paiement à la connexion suivante au lieu de le faire échouer.
Ce qui arrête la cascade
Quatre situations l'arrêtent. Une seule représente une bonne nouvelle.
Un prestataire a accepté. Cela comprend une acceptation avec pending ou requires_action. Le
prestataire prend en charge le paiement dès cet instant et aucune autre connexion n'est essayée.
Un prestataire a refusé pour un motif qui se reproduirait. Un portefeuille vide, un numéro non
enregistré, un plafond de l'opérateur, une carte refusée ou une demande laissée expirer par le payeur.
Le moteur renvoie immédiatement 402 sans consulter le candidat suivant, car un deuxième
prestataire poserait la même question à la même personne.
Une de vos connexions est mal configurée. Identifiants manquants, identifiants refusés par le prestataire ou champ obligatoire absent pour ce canal. Ces problèmes arrêtent également la cascade au lieu de passer à la connexion suivante. Une seule connexion défectueuse au début de votre liste peut donc vous faire perdre tous les paiements qui lui sont routés. Détectez ce cas rapidement. Le journal de routage le précise sur la ligne de la tentative.
Trois prestataires ont été essayés. orchestration.executor.max_attempts vaut 3 sur toute la
plateforme et ne peut pas être configuré par compte. Même une liste de dix candidats est parcourue
sur trois lignes au maximum. La requête se termine avec 402, alors que des connexions admissibles
n'ont pas été essayées.
Un refus ne met pas fin au paiement
Une réponse 402 laisse la transaction au statut pending, pas failed. Le payeur peut réessayer
sur le même paiement avec un autre numéro ou une autre carte. Ce deuxième appel reprend le routage
depuis le début. Vous décidez dans votre propre code si cette possibilité lui est proposée.
Chaque tentative laisse une ligne
Une tentative correspond à un enregistrement Processing sur le paiement. Il est créé avant
l'appel du prestataire, puis mis à jour avec la réponse reçue. Un paiement qui est passé deux fois à
la connexion suivante en contient trois, dans l'ordre. Chacun indique le prestataire essayé, le code
et le message de la passerelle, la latence et son rang dans la décision.
Vous les consultez dans le Dashboard, sous la chronologie du paiement, et dans Konsole à côté de la décision qui les a produits. L'historique des tentatives n'existe qu'à ces endroits. L'objet paiement renvoyé par l'API n'en contient aucune trace.
Un paiement, deux prestataires
- 12:31:40
tentative 1status: failedRang 1 de la décision, priorité 100, score 2550. L'opérateur n'a pas répondu avant l'expiration du délai. L'échec a donc été comptabilisé pour cette route.
- provider
- cinetpay
- gateway_response_code
- timeout
- latency
- 8.0 s
- 12:31:49
tentative 2status: processingRang 2, même palier de priorité. L'opérateur a accepté d'envoyer une demande au payeur. Il s'agit d'une acceptation, la cascade s'est donc arrêtée ici.
- provider
- flutterwave
- gateway_response_code
- pending
- latency
- 0.9 s
La deuxième ligne explique la majeure partie de la confusion autour de la cascade.
Aucun basculement n'a lieu après l'acceptation de la demande
Un prestataire Mobile Money répond pending dès que l'opérateur accepte d'envoyer la demande,
plusieurs secondes avant toute action du payeur sur son téléphone. Cette acceptation arrête la
cascade. Si le payeur ne confirme jamais, le paiement échoue quelques minutes plus tard pendant
la vérification ou à la réception d'un webhook du prestataire, bien après la fin de l'exécution.
Aucun autre prestataire n'est essayé. La plupart des situations que les marchands interprètent
comme l'échec d'une cascade correspondent à ceci : la cascade n'a jamais démarré, car le premier
prestataire a répondu oui.
Ce que décide la classification des échecs
Chaque échec est associé à une classe canonique, d'abord à partir du code d'erreur du prestataire, puis à partir de mots-clés dans son message. Cette classe ne décide pas si la cascade avance. Elle décide deux autres éléments qui concernent tous deux la réputation de la route, pas ce paiement.
| Classe | Côté | Pénalise la route |
|---|---|---|
operator_timeout | Chemin | Oui |
operator_unavailable | Chemin | Oui |
path_auth_error | Chemin | Oui |
float_exhausted | Chemin | Oui |
unknown | Non classé | Oui |
insufficient_funds | Client | Non |
invalid_number | Client | Non |
limit_exceeded | Client | Non |
customer_action_timeout | Client | Non |
pending_unresolved | Cycle de vie | Coupe-circuit uniquement |
duplicate | Cycle de vie | Coupe-circuit uniquement |
Retenez la règle qui régit la dernière colonne : un échec ne pénalise une route que s'il reflète sa fiabilité. Le portefeuille vide d'un payeur ne prouve pas que MTN rencontre un problème. Le prendre en compte éloignerait progressivement votre trafic d'une connexion en parfait état. Le coupe-circuit ignore entièrement les quatre classes liées au client. Le taux de réussite en direct est uniquement calculé à partir des classes liées au chemin.
Le coupe-circuit
Une route qui échoue constamment est retirée de la rotation avant de vous faire perdre davantage de
paiements. Ici, une route correspond à votre compte, à un canal et à un prestataire. Une connexion
défaillante sur cm.mtn continue donc de traiter cm.orange, sans affecter les autres marchands.
| Ouverture après | 5 échecs en 60 secondes, hors échecs liés au client |
| Durée d'ouverture | 5 minutes |
| Ensuite | Une tentative de contrôle est autorisée |
| Si le contrôle réussit | Les compteurs sont effacés et la route revient dans la rotation normale |
| Si le contrôle échoue | La période d'ouverture recommence et double à chaque fois, jusqu'à 16 fois la durée de base |
Une route ouverte est retirée avant le classement. Une connexion que vous pensiez voir peut donc être entièrement absente d'une décision. Elle n'est pas retirée silencieusement : la décision l'enregistre avec son motif et Konsole l'affiche sur sa propre ligne.
Décision de routage · cm.mtn · 25 000 XAF
Une route hors rotation, deux connexions classées et la première a traité le paiement.
- 1

flutterwaveaccepté0.9 spriority 100 · score 250 - 2

pawapayjamais appeléepriority 100 · score 0 cinetpayIgnorée avant le classement. Son circuit est ouvert sur ce canal après des échecs répétés du chemin.
Si cette route était votre route préférée, l'effet est visible et difficile à comprendre sans cette page : une règle qui cible CinetPay semble ignorée pendant cinq minutes. Elle ne l'est pas. Le candidat n'a jamais figuré dans la liste à noter.
Deux prestataires ne peuvent jamais débiter en même temps
Au cours d'un appel, l'exécution s'arrête à la première acceptation. Une seule tentative peut donc réussir. Vous devez surtout faire attention à la répétition de l'appel lui-même.
Envoyez un en-tête Idempotency-Key avec POST /payments/{id}. La réponse est mise en cache pendant
24 heures pour votre compte, la clé et un condensé du payload. Répéter le même appel renvoie alors
la même réponse sans exécuter une deuxième cascade. Sans cet en-tête, aucune protection de ce type
n'existe. Un client qui répète une requête dont il n'a jamais reçu la réponse peut lancer une
deuxième cascade sur un paiement déjà réussi.
Une clé par tentative de paiement
Dérivez la clé d'une valeur stable de votre propre système, comme la référence de la commande
suivie du numéro de tentative. Elle accepte jusqu'à 128 caractères parmi A-Z a-z 0-9 . _ : -.
Un payload différent avec la même clé est considéré comme une requête différente.
Lorsque la liste était vide dès le départ
Une réponse 422 sur la clé channel signifie qu'aucun candidat n'a passé les filtres. Rien n'a
donc été essayé et aucune nouvelle tentative ailleurs n'est possible. Il s'agit d'un problème de
configuration du compte, pas du payeur : le canal, la devise, l'absence de driver ou le
coupe-circuit a retiré toutes les connexions avant le classement.
La correction ne se trouve jamais dans votre requête. Ouvrez le journal de routage, recherchez la décision et identifiez le filtre qui a vidé la liste.
Pages associées
- Orchestration des paiementsLa construction et l'ordre initial de la liste des candidats.
- Règles de routageCe qu'une règle peut fixer et les situations où elle ne peut pas aider.
- Analyse de l'orchestrationLe nombre de paiements réellement récupérés par la cascade.
- IdempotenceL'en-tête, sa durée et les critères d'une requête identique.