Allya Payments
Comece aqui

Testar webhooks localmente

Como expor sua aplicação local em uma URL HTTPS pública para receber webhooks da Allya Payments.

A Allya envia webhooks outbound para URLs HTTPS públicas. Em desenvolvimento, http://localhost:3000/webhooks/allya, IPs privados, hosts .local e nomes internos não são aceitos. Para receber eventos na sua máquina, exponha a rota da sua aplicação com um túnel HTTPS e cadastre a URL pública no painel.

Este guia cobre o cenário do cliente da API: sua aplicação local recebendo webhooks da Allya hospedada. A chamada para criar pagamentos continua indo para https://payments-api.allyasolutions.com; o túnel serve apenas para a Allya alcançar seu endpoint local.

Fluxo

sua aplicação local
  <- túnel HTTPS público
  <- webhook outbound da Allya
  <- evento normalizado do gateway

Use este fluxo para validar handlers de payment.* e subscription.* antes de publicar o endpoint definitivo.

1. Suba seu endpoint local

Sua aplicação precisa ter uma rota HTTP que receba o webhook da Allya. Exemplo:

POST http://localhost:3000/webhooks/allya

O handler deve ler o body cru e validar X-Allya-Signature. Veja o exemplo completo em Webhooks.

2. Instale e autentique o ngrok

# macOS (Homebrew)
brew install ngrok

# Linux (apt)
curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
  | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null \
  && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" \
  | sudo tee /etc/apt/sources.list.d/ngrok.list \
  && sudo apt update && sudo apt install ngrok

Crie uma conta em ngrok.com, copie o authtoken do dashboard e configure:

ngrok config add-authtoken SEU_TOKEN_AQUI

3. Abra o túnel para sua aplicação

Aponte o túnel para a porta onde a sua aplicação está rodando:

ngrok http 3000

A saída mostra uma URL HTTPS pública:

Forwarding   https://abcd-1234.ngrok-free.app -> http://localhost:3000

Monte a URL final do webhook com o caminho da sua rota:

https://abcd-1234.ngrok-free.app/webhooks/allya

No plano gratuito do ngrok, essa URL muda a cada reinício.

4. Cadastre no painel da Allya

No painel:

  1. Entre no projeto.
  2. Selecione o ambiente Sandbox.
  3. Acesse Webhooks.
  4. Clique em Novo endpoint.
  5. Cadastre a URL pública do túnel, por exemplo:
https://abcd-1234.ngrok-free.app/webhooks/allya

Copie o secret exibido na criação e use-o no seu handler local para validar X-Allya-Signature.

5. Dispare um pagamento em sandbox

Crie o pagamento chamando a API hospedada da Allya, não a URL do túnel:

curl -X POST https://payments-api.allyasolutions.com/v1/payments \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1990,
    "currency": "BRL",
    "method": "pix",
    "externalId": "pedido_teste_local_1",
    "customer": {
      "name": "Cliente Teste",
      "email": "cliente@example.com",
      "document": "00000000000"
    }
  }'

Quando o gateway confirmar o pagamento em sandbox, a Allya atualiza o status e envia o webhook outbound para a URL do túnel. No painel, confira Webhooks → Histórico de entregas para ver HTTP status, tentativa e timestamp.

Cloudflare Tunnel

Cloudflare Tunnel é uma alternativa ao ngrok. O quick tunnel cria uma URL temporária:

# macOS
brew install cloudflared

# Linux: siga o instalador da distribuição em developers.cloudflare.com
cloudflared tunnel --url http://localhost:3000

A saída mostra uma URL pública:

https://random-words-1234.trycloudflare.com

Cadastre no painel da Allya usando o caminho do seu webhook:

https://random-words-1234.trycloudflare.com/webhooks/allya

Para URL fixa, use um túnel nomeado com domínio próprio:

cloudflared tunnel login
cloudflared tunnel create allya-webhooks-local
cloudflared tunnel route dns allya-webhooks-local webhooks.suaempresa.com
cloudflared tunnel run --url http://localhost:3000 allya-webhooks-local

Troubleshooting

O endpoint foi rejeitado como URL inválida

A Allya bloqueia URLs que não sejam HTTPS públicas:

  • http://...: não usa HTTPS.
  • https://localhost:3000 e IPs privados (10.x, 172.16-31.x, 192.168.x).
  • *.local, *.internal e link-local (169.254.x).
  • Hosts sem DNS público, como https://meu-servidor.

Use a URL HTTPS retornada pelo ngrok ou cloudflared. Se ainda falhar, teste a URL em outra rede com curl: se a conexão não abrir fora da sua máquina, a URL não está pública.

A entrega aparece como FAILED

  • A aplicação local não está rodando na porta apontada pelo túnel.
  • A rota cadastrada não existe ou não aceita POST.
  • O handler demorou mais de 8 segundos para responder.
  • A aplicação respondeu 4xx ou 5xx.
  • O endpoint foi cadastrado em outro ambiente. Uma API key sk_test_... gera evento no sandbox; confira se o endpoint também está no sandbox.

Depois de corrigir, use Webhooks → Histórico de entregas → Reenviar no painel.

Recebi o webhook, mas a assinatura não bate

As causas mais comuns são:

  • O handler usa req.json() antes de calcular o HMAC. Use body cru.
  • O HMAC foi calculado só com o body, sem o prefixo {timestamp}..
  • O secret usado no handler é de outro endpoint ou foi rotacionado.
  • Algum middleware reserializou o JSON antes da validação.

Compare com o exemplo em Webhooks.

A URL do túnel mudou

No ngrok gratuito e no quick tunnel do Cloudflare, a URL muda ao reiniciar. Atualize o endpoint em Webhooks ou use domínio reservado/túnel nomeado.

Inspecionar payload com mitmproxy

Se você usa cloudflared ou quer registrar/reproduzir payloads localmente, coloque o mitmproxy entre o túnel e a aplicação:

brew install mitmproxy
# Linux: apt install mitmproxy

mitmweb --listen-port 8080 --mode reverse:http://localhost:3000

Depois aponte o túnel para o mitmproxy:

ngrok http 8080
# ou
cloudflared tunnel --url http://localhost:8080

Cadastre a URL pública do túnel no painel da Allya. A requisição aparece na interface do mitmweb e segue para sua aplicação local.

Cuidados

  • Não cadastre túnel de desenvolvimento no ambiente de produção.
  • Apague ou desative o endpoint temporário quando terminar o teste.
  • Se um secret usado localmente vazar em logs, rotacione o endpoint no painel.
  • Não trate processing como sucesso: espere payment.paid ou rode POST /v1/payments/:id/sync.

Veja também

On this page