Como Capturar e Validar Webhooks do Stripe em CI com Apidog

Aprenda a testar webhooks do Stripe em CI com o Apidog: capture eventos no seu backend, registre-os e então valide o payload com um Processador Pós-Requisição.

INEZA Felin-Michel

INEZA Felin-Michel

16 julho 2026

Como Capturar e Validar Webhooks do Stripe em CI com Apidog

Apidog para empresas

Implantação local

SSO & RBAC

Conforme SOC 2

Explorar Apidog Enterprise

Um cliente paga, o Stripe dispara um evento payment_intent.succeeded para o seu backend, e seu endpoint deve marcar o pedido como pago. Esse último passo é o que falha silenciosamente. O webhook chega, seu manipulador falha (lança um erro), e ninguém percebe até que um ticket de suporte diga "Eu paguei, mas minha conta ainda aparece como não paga." Você quer um teste em CI que comprove que o evento chegou e foi tratado corretamente, toda vez que você faz um deploy.

A parte complicada é que um webhook é uma chamada HTTP de entrada do Stripe para você, não uma requisição que você faz. A maioria das ferramentas de teste de API são construídas para enviar uma requisição e verificar a resposta, o que é o formato oposto. Então a questão se torna: como você valida algo que chega em seu próprio cronograma, dentro de uma execução de CI, sem um humano observando? Este guia mostra a maneira honesta e suportada de fazer isso com Apidog, e começa com uma limitação que você precisa saber de antemão. Se você quiser uma visão mais ampla de como testar endpoints orientados a eventos primeiro, nosso guia sobre como testar webhooks prepara o terreno, e a própria documentação de webhooks do Stripe aborda o modelo de entrega de eventos.

A restrição que você precisa considerar no design

Aqui está o fato crucial, declarado claramente na própria documentação do Apidog: "O ApiDog não suporta nativamente a escuta de webhooks." O Apidog não se posiciona em uma URL pública para capturar as chamadas de entrada do Stripe em tempo real. Se você esperava apontar o Stripe para um listener do Apidog e ver os eventos chegarem, esse caminho não existe.

Isso parece um beco sem saída. Não é. Apenas muda a forma do teste. Em vez de interceptar o webhook assim que ele chega, você o captura no seu próprio backend, o armazena e, em seguida, faz com que o Apidog consulte esse registro armazenado e faça a validação sobre ele. Capturar primeiro, validar depois. Assim que você aceita essa divisão, todo o fluxo de trabalho se torna direto e, importante, se encaixa perfeitamente na CI porque uma consulta de banco de dados é determinística e repetível.

Como é o padrão de captura e consulta

O padrão recomendado pela documentação do Apidog possui quatro partes móveis:

  1. Crie um endpoint em seu serviço de backend para capturar webhooks de entrada do Stripe.
  2. Armazene os dados do evento do webhook em uma tabela Stripe event logs em seu banco de dados.
  3. Use o Processador Pós-Requisição do Apidog para consultar seu banco de dados.
  4. Recupere o evento do webhook armazenado e valide-o em relação aos resultados esperados.

Duas dessas etapas ficam no seu código, e duas ficam no Apidog. O endpoint de captura e a tabela de log são sua responsabilidade construir, porque eles rodam dentro da sua própria aplicação. O trabalho do Apidog começa assim que o evento está no seu banco de dados: ele se conecta a esse banco de dados e lê a linha de volta para confirmar que o evento foi tratado da maneira que você espera. Mantenha essa divisão clara e o resto se encaixará.

Passo 1: Construa o endpoint de captura

Seu backend precisa de uma rota para a qual o Stripe possa fazer uma requisição POST. Este é um código de aplicação comum, não um recurso do Apidog. Um manipulador Express mínimo que verifica a assinatura e registra o evento se parece com isto:

import express from "express";
import Stripe from "stripe";

const app = express();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;

app.post(
  "/webhooks/stripe",
  express.raw({ type: "application/json" }),
  async (req, res) => {
    let event;
    try {
      event = stripe.webhooks.constructEvent(
        req.body,
        req.headers["stripe-signature"],
        endpointSecret
      );
    } catch (err) {
      return res.status(400).send(`Signature check failed: ${err.message}`);
    }

    // Persist the event so a test can read it back later.
    await db.query(
      `INSERT INTO stripe_event_logs (event_id, type, payload, handled_at)
       VALUES ($1, $2, $3, now())
       ON CONFLICT (event_id) DO NOTHING`,
      [event.id, event.type, JSON.stringify(event.data.object)]
    );

    if (event.type === "payment_intent.succeeded") {
      const intent = event.data.object;
      await markOrderPaid(intent.metadata.order_id);
    }

    res.json({ received: true });
  }
);

Duas coisas importam aqui. Primeiro, você verifica a assinatura do Stripe com constructEvent antes de confiar em qualquer coisa, o que é a etapa de segurança não negociável para qualquer receptor de webhook. Se você quiser o raciocínio completo por trás dessa verificação, nossa explicação sobre verificação de assinatura de webhook detalha por que uma comparação do corpo bruto é a única maneira segura de fazer isso. Segundo, você escreve o evento em uma tabela Stripe event logs. Essa linha é o que o Apidog lerá. A cláusula ON CONFLICT DO NOTHING mantém o log idempotente, já que o Stripe pode entregar o mesmo evento mais de uma vez.

Passo 2: Conecte seu banco de dados no ambiente Apidog

O Apidog suporta a conexão com um banco de dados no ambiente correspondente, e essa conexão é o que faz todo esse padrão funcionar. Configure uma conexão de banco de dados para o ambiente que sua execução de CI almeja, seja um Postgres de staging ou um banco de dados de teste dedicado. Uma vez que a conexão esteja configurada, uma etapa de teste pode executar SQL contra ele e puxar linhas reais.

Correlacione a conexão com o ambiente que você está testando. Um teste que roda em staging deve consultar o banco de dados de staging, para que o evento que seu teste dispara seja o evento que seu teste lê. Ambientes incompatíveis são a razão mais comum para um endpoint de captura que passa ainda falhar na asserção.

Passo 3: Adicione um Processador Pós-Requisição para consultar o log

Este é o ponto central. O Processador Pós-Requisição é o recurso do Apidog que consulta seu banco de dados e valida o evento de webhook registrado dentro de um teste. Você o anexa a uma requisição em seu cenário de teste. Após a execução da requisição, o processador executa seu SQL, lê o evento armazenado e permite que você faça asserções sobre o resultado.

Um fluxo realista para o caso payment_intent.succeeded:

  1. Seu cenário de teste dispara o pagamento. Isso pode ser uma requisição que cria um Payment Intent e o confirma no modo de teste do Stripe, ou um fixture que dispara um evento de teste conhecido para o seu endpoint de captura.
  2. O Stripe entrega o webhook para sua rota /webhooks/stripe, que verifica a assinatura e escreve uma linha na tabela stripe_event_logs.
  3. Um Processador Pós-Requisição na próxima etapa consulta essa tabela para o evento.

A consulta que o processador executa é SQL puro:

SELECT event_id, type, payload, handled_at
FROM stripe_event_logs
WHERE type = 'payment_intent.succeeded'
ORDER BY handled_at DESC
LIMIT 1;

Você então faz asserções sobre a linha retornada. O teste passa quando os dados registrados correspondem às suas expectativas: o type é payment_intent.succeeded, o event_id corresponde ao que você disparou, o valor do payload é igual ao que você cobrou, e handled_at está preenchido, o que comprova que seu manipulador realmente executou em vez de a linha ser um placeholder. Recupere o evento de webhook armazenado, compare-o com o resultado esperado e deixe a asserção decidir se passa ou falha.

Como o tempo de entrega do webhook não é instantâneo, dê um momento para o evento chegar antes de você consultar. Uma pequena etapa de atraso, ou um loop de polling que tenta a consulta algumas vezes antes de falhar, evita que o teste corra contra a entrega do Stripe. Este é o único lugar onde a natureza assíncrona dos webhooks vaza para o seu design de teste, e uma pequena janela de retentativa o trata de forma limpa.

Uma nota sobre o encaminhamento em tempo real durante o desenvolvimento local

O padrão de captura e consulta é construído para CI, onde um banco de dados e um registro armazenado são exatamente o que você deseja. O desenvolvimento local é uma situação diferente. Quando você está escrevendo o manipulador em seu laptop, o Stripe não consegue alcançar o localhost diretamente, então você precisa de algo para encaminhar eventos para sua máquina em tempo real.

Para isso, a documentação do Apidog aponta para um serviço de retransmissão de webhook, citando o Stripe CLI e o Ngrok como exemplos. O Stripe CLI pode escutar e encaminhar eventos diretamente para sua porta local:

stripe listen --forward-to localhost:3000/webhooks/stripe

Isso fornece eventos ao vivo enquanto você constrói o manipulador. O Ngrok faz o mesmo trabalho expondo sua porta local em uma URL pública que você registra como um endpoint do Stripe. Use-os para o loop de desenvolvimento interno e, em seguida, conte com o banco de dados mais o fluxo do Processador Pós-Requisição para as asserções que rodam em seu pipeline. Os dois são complementares: retransmissão para construir, captura e consulta para comprovar.

Não confunda isso com o recurso nativo de Webhook do Apidog

O Apidog possui um recurso literalmente chamado Webhook, e é fácil presumir que é assim que você captura eventos do Stripe. Não é, e confundi-los custará uma tarde. O recurso nativo Webhook serve para definir e documentar um webhook de saída, o que significa um endpoint HTTP que seu próprio sistema chama quando um evento ocorre. O sistema inicia a chamada para uma URL externa, o que é o oposto de um endpoint regular onde os clientes chamam você. É usado para descrever notificações de mudança de estado e resultados de tarefas assíncronas em sua documentação de API, não para receber chamadas de entrada do Stripe.

Se você deseja documentar um de seus próprios webhooks de saída, o fluxo é curto:

  1. Clique no ícone + na barra lateral esquerda.
  2. Selecione New Other Protocol APIs (Novas Outras APIs de Protocolo), depois Webhook.
  3. Preencha os campos obrigatórios: Request Method (Método de Requisição, tipicamente POST), um Webhook Name (Nome do Webhook), uma Debug URL (URL de Depuração) opcional apenas para testes, e Other Info (Outras Informações) para o corpo da requisição, cabeçalhos e configuração.
  4. Clique em Save (Salvar).

Para testar, insira uma URL no campo Debug URL e clique em Send (Enviar) para simular a chamada do webhook. Uma ressalva importante: a Debug URL é apenas para testes e não aparecerá em sua documentação publicada ou em sua exportação OpenAPI. Para um tratamento mais completo do design e documentação de callbacks de eventos, nosso artigo sobre webhooks no design de API aborda onde eles se encaixam. A versão resumida para este artigo: o recurso nativo Webhook define seus eventos de saída, e o padrão de captura e consulta valida os eventos de entrada do Stripe. Mantenha os dois claramente separados.

Variações e robustecimento

Uma vez que a asserção básica funcione, alguns refinamentos a tornam de nível de produção. Primeiro, faça asserções em mais do que apenas o tipo de evento. Verifique o event_id de ponta a ponta para que você saiba que o evento exato que você disparou é o que você validou, e não um resquício de uma execução anterior. Trunque ou defina o escopo da tabela stripe_event_logs por execução de teste se os eventos se acumularem.

Segundo, teste os caminhos de falha. Dispare um evento que seu manipulador deveria rejeitar, uma assinatura inválida ou um tipo inesperado, e verifique se nenhum timestamp handled_at é gravado. Um conjunto de testes de webhook que verifica apenas o caminho feliz perde os casos que realmente te acionam às 2 da manhã. Nossas notas sobre melhores práticas de webhooks de pagamento cobrem a idempotência e o comportamento de retentativa que vale a pena codificar nesses testes.

Terceiro, mantenha a asserção ligada ao significado de negócio, não apenas à entrega. "O evento chegou" é mais fraco do que "o pedido mudou para pago." Se seu manipulador atualiza uma tabela orders, adicione uma segunda consulta que confirme que o estado a jusante mudou, para que o teste prove toda a cadeia e não apenas a gravação do log.

Você também pode levar isso além do ponto de fusão (merge gate). Uma vez que o cenário é salvo no Apidog, agende-o para rodar em uma cadência para que um manipulador de webhook quebrado apareça mesmo entre os deploys. Nosso guia sobre como agendar testes de API no Apidog mostra como colocar essa mesma validação em um temporizador.

Automatize o fluxo de trabalho com a CLI do Apidog

Tudo o que foi dito acima compensa quando é executado sem supervisão, e é aí que a CLI do Apidog entra. Esta é intrinsecamente uma história de CI, então integrar o cenário salvo ao seu pipeline é o desfecho natural. Instale a CLI e autentique-se com seu token:

npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>

Em seguida, execute seu cenário de validação de webhook salvo de forma "headless" (sem interface gráfica) contra o ambiente cujo banco de dados contém os logs de eventos:

apidog run --access-token $APIDOG_ACCESS_TOKEN -t <SCENARIO_ID> -e <ENV_ID> -r cli

Aqui -t é o ID do cenário de teste, -e é o ID do ambiente e -r seleciona o relator. Use -r html,cli se quiser um relatório navegável junto com a saída do console para seus artefatos de CI. O cenário carrega o Processador Pós-Requisição e sua consulta ao banco de dados, então um único comando dispara o fluxo, lê a linha de stripe_event_logs e retorna um código de saída diferente de zero se a asserção falhar, o que é exatamente o que um pipeline precisa para barrar um merge. O guia de instalação da CLI do Apidog cobre a configuração do token, e nossa explicação do pipeline de CI/CD mostra toda a integração do GitHub Actions em torno deste comando.

Perguntas frequentes

O Apidog pode receber um webhook do Stripe diretamente? Não. A documentação do Apidog afirma claramente que ele "não suporta nativamente a escuta de webhooks." Você captura o evento em seu próprio endpoint de backend, armazena-o em um banco de dados, e o Apidog o lê de volta com um Processador Pós-Requisição. Para encaminhamento em tempo real durante o desenvolvimento local, use um retransmissor como o Stripe CLI ou Ngrok.

Onde as asserções realmente acontecem? Dentro da etapa do Processador Pós-Requisição em uma requisição em seu cenário de teste. Ele consulta sua tabela Stripe event logs através da conexão de banco de dados que você configurou no ambiente, recupera o evento armazenado e o compara com seus valores esperados. O teste passa quando os dados registrados correspondem.

Preciso de um plano pago para o fluxo de validação de banco de dados? A documentação do Apidog para este fluxo de trabalho não menciona nenhuma restrição de plano, então este guia não vai inventar uma. A resposta honesta é verificar os detalhes do plano atual na página de preços. Você pode Baixar Apidog e configurar um projeto de teste para ver o Processador Pós-Requisição e a conexão com o banco de dados do ambiente por si mesmo.

Como lidar com o atraso entre o disparo e a entrega? A entrega de webhook não é instantânea, então adicione uma pequena espera ou uma retentativa de polling antes da consulta para que seu teste não corra contra o Stripe. Algumas retentativas ao longo de alguns segundos geralmente são suficientes. Se você é novo em fazer asserções em endpoints assíncronos, comece com o guia geral como testar webhooks antes de aprofundar nas especificidades do Stripe.

O recurso nativo de Webhook é útil aqui? Não para capturar eventos do Stripe. Esse recurso define e documenta seus próprios webhooks de saída, onde seu sistema chama uma URL externa. É uma ferramenta de documentação e design, separada do padrão de captura e consulta de entrada que este artigo utiliza. Mantenha os dois claramente separados.

Concluindo

Você não pode apontar o Stripe para o Apidog e capturar eventos ao vivo, e fingir o contrário leva a uma tarde frustrante. O caminho suportado é mais limpo do que parece à primeira vista: capture o webhook em seu próprio endpoint, registre-o em uma tabela Stripe event logs e, em seguida, deixe o Processador Pós-Requisição do Apidog consultar esse registro e afirmar que o evento foi tratado. Envolva o cenário salvo em apidog run e seu pipeline prova, em cada merge, que um evento de pagamento real move seu pedido para pago. Experimente gratuitamente, sem cartão de crédito, e coloque uma asserção real por trás do webhook que mais importa.

Pratique o design de API no Apidog

Descubra uma forma mais fácil de construir e usar APIs