Stripe webhook: integrar pagamentos com segurança
Transforme seu site em uma máquina de pagamento conectando Stripe e recebendo eventos em tempo real, da aprovação à liberação automática do acesso.
Por que isso é importante
Stripe webhook com segurança: Dashboard → endpoint HTTPS → leia o body cru (express.raw antes do json / request.text no App Router) → constructEvent com Stripe-Signature + whsec_ → persista event.id (idempotência) → responda 2xx rápido. IP allowlist é opcional; nunca confie no JSON parseado sem assinatura.
Leitura relacionada: gateway de pagamento com Node.js · Abacate Pay na prática · como criar API REST com Node.js · Swagger na prática com Fastify · curso de Node.js.
Stripe webhook: do pagamento ao acesso liberado (SaaS/curso)
Um Stripe webhook entrega eventos de pagamento (ex.: checkout.session.completed, payment_intent.succeeded) ao seu endpoint HTTPS para liberar acesso, emitir nota ou atualizar assinatura — desde que você verifique a assinatura e trate retries com idempotência.
Comece pela Dashboard do Stripe
Após acessar a página inicial do Stripe, vá até o menu inferior e selecione Desenvolvedores . Dentro dessa área, clique em Webhooks — o local central para criar sua integração.
Adicione um novo destino de webhook
Clique em Adicionar destino e mantenha configurada a opção "minha conta". Esta etapa vai conectar sua aplicação ao Stripe, tornando possível enviar e receber notificações de eventos.
Não marque “todos os eventos”: escolha o mínimo necessário
Atenção
Selecionar todos os eventos disponíveis pode prejudicar sua aplicação, sobrecarregar recursos e até gerar notificações desnecessárias. O próprio Stripe alerta: escolha apenas o que seu sistema requer.
Selecione apenas os grupos de eventos essenciais para o seu fluxo: pagamentos, checkouts, faturas, cobranças personalizadas. Isso otimiza o monitoramento e torna o webhook mais eficiente.
Eventos que importam: checkout.session.completed e payment_intent.succeeded
Atenção
Utilize uma lista reduzida de eventos. Uma seleção adequada para e-commerces geralmente inclui doze eventos principais — como pagamentos aprovados, fatura criada e sessão de checkout concluída.
Esses são os eventos que permitem confirmar transações e liberar acessos automáticos. No seu painel, agrupe-os em categorias como Checkouts , Custom , Invoice e Pagamento .
Do Dashboard ao endpoint HTTPS: checklist rápido
Ao finalizar a seleção de eventos, clique em Continuar . Não altere a opção de endpoint: mantenha marcada como Webhook endpoint — esse será o endereço que receberá cada notificação do Stripe.
Dê nomes claros aos seus destinos
Atenção
Nomear o destino do webhook com o nome da sua aplicação facilita o gerenciamento e evita conflitos, principalmente ao lidar com múltiplos projetos e endpoints em produção.
Copie o nome da sua aplicação e cole no campo sugerido. Organização agora evita dores de cabeça na escala.
URL do endpoint na central de webhooks
No seu sistema, vá até Integrações e acesse as configurações do Stripe (ícone de engrenagem). Seu painel geralmente mostra o endpoint exato que deve ser usado no Stripe. Copie essa URL.
Cole a URL HTTPS exata do seu handler
Volte à dashboard do Stripe e cole a URL copiada no campo de endpoint. Se desejar, adicione uma breve descrição para referência futura — mas mantenha simples e direto.
Entenda o que acontece por trás: notificações em tempo real
Atenção
Via webhook, o Stripe envia dados criptografados para o seu endpoint toda vez que um evento configurado acontece. Da aprovação do cartão à renovação de assinatura, tudo é transmitido na hora.
Sua aplicação processa essa requisição e executa as ações necessárias, como liberar clientes, disparar alertas ou atualizar sistemas internos.
Finalize e ative seu webhook
Depois de preencher tudo, clique em Criar destino . Seu webhook Stripe está pronto para operar e receber notificações — um passo fundamental para automação de pagamentos e ativação de produtos online.
Verifique Stripe-Signature com constructEvent (nunca confie no JSON cru)
Atenção
Jamais divulgue ou exponha seu endpoint de webhook em locais públicos. Isso protege seu sistema contra ataques e notificações maliciosas.
Endpoints abertos sem verificação permitem eventos falsos (liberar acesso, fraudar pedido). Prioridade: verificar a assinatura Stripe (Stripe-Signature + secret whsec_, body raw) com a lib oficial. IP allowlist da lista pública do Stripe é camada opcional — IPs mudam; assinatura é o essencial. Idempotência no event.id evita double-fulfill.
Lembre-se: monitore e evolua sua integração
Testes constantes, logs detalhados e atualizações de eventos permitem maximizar a confiabilidade da integração Stripe no seu SaaS.
Próximos passos: gateway Node e Abacate Pay (cross-links)
Desvende segredos e novidades práticas em integrações Stripe, Node e React no canal Dev Doido no Youtube. Aprofunde neste assunto essencial para desenvolvedores que querem automação e resultados reais.
Síntese: eventos certos + assinatura + idempotência
Checklist de unlock SaaS/curso: destino HTTPS → eventos mínimos → raw body + constructEvent → idempotência por event.id → fulfill acesso → 2xx rápido → CLI no local. O maior erro não é “esquecer a URL” — é confiar no JSON sem Stripe-Signature ou processar o mesmo pagamento duas vezes.
Raw body no Node/Next: o gotcha que quebra a assinatura
A verificação da assinatura exige o body bruto (bytes/string), não o objeto já parseado por express.json()/Next. Se o body for parseado antes, constructEvent falha ou — pior — você pode acabar confiando em JSON sem assinatura válida. Docs: docs.stripe.com/webhooks.
Express — monte a rota do webhook ANTES de app.use(express.json()), com express.raw:
import express from "express";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; // whsec_...
const app = express();
app.post(
"/webhook",
express.raw({ type: "application/json" }),
(req, res) => {
const sig = req.headers["stripe-signature"];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
} catch (err) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// trate event.type; responda 2xx rápido
res.json({ received: true });
}
);
// só depois: JSON para o resto da API
app.use(express.json());Next.js App Router (route.ts) — leia o texto cru e passe para constructEvent:
import { NextResponse } from "next/server";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET!;
export async function POST(request: Request) {
const body = await request.text(); // raw — não request.json()
const sig = request.headers.get("stripe-signature");
if (!sig) return NextResponse.json({ error: "missing signature" }, { status: 400 });
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(body, sig, endpointSecret);
} catch (err) {
return NextResponse.json({ error: "invalid signature" }, { status: 400 });
}
// idempotência em event.id + fulfill
return NextResponse.json({ received: true });
}Nunca invente atalho “pule assinatura em prod”. IP allowlist da lista pública do Stripe é camada opcional; a assinatura (Stripe-Signature + whsec_) é o essencial.
Idempotência por event.id e liberar acesso
Stripe reenvia eventos (retries). Persista event.id já processado (tabela processed_stripe_events ou equivalente) e só então liberar curso/SaaS/assinatura. Se o mesmo id chegar de novo, retorne 2xx sem reaplicar o fulfill.
- constructEvent com body raw + Stripe-Signature + whsec_
- lookup do event.id na tabela de processados
- se novo → fulfill acesso / atualizar pedido
- marcar id como processado
- responder 2xx rápido — trabalho pesado (e-mail, PDF, sync) pode ir para fila depois do ack
Eventos mínimos típicos de unlock: checkout.session.completed e/ou payment_intent.succeeded — escolha o que casa com seu Checkout/PaymentIntent; evite “selecionar todos”.
Stripe CLI: testar local sem atalho inseguro
Local sem expor a máquina: Stripe CLI encaminha eventos reais de teste para o seu handler.
# terminal 1 — app local na porta 3000 (ou a sua)
# terminal 2
stripe listen --forward-to localhost:3000/webhook
# use o whsec_ que o CLI imprimir como STRIPE_WEBHOOK_SECRET no .env local
stripe trigger payment_intent.succeededStaging e live usam endpoint secrets diferentes (Dashboard → Webhooks). Nunca “pule assinatura” em produção. Clock skew / URL errada / body parseado cedo são as falhas clássicas — monitore entregas na Dashboard.
Fontes
Revisão em agosto de 2026. Segurança de webhook Stripe: verifique assinatura (Stripe-Signature + whsec_) como essencial; allowlist de IP é camada opcional. Tutorial educacional — não é aconselhamento PCI/compliance.
Stripe Webhooks. Stripe — Signature verification. Stripe — Go live checklist.
Perguntas frequentes
Como integrar Stripe webhook com segurança?
Crie destino no Dashboard, aponte para endpoint HTTPS, leia o body cru e valide Stripe-Signature com o whsec_ via constructEvent. Depois trate o evento com idempotência em event.id e libere o acesso do produto. IP allowlist é opcional — assinatura vem primeiro.
Por que verificar a assinatura do webhook Stripe?
Sem verificação, qualquer um pode POSTAR um “pagamento ok” no seu endpoint. A Stripe documenta signature + secret como essencial; filtrar só por IP não substitui. Raw body errado (JSON parse antes) também falha a verificação.
Como testar Stripe webhook localmente?
Use o Stripe CLI para encaminhar eventos ao localhost (listen --forward-to). Assim você exercita assinatura e handlers sem expor a máquina. Evite ngrok aberto sem auth; em produção, responda 2xx rápido e processe o pesado de forma assíncrona.
Quais eventos Stripe usar para confirmar pagamento?
Para Checkout, checkout.session.completed costuma ser o eixo; com PaymentIntent, payment_intent.succeeded. Não marque “todos os eventos” sem handler. Idempotência evita liberar duas vezes no retry da Stripe.
Continue explorando
Perguntas frequentes
Como integrar Stripe webhook com segurança?
Crie destino no Dashboard, aponte para endpoint HTTPS, leia o body cru e valide `Stripe-Signature` com o `whsec_` via `constructEvent`. Depois trate o evento com idempotência em `event.id` e libere o acesso do produto. IP allowlist é opcional — assinatura vem primeiro.
Por que verificar a assinatura do webhook Stripe?
Sem verificação, qualquer um pode POSTAR um “pagamento ok” no seu endpoint. A Stripe documenta signature + secret como essencial; filtrar só por IP não substitui. Raw body errado (JSON parse antes) também falha a verificação.
Como testar Stripe webhook localmente?
Use o Stripe CLI para encaminhar eventos ao localhost (`listen --forward-to`). Assim você exercita assinatura e handlers sem expor a máquina. Evite ngrok aberto sem auth; em produção, responda 2xx rápido e processe o pesado de forma assíncrona.
Quais eventos Stripe usar para confirmar pagamento?
Para Checkout, `checkout.session.completed` costuma ser o eixo; com PaymentIntent, `payment_intent.succeeded`. Não marque “todos os eventos” sem handler. Idempotência evita liberar duas vezes no retry da Stripe.