R-001 — Expiração de pagamento PIX e cancelamento de sessão
TLDR: Um pagamento PIX não confirmado em 30 minutos é expirado pelo sistema, que destrói permanentemente todas as sessões pendentes ligadas àquela order.
Given / When / Then
Dado uma order com payment_method: pix e payment.status: pending
Quando Payments::ExpireJob roda 30 minutos após a criação do pagamento sem webhook de confirmação
Então o pagamento é marcado como expired, as sessões são canceladas com o motivo “Sistema: Cancelada por falta de pagamento.” e as sessões pendentes são destruídas permanentemente
Tabela de decisão
| Status do pagamento na execução do job | Status das sessões | Resultado |
|---|---|---|
pending |
pending |
Pagamento → expired, sessões destruídas |
pending |
scheduled |
Pagamento → expired, sessões canceladas (não destruídas) |
paid / expired / outro |
qualquer | Job sai antecipadamente — nenhuma mudança |
Restrições
- A janela de expiração é exatamente 30 minutos a partir da criação do pagamento (
Payments::QueueJobs) Payments::Expiresó roda sepayment.pending?— idempotente por design- Sessões em estado
pendingsão destruídas permanentemente (sem soft delete) viaMeetings::DestroyAllByRelatedPayment - Sessões já
scheduledsão apenas canceladas, não destruídas - Se o webhook do gateway chegar depois da expiração e confirmar o pagamento como
paid, o sistema atualizapayment.statusparapaidmas não reativa ou recria as sessões —UpdateMeetingsByGatewayStatusverificaorder.meetings.pending.exists?
Risco de race condition
Existe uma janela crítica entre a criação do pagamento e a expiração de 30 minutos:
00:24 — Order + Payment criados (pending)
00:25 — Cliente paga o PIX
00:54 — ExpireJob roda → pagamento expirado, sessões destruídas
~depois — Webhook chega → pagamento atualizado para paid, mas não há sessões
Nesse cenário o pagamento acaba paid no banco mas sem sessões ativas e sem payout para o terapeuta — exigindo intervenção manual.
Teste vinculado
spec/use_cases/payments/expire_spec.rb — (sem teste ainda)