Pular para o conteúdo
KrokoPay
Voltar para o blog

Pagamentos

Pix do lado de quem integra: checkout, estados e eventos

Todo mundo no time já pagou com Pix. Integrar é outra história: a confirmação chega depois, o código expira e o cliente sai da sua página. Veja como desenhar esse fluxo, quais eventos tratar e como testar sem mexer em dinheiro.

Escrito por Time KrokoPayPublicado em 7 min de leitura

Seu time não precisa que ninguém explique o que é Pix: todo mundo já leu um QR Code na fila do caixa ou colou um código no app do banco para fechar uma compra online. O problema é que conhecer o Pix como usuário não ensina muita coisa sobre recebê-lo dentro de um produto. Do lado de quem integra, o Pix é um pagamento assíncrono, que acontece fora da sua página e tem prazo de validade.

Este artigo é para quem vai colocar o Pix no checkout de um SaaS, loja ou produto digital e quer acertar de primeira: o que muda na arquitetura, quais estados a cobrança atravessa na KrokoPay, quais eventos ouvir e os detalhes de interface que fazem a pessoa terminar de pagar.

O que você já sabe, visto pelo outro lado

Do ponto de vista técnico, o Pix tem uma característica que define tudo: quem inicia o pagamento é o pagador, no app da instituição onde ele tem conta. O seu sistema só publica um pedido de pagamento, em forma de QR Code ou de código copia e cola, e espera. Você nunca recebe dados de conta, senha ou cartão.

Se alguém do time já integrou cartão, vale deixar a diferença explícita. No cartão, você puxa o dinheiro: recebe os dados e pede autorização, e a resposta volta na mesma requisição. No Pix, o cliente empurra o dinheiro: você mostra o pedido e fica aguardando uma confirmação que acontece num lugar que você não enxerga.

O que muda no seu checkout

  1. Não existe formulário de pagamento. Além dos dados básicos de quem paga, a etapa de pagamento é um QR Code, um código para copiar e instruções claras.
  2. O cliente sai da sua página. No celular, ele troca para o app do banco; no computador, pega o celular. A página precisa aguentar ficar em segundo plano, ser recarregada ou reaberta.
  3. A confirmação é assíncrona. Criar a cobrança não diz nada sobre o pagamento. O resultado chega depois, por evento, e a interface precisa saber esperar.
  4. O código expira. Cada pedido vale por um tempo limitado. Depois disso, a cobrança não pode mais ser paga e é preciso gerar outra.

Na KrokoPay, você não precisa montar nada disso na sua interface. Seu servidor cria a cobrança, você redireciona o cliente para o checkout_url e o checkout hospedado cuida do QR Code, do copia e cola, da contagem regressiva e da tela de espera. O que continua com você é o lado do servidor: saber quando a cobrança foi paga e agir uma única vez.

Os estados de uma cobrança Pix

Toda cobrança na KrokoPay nasce pending e termina em um único desfecho. No Pix, os caminhos são poucos: o cliente paga dentro do prazo ou não paga.

StatusO que significaEvento
pendingA cobrança existe. Quando o cliente escolhe Pix, ela ganha um expires_at.charge.created
paidO pagador confirmou o Pix no app e o pagamento foi recebido.charge.paid
expiredNinguém pagou antes do expires_at. A cobrança está encerrada.charge.expired
refunded / partially_refundedVocê devolveu todo ou parte do valor de uma cobrança paga.charge.refunded

Repare que o Pix não tem o caminho failed, comum no cartão recusado. Ou o dinheiro é enviado ou não é, então o desfecho que pede cuidado é o expired. A tabela completa, com os casos de cartão, está em Criando cobranças.

Quais eventos ouvir

Inscreva seu endpoint de webhook em charge.paid, charge.expired e charge.refunded. Libere o pedido no charge.paid, devolva o estoque reservado no charge.expired e ajuste acesso ou financeiro no charge.refunded. Um handler enxuto fica assim:

Tratando os desfechos do PixTypeScript
// Chamado depois de validar a assinatura e deduplicar pelo id do evento.async function handleChargeEvent(event: { id: string; type: string; data: { object: Charge } }) {  const charge = event.data.object;  const order = await orders.findByChargeId(charge.id);  if (!order) return;​  switch (event.type) {    case "charge.paid":      await orders.markPaid(order.id, charge.paid_at);      await fulfil(order.id); // idempotente: pode rodar duas vezes      break;    case "charge.expired":      await orders.markExpired(order.id);      await stock.release(order.id);      break;    case "charge.refunded":      await orders.recordRefund(order.id, charge.refunded_amount, charge.status);      break;  }}

Atenção: Não confie no redirecionamento

É muito comum o cliente fechar a aba assim que o app do banco mostra o comprovante e nunca voltar para a sua página de sucesso. A fonte da verdade é o webhook (ou um GET /v1/charges/{id} feito pelo seu servidor), nunca o navegador.

Detalhes de UX que fazem diferença

Como o trabalho de pagar acontece em outro app, o papel do checkout é orientar e tranquilizar. São estes os detalhes que cuidamos no checkout da KrokoPay, e os que vale revisar em qualquer tela que você construir em volta dele.

Copia e cola no celular, QR Code no computador

Ninguém consegue ler um QR Code mostrado no próprio celular. Em telas pequenas, o botão de copiar o código é a ação principal, com uma confirmação visível de que o código foi copiado e um lembrete de onde colar. Em telas maiores, o QR Code vem primeiro, porque o celular vira o leitor. As duas opções continuam disponíveis em qualquer tela: tem gente que prefere a outra.

Contagem regressiva e uma espera honesta

  • Mostre quanto tempo o código ainda vale, calculado a partir do expires_at, e não da hora em que a página carregou.
  • Depois de mostrar o código, exiba um estado de espera tranquilo, avisando que a página se atualiza sozinha quando o pagamento chegar. Anuncie as mudanças também para leitores de tela.
  • Não use um botão "Já paguei" como mecanismo de confirmação. No máximo, ofereça uma forma de verificar de novo.
  • Garanta que recarregar a página mostre a mesma cobrança pendente e o tempo restante, sem criar uma cobrança nova.

Expirou? Ofereça um novo código

Quando a contagem chegar a zero, diga isso com clareza e mostre o próximo passo. Uma cobrança expirada não aceita nova tentativa, então o caminho é uma cobrança nova: mande o cliente de volta para o link de pagamento de origem ou crie outra cobrança no servidor, com uma nova chave de idempotência. Mantenha o carrinho intacto para que tentar de novo custe um toque.

Testando o Pix na KrokoPay

Dá para percorrer o fluxo inteiro sem app de banco e sem dinheiro de verdade. No ambiente de teste, o checkout mostra um QR Code e um código copia e cola fictícios, junto com um controle que simula a confirmação do pagador. No modo de teste, o código Pix expira 15 minutos depois de gerado; o prazo em produção ainda será definido.

  1. Crie uma cobrança com a chave de teste (kp_test_sk_…) e methods: ["pix"], como em Criando cobranças.
  2. Abra o checkout_url, escolha Pix e simule o pagamento. Confira se o seu endpoint recebe o charge.paid e libera o pedido uma única vez.
  3. Crie outra cobrança e deixe a contagem terminar. Confira se o charge.expired devolve o que estava reservado e se o cliente consegue recomeçar.
  4. Faça o reembolso de uma cobrança de teste paga e veja se os seus registros acompanham o charge.refunded.

Depois, teste os caminhos desconfortáveis: feche a aba logo após pagar, recarregue durante a espera, abra o mesmo checkout em dois aparelhos. Se no fim os seus registros estiverem certos, a integração está pronta para o jeito como as pessoas realmente pagam.

Resumindo

  • No Pix, quem inicia o pagamento é o cliente, no app do banco, por QR Code ou copia e cola.
  • O checkout vira uma passagem guiada mais uma sala de espera; a confirmação chega depois.
  • Trate pending → paid e pending → expired, e use o webhook como fonte da verdade.
  • Priorize o copia e cola no celular e o QR Code no computador, mostre uma contagem real e faça a expiração ter saída.

Quer ver funcionando antes de escrever código? A página do Pix tem uma demonstração ao vivo do checkout.

  • Produto7 min de leitura

    Anatomia de um checkout que converte

    Poucos campos, um total que não muda, uma escolha de método clara, recusas explicadas em português claro e uma tela para cada desfecho. O que uma página de pagamento precisa acertar, com o nosso próprio checkout como exemplo.

  • Engenharia8 min de leitura

    Webhooks sem surpresas

    Reenvios, duplicatas e eventos fora de ordem não são casos raros: é isso que entrega "pelo menos uma vez" quer dizer. Como montar um consumidor que verifica, responde rápido, processa uma vez só e concilia.

Experimente no ambiente de teste

Crie uma conta para pegar suas chaves de teste, abrir o checkout hospedado e mandar um webhook assinado para você mesmo. Nada de verdade é cobrado.

As condições comerciais ainda serão anunciadas. Veja o que já está definido em preços