Skip to Content
ConceitosSessões
View as Markdown

Sessões

Uma CheckoutSession é com o que o comprador interage: um objeto com tempo limitado, de uso único, que é dono da URL do checkout hospedado. É a mais leve das três entidades centrais. A maior parte da sua lógica trabalha com Orders e Payment Intents (veja abaixo).

O modelo de dados de três entidades

CheckoutSession ← 1:1 → Order ← 1:N → PaymentIntent (comprador) (catálogo) (cada tentativa de pagamento)
EntidadePropósitoTempo de vida
CheckoutSessionVoltado ao comprador — tem session_key, checkout_url, TTLMinutos (padrão 30)
OrderSeu estado de catálogo — itens, totais, reembolsosRegistro permanente
PaymentIntentUma tentativa de pagamento em uma rede/ativoHoras; liquida ou expira

Você cria uma sessão e um pedido juntos (via POST /b2b/v1/checkout-sessions/quick). Cada vez que o comprador escolhe um ativo na página de checkout, um PaymentIntent novo é aberto na rede certa. Se ele trocar de ativo no meio do checkout, o intent anterior vai para EXPIRED e um novo começa.

Identificador

Uma sessão é identificada pelo seu session_key:

cst_G-SO92J7HNWkwMHEHjD4oO1Z

URL-safe, com cerca de 24 caracteres depois do prefixo. A página de checkout hospedada é https://checkout.infraio.xyz/<session_key> — trate o session key como uma credencial bearer para aquele único checkout.

Ciclo de vida — CheckoutSession

EstadoSignifica
ACTIVESessão criada e aberta. A URL do checkout está utilizável.
COMPLETEDUm PaymentIntent dessa sessão foi liquidado. O Order agora está PAID (ou PARTIAL_PAID se foi pagamento insuficiente).
EXPIREDexpires_at passou sem liquidação. Qualquer Order aberto é cancelado.
CANCELEDCancelamento explícito — o comprador clicou em “cancelar” ou você chamou o endpoint de cancel.

Os três estados terminais são mutuamente exclusivos e finais. Uma nova CheckoutSession contra o mesmo Order pode ser criada se você quiser tentar de novo (por exemplo, depois de um pagamento insuficiente).

TTL

  • Padrão: 30 minutos (configurável pelo campo expires_in na criação, em segundos).
  • Limites: Não há mínimo nem máximo aplicado. Escolha um valor que combine com a janela de decisão esperada do seu comprador: menos de 60 segundos arrisca expirar compradores legítimos, e uma sessão que fica aberta por mais de 7 dias provavelmente foi abandonada.
  • Padrão por lojista: Você pode definir um padrão no dashboard, mas só POST /b2b/v1/checkout-sessions (em dois passos) o honra. POST /b2b/v1/checkout-sessions/quick usa 30 minutos quando expires_in é omitido, independentemente da configuração do dashboard. Para usar um padrão diferente com /quick, envie expires_in em toda chamada.
  • Aplicação: Uma sessão cujo expires_at já passou é tratada como EXPIRED mesmo que o estado ainda não tenha sido atualizado, então não dependa do valor do estado no instante exato da expiração.

Pagamento insuficiente

Se o comprador envia menos do que o valor da sessão, o PaymentIntent ainda liquida pelo valor parcial e o Order transita para PARTIAL_PAID. A CheckoutSession vai para COMPLETED (um PaymentIntent liquidou), então deixa de ser reaproveitável.

Para aceitar o déficit como pagamento total, o pedido pode ser resolvido para PAID. Veja Conceitos → Pedidos (a resolução não está disponível pela API; para continuar self-service, cobre o restante). Para cobrar o restante, crie uma nova CheckoutSession contra o mesmo Order com o valor residual.

Pagamento excedente

Se o comprador envia mais do que o valor da sessão (raro, mas acontece com transferências manuais), a InfraIO Pay detecta o excedente dentro de 24 horas e avisa você. Ele não é reembolsado automaticamente. Emita o reembolso pela API de reembolsos ou pelo dashboard.

Pagamentos com ativo errado

O endereço de depósito é gerado para uma sessão, uma rede e um ativo. Se um comprador envia um ativo diferente para ele, o pagamento não é reconhecido e o PaymentIntent fica aberto até a sessão expirar. O suporte pode ajudar a recuperar os fundos, mas isso não é automático. Oriente os compradores a enviar exatamente o ativo mostrado na página de checkout.

Em TRON, Solana e TON não há endereço de depósito, então isto vale apenas para redes EVM: o comprador paga diretamente a sua carteira. Veja Redes com pagamento direto na carteira.

Idempotência na criação

POST /b2b/v1/checkout-sessions/quick aceita um campo idempotency_key no body da requisição (atenção: campo do body, não header HTTP). Gere um UUID se você não tiver uma chave natural.

A chave deduplica o Order, não a CheckoutSession. Em uma retentativa com a mesma chave, /quick retorna o pedido original (order_id é estável), mas cria uma CheckoutSession nova — um session_key e uma checkout_url novos a cada vez. Isso é intencional: um Order pode dar suporte a várias tentativas de checkout (veja Pedidos), então um /quick em retry entrega ao comprador uma sessão limpa sem duplicar o pedido.

Dois comportamentos para ter em mente:

  • O body não é hasheado nem comparado. Reusar uma chave com um body diferente não retorna 409 — o servidor silenciosamente retorna o pedido já armazenado sob aquela chave e ignora o body novo. Então trate uma idempotency_key como um token de uso único para um único pedido lógico; nunca reaproveite uma entre carrinhos diferentes.
  • Só o Order é deduplicado, não a sessão. Se você precisa da mesma URL de checkout de volta, persista session_key / checkout_url da primeira resposta — chamar /quick de novo não vai retornar a antiga. Para enumerar cada sessão criada contra um pedido, use GET /b2b/v1/checkout-sessions/by-order/:order_id.

Endpoints da API

MétodoPathNotas
POST/b2b/v1/checkout-sessions/quickCria order + sessão em uma chamada
POST/b2b/v1/checkout-sessionsCria sessão contra um order existente
GET/b2b/v1/checkout-sessions/by-order/:order_idLista todas as sessões de um pedido (para histórico de retries)

Veja o Início rápido para o body completo de criação e a assinatura.

Próximos passos