Grátis · licença MIT
Webhook da Cakto que não libera duas vezes.
Um arquivo, zero dependências. Confere a assinatura HMAC da Cakto, trava a mesma compra no banco e revoga no reembolso. Funciona em Next.js, Cloudflare, Supabase Edge, Vercel e Bun. Pode copiar.
- Assinatura:
v1=HMAC-SHA256 detimestamp.corpo, com no máximo 5 minutos de diferença (contra replay). - Idempotência:
INSERT ... ON CONFLICT DO NOTHINGpelodata.id. Duas entregas iguais, uma liberação. - Reembolso fora de ordem: se o reembolso chega antes, a compra atrasada não libera.
- Só purchase_approved libera. Pix gerado, boleto e abandono não.
Como usar em 3 passos
- Crie a tabela
cakto_eventos(o SQL está no topo do arquivo). - Coloque o
secretdo painel da Cakto emCAKTO_WEBHOOK_SECRET, no servidor. - Escreva o seu
liberar()e o seurevogar().
Carregando o código…
Formato conferido em docs.cakto.com.br/conceitos/webhooks em outubro de 2026. Se a Cakto mudar, o kit recebe a atualização.
Grátis · checklist de produção
As 12 situações que todo webhook de pagamento encontra.
O teste com cliente de verdade é onde webhook gerado às pressas quebra. Se você não sabe o que o seu faz em cada linha desta tabela, ainda não está pronto para vender.
| # | Situação real | O certo é |
|---|---|---|
| 1 | O gateway manda o mesmo aviso 2 vezes, ou 10 ao mesmo tempo | Liberar uma vez só, com a trava no banco |
| 2 | Reembolso dentro dos 7 dias | Cortar o acesso na hora |
| 3 | Chargeback no cartão | Cortar igual ao reembolso |
| 4 | A pessoa só pediu reembolso | Não cortar ainda |
| 5 | O reembolso chega antes da compra | A compra atrasada não libera |
| 6 | O pagamento chega sem o id do pedido, com outro e-mail | Guardar como órfão e ter um jeito de ligar depois |
| 7 | O órfão foi reembolsado | Ninguém consegue ligar mais |
| 8 | Pagou o Pix com o e-mail da mãe | Liberar pelo id do pedido, não pelo e-mail |
| 9 | O banco cai no meio do processamento | Nada fica pela metade, e o reenvio resolve |
| 10 | Alguém reenvia um aviso antigo (replay) | Recusar pela data da assinatura |
| 11 | A renovação mensal chega duas vezes | Somar 30 dias uma vez só |
| 12 | Pix gerado e não pago, cartão recusado | Não liberar nada |
No kit pago, cada linha é um teste automático (P1 a P12) que roda em SQLite e em Postgres. O webhook grátis acima já cobre 1, 2, 3, 4, 5, 9, 10 e 12. Faltam a ligação ao pedido certo (6, 7, 8) e a renovação (11).
Prompt grátis: o Claude Code audita o seu webhook com esta tabela
Cole no Claude Code (ou no Cursor) dentro do seu projeto. Ele só lê e responde item por item, sem mexer no código.
Revise o webhook de pagamento deste projeto (ache a rota que recebe o aviso do gateway: Cakto, Kiwify, Hotmart, Stripe, Mercado Pago ou AbacatePay). NÃO altere nada ainda: só leia e me responda, item por item, com "ok", "falta" ou "não sei", citando arquivo e linha. 1. Origem: confere a assinatura ou o token do gateway ANTES de qualquer coisa, sobre o corpo cru (não sobre o JSON já parseado)? 2. Replay: recusa assinatura com timestamp velho (mais de 5 minutos), quando o gateway manda timestamp? 3. Duplicado: se o mesmo aviso chegar 2 vezes, ou 10 ao mesmo tempo, libera uma vez só? A trava está no banco (chave única), não num "if" em memória? 4. Reembolso: o evento de reembolso tira o acesso? 5. Chargeback: o evento de chargeback tira o acesso? 6. Pedido de reembolso: o "reembolso solicitado" NÃO tira o acesso (só o reembolso feito)? 7. Ordem trocada: se o reembolso chegar ANTES da compra, a compra atrasada deixa de liberar? 8. Ligação: como o pagamento é ligado ao usuário certo? Por um id que o meu servidor criou e mandou no link do checkout, ou só pelo e-mail? O que acontece se a pessoa pagar com outro e-mail? 9. Órfão: se o pagamento chegar sem dar para ligar a ninguém, ele fica guardado em algum lugar para eu resolver depois, ou some? 10. Falha no meio: se o banco cair depois de marcar "pago" e antes de liberar, o que fica no banco? O reenvio conserta? 11. Front: alguma tela libera acesso sozinha (redirect de sucesso, ?pago=true, localStorage) sem o servidor confirmar? 12. Segredos: o segredo do webhook e as chaves ficam só no servidor (nunca em VITE_, NEXT_PUBLIC_ ou no git)? No fim, liste os itens "falta" em ordem de risco (o que perde dinheiro primeiro) e proponha o menor conserto de cada um. Só mude o código depois que eu disser qual consertar.
Revisor grátis
Seu webhook tem bug? Cole e veja.
Seis checagens: origem, corpo cru, idempotência, reembolso, evento certo e segredo fora do código. É uma triagem rápida, não uma auditoria. O código não é guardado.
Quer o resto pronto?
Checkout com o id do pedido, chave de acesso, recuperar por e-mail, Kiwify e Hotmart, LGPD, os 12 testes de produção, o roteiro "paguei e não liberou" e a skill /cobrar que instala tudo no seu app. Testado num app estilo Lovable e num Next.js.