Pular para o conteúdo
LeztyPay docs
Painel

Expiração

Duas coisas acontecem com uma cobrança depois que ela sai da sua tela: ela expira, ou ela é estornada. As duas têm armadilha.

O prazo que você pede é um pedido

pix.expires_in_seconds na criação é o prazo que você gostaria. Quem decide é o processador de pagamentos, e ele pode encurtar, estender ou simplesmente ignorar o seu pedido. Alguns processadores expiram tudo à meia-noite, por exemplo.

Por isso existe uma regra só:

Use pix.expires_at da resposta. Nunca calcule a expiração somando o seu prazo ao horário da criação.

O contador na sua tela de checkout sai de expires_at. O seu job de limpeza também. A faixa aceita para o pedido vai de 5 minutos a 30 dias, e o padrão é uma hora (Limites).

A expiração não é instantânea

A cobrança vira expired pouco depois de expires_at, não exatamente nele. A folga existe de propósito, para um pagamento que chegou no último segundo não ser perdido por corrida de relógio.

Então: expires_at no passado e status ainda pending é normal por alguns minutos. Não trate isso como erro nem como expirada; espere o status mudar ou o evento transaction.expired chegar.

Pagamento tardio existe

Uma cobrança expired pode virar paid. Acontece quando o processador aceitou um pagamento que entrou na janela dele, mais larga que a nossa.

O seu sistema precisa aguentar isso. Concretamente:

  • Não apague o pedido quando o transaction.expired chegar. Marque como não pago e siga.
  • Continue aceitando transaction.paid daquela cobrança depois disso, e libere o produto.
  • Se o seu fluxo não puder entregar depois do prazo, trate como um caso de estorno, não ignorando o evento.

Os eventos podem até chegar fora de ordem no seu endpoint. A verdade final está sempre na consulta pelo id.

Expirada some das listagens

Cobrança expired não aparece na listagem por padrão, nem entra nos totais. Foi uma decisão de produto: a lista de cobranças é uma lista de coisas que importam, e expirada é ruído em volume.

Pedir status=expired explicitamente não é permitido e responde 400 validation_failed. A contagem de expiradas nos totais sai sempre zero.

Isso vale só para as listagens. A consulta pelo id, a timeline e o evento transaction.expired continuam mostrando tudo normalmente. Detalhes em Consultar.

Estorno

Estorno é sempre do valor total; não existe estorno parcial. Ele só é possível em cobrança paid, e leva o status para refunded.

O pedido de estorno é feito pelo painel, pela pessoa dona da conta. Não existe rota de estorno por chave de API, e isso é proposital: estorno é operação de dinheiro saindo, e exige a confirmação extra que só a sessão do painel tem.

Pela API você observa o estorno, e isso é tudo o que a sua integração precisa:

  • O evento transaction.refunded chega no seu webhook.
  • A consulta pelo id passa a trazer status em refunded e a data em refunded_at.
  • A timeline registra o lançamento correspondente.

O valor sai do saldo no mesmo instante, e o saldo disponível pode ficar negativo por causa disso. chargeback segue o mesmo caminho, com o evento transaction.chargeback, com a diferença de ser iniciado pelo cliente e não por você.

Próximo passo

Consultar.

Referência: Consulta uma cobrança e Timeline de uma cobrança.