GH GambleHub

Refands partiels et complets

TL; DR

Refand est une opération inverse sur la somme capturée. La transaction complète ferme l'ensemble, la partie partielle retourne la partie (il peut y avoir une série partielle jusqu'à la totalité). Critique : refund-to-source, idempotence stricte, journal des causes, et orchestration avec webhooks/retraits. Nous mesurons Refund Rate, TtR p95, Refund Error et éliminons les doublons/incohérences par auto-rapprochement.

1) Termes et différences fondamentales

Full Refund : Renvoie la totalité du montant fixé ('refund _ amount = capture_amount').
Refund partiel : Renvoie une partie ('0 <refund_amount <capture_amount'), autorise le reste de la partie jusqu'à la somme' capture _ amount'.
Refund to Source - Retour à la méthode de paiement/rails d'origine (réglementé de préférence/obligatoire).
Void - annulation avant capture (si supporté par les rails), n'est pas considéré comme un refand.
Reversal/Chargeback - la mécanique bancaire/ferroviaire en dehors de votre initiative (controverse, chargebacks) - à ne pas confondre avec le refand.

2) Quand délivrer vs partial complet

Complet (Complet) :
  • Annulation de la commande/du service en entier, double débit, erreur système.
  • Obligatoire en cas d'échec de la prestation du service (selon les règles du consommateur/régulateur).
Partiel (Partial) :
  • Annulation partielle du service, ajustements proportionnels (rabais, compensation des retards).
  • Limites techniques du rail (montant maximum par opération) - série partiale.
  • La rétention de commissions (lorsque la réglementation est autorisée) est moins fréquente dans iGaming.
Solution : nous cousons la matrice 'reason _ code × method × jurisdiction' → policy = fullpartialboth, limites, niveau d'approbation requis.

3) Politiques et limites

Refund-to-source = true par défaut ; exceptions - via MLRO/cas de conformité (logé).
Cut-off : les refands sont autorisés N jours à compter de la capture (selon la méthode/juridiction).
Max Partial Count : pas plus de K partial par paiement (typiquement K ≤ 5).
Min Partial Amount : Pas inférieur au minimum technique rail/PSP.

Approval Matrix:
  • Agent de Sapport : partial ≤ X, full ≤ Y.
  • Gestionnaire/Finances : plus de limites, exceptions transversales.
  • Cooling-off pour les tentatives répétées (anti-drebezg).

4) Architecture et flux d'événements

Composants :
  • Payment Orchestrator est la source de la vérité des statuts.
  • Refund Service - API, idempotence, orchestration de retraits, journalisation.
  • Adaptateurs PSP - intégration par méthode.
  • Reconnaissance - auto-rapprochement, DLQ, corrections.
  • Ledger/Comptabilité - câblage, defers, alignement avec compensation.
  • Risk/Compliance - contrôles de sanctions/SoF dans les scénarios controversés.
Séquence (partial/full) :

1. `Refund. Create '(API) → validation (limites, solde, politique, KYC/SoF si nécessaire).

2. Генерация idempotency_key (`hash(payment_id + refund_amount + reason + nonce)`).

3. L'appel PSP → le statut 'PENDING'.

4. Webhook/polling → 'SUCCESS '/' FAILED' ; En cas de délai, retraits avec la même clé.

5. Publication de l'événement dans Kafka → Ledger, BI, alerte.

6. Auto-rapprochement : Correspondance de 'provider _ refund _ id' avec le registre.

5) Idempotence et anti-doublage

Le même refand ne peut pas être crédité deux fois : toute la logique via le stockage idempotency (KV/Redis + TTL).
Clés de payment_id × amount × reason (et, si nécessaire, 'partial _ index').
Les retraits utilisent la même clé.
Les partiels parallèles sont protégés par row-level locks/optimistic version sur aggregate somme.

Pseudo-code :
python def refund(payment_id, amount, reason, idem_key):
if idem_store. exists(idem_key): return idem_store. get(idem_key)
with tx():
p = db. get_payment(payment_id, for_update=True)
assert p. captured_amount - p. refunded_amount >= amount > 0 r = p. create_refund(amount, reason, status='PENDING', idem_key=idem_key)
resp = psp. refund(p. provider_txid, amount, idem_key)
return finalize(r, resp. status, resp. ext_id)

6) Modèle de données (minimum suffisant)

json
{
"payment_id": "pay_123",
"captured_amount": 150. 00,
"currency": "EUR",
"refunded_amount": 40. 00,
"refunds": [
{
"refund_id": "rf_001",
"type": "partial    full",
"amount": 20. 00,
"reason_code": "PARTIAL_SERVICE",
"idempotency_key": "idem_a1",
"status": "PENDING    SUCCESS    FAILED",
"provider_refund_id": "psp_rf_9xz",
"created_at": "2025-11-03T12:00:00Z",
"credited_at": "2025-11-03T15:05:00Z",
"notes": "ticket #456"
}
],
"flags": {
"refund_to_source": true,
"jurisdiction": "EEA",
"kyc_tier_required": "tier2"
}
}

7) Caractéristiques sur les rails de paiement

Cartes (Visa/Mastercard)

Prise en charge complète/partielle ; souvent plusieurs partiaux ; TtR dépend de la banque du client (T + 1... T + 5 b.d.).
Les webhooks sur le succès arrivent rapidement, mais l'inscription sur l'extrait peut être en retard → nous expliquons dans les modèles de saphport.

A2A/Open Banking/RTP

Retour souvent instantané (reversal/credit push) ; certains fournisseurs ne prennent en charge que le full ou 1 partial.
Un lien strict avec le compte source ; refund-to-source est obligatoire.

Porte-monnaie électronique

Normal complet/partial ; TtR en minutes ; limitation du nombre de parties et du montant minimal.

Bons/Prépaid

Normalement, la politique → n'est pas disponible : retour au portefeuille interne ou bon d'achat (si le fournisseur le sait). Exige des réserves de conformité.

Crypto

Les rails sont volatils ; il est préférable de ne pas l'utiliser comme méthode de refand. Si autorisé : retour à la même adresse/bourse avec cours et commissions documentés ; Dépistage AML.

8) Comptabilité, rapprochement et finances

Ledger : câblage 'DR Revenue/CR Cash'à la capture ; à refund, les entrées inversées. Partial se reflète proportionnellement.
Reconnaissance : dans iGaming, le refand réduit le RGG de la période correspondante (comptable).
Reconnaissance : rapprochement quotidien 'merchant _ refund _ id ↔ provider_refund_id', statuts, montants, cours FX.
FX : enregistrez la logique des cours (au moment de la capture ou au moment du retrait), le cas échéant ; Gardez la grille des spreads.

9) KPI, objectifs et alertes (Refund Health)

Taux de refund = 'Refunded _ Tx/ Captured_Tx' (segmenter : par raison).
Refund Amount Ratio = `Refunded_Amount / Captured_Amount`.
TtR p95 = p95 ('credited _ at - created_at') selon la méthode.
Refund Error Rate = `Failed / Attempted` (<0. 3%).
Refund-to-Source % ≥ 95 % (le cas échéant).
Double Refund Incidents = 0.

Alert :
  • 'TtR p95 'ci-dessus SLO selon la méthode → P2.
  • Spikes par 'Refund Rate' en un seul fournisseur/BIN → P1 (vérifier les prises/prises).
  • N'importe quel 'Double Refund> 0' → P0 (gel immédiat des auto-refands).

10) tranches SQL

10. 1 Profil des refands

sql
SELECT
DATE_TRUNC('day', r. created_at) AS d,
method_code, provider,
COUNT() FILTER (WHERE r. status='SUCCESS')  AS refunds_ok,
COUNT() FILTER (WHERE r. status='FAILED')  AS refunds_fail,
SUM(r. amount) AS refunded_amount,
PERCENTILE_CONT(0. 95) WITHIN GROUP (ORDER BY EXTRACT(EPOCH FROM (r. credited_at - r. created_at))) AS ttr_p95_sec
FROM refunds r
JOIN payments p ON p. payment_id = r. payment_id
GROUP BY 1,2,3;

10. 2 Contrôle du résidu pour partial

sql
SELECT p. payment_id,
p. captured_amount,
SUM(r. amount) AS refunded_sum,
(p. captured_amount - SUM(r. amount)) AS refundable_left
FROM payments p
LEFT JOIN refunds r ON r. payment_id = p. payment_id AND r. status IN ('SUCCESS','PENDING')
GROUP BY 1,2
HAVING (p. captured_amount - SUM(r. amount)) < 0;

11) UX et Sapport

Modèles de messages par méthode : nous expliquons aux cartes un retard possible sur le relevé, A2A - presque instantanément.
Statuts dans le bureau : 'Formalisé → En cours de traitement → Retourné' ; indiquer la date d'inscription prévue.
Les raisons (reason_code) sont humaines : « Double débit », « Annulation du service », « Compensation partielle ».
Self-service partial - sécurisé uniquement avec des limites et des règles claires.

12) Risque et conformité

Anti-blanchiment : le refand ne doit pas se transformer en une sortie sur un canal alternatif ; enregistrer des exceptions avec l'approbation MLRO.
Sanctions/RER : lors des retours initiés sur des comptes/détails « rouges » - vérification obligatoire.
DSAR/Rétention : conservez des traces de refands dans le cadre de la politique de stockage.
Règles locales : calendrier et ordre des retours (par exemple, règles de consommation) - reflétées dans la politique.

13) Erreurs fréquentes et comment les éviter

Le double refand, en raison de l'absence d'idempotence et des webhooks répétés, → stocker idem clé/état, vérifier le reste.
Partial> reste → row-lock/version optimiste et contrôles rigoureux.
Le refund cross-method sans autorisation de conformité perturbe → le refund-to-source.
Le mélange void et refund dans les rapports → la distorsion KPI.
Il n'y a pas d'auto-swerok → de « trous noirs » entre le PSP et votre ledger.

14) Pleybooks

L'augmentation des retours par fournisseur de services → vérifier les pannes d'autorisation/prises de capture, allumer le faussaire, contacter le PSP.
Les compensations partiales massives (campagne) → augmenter la limite partiale, inclure les opérations de groupe, renforcer les rapprochements.
L'erreur des webhooks → passer à la polling, augmenter la TTL d'idempotence, reporter les auto-refands.
L'exclusion de refund-to-source (rarement) → l'escalade du MLRO, le paiement documenté et la marque 'bou _ approved = true'.

15) Cas de test (UAT/Prod)

1. Refund complet après une seule capture → annule correctement le reste.
2. Série partiale (3 ×) → somme ≤ capture ; puis plein pour le reste.
3. Idempotence : répéter la même requête → 1 résultat.
4. Webhook-drebezg : 3 notifications identiques → un prélèvement/crédit.
5. Rapprochements : mismatch artificiel → alert et auto-correction.
6. Limitation des droits : l'agent ne peut pas dépasser la limite partielle.
7. Cut-off : tentative de refand tardif → échec correct et loging.

16) Chèque de vérification de mise en œuvre

  • Politiques complètes/partielles + refund-to-source par pays/méthode.
  • Idempotentialité, retraits, webhooks et polling, DLQ.
  • Modèle de données avec solde de retour et de reason_code.
  • Ledger et les auto-rapprochements quotidiens.
  • KPI/dashboard : Taux de refoulement, TtR, Error, Double Refund = 0.
  • Droits et matrice d'appellation, modèles de Sapport.
  • Cas de test UAT et alerte de niveau pro.

Résumé

La gestion des refands est une discipline rigoureuse des processus : refund-to-source, idempotence, modèle de données transparent, auto-rapprochement et politiques compréhensibles partial/full. Avec de telles bases, vous gardez le TtR bas, les erreurs sont à zéro, les prises sont impossibles, et la conformité et la finance sont synchronisées avec les objectifs commerciaux.

Contact

Prendre contact

Contactez-nous pour toute question ou demande d’assistance.Nous sommes toujours prêts à vous aider !

Telegram
@Gamble_GC
Commencer l’intégration

L’Email est obligatoire. Telegram ou WhatsApp — optionnels.

Votre nom optionnel
Email optionnel
Objet optionnel
Message optionnel
Telegram optionnel
@
Si vous indiquez Telegram — nous vous répondrons aussi là-bas.
WhatsApp optionnel
Format : +code pays et numéro (ex. +33XXXXXXXXX).

En cliquant sur ce bouton, vous acceptez le traitement de vos données.