Répétitions et backoff dans les paiements
Répétitions et backoff dans les paiements
1) Pourquoi des répétitions sont nécessaires
Conversion : les pannes molles (timeouts, erreurs 3DS, pannes de réseau) sont souvent récupérées à la répétition : + 2-7 pp au taux Auth.
Durabilité : les défaillances locales PSP/ACS/banque sont lissées par des retraits avec des itinéraires alternatifs.
L'expérience du joueur : des répétitions correctement construites cachent le « bruit » de l'infrastructure sans double annulation.
2) Principes de base
1. Idempotence au niveau « payment intent » (PI) : une opération = une 'idempotency _ key' ; toute nouvelle conversion ne modifie pas la fortune monétaire.
2. Séparation des erreurs :- Hard decline (par ex. ' Do not honor ' à la politique rigide de l'émetteur, ' Insufficient funds') → d'habitude non ретраим à la fois.
- Soft decline/technique (timeout, 'Issuer unavailable', 'Try again') → rétrospective autorisée.
- 3. Backoff + limitation des tentatives : augmentez exponentiellement le délai, ajoutez un jitter et ne dépassez pas les limites (généralement 2-3 tentatives).
- 4. Routage dans le lien : Retray n'est pas seulement une « répétition au même PSP », mais aussi un changement de mode/méthode PSP/MID/3DS.
- 5. Observabilité : chaque hop est enregistré dans la Route Journal (PSP, reason, latinité, mode 3DS, fee, résultat).
3) Classification des erreurs pour la décision de rétractation
4) Stratégies backoff (pratique)
4. 1 Backoff exponentiel avec jitter (recommandé)
База: `delay_n = min(base 2^n, max_delay)`
Gitter : 'delay = rand (0, delay_n)' - réduit les « stampedes » lorsque de nombreuses requêtes sont répétées simultanément.
Paramètres typiques : 'base = 200-500 ms', 'max _ delay = 5-10 s', 'n≤2 -3'.
4. 2 Backoff linéaire
C'est simple, mais pire quand on est en ligne. Inférieur à l'exponentiel + jitter.
4. 3 Politique de temporisation
Client timeout (votre) ≤ PSP SLA (par exemple, 3-5 s), sinon le risque de doublons/accroissements augmente.
Définissez séparément le temps d'attente webhook/confirm : si la confirmation n'est pas arrivée → le rapprochement compensatoire (ledger/PSP).
5) Idempotence et protection contre les prises
Payment Intent (PI) stocke l'état, la somme, la méthode, 'idempotency _ key', l'historique des itinéraires.
Chaque hop et retry utilise la même clé.
Transactions compensatoires : dans le cas d'une dissynchrone (approve dans PSP, et vous avez un timeout) - "reconcile-pull' + ajustement du ledger.
Excluez la réautorisation lors de la réadmission du webhook : vérifiez l'unicité de 'transaction _ id '/' PSP reference'.
6) 3DS/SCA et répétitions
Soft decline après frictionless → rétrospective avec challenge.
ACS timeout/unavailable → un backoff exponentiel, puis un canal alternatif (open banking/APM) ou un autre PSP.
Avec la dégradation massive de l'ACS - circuit-breaker, la croissance de « challenge rate », les limites de temps sur les montants.
7) Répétitions pour APM/open banking
Open banking/instant rails (SEPA Instant/FPS/Pix/UPI):- Les retraits sont limités : vérifiez l'idempotence du côté du fournisseur et les statuts dans les webhook'ax retardés.
- Avec un statut incertain - polling avec backoff et des rapprochements stricts.
- Bons/espèces : les retraits ne s'appliquent pas comme une « transaction en ligne », mais le contrôle du délai de paiement et le « status refresh » s'appliquent.
8) Payouts (conclusions) : répétitions et files d'attente
Échec technique de la banque/PSP → payouts queued avec drain backoff.
KYT/velocity fail → n'est pas rétroactif, le transfert à la vérification manuelle.
Priorité de la file d'attente : VIP/petits montants/durée de la demande ; debline SLA et auto-escalade.
Rails alternatifs (RTP/FPS/SEPA Instant/Pix) dans la deuxième étape rétractable.
9) Circuit-breaker et Retrai
Local (sur PSP/MID/BIN) : en cas de surtension d'erreurs, → arrêtons les retraits sur cette route, passons à une autre.
Global (par méthode/région) : la dégradation du système → désactivons la méthode, nous proposons APM/open banking.
Half-open : Nous retournons une partie du trafic (1-5 %) pour vérifier la récupération avant le retour complet.
10) Pseudo-code de la stratégie des rétrogrades
python def pay_with_retries(pi):
ensure_idempotency(pi.key)
if not compliance_pass(pi): return REJECT
routes = rank_candidates(pi) # по вероятности approve, fee, health attempts = 0 for route in routes:
policy3ds = select_3ds(pi, route)
res = call_psp(route, pi, policy3ds, pi.key, timeout=3.0)
log_attempt(pi, route, res)
if res.approved: return APPROVED
if is_soft_decline(res) or is_transient_error(res):
while attempts < MAX_ATTEMPTS and not breaker_open(route):
delay = backoff_with_jitter(base=0.3, attempt=attempts, cap=8.0)
sleep(delay)
policy3ds = maybe_toggle_3ds(policy3ds, res)
res = call_psp(route, pi, policy3ds, pi.key, timeout=3.0)
log_attempt(pi, route, res)
attempts += 1 if res.approved: return APPROVED if is_hard_decline(res): break перейти к следующему маршруту (PSP-B/APM/open banking)
return DECLINED
11) KPI et repères cibles
Approvals incrémentiels de Retries : + 2-7 pp à la conversion de base.
Avg Retry Attempts per Approved Tx: 1. 2–1. 5 (gardez en dessous de 1. 7).
Retry Success Rate (soft/tech): ≥ 25–40%.
Taux de duplication : 0 avec idempotence correcte.
P95 Latency (avec les retraits) : <7 s jusqu'à la réponse finale.
Payout SLA (instant share) : ≥ 70 % des chèques légers, retard <seuil cible.
12) Pleybooks d'incidents
A. Timeouts de masse sur PSP-A
1. Ouvrir un breaker local pour PSP-A.
2. Redistribuer les retraits au PSP-B/APM.
3. Backoff exponentiel avec jitter, limite 2-3 tentatives.
4. Canaris half-open dans 10-15 min.
B. Dégradation ACS/3DS
1. Détail sur la taille « soft decline », timeouts.
2. Augmenter le taux de défi ; une partie du trafic → open banking.
3. Différer les chèques lourds, inclure les limites de velocity.
C. Retards de paiement
1. Transfert en file d'attente, priorité VIP/petites sommes.
2. Rails alternatifs (RTP/FPS/SEPA Instant/Pix).
3. Communication aux joueurs + auto-escalade.
13) Observabilité et données
Route Journal: PSP/MID, BIN/issuer, reason, latency, 3DS-режим, retry chain, итог, fee.
Dashboards : Auth Rate (par banques), Retry Success, Avg Attempts, Decline Mix, p95 latency, Payout Queue Depth.
Alerties : spikes par code reason, augmentation des tentatives/latency, débordement des files d'attente des conclusions.
14) Chèques-feuilles de mise en œuvre
Architecture/données
- Payment Intent + `idempotency_key` на все hops.
- Matrice configurée des codes reason : retryable vs non-retryable.
- Abonné webhooks, déduplication par référence PSP.
Backoff/règles
- Backoff exponentiel avec jitter ; limite d'essai et heure de fenêtre.
- Smart retry : changement de 3DS/MID/PSP/méthode ; distinction pour les cartes vs APM/open banking.
- Circuits-breakers (local/global), half-open-canaris.
Ledger/rapprochement
- Opérations compensatoires avec statuts « suspendus ».
- T + 0/T + 1 rapprochements : PSP ↔ banque ↔ ledger monétaire.
- Politique de temporisation et SLA sur confirm/webhook.
Opérations/conformité
- RG/Sanctions/PEP/Âge - avant les rétrogrades.
- KYT/velocity на payouts; les règles de la rhubarbe manuelle.
- Runbooks et RACI pour les incidents/escalade.
15) Économie et risque
Comptez le taux effectif en tenant compte de 3DS-fia, FX, charjbek-value, retray-overhead.
Limitez fortement les retraits sur les segments à risque élevé afin de ne pas surclasser la charge et les réserves.
16) Résultat
Les répétitions fonctionnent lorsqu'elles sont gérables : idempotence, matrice de codes reason claire, backoff exponentiel avec jitter, limitation des tentatives et lien avec le routage (changement de PSP/3DS/méthode). Ajoutez un circuit-breaker, des files d'attente pour les payouts et de solides rapprochements - et vous augmenterez la conversion de façon stable sans créer de prises et de « trous » de caisse.