Refanda parcial e cheia
TL; DR
Refand é uma operação invertida de valor capturado. A transação completa fecha a transação inteira e a parcial devolve a parte (pode ser a série partial até a totalidade). Crítica: refund-to-nature, idempotidade rigorosa, revista de causas, e orquestração com webhooks/retrações. Medimos o Refund Rate, o TtR p95, o Refund Erro e eliminamos as duplicações/discrepâncias através do controle automático.
1) Termos e diferenças fundamentais
Full Refund - Devolve a totalidade do valor fixado ('refund _ amount = capture _ amount').
Parcial Refund - Devolve a parte ('0 <refund _ amount <capture _ amount'), permite o restante do parcial até o total 'capture _ amount'.
Refund to Nature - retorno ao método de origem/roteiros de pagamento (preferencialmente/obrigatório).
Void - Cancelar até capture (se suportado por trilhos) não é considerado refand.
Reversal/Chargeback - mecânicos bancários/roteiros fora da sua iniciativa (disputas, charjbacks) - não confundir com refand.
2) Quando emitir vs total parcial
Completo (Full):- Cancelar o pedido/serviço inteiro, cancelamento duplicado, erro de sistema.
- Obrigatório quando a prestação do serviço falhou (de acordo com as regras do consumidor/regulador).
- Cancelamento parcial do serviço, correções proporcionais (descontos, compensação de atrasos).
- Os limites técnicos do roteiro (valor máximo por operação) são uma série de partiais.
- A retenção pós-faturamento das comissões (onde regulatório é permitido) é mais rara em iGaming.
3) Políticas e limites
Refund-to-nature = true padrão; exceções por meio de mochilas MLRO/complaens (logado).
Cut-off: os refandos são permitidos em N dias a partir do momento da capture (método/jurisdição).
Max Partial Count: não mais do que K partial para payment (típico K ≤ 5).
Min Partial Amount: Não abaixo do mínimo técnico rail/PSP.
- Agente de saforta: parcial ≤ X, full ≤ Y.
- Gerente/finanças: acima dos limites, exceções cruzadas.
- Cooling-off para reaproveitamento (anti-drebesg).
4) Arquitetura e fluxo de eventos
Componentes:- Payment Orquestrator é a origem da verdade das estatais.
- Refund Service - API, Idempotação, Orquestração de Retrações, Revista.
- PSP Adapters - integração de métodos.
- Reconciação - controle automático, DLQ, correção.
- Ledger/Accounting - fios, deferências, alinhamento com clearings.
- Risk/Compliance - Verificações de sanções/SoF em cenários controversos.
1. `Refund. Create '(API) → validação (limites, saldo, policy, KYC/SoF se necessário).
2. Генерация idempotency_key (`hash(payment_id + refund_amount + reason + nonce)`).
3. A chamada PSP → o status 'PENDING'.
4. Webhook/polling → 'SUCESS '/' FAILED'; O tempo a tempo é um retrai com a mesma chave.
5. Publicar o evento em Kafka → Ledger, BI, alertas.
6. Ajuste automático: mapeamento 'provider _ refund _ id' com o registro.
5) Idempotidade e anti-duplicação
O mesmo refand não pode ser inscrito duas vezes, toda a lógica através do armazenamento idempotency (KV/Redis + TTL).
Chaves para payment _ id x amount x reason (e, se necessário, 'partial _ index').
Os retais usam a mesma chave.
As partituras paralelas são protegidas por row-level locks/otimística versão no valor 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) Modelo de dados (mínimo suficiente)
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) Características de roteiros de pagamento
Cartões (Visa/Mastercard)
Suportam full/partial; muitas vezes, um pouco de partial; TtR depende do banco do cliente (T + 1... T + 5 b.d.).
Os webhooks de sucesso vêm rapidamente, mas a inscrição pode atrasar-se nos padrões de safort.
A2A/Open Banking/RTP
Muitas vezes retorno instantâneo (reversal/credit push); alguns provedores suportam apenas full ou 1 partial.
Vinculação rigorosa à conta de origem; refund-to-nature é obrigatório.
Carteiras eletrônicas
Normal full/partial; TtR minutos; limitação de número parcial e valor mínimo.
Vales/Prepaid
Normalmente, o refund-to-nature não está disponível → política de retorno para a carteira interna ou vale de e-issue (se o provedor conseguir). Requer reservas completas.
Cripto
Os trilhos são voláteis; preferencialmente não usar como método de refanda. Se permitido: retorno para o mesmo endereço/bolsa com curso e comissão documentados; Um screening AML.
8) Contabilidade, contabilidade e finanças
Ledger: cabos 'DR. Revenue/CR Cash' para capture; no refund, registros reversos. O Parcial se reflete proporcionalmente.
Reconnition: No iGaming de refand, a GGR reduz o período adequado (política de contabilidade).
Reconciação: cruzamentos diários 'merchant _ refund _ id ↔ provider _ refund _ id', estatais, somas, cursos FX.
FX: Fixe a lógica dos cursos (no momento da capture ou no momento do refund), quando aplicável; mantenha as grades dos spreads.
9) KPI, alvos e alertas (Refund Health)
Refund Rate = 'Refunded _ Tx/Captured _ Tx' (segmentar: por razões).
Refund Amount Ratio = `Refunded_Amount / Captured_Amount`.
p95 = p95 ('credited _ at - created _ at') pelo método.
Refund Error Rate = `Failed / Attempted` (<0. 3%).
Refund-to-Nature% ≥ 95% (onde disponível).
Double Refund Incidents = 0.
- 'p95' acima do SLO no método P2.
- Spikes por 'Refund Rate' em um provedor/BIN → P1 (verificar captações/duplicações).
- Qualquer 'Duplo Refund> 0' → P0 (congelamento imediato de refandos automáticos).
10) Cortes SQL
10. 1 Perfil de Refanda
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 Controle de saldo para 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 e safort
Modelos de mensagens de métodos: mapas explicamos o possível atraso no extrato, A2A quase instantaneamente.
Estado do gabinete: 'Decorado → Em processamento → Devolvido'; mostrar a data de inscrição prevista.
As razões (reason _ código) são: «Duplicação de cancelamento», «Cancelamento de serviço», «Compensação parcial».
Self-service partial é seguro apenas com limites e regras claras.
12) Risco e complacência
Anti-lavagem: o refand não deve ser transformado em um canal alternativo; registar exceções com aprovação MLRO.
Sanções/RER: As devoluções iniciadas para contas/adereços vermelhos são uma verificação obrigatória.
DSAR/Retenção: guarde traços de refanda como parte de uma política de armazenamento de dados.
Regras locais: prazos e ordem de devoluções (por exemplo, regulamentos de consumo) - refletindo em policy.
13) Erros frequentes e como evitá-los
Duplo refand devido à falta de idempotação e de webhooks repetidos → armazenar idem-chave/status, verificar o saldo.
Partial> restante → row-lock/otimística versão e verificações rigorosas.
Cross-method refund sem permissão completa → viola refund-to-nature.
A mistura de void e refund nos relatórios → uma distorção do KPI.
Não há nenhum «buraco negro» entre o PSP e o seu candeeiro.
14) Playbooks
O aumento de retorno do provedor → verificar falhas autorais/duplicações capture, ativar o feedback, entrar em contato com o PSP.
A compensação em massa partidal (campanha) → elevar o limite de partial, incluir operações em grupo e aumentar o cruzamento.
Erro nos webhooks → mudar para o poling, aumentar a idempotação TTL, adiar o refanda automático.
A exceção de refund-to-nature (raramente) → escalação MLRO, pagamento documentado e marcação de 'comp _ approved = true'.
15) Malas de teste (UAT/Prod)
1. Full refund após uma capture → anula corretamente o restante.
2. Série partial (3 x) → soma ≤ capture; depois full para o resto.
3. Idempotidade: repetição da mesma solicitação → 1 resultado.
4. Webhook - 3 notificações idênticas → um cancelamento/inscrição.
5. Comprimidos: mismatch artificial, alert e correção automática.
6. Limite de permissão: o agente não pode ultrapassar o limite de partial.
7. Cut-off: tentativa de refanda tardia → falha correta e loging.
16) Folha de cheque de controle de implementação
- Políticas full/partial + refund-to-nature sobre jurisdições/métodos.
- Idempotidade, retraí, webhooks e polling, DLQ.
- Modelo de dados com saldo de retorno e reason _ código.
- Ledger e comprimidos automáticos diários.
- KPI/dashboard: Refund Rate, TtR, Erro, Duplo Refund = 0.
- Direitos e matriz de apprave, modelos de safort.
- Malas de teste UAT e alertas de nível prod.
Currículo
Gerenciamento de refandos é uma disciplina rigorosa de processos: refund-to-nature, idempotidade, modelo de dados transparente, automáticos e políticas de partial/full compreensíveis. Com esses fundamentos, mantêm-se baixos, os erros são nulos, as duplicações são impossíveis, e as complicações e as finanças são sincronizadas com os objetivos empresariais.