Жарым-жартылай жана толук Refand
TL; DR
Refand - бул captured сумма боюнча тескери операция. Толук бүтүмдү толугу менен жабат, жарым-жартылай бир бөлүгүн кайтарып берет (толук партиялык сериясы болушу мүмкүн). Критикалык: refund-to-source, катуу демпотенттик, себептерин каттоо, жана Webhook/Retrains менен оркестр. Refund Rate, TtR p95, Refund Error өлчөө жана auto-текшерүү аркылуу эки/айырмачылыктарды жоюу.
1) Терминдер жана принципиалдуу айырмачылыктар
Full Refund - бардык белгиленген сумманын кайтарылышы ('refund _ amount = capture_amount').
Partial Refund - бөлүктүн кайтарылышы ('0 <refund_amount <capture_amount'), калган partial жалпы' capture _ amount 'чейин жол берет.
Refund to Source - баштапкы ыкмасына/төлөм рельстерине кайтаруу (жөнгө салуучу артыкчылык/милдеттүү).
Void - capture чейин жокко чыгаруу (рельстер тарабынан колдоого алынса), рефанд болуп эсептелбейт.
Reversal/Chargeback - Сиздин демилгенин сыртында банк/рельс механиктери (талаш-тартыштар, чаржбэки) - refand менен чаташтырбоо.
2) Качан толук vs жарым-жартылай берүү
Толук (Толук):- Толугу менен буйрутманы/кызматты жокко чыгаруу, эсептен чыгарууну кайталоо, системалык ката.
- Кызмат көрсөтүлбөгөндө милдеттүү (керектөөчүнүн/жөнгө салуучунун эрежелери боюнча).
- Кызмат көрсөтүүнү жарым-жартылай жокко чыгаруу, пропорционалдуу түзөтүүлөр (арзандатуулар, кечигүүлөрдүн ордун толтуруу).
- Рельстин техникалык лимиттери (бир операция үчүн максималдуу сумма) - партиялык сериялар.
- Постфактум комиссияларды кармап туруу (регулятивдик жол берилген жерде) - iGamingде азыраак.
3) Саясаттар жана лимиттер
Refund-to-source = true демейки; өзгөчөлүктөр - MLRO/комплаенс-кейстер аркылуу (логикалык).
Cut-off: Refand (ыкма/юрисдикция боюнча) тартып N күн жол берилет.
Max Partial Count: көп эмес K partial боюнча төлөө (типтүү K ≤ 5).
Min Partial Amount: техникалык минималдуу темир жол/PSP төмөн эмес.
- Саппорт агенти: partial ≤ X, full ≤ Y.
- Менеджер/финансы: лимиттерден жогору, кросс-методикалык өзгөчөлүктөр.
- Cooling-off үчүн кайталап аракет (анти-кулап).
4) Архитектура жана окуялардын агымы
Компоненттери:- Payment Orchestrator - статустардын чындыгынын булагы.
- Refund Service - API, демпотенттик, ретраждык оркестр, журнал.
- PSP Adapters - ыкмалары боюнча бириктирүү.
- Reconciliation - auto-текшерүү, DLQ, түзөтүү.
- Ledger/Accounting - зымдар, деферлер, тазалоо менен тегиздөө.
- Risk/Compliance - талаштуу жагдайларда санкцияларды/SoF текшерүү.
1. `Refund. Create '(API) → валидация (лимиттер, баланс, саясат, керек болсо KYC/SoF).
2. Генерация idempotency_key (`hash(payment_id + refund_amount + reason + nonce)`).
3. PSP чакыруу → статус 'PENDING'.
4. Вебхук/поллинг → 'SUCCESS '/' FAILED'; тайм-аутта - ошол эле ачкыч менен ретра.
5. Кафкадагы окуяны жарыялоо → Ledger, BI, алерталар.
6. Auto-салыштыруу: салыштыруу 'provider _ refund _ id' реестри менен.
5) Idempotentity жана анти-дубли
Бир эле рефанд эки жолу кире албайт: бардык логика idempotency storage (KV/Redis + TTL) аркылуу.
payment_id × amount × reason баскычтары (жана, зарыл болсо, 'partial _ index').
Retrailer ошол эле ачкычты колдонот.
Параллель партия row-level locks/optimistic version боюнча aggregate суммасы корголгон.
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) Маалыматтар модели (минималдуу жетиштүү)
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) Төлөм рельстери боюнча өзгөчөлүктөр
Карталар (Visa/Mastercard)
full/partial колдоо; көп учурда бир нече партиялык; TtR кардардын банкына көз каранды (T + 1... T + 5 б.д.).
Ийгилик жөнүндө Webhuke тез келет, бирок бошотуу боюнча каттоо кечигип калышы мүмкүн → саппорттун үлгүлөрүндө түшүндүрүлөт.
A2A/Open Banking/RTP
Көбүнчө заматта кайтаруу (reversal/credit push); кээ бир провайдерлер гана full же 1 partial колдойт.
Баштапкы эсепке катуу байланыш; refund-to-source милдеттүү.
Электрондук капчыктар
Кадимки full/partial; TtR мүнөт; партиялык саны жана минималдуу суммасы боюнча чектөөлөр.
Ваучерлер/Prepaid
Адатта, refund-to-source жеткиликсиз → саясат: ички капчыкка же ваучерге кайтаруу (эгер провайдер билсе). Комплаенс-эскертүүлөрдү талап кылат.
Крипто
Рельстер - туруксуз; рефанд ыкмасы катары колдонулбайт. Уруксат берилсе: ошол эле дарекке/документтештирилген курс жана комиссиялары бар биржага кайтаруу; AML-скрининг.
8) Эсепке алуу, салыштыруу жана финансы
Ledger: кабелдик 'DR Revenue/CR Cash' capture; refund - артка жазуулар. Partial пропорционалдуу чагылдырылат.
Recognition: iGaming refand тиешелүү мезгилдин GGR азайтат (эсеп саясаты).
Reconciliation: күнүмдүк салыштыруу 'merchant _ refund _ id provider_refund_id', статусу, суммасы, FX курстары.
FX: Курстардын логикасын жазыңыз (capture учурда же refund учурда), кайда колдонулса; спред торчосун кармаңыз.
9) KPI, максаттары жана Алерт (Refund Health)
Refund Rate = 'Refunded _ Tx/ Captured_Tx' (сегменттөө: себептерден улам).
Refund Amount Ratio = `Refunded_Amount / Captured_Amount`.
TtR p95 = p95 ('credited _ at - created_at') ыкмасы боюнча.
Refund Error Rate = `Failed / Attempted` (<0. 3%).
Refund-to-Source% ≥ 95% (жеткиликтүү жерде).
Double Refund Incidents = 0.
- 'TtR p95' SLO → P2 ыкмасы боюнча жогору.
- Бир камсыздоочу/BIN → P1 боюнча Spikes 'Refund Rate' (кармоо/дубль текшерүү).
- Ар кандай 'Double Refund> 0' → P0 (токтоосуз тоңдурулган auto-refand).
10) SQL тилкелери
10. 1 Refand кароо
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 партиялык үчүн калдыктарды башкаруу
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 жана саппорт
Методдор боюнча билдирүүлөрдүн шаблондору: карталар мүмкүн болуучу кечигүүнү түшүндүрөт, A2A - дээрлик дароо.
Кабинеттеги статустар: "Иштелип чыккан → Иштетилген → Кайтарылган"; күтүлгөн кабыл алуу күнүн көрсөтүү.
Себептери (reason_code) - адам окуйт: "Эсептен чыгарууну кайталоо", "Кызмат көрсөтүүнү жокко чыгаруу", "Жарым-жартылай компенсация".
Self-service partial - чек жана так эрежелер менен гана коопсуз.
12) Тобокелдик жана комплаенс
Анти-адалдоо: Refand альтернативдик каналга чыгууга айланбашы керек; MLRO макулдугу менен өзгөчөлүктөрдү жазыңыз.
Санкциялар/ЖӨБ: "кызыл" эсептерге/реквизиттерге демилгеленген кайтаруулар - милдеттүү текшерүү.
DSAR/Retention: Маалымат сактоо саясатынын алкагында рефандалардын издерин сактаңыз.
Жергиликтүү эрежелер: кайтаруунун мөөнөттөрү жана тартиби (мисалы, керектөө регламенттери) - policy.
13) Көп каталар жана аларды алдын алуу үчүн кантип
Double Refand, анткени демпотенттик жоктугунан жана кайталанган Webhook → idem ачкычын/статусун сактоо, калдыгын текшерүү.
Partial> калдык → row-lock/optimistic version жана катуу текшерүү.
Комплаенс уруксатсыз кайчылаш ыкма кайчылаш → кайчылаш кайчылаш бузат.
void жана refund отчеттордо аралаштыруу → KPI бурмалоо.
PSP жана сиздин башкаруучу ортосунда эч кандай auto-текшерүү → "кара тешиктер".
14) Playbook
жөнөтүүчү боюнча кайтарымдарды жогорулатуу → текшерүү авторизациялык мүчүлүштүктөр/doubly capture, Feylover, PSP менен байланыш күйгүзүү.
Массалык партиялык компенсация (кампания) → партиялык чекти көтөрүү, топтук операцияларды киргизүү, текшерүүлөрдү күчөтүү.
Webhook ката → Polling өтүү, TTL ыктымалдыгын жогорулатуу, auto-refand кийинкиге калтыруу.
refund-to-source (сейрек) → MLRO эскалациясы, документтештирилген төлөм жана белги 'comp _ approved = true'.
15) Test Cases (UAT/Prod)
1. Full refund кийин бир capture → туура нөлгө калдыгы.
2. partial сериясы (3 ×) → суммасы ≤ capture; андан кийин калдыгы боюнча толук.
3. Idempotentity: бир эле суроо кайталоо → 1 натыйжасы.
4. Вебхук-дребезг: 3 бирдей билдирүүлөр → бир эсептен чыгаруу/чегерүү.
5. Салыштыруу: жасалма mismatch → alert жана auto оңдоо.
6. Укуктарды чектөө: агент партиялык чектен аша албайт.
7. Cut-off: кеч refanda аракет → туура баш тартуу жана логин.
16) Киргизүүнүн контролдук чек-баракчасы
- Юрисдикциялар/ыкмалар боюнча full/partial + refund-to-source саясаты.
- Idempotentity, Retry, Webhuke жана Polling, DLQ.
- кайтаруу жана reason_code калдыгы менен маалыматтар модели.
- Ledger жана күнүмдүк auto-текшерүү.
- KPI/dashboard: Refund Rate, TtR, Error, Double Refund = 0.
- Укуктар жана Апрув-матрица, саппорттун үлгүлөрү.
- UAT сыноо учурлары жана прод-деңгээл алерталар.
Резюме
Рефандаларды башкаруу - бул процесстердин катуу тартиби: рефунд-к-булак, демпотенттүүлүк, маалыматтардын ачык-айкын модели, авто-салыштыруу жана түшүнүктүү партиялык/толук саясат. Мындай негиздер менен сиз TtR төмөн кармап, каталар - нөл, эки - мүмкүн эмес, ал эми комплаенс жана каржы - бизнес максаттары менен синхрондоштурулган.