Pular para o conteúdo principal

Status: Approved · v2 · SPEC-DOMAIN-PAYMENT-001

depends_on: SPEC-DOMAIN-BASE-001

used_by: IS-MVP-07.2, IS-MVP-09.2, IS-MVP-10.1

Pagamentos Pix

Cobranças externas por Pix para apoio, patrocínio e publicação de campeonato, inicialmente por provider simulado.

Objetivo e limites

Esta especificação define o comportamento canônico do domínio Pagamentos Pix no RaizFC. Ela deve ser consultada antes de alterar contratos, mocks, endpoints, telas, permissões ou Increment Specifications relacionados.

Incluído no MVP

  • Pix único método.
  • Provider fake substituível.
  • QR/copia e cola.
  • Expiração 30 minutos.
  • Webhook/status idempotente.
  • Purposes support, sponsorship e championship_publication.

Fora do MVP

  • Cartão.
  • Boleto.
  • Split real do provider.
  • Estorno automático complexo.
  • Múltiplos gateways simultâneos.

Atores e responsabilidades

AtorResponsabilidade
PagadorGera e paga cobrança.
GestorInicia patrocínio/publicação.
Payment ProviderEmite QR e confirma status.
SistemaAplica efeito idempotente.
OperaçãoConsulta e trata exceções.

Conceitos canônicos

Payment

Registro canônico da cobrança.

PaymentPurpose

Finalidade que determina efeito.

ProviderReference

ID externo.

PaymentEvent

Evento imutável de provider/status.

Effect Application

Aplicação idempotente do resultado no domínio.

Invariantes

  • Frontend nunca confirma pagamento.
  • Payment possui purpose, amount, status e expiresAt.
  • Confirmação paid aplica efeito exatamente uma vez.
  • Valor em centavos e maior que zero.
  • Webhook é autenticado/validado conforme provider.
  • Expiração não remove rascunho de campeonato nem dados de checkout; apenas impede confirmação daquela cobrança.
  • Payment não reutiliza Idempotency-Key para finalidades diferentes.

Estados

EstadoSignificadoVisibilidade/efeito
waiting_paymentCriado e aguardandoQR válido.
paidConfirmadoEfeito aplicado/pendente de retry técnico.
expiredPrazo vencidoNova cobrança necessária.
failedFalha do providerPode tentar nova cobrança.
cancelledCanceladoSem efeito.
refundedEstornadoPós-MVP ou operação controlada.

Transições permitidas

OrigemAçãoDestinoAutoridadeEfeitos
createwaiting_paymentSistema/providerEmite QR.
waiting_paymentconfirmpaidWebhook/checkAplica efeito.
waiting_paymentexpireexpiredProvider/jobInvalida QR.
waiting_paymentfailfailedProviderRegistra código.
waiting_paymentcancelcancelledSistema/operaçãoLibera recursos reservados.

Permissões

Permission keyQuem recebe por padrãoAção protegidaAuditoria
payment.createSupportPúblicoApoio anônimo/identificadoSim
payment.createSponsorshipGestor financeiroPatrocínioSim
payment.createChampionshipPublicationGestor campeonatoPublicaçãoSim
payment.readPagador autenticado/gestor contextualConsultarNão
payment.webhookProviderAtualizar statusSim

Fluxos funcionais

Criação

  1. Cliente envia purpose e contexto com Idempotency-Key.
  2. Backend calcula valor canônico quando aplicável.
  3. Provider fake/real cria cobrança.
  4. Payment waiting_payment é persistido com QR e expiresAt.

Confirmação

  1. Provider envia webhook ou backend consulta status.
  2. Evento é deduplicado.
  3. Payment passa a paid.
  4. Handler de purpose credita wallet, ativa sponsor ou publica campeonato.
  5. Falha técnica no efeito é retentável sem duplicar dinheiro.

Expiração

  1. Job/provider marca expired.
  2. Reservas de sponsor são liberadas.
  3. Campeonato continua draft.
  4. Tela oferece gerar novo Pix.

Casos-limite e erros

CenárioComportamento esperadoCódigo/estado
Idempotency repetidaRetornar payment originalIDEMPOTENCY_REPLAY
Valor adulteradoIgnorar/rejeitar valor do clientePAYMENT_AMOUNT_MISMATCH
Webhook duplicadoNão reaplicar efeitoPAYMENT_EVENT_DUPLICATE
Webhook inválidoRejeitar e alertarINVALID_WEBHOOK
Payment expirado recebe paid tardioAplicar regra do provider com revisão/auditoria; fake rejeitaPAYMENT_EXPIRED
Purpose incompatívelRejeitarINVALID_PAYMENT_PURPOSE

Privacidade e exposição pública

  • QR e payload podem ser exibidos ao pagador, mas não indexados publicamente.
  • Provider secrets nunca chegam ao cliente.
  • Apoio anônimo não vincula identidade pública.
  • Logs mascaram payloads sensíveis.

Notificações e auditoria

  • Payment paid/expired/failed.
  • Efeito aplicado.
  • Falha técnica crítica gera alerta operacional.
  • Eventos e requestId preservados.

API relacionada

MétodoRotaAcessoFinalidade
POST/api/v1/payments/pixPúblico/protegido por purposeCriar
GET/api/v1/payments/:idContextualConsultar
POST/api/v1/payments/:id/check-statusContextualConsultar provider
POST/api/v1/payments/webhooks/:providerProviderWebhook

Contratos compartilhados

  • PaymentEntity
  • PaymentPurpose
  • PaymentStatus
  • CreatePixPaymentRequest/Response
  • PixPayloadDto
  • PaymentEventDto
  • PaymentEffectResult

Requisitos de UX

  • Tela mostra QR, copia e cola, valor, destinatário lógico, finalidade e cronômetro.
  • Status é atualizado por polling moderado ou retorno manual.
  • Expirado oferece novo Pix, sem prometer que pagamento anterior será aceito.
  • Frontend nunca possui botão “marcar como pago”.

Comportamento dos mocks

  • Provider fake com clock controlável.
  • paid, expired, failed e delayed.
  • Webhook duplicado.
  • Falha de efeito seguida de retry.

Critérios de aceite

  • Expira em 30 min.
  • Confirmação automática/provider.
  • Efeito idempotente.
  • Purpose correto.
  • Frontend não confirma.
  • Reservas liberadas na expiração.

Testes obrigatórios

  • Create idempotent.
  • Webhook auth/dedup.
  • Efeitos por purpose.
  • Expiração.
  • Retry de efeito.
  • Valor adulterado.

Pós-MVP

  • Provider real selecionado.
  • Estorno.
  • Múltiplos métodos.
  • Conciliação financeira.

Decisões registradas

  • Pix é único método no MVP.
  • Backend é fonte da verdade.
  • Publicação de campeonato usa pagamento separado.
  • Provider inicial é fake, mas interface deve ser realista.

Machine summary

spec: SPEC-DOMAIN-PAYMENT-001
domain: Pagamentos Pix
must_preserve:
- Frontend nunca confirma pagamento.
- Payment possui purpose, amount, status e expiresAt.
- Confirmação paid aplica efeito exatamente uma vez.
- Valor em centavos e maior que zero.
- Webhook é autenticado/validado conforme provider.
- Expiração não remove rascunho de campeonato nem dados de checkout; apenas impede confirmação daquela cobrança.
- Payment não reutiliza Idempotency-Key para finalidades diferentes.
touches:
- contracts
- mocks
- api
- frontend
- backend
- tests
- documentation