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.
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.
<a href="https://docs.stripe.com/webhooks">Stripe Webhooks</a>. <a href="https://docs.stripe.com/webhooks/signatures">Stripe — Signature verification</a>. <a href="https://docs.stripe.com/webhooks/go-live">Stripe — Go live checklist</a>.
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.