Um cliente paga, o Stripe envia um evento payment_intent.succeeded ao seu backend, e seu endpoint precisa marcar o pedido como pago. É exatamente nesse último passo que falhas silenciosas costumam aparecer: o webhook chega, o manipulador lança um erro e ninguém percebe até surgir um ticket dizendo: “Eu paguei, mas minha conta ainda aparece como não paga”. Para evitar isso, crie um teste de CI que comprove, a cada deploy, que o evento foi recebido e que a regra de negócio foi executada.
Webhooks são diferentes de requisições HTTP convencionais: o Stripe chama sua aplicação, e não o contrário. A maioria das ferramentas de teste de API foi projetada para enviar uma requisição e validar a resposta, o que inverte esse fluxo. Este guia mostra como validar webhooks do Stripe em CI com Apidog, usando o padrão capturar primeiro, validar depois. Para o contexto geral, consulte o guia sobre como testar webhooks e a documentação de webhooks do Stripe.
A restrição que você precisa considerar no design
A documentação do Apidog declara que o produto não suporta nativamente a escuta de webhooks. Ou seja: você não pode apontar o Stripe para uma URL do Apidog e esperar que ele capture eventos de entrada em tempo real.
A solução é persistir o evento na sua própria infraestrutura:
- O Stripe envia o webhook ao seu backend.
- Seu endpoint valida a assinatura e registra o evento no banco.
- O Apidog consulta esse registro.
- O cenário de teste valida o evento e o efeito de negócio.
Esse formato funciona bem em CI porque consultar um registro persistido é repetível, auditável e menos sujeito a condições de corrida do que tentar interceptar uma chamada externa em tempo real.
Como funciona o padrão de captura e consulta
O fluxo possui quatro componentes:
- Um endpoint no backend para receber webhooks do Stripe.
- Uma tabela, como
stripe_event_logs, para armazenar os eventos recebidos. - Uma conexão de banco de dados configurada no ambiente do Apidog.
- Um
Processador Pós-Requisiçãoque consulta os dados e executa as asserções.
Seu código é responsável por receber, verificar e persistir o webhook. O Apidog entra depois: ele lê o registro salvo e valida se o evento e seus efeitos correspondem ao esperado.
Passo 1: implemente o endpoint de captura
Crie uma rota HTTP POST que o Stripe possa chamar. Em Express, mantenha o corpo bruto da requisição para validar corretamente a assinatura.
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}`);
}
// Persista o evento para que o cenário de teste possa consultá-lo.
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);
}
return res.json({ received: true });
}
);
Há dois pontos essenciais nesse código:
- Use
stripe.webhooks.constructEvent()antes de confiar no payload. A validação de assinatura é obrigatória para confirmar que a requisição veio do Stripe. Veja mais detalhes sobre verificação de assinatura de webhook. - Persista o evento em uma tabela consultável. A cláusula
ON CONFLICT (event_id) DO NOTHINGmantém o processo idempotente, já que o Stripe pode reenviar o mesmo evento.
Uma estrutura mínima para a tabela poderia ser:
CREATE TABLE stripe_event_logs (
event_id TEXT PRIMARY KEY,
type TEXT NOT NULL,
payload JSONB NOT NULL,
handled_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
Se você precisar distinguir execução, recebimento e processamento concluído, considere armazenar timestamps separados, como
received_at,handled_atefailed_at.
Passo 2: conecte o banco de dados ao ambiente do Apidog
Configure uma conexão de banco de dados no ambiente do Apidog usado pelo seu cenário de CI. Por exemplo:
- Ambiente
staging→ banco de dados de staging. - Ambiente
test→ banco de dados isolado para testes automatizados.
A conexão precisa apontar para o mesmo banco em que o endpoint do webhook grava os eventos. Se o seu teste dispara um pagamento em staging, mas o Processador Pós-Requisição consulta outro banco, a asserção falhará mesmo que o webhook tenha sido processado corretamente.
Antes de criar o cenário, confirme:
- O banco está acessível a partir da execução do Apidog.
- As credenciais usadas têm permissão de leitura em
stripe_event_logs. - O ambiente selecionado no cenário corresponde ao ambiente da aplicação.
- A tabela não contém eventos antigos capazes de gerar falsos positivos.
Passo 3: consulte o log com um Processador Pós-Requisição
O Processador Pós-Requisição é o ponto em que o Apidog consulta o banco e valida o webhook persistido.
Um cenário para payment_intent.succeeded pode seguir esta sequência:
- Dispare um pagamento no modo de teste do Stripe.
- Aguarde o Stripe enviar o evento para
/webhooks/stripe. - Deixe o endpoint validar, registrar o evento e atualizar o pedido.
- Execute uma consulta SQL no
Processador Pós-Requisição. - Faça asserções sobre o evento e sobre o estado do pedido.
Uma consulta inicial pode ser:
SELECT event_id, type, payload, handled_at
FROM stripe_event_logs
WHERE type = 'payment_intent.succeeded'
ORDER BY handled_at DESC
LIMIT 1;
Em um teste robusto, não valide apenas o type. Faça asserções sobre dados que identificam exatamente a execução atual:
-
event_idcorresponde ao evento disparado. -
typeépayment_intent.succeeded. -
payloadcontém o valor e os metadados esperados. -
handled_atfoi preenchido. - O pedido associado mudou para o estado
paid.
Por exemplo, valide também o efeito de negócio:
SELECT id, status, paid_at
FROM orders
WHERE id = :order_id;
O resultado esperado deve indicar que o pedido foi pago:
status = 'paid'
paid_at IS NOT NULL
Isso evita um teste fraco que prova apenas que o evento foi gravado, mas não que o manipulador executou a ação necessária.
Trate o atraso de entrega
Webhooks são assíncronos. Se você consultar o banco imediatamente após disparar o pagamento, o Stripe pode ainda não ter feito a entrega.
Use uma pequena espera ou polling com retentativas antes de declarar falha. A estratégia é:
- Consultar o evento.
- Se ele não existir, aguardar alguns segundos.
- Repetir por um número limitado de tentativas.
- Falhar com uma mensagem clara se o evento não aparecer.
Evite aumentar demais o tempo de espera. O objetivo é acomodar a entrega assíncrona sem transformar seu pipeline em uma execução lenta e imprevisível.
Desenvolvimento local: encaminhe eventos em tempo real
O padrão de captura e consulta é ideal para CI. No desenvolvimento local, você precisa de uma forma de receber eventos do Stripe no seu localhost.
O Stripe CLI pode encaminhar eventos para sua aplicação local:
stripe listen --forward-to localhost:3000/webhooks/stripe
Isso permite testar o manipulador enquanto você desenvolve. Ferramentas como Ngrok também podem expor sua porta local por meio de uma URL pública.
Use esse fluxo para desenvolvimento:
Stripe CLI ou Ngrok → localhost → endpoint de webhook
E use este fluxo para CI:
Stripe → endpoint do ambiente → banco de dados → Apidog → asserções
Os dois processos são complementares: encaminhamento em tempo real para desenvolver; captura e consulta para comprovar o comportamento automatizado.
Não confunda isso com o recurso nativo de Webhook do Apidog
O Apidog possui um recurso chamado Webhook, mas ele serve para definir e documentar webhooks de saída do seu sistema.
Esse recurso descreve situações em que sua aplicação chama uma URL externa quando algo acontece, por exemplo:
- um pedido foi criado;
- uma importação terminou;
- uma assinatura foi cancelada.
Ele não serve para capturar chamadas de entrada do Stripe.
Para documentar um webhook de saída no Apidog:
- Clique no ícone
+na barra lateral. - Selecione
New Other Protocol APIs. - Escolha
Webhook. - Preencha
Request Method,Webhook Name,Debug URLe os dados da requisição. - Clique em
Save.
Você pode usar a Debug URL para simular o envio durante o teste. Essa URL é exclusiva para depuração e não aparece na documentação publicada nem na exportação OpenAPI.
Para aprofundar o tema, consulte o artigo sobre webhooks no design de API.
Torne o teste mais robusto
Depois de validar o caminho feliz, adicione verificações que protejam o sistema contra regressões reais.
1. Correlacione o evento com a execução atual
Não consulte apenas o evento mais recente por tipo. Isso pode capturar um registro deixado por uma execução anterior.
Prefira filtrar pelo event_id, pelo ID do pedido ou por uma chave de correlação inserida nos metadados do Payment Intent:
SELECT event_id, type, payload, handled_at
FROM stripe_event_logs
WHERE event_id = :stripe_event_id
LIMIT 1;
Ou, se você controla os metadados:
SELECT event_id, type, payload, handled_at
FROM stripe_event_logs
WHERE payload->'metadata'->>'order_id' = :order_id
AND type = 'payment_intent.succeeded'
ORDER BY handled_at DESC
LIMIT 1;
2. Limpe ou isole os dados de teste
Para evitar interferência entre execuções:
- Use um banco de dados dedicado para testes.
- Gere IDs únicos por execução.
- Remova registros de teste ao fim do cenário.
- Filtre consultas por uma chave de correlação.
3. Teste falhas e rejeições
Não valide somente o fluxo de sucesso. Inclua casos como:
- Assinatura inválida.
- Tipo de evento inesperado.
- Pedido inexistente.
- Falha ao atualizar o pedido.
- Reentrega do mesmo evento.
Para uma assinatura inválida, por exemplo, o comportamento esperado pode ser:
HTTP 400
Nenhum registro de processamento concluído
Nenhum pedido marcado como pago
As melhores práticas de webhooks de pagamento ajudam a estruturar testes para idempotência, retentativas e tratamento de erro.
4. Prove o resultado de negócio
“O evento chegou” não é a mesma coisa que “o pagamento foi aplicado”.
Sempre que possível, valide a tabela ou serviço alterado pelo webhook:
SELECT status
FROM orders
WHERE id = :order_id;
A asserção deve provar o resultado esperado:
status = 'paid'
Automatize o cenário com a CLI do Apidog
Quando o cenário estiver salvo no Apidog, execute-o no pipeline usando a CLI.
Instale e autentique:
npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
Execute o cenário contra o ambiente correto:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t <SCENARIO_ID> -e <ENV_ID> -r cli
Parâmetros principais:
-
-t: ID do cenário de teste. -
-e: ID do ambiente. -
-r: formato do relatório.
Para gerar saída de console e relatório HTML:
apidog run \
--access-token $APIDOG_ACCESS_TOKEN \
-t <SCENARIO_ID> \
-e <ENV_ID> \
-r html,cli
Se qualquer asserção falhar, a execução deve retornar um código diferente de zero. Assim, o pipeline pode bloquear o merge ou o deploy.
Para configurar a CLI, consulte o guia de instalação da CLI do Apidog. Para integrar ao GitHub Actions, veja a explicação sobre pipeline de CI/CD.
Perguntas frequentes
O Apidog pode receber um webhook do Stripe diretamente?
Não. O Apidog não suporta nativamente a escuta de webhooks de entrada. Capture o evento no seu backend, registre-o no banco e use um Processador Pós-Requisição para consultar e validar o resultado.
Para desenvolvimento local, encaminhe eventos com Stripe CLI ou Ngrok.
Onde as asserções acontecem?
No Processador Pós-Requisição do cenário de teste. Ele consulta a tabela de logs por meio da conexão de banco configurada no ambiente e compara os resultados com os valores esperados.
Preciso validar apenas a tabela de logs?
Não. Validar o log confirma que o evento foi persistido, mas a melhor cobertura vem de validar também o efeito de negócio, como o status do pedido na tabela orders.
Como lidar com o atraso entre o disparo e a entrega?
Use uma pequena espera ou polling com retentativas. O teste deve aguardar por tempo limitado até que o evento apareça no banco antes de falhar.
Se você está começando a testar fluxos assíncronos, leia primeiro o guia sobre como testar webhooks.
O recurso nativo de Webhook do Apidog ajuda nesse caso?
Não para receber eventos do Stripe. Ele serve para definir e documentar webhooks de saída do seu próprio sistema, enquanto este artigo trata da validação de webhooks de entrada com captura e consulta.
Conclusão
Você não aponta o Stripe para o Apidog para capturar eventos ao vivo. O fluxo suportado é:
- Receba o webhook no seu backend.
- Verifique a assinatura.
- Persista o evento em
stripe_event_logs. - Consulte o registro com o
Processador Pós-Requisiçãodo Apidog. - Valide o evento e a alteração de negócio.
- Execute o cenário com
apidog runno CI.
Com esse padrão, cada merge pode comprovar que um payment_intent.succeeded não apenas chegou ao sistema, mas também marcou o pedido correto como pago.
Top comments (0)