1

Pitch: Construindo uma ferramenta de teste de webhook: o problema, as decisões técnicas e o resultado

Trabalho com Laravel no dia a dia, e em algum momento comecei a integrar mais de um gateway de pagamento no mesmo projeto. Cada gateway manda webhook de um jeito diferente: payload diferente, header diferente, assinatura validada de um jeito diferente. Nada surpreendente para quem já passou por isso, mas o volume de teste manual foi crescendo rápido.

As ferramentas que eu já usava

Comecei usando o expose.dev, porque já fazia parte do ecossistema Laravel que eu mexia todo dia. Funcionava bem no básico: subi um túnel, apontei o provedor pra lá, recebi o webhook. Conforme fui precisando de testes mais constantes, paguei pela versão com subdomínio fixo, pra não precisar reconfigurar o endpoint no provedor a cada sessão.

O problema apareceu na persistência. As requests só ficavam visíveis enquanto o console estava aberto. Fechei o terminal, fechei a sessão, perdi o histórico. Para depurar algo que aconteceu uma hora antes, não tinha pra onde voltar.

Pra resolver isso, passei a usar o webhook.site em paralelo, porque ele guarda o histórico. Só que o tunelamento dele é bem cru: sem reconexão automática estável, e eu perdia o link de encaminhamento com frequência, o que quebrava o teste no meio.

Resultado: eu estava com duas assinaturas, cada uma cobrindo metade do problema.

A decisão

Em algum momento bateu a conta simples: eu já pagava por duas ferramentas incompletas. O valor das duas juntas dava pra manter um servidor rodando. Não foi um plano de criar um produto, foi literalmente isso: já que vou pagar de qualquer jeito, por que não construir uma coisa que resolva os dois problemas ao mesmo tempo?

Decisões técnicas

A primeira decisão foi a forma de tunelamento. Em vez de fazer polling ou esperar o provedor reenviar, optei por manter uma conexão WebSocket persistente entre uma CLI local e o servidor: a request pública chega no servidor, é repassada como frame pelo socket pra CLI, a CLI bate no app local e devolve a resposta real para o servidor, que retorna para o provedor original. Isso elimina a espera de retry do provedor pra testar de novo, e me dá status de conexão em tempo real (sei na hora se o túnel caiu).

A segunda foi separar captura de manipulação. No começo o objetivo era só inspecionar e tunelar, mas percebi que precisava alterar a request antes dela chegar no meu ambiente local: corrigir um header, simular um payload diferente, validar uma assinatura antes de deixar passar. Em vez de isso virar código hardcoded de teste, virou um sistema de flow: nodes que executam em sequência assim que a request chega, antes do túnel. Verificação de assinatura HMAC, switch por campo do payload, transformação de header/body/method, enriquecimento via chamada externa, idempotência com janela de tempo, condicional simples. Dá pra montar isso visualmente, sem precisar de redeploy a cada cenário de teste.

Dificuldades

A parte mais chata não foi o túnel em si, foi manter a sensação de "tempo real" sem travar a UI quando chegam várias requests em sequência rápida, principalmente em teste de concorrência. Outro ponto foi decidir o que persistir: guardar tudo indefinidamente não escala, então limitei a retenção (hoje guardo as últimas 1.000 requests por conta) em vez de tentar manter histórico infinito.

O que todo dev gosta

Uma coisa que eu queria desde o início era não depender do painel web pra acompanhar o dia a dia. Gosto de trabalhar com terminal aberto, e abrir um app web só pra ver se um webhook chegou quebra esse fluxo. Por isso, depois que a base ficou funcional, fiz um tail das requests direto na CLI: dá pra ver cada request chegando em tempo real, com status, latência e tabela colorida, sem nunca abrir o navegador. Pra quem vive no terminal, isso sozinho já mudou bastante o jeito de testar.

Comparação

Contra webhook.site: ele resolve bem a parte de inspecionar e persistir, mas não tunela de forma estável, e não tem nada parecido com manipulação de payload antes da entrega.

Acabei não encontrando uma ferramenta que juntasse as três pontas (inspecionar, tunelar de forma estável, manipular antes de entregar), então construí. Hoje uso isso todos os dias pra testar integração de pagamento, e deixei disponível pra quem quiser: routely.me.

Carregando publicação patrocinada...