Webhooks do Stripe: configurar, verificar e testar

Guia de webhooks do Stripe

Webhooks do Stripe: endpoint, assinatura e testes no CLI | We.Inc

Configure um endpoint de webhook do Stripe, verifique o Stripe-Signature com o corpo bruto, teste com stripe listen e stripe trigger e atenda cada pedido do Checkout uma única vez.

Um webhook do Stripe é um endpoint HTTPS no seu servidor para o qual o Stripe envia por POST o JSON de um evento, como checkout.session.completed depois de um pagamento. O seu handler precisa verificar o header Stripe-Signature contra o corpo bruto intacto usando o segredo whsec_ do endpoint, devolver um 2xx rapidamente e tolerar que o mesmo evento chegue mais de uma vez.

O essencial dos webhooks do Stripe (conferido na documentação do Stripe, outubro de 2026)

A maioria das integrações com o Stripe que dão problema falha em um de três pontos: o framework fez o parse do corpo antes da verificação, o handler fez um trabalho lento e estourou o tempo, ou um evento reenviado atendeu um pedido duas vezes. Este guia mostra um handler que evita os três, com um verificador abaixo que confere um header Stripe-Signature no seu navegador para você ver exatamente o que a biblioteca calcula.

Perguntas frequentes

Por que recebo "No signatures found matching the expected signature"?

Quase sempre porque o corpo foi alterado antes da verificação, por exemplo pelo express.json() ou por um body parser que recodifica o JSON. Monte express.raw({ type: "application/json" }) apenas na rota do webhook, ou leia request.text() em um route handler do Next.js. Um segredo errado gera a mesma mensagem.

Quais eventos preciso para o Stripe Checkout?

checkout.session.completed para pagamentos com cartão, mais checkout.session.async_payment_succeeded para métodos com confirmação tardia, como débito bancário. O Stripe também sugere tratar checkout.session.async_payment_failed para você avisar o cliente. Confira o payment_status da sessão antes de atender o pedido.

Posso confiar na página de sucesso em vez de um webhook?

Não. A própria documentação do Stripe diz que o cliente pode pagar e fechar a aba antes de a página de sucesso carregar. Use a página de sucesso para uma confirmação rápida se quiser, mas o webhook também precisa disparar o atendimento, e os dois caminhos precisam ser seguros para rodar duas vezes.

Os eventos do Stripe chegam em ordem?

O Stripe não garante a ordem. invoice.paid pode chegar antes de customer.subscription.created. Registre os ids dos eventos para identificar duplicados e busque o objeto relacionado na API quando precisar do estado mais recente.

Como reenvio um evento que falhou?

Clique em Resend no evento, no Dashboard (funciona até 15 dias após a criação), ou rode stripe events resend <event_id> --webhook-endpoint=<endpoint_id> no CLI (até 30 dias). As novas tentativas automáticas continuam de qualquer forma.

A regra do corpo bruto

Responda primeiro, trabalhe depois

Atenda exatamente uma vez

Código do handler

Express com stripe-node

O express.raw é montado apenas nesta rota, então o corpo chega ao constructEvent com os bytes originais.

Route handler do App Router do Next.js

request.text() entrega o corpo sem parse. Um erro lançado dentro do constructEvent significa que a assinatura ou o segredo está errado.

Testando com o Stripe CLI

Encaminhe e dispare eventos localmente

O listen exibe um segredo whsec_ para esta sessão. Coloque-o no seu env local e dispare eventos em um segundo terminal.

Eventos que vale a pena tratar

Tipos de evento comuns do Stripe e o que fazer

Verificador de Stripe-Signature

Cole um header Stripe-Signature, o corpo bruto e o seu segredo whsec_ para ver a mesma verificação que as bibliotecas fazem. Roda no seu navegador com Web Crypto e não envia nada. Use um segredo de modo de teste, nunca um de produção.

Header Stripe-Signature

Corpo bruto da requisição

Segredo do endpoint (whsec_...)

Tolerância em segundos

Assinar este corpo agora

Verificar

Resultado

O header não tem timestamp t=.

O header não tem assinatura v1=.

v1 esperado: {v}

A assinatura confere.

A assinatura não confere: o corpo foi alterado ou o segredo está errado.

O timestamp tem {n} segundos, dentro da tolerância.

O timestamp tem {n} segundos, fora da tolerância: uma biblioteca o rejeitaria.

Comece grátis · Sem cartão de crédito

Relacionados: Guias

Produto

Para quem é

Recursos

Recursos

Empresa

Mapa do site