Estados no front da Nero

O front (nero_client) não conhece o Dracma. Ele vê um conjunto fechado de estados, fixado no Contrato §11, que o nero_payments calcula a partir de duas fontes: o estado local do outbox dracma_intents e o último estado do Dracma aplicado (lido por fetch-back). Esta página é a tabela de tradução.

Regra geral: o estado mostrado ao jogador nunca adianta dinheiro. paid só aparece depois que o crédito (depósito) ou a finalização (saque) foi gravado no nero_ledger.

1. Rotas do portal (Contrato §11)

Método e rota (portal :8080) Auth Pedido → resposta
POST /api/payments/deposits jogador {amount: number (reais, ex. 50.00), method: "pix", accept_bonus: bool, cpf?: string} → 201/202 {deposit_id, status, amount, currency, method, pix?: {copy_paste, qr_code_png_base64?, expires_at}, expires_at}
GET /api/payments/deposits/{deposit_id} jogador (só o dono; outro → 404) mesmo formato; o front faz polling até paid/expired
POST /api/wallet/withdraw/request jogador corpo legado {amount, type: "pix", pix_key, pix_type, accept_terms, currency?} → 200 {status: true, withdrawal_id, state: "processing" \| "under_review", message}; erros de negócio mantêm as mensagens atuais
GET /api/payments/withdrawals/{withdrawal_id} jogador (só o dono) {withdrawal_id, state, amount, currency, created_at, updated_at}
POST /api/payments/dracma/webhook nenhuma no portal; assinatura no conector + allowlist de IP no Caddy 200/401/400/503 (ver webhook-e-jobs.md)

deposit_id/withdrawal_id são o external_id enviado ao Dracma (dep_<uuidv7>/wdr_<uuidv7>), opacos. O id do Dracma (dep_<32 hex>) fica só no nero_payments.

Rotas removidas (respondem 404 depois do corte): /api/wallet/deposit/payment, /api/payments/{deposits,callbacks,status}/{gateway}, /api/{gateway}/qrcode-pix, /api/{gateway}/consult-status-transaction e os callbacks/ACKs legados dos 6 gateways.

2. Depósito: Dracma → front

Estados do front: creating | pending | paid | expired | cancelled | failed | under_review.

Situação no nero_payments Estado do Dracma (fetch-back) Front vê Dinheiro na carteira Mensagem sugerida
intent gravado, chamada ainda sem resposta conclusiva (timeout, 5xx, 429) — creating nada "Gerando seu PIX…"
202 do Dracma created creating nada "Gerando seu PIX…"
— pending pending (com pix) nada "Pague o PIX até {expires_at}"
— under_review under_review nada "Pagamento recebido, em análise."
crédito gravado no ledger paid paid creditado uma vez "Depósito confirmado."
— expired expired nada "O PIX expirou. Gere outro."
— cancelled cancelled nada "Depósito cancelado."
— failed failed nada "Não foi possível gerar o PIX. Tente de novo."
— returned failed nada "O pagamento foi devolvido ao pagador."
paid já creditado, depois estorno/MED refunded / chargeback paid (continua) não mexe: needs_decision (D6) — (tratado pelo backoffice)
— pending_compliance / frozen (v1.1.0) under_review nada "Pagamento em análise."
— paid_partial (v1.1.0) under_review nada: needs_decision "Pagamento em análise."
— estado desconhecido mantém o último estado mostrado (ou under_review se era pending) nada "Pagamento em análise."
4xx na criação (sem objeto no Dracma) — erro HTTP ao front (sem deposit_id utilizável) nada ver tabela de erros em deposito.md
produção sem Dracma configurado (D5) — erro 503 payment_provider_not_configured nada "Depósito indisponível no momento."

Observações:

  • returned não existe na lista do §11: a Nero mostra failed com a mensagem de devolução.
  • refunded/chargeback acontecem depois de o jogador ter visto paid. A tela não volta atrás; o caso vai para a fila needs_decision (revisao-e-decisoes.md).
  • Nunca explique under_review com o motivo (PAYER_MISMATCH, AMOUNT_MISMATCH…) ao jogador; o suporte vê. Com o Mercado Pago, under_review por PAYER_UNKNOWN fica mais comum (o PSP não informa o pagador).

3. Saque: Dracma → front

Estados do front: processing | under_review | paid | rejected | failed | cancelled.

Situação no nero_payments Estado do Dracma (fetch-back) Front vê Reserva no ledger Mensagem sugerida
intent + reserva gravados, sem resposta conclusiva — processing mantida "Saque em processamento."
— requested (DICT pendente) processing mantida "Saque em processamento."
— approved / processing processing mantida "Saque em processamento."
— under_review under_review mantida "Saque em análise."
finalização gravada paid paid finalizada (saída definitiva) "Saque enviado."
— rejected rejected devolvida "Saque não aprovado. O valor voltou para sua carteira."
— failed failed devolvida "Não foi possível enviar o PIX. O valor voltou para sua carteira."
— cancelled cancelled devolvida "Saque cancelado. O valor voltou para sua carteira."
paid já finalizado, banco devolveu returned under_review não mexe: needs_decision (D7) "Saque em análise."
— pending_compliance / sent / in_transit / recall_requested (v1.1.0) processing mantida "Saque em processamento." (nunca dizer "compliance", D24)
— recalled (v1.1.0) under_review não mexe: needs_decision (D18) "Saque em análise."
— estado desconhecido processing mantida "Saque em processamento."
4xx na criação (422, 400) — 200 {status: false, message} (mensagem legada) devolvida ver saque.md
409 idempotency_key_reused no envio — processing mantida: needs_decision (D12) "Saque em processamento."

Resposta do POST /api/wallet/withdraw/request:

  • state: "under_review" quando o 201 do Dracma veio com under_review;
  • state: "processing" em todos os outros casos aceitos (approved, requested, e também quando o Dracma não respondeu de forma conclusiva — o pedido está gravado no outbox e a reserva está feita).

4. Como calcular o estado sem corrida

estado_front(intent):
  se intent.dracma_version é nulo:                         # Dracma ainda não respondeu de forma conclusiva
      devolve "creating" (depósito) | "processing" (saque)
  s = intent.dracma_status                                   # último estado APLICADO (fetch-back, versão maior)
  devolve TABELA[s] ou PADRAO_DESCONHECIDO
  • Aplique um estado novo só se version for maior que intent.dracma_version (webhooks chegam fora de ordem).
  • O efeito de dinheiro e a atualização de dracma_status vão na mesma transação do ledger. Assim o front nunca vê paid antes do crédito.
  • O polling do front não chama o Dracma a cada pedido. Se o intent está parado em creating/pending há mais de 60 s, o nero_payments pode fazer um fetch-back por id (no máximo a cada 10 s por objeto), além do webhook e do job de /events.