Aceitar seu primeiro pagamento: produto, link de pagamento e webhook
Guia passo a passo para receber seu primeiro pagamento: criar um produto com preço, gerar uma página de pagamento hospedada e confirmar via webhook.
Este guia mostra o caminho mais curto até o primeiro pagamento confirmado: criar um produto com preço, gerar uma página de pagamento hospedada e escutar a confirmação por webhook. No fim, você paga essa página com um cartão de teste e vê a confirmação chegar — a mesma mecânica que roda em produção, sem SDK e sem escrever frontend.A ideia central, antes de qualquer chamada: a página de sucesso não é confirmação de pagamento. Quem confirma é o webhook. Com cartão isso acontece na hora, durante o checkout; com PIX e boleto acontece depois, de forma assíncrona — a mesma página aceita os três métodos sem nenhuma mudança de código. Este guia mostra os três; para o comparativo lado a lado e como simular cada cenário no sandbox, veja Crie e comece a usar um sandbox.
URL pública e reutilizável que abre a página de pagamento hospedada.
checkout_session
Seu backend, por comprador
Alternativa ao payment link quando a cobrança precisa ficar amarrada a um pedido específico.
Evento de webhook
Chargefy → seu servidor
A confirmação real de que o dinheiro entrou.
Etapa
O que acontece
1
Você cadastra o produto e o preço.
2
Você cria o link de pagamento.
3
Você cadastra o webhook que confirmará o resultado.
4
O comprador paga.
5
Seu sistema recebe a confirmação e entrega o produto.
Tudo aqui roda em test mode (chave ch_test_...): sem dinheiro real, sem
risco. Os objetos de teste ficam isolados dos de produção, e ir para produção
no final é trocar a chave. Veja Sandbox.
Uma conta Chargefy com uma organização criada —
cadastre-se aqui se ainda não tem.
Uma API key de teste: no dashboard, abra Developers → Chaves de API,
clique em Nova chave e selecione o ambiente test. O token começa com
ch_test_. Detalhes em API keys.
Um terminal com curl (ou qualquer cliente HTTP). Nos exemplos abaixo,
troque {{API_KEY}} pela sua chave de teste.
Por que essa etapa existe: é o que você vende. POST /v1/products
aceita prices[] inline — um único request resolve os dois, e o primeiro
preço do array já vira o default_price do produto.
Guarde o id do preço (price_9Fi9fZyEeA9WuR38 no exemplo): é ele que você vai vender
no próximo passo.
2
Gere um link de pagamento
Por que essa etapa existe: é o caminho mais curto até o primeiro
pagamento. Um payment link é uma URL pública e reutilizável — cada
clique de um comprador abre uma página de checkout nova. Serve para bio de
rede social, e-mail, QR code ou botão “comprar” em qualquer site.
Abra a url no navegador. Essa é a sua página de pagamento — hospedada
pela Chargefy, responsiva, com a identidade visual da sua organização e as
abas de cartão (com parcelamento), PIX e boleto já habilitadas.
Você não escreveu nenhum frontend, e a mesma página atende os três métodos.
A mesma página hospedada — as três abas de método de pagamento aparecem sem nenhuma configuração extra.
Prefere não usar terminal agora? Dá para criar o mesmo link no dashboard, em
Payment Links → Novo link — sem código nenhum. Veja
Links de pagamento.
O payment link é a mesma URL para todo mundo. Quando o seu backend inicia
a compra — um carrinho, um pedido específico —, crie uma checkout
session: uma sessão descartável, de um único comprador, que você amarra ao
seu pedido via metadata.
A resposta traz a mesma página hospedada em url — redirecione o comprador
para ela e pronto. O metadata volta ecoado em todos os webhooks da
sessão, então você reconcilia o pagamento com o seu pedido sem guardar nada
além do seu próprio order_id. Todas as opções do create (cliente travado,
aparência, descontos, trial) estão em
Checkout Sessions.
3
Cadastre o endpoint de webhook
Por que essa etapa existe: aqui está a parte que separa “página bonita”
de “dinheiro confirmado”. A página de sucesso não é confirmação de
pagamento — quem confirma é o webhook, o POST que a Chargefy faz no
seu servidor quando algo acontece de verdade.No dashboard, abra Configurações → Webhooks e cadastre uma URL HTTPS
no ambiente test. Guarde o secret (whsec_...) — é com ele que você
verifica a assinatura de cada entrega.Para desenvolver na sua máquina, exponha a porta local com um tunnel:
ngrok http 3000# cadastre a URL https gerada, ex.: https://abc123.ngrok.io/webhooks/chargefy
4
Suba um receiver mínimo
Por que essa etapa existe: é o código que verifica a assinatura de cada
entrega e decide o que fazer com o evento.Verifique a assinatura com qualquer biblioteca compatível com
Standard Webhooks e trate três
eventos:
import express from 'express';import { Webhook } from 'svix';const app = express();const wh = new Webhook(process.env.CHARGEFY_WEBHOOK_SECRET); // whsec_...// IMPORTANTE: corpo bruto — parsear o JSON antes quebra a assinatura.app.post('/webhooks/chargefy', express.raw({ type: 'application/json' }), (req, res) => { let evt; try { evt = wh.verify(req.body, { 'webhook-id': req.headers['webhook-id'], 'webhook-timestamp': req.headers['webhook-timestamp'], 'webhook-signature': req.headers['webhook-signature'] }); } catch { return res.status(401).json({ error: 'Invalid signature' }); } const session = evt.data.object; switch (evt.type) { case 'checkout.session.completed': if (session.payment_status === 'paid') { // Cartão aprovado na hora: pode entregar. deliverOrder(session); } else { // PIX ou boleto: o comprador recebeu as instruções. // O dinheiro ainda não entrou — aguarde o evento assíncrono. markOrderPending(session); } break; case 'checkout.session.async.payment.succeeded': // PIX/boleto compensou: agora sim, entregue. deliverOrder(session); break; case 'checkout.session.async.payment.failed': // O pagamento assíncrono falhou ou expirou. cancelOrder(session); break; } res.status(200).json({ received: true });});app.listen(3000);
import { NextRequest, NextResponse } from 'next/server';import { Webhook } from 'svix';const wh = new Webhook(process.env.CHARGEFY_WEBHOOK_SECRET!); // whsec_...export async function POST(req: NextRequest) { const body = await req.text(); // corpo bruto — não use req.json() let evt: any; try { evt = wh.verify(body, { 'webhook-id': req.headers.get('webhook-id')!, 'webhook-timestamp': req.headers.get('webhook-timestamp')!, 'webhook-signature': req.headers.get('webhook-signature')! }); } catch { return NextResponse.json({ error: 'Invalid signature' }, { status: 401 }); } const session = evt.data.object; if (evt.type === 'checkout.session.completed' && session.payment_status === 'paid') { await deliverOrder(session); // cartão: pago na hora } if (evt.type === 'checkout.session.async.payment.succeeded') { await deliverOrder(session); // PIX/boleto: compensou agora } if (evt.type === 'checkout.session.async.payment.failed') { await cancelOrder(session); } return NextResponse.json({ received: true });}
5
Responda 2xx em até 20 segundos
Por que essa etapa existe: entregas que não recebem 2xx a tempo são
reenviadas — sem isso, você corre o risco de processar o mesmo pagamento
mais de uma vez ou perder a confirmação.Verifique a assinatura, persista o evento e responda 200 na hora; processe
o resto em background. Entregas que falham são reenviadas automaticamente —
detalhes em Entrega de webhooks.
6
Pague com cartão, PIX e boleto
Por que essa etapa existe: é o jeito mais rápido de ver o fluxo inteiro
funcionando de ponta a ponta — produto, link, checkout e webhook. Comece
pelo cartão: é o caminho síncrono, a aprovação acontece durante o
checkout, sem esperar nenhum evento assíncrono.Abra a url do seu link, preencha os dados e pague com o cartão de teste
4242 4242 4242 4242 (qualquer CVC de 3 dígitos, qualquer validade futura).
A aprovação é síncrona: acontece ali, durante o checkout. Segundos
depois, seu endpoint recebe o checkout.session.completed já pago:
PIX e boleto: mesma página, confirmação assíncrona
Abra o link de novo e escolha a aba PIX. O comprador recebe um QR code
para pagar — nenhuma configuração adicional foi necessária:
PIX gerado na mesma página hospedada: QR code, instruções e o código copia-e-cola.
Ou escolha Boleto — o checkout passa a exigir CPF/CNPJ e endereço, e o
comprador recebe um boleto com código de barras:
Boleto gerado na mesma página: código de barras, linha digitável e link para o PDF.
Nos dois casos o seu endpoint recebe o checkout.session.completed com
payment_status: "unpaid" assim que o comprador conclui o checkout — o
dinheiro ainda não confirmou. Em produção, isso resolve sozinho: PIX
compensa em segundos, boleto em 1–2 dias úteis. No sandbox, use um e-mail de
teste para escolher um resultado imediato ou atrasado; no checkout
hospedado, a barra de sandbox também permite simular pagamento ou expiração.
O guia Crie e comece a usar um
sandbox ensina o fluxo passo a passo.
Esses três eventos são tudo que o seu receiver precisa tratar — mesmo que hoje
você só tenha testado o caminho do cartão:
Evento
O que significa
O que fazer
checkout.session.completed
O comprador concluiu o checkout. Cartão aprovado já vem paid; PIX/boleto vêm unpaid.
paid → entregar. unpaid → marcar como pendente.
checkout.session.async.payment.succeeded
O PIX foi pago ou o boleto compensou.
Entregar.
checkout.session.async.payment.failed
O pagamento assíncrono falhou ou expirou.
Cancelar o pedido e avisar o comprador.
Regra de ouro: entregue o produto quando payment_status virar "paid" —
nunca só porque o comprador voltou para a página de sucesso. Isso vale sempre,
e importa ainda mais em PIX e boleto, onde o redirect acontece antes de o
comprador pagar. Comparação lado a lado de cada método e como simular cada
cenário: Crie e comece a usar um
sandbox.
O fluxo é o mesmo em produção — muda o ambiente, não o código:
Ative a organização. Complete o cadastro do negócio no dashboard (dados
da empresa e conta para saques). Pagamentos reais só processam depois da
aprovação do cadastro financeiro — veja KYC.
Crie uma chave live (ch_live_...) e troque no lugar da ch_test_.
Dados de teste não migram: recrie produto, preço e link com a chave live.
Cadastre o endpoint de webhook no ambiente live. Endpoints e secrets são
separados por ambiente.
Compartilhe o link — e deixe o webhook decidir quando entregar.