Skip to main content

O que são Webhooks?

Webhooks são notificações HTTP enviadas automaticamente pela EconPay quando eventos importantes acontecem, como:
  • Pagamento aprovado
  • Pagamento recusado
  • Reembolso processado
  • Boleto pago
Em vez de ficar consultando a API constantemente (polling), você recebe notificações instantâneas.

Como Funcionam

1

Configure a URL

No dashboard, configure a URL que receberá as notificações
2

Evento ocorre

Um pagamento é aprovado, por exemplo
3

EconPay envia POST

Enviamos um POST HTTP para sua URL com os dados do evento
4

Seu sistema processa

Você recebe, valida e processa a notificação
5

Retorna 200 OK

Seu servidor responde com status 200 para confirmar recebimento

Configuração

1. Criar Endpoint

Crie um endpoint em sua aplicação para receber webhooks:
Node.js/Express
app.post('/webhooks/econpay', express.json(), (req, res) => {
  const event = req.body;
  
  console.log('Webhook recebido:', event);
  
  // Processar evento
  switch (event.event) {
    case 'payment.approved':
      handlePaymentApproved(event);
      break;
    case 'payment.failed':
      handlePaymentFailed(event);
      break;
    case 'payment.refunded':
      handlePaymentRefunded(event);
      break;
    default:
      console.log('Evento desconhecido:', event.event);
  }
  
  // IMPORTANTE: Retornar 200 OK
  res.status(200).json({ received: true });
});
Python/Flask
@app.route('/webhooks/econpay', methods=['POST'])
def webhook():
    event = request.json
    
    print('Webhook recebido:', event)
    
    # Processar evento
    if event['event'] == 'payment.approved':
        handle_payment_approved(event)
    elif event['event'] == 'payment.failed':
        handle_payment_failed(event)
    elif event['event'] == 'payment.refunded':
        handle_payment_refunded(event)
    else:
        print('Evento desconhecido:', event['event'])
    
    # IMPORTANTE: Retornar 200 OK
    return jsonify({'received': True}), 200
PHP
<?php
// webhook.php

$payload = file_get_contents('php://input');
$event = json_decode($payload, true);

error_log('Webhook recebido: ' . print_r($event, true));

// Processar evento
switch ($event['event']) {
    case 'payment.approved':
        handlePaymentApproved($event);
        break;
    case 'payment.failed':
        handlePaymentFailed($event);
        break;
    case 'payment.refunded':
        handlePaymentRefunded($event);
        break;
    default:
        error_log('Evento desconhecido: ' . $event['event']);
}

// IMPORTANTE: Retornar 200 OK
http_response_code(200);
echo json_encode(['received' => true]);
?>

2. Expor URL Publicamente

Sua URL precisa ser acessível pela internet:
Use um domínio real:
https://seusite.com.br/webhooks/econpay

3. Cadastrar no Dashboard

  1. Acesse Dashboard EconPay
  2. Vá em Configurações > Webhooks
  3. Adicione sua URL
  4. Salve

Eventos Disponíveis

payment.approved

Enviado quando um pagamento é aprovado.
{
  "event": "payment.approved",
  "transaction_id": 123,
  "order_number": "ORD-20240122-123456",
  "status": "APPROVED",
  "amount": 10000,
  "payment_type": "pix",
  "customer": {
    "name": "João da Silva",
    "email": "[email protected]",
    "document": "12345678900"
  },
  "paid_at": "2024-01-22T10:35:00Z",
  "created_at": "2024-01-22T10:30:00Z"
}

payment.failed

Enviado quando um pagamento falha ou é recusado.
{
  "event": "payment.failed",
  "transaction_id": 124,
  "order_number": "ORD-20240122-123457",
  "status": "FAILED",
  "amount": 15000,
  "payment_type": "credit",
  "failure_reason": "Cartão recusado pela operadora",
  "customer": {
    "name": "Maria Santos",
    "email": "[email protected]",
    "document": "98765432100"
  },
  "failed_at": "2024-01-22T11:00:00Z",
  "created_at": "2024-01-22T10:59:00Z"
}

payment.refunded

Enviado quando um reembolso é processado.
{
  "event": "payment.refunded",
  "transaction_id": 123,
  "order_number": "ORD-20240122-123456",
  "status": "REFUNDED",
  "amount": 10000,
  "refund_amount": 10000,
  "payment_type": "pix",
  "refund_reason": "Solicitação do cliente",
  "customer": {
    "name": "João da Silva",
    "email": "[email protected]",
    "document": "12345678900"
  },
  "refunded_at": "2024-01-22T15:00:00Z",
  "created_at": "2024-01-22T10:30:00Z"
}

Processamento de Webhooks

Idempotência

Webhooks podem ser enviados mais de uma vez. Implemente idempotência:
const processedWebhooks = new Set();

app.post('/webhooks/econpay', async (req, res) => {
  const event = req.body;
  const webhookId = `${event.event}-${event.transaction_id}-${event.paid_at || event.failed_at || event.refunded_at}`;
  
  // Verificar se já processamos este webhook
  if (processedWebhooks.has(webhookId)) {
    console.log('Webhook já processado:', webhookId);
    return res.status(200).json({ received: true, duplicate: true });
  }
  
  // Processar webhook
  await processWebhook(event);
  
  // Marcar como processado
  processedWebhooks.add(webhookId);
  
  res.status(200).json({ received: true });
});

Processamento Assíncrono

Para webhooks complexos, processe de forma assíncrona:
app.post('/webhooks/econpay', async (req, res) => {
  const event = req.body;
  
  // Retornar 200 OK imediatamente
  res.status(200).json({ received: true });
  
  // Processar em background
  processWebhookAsync(event).catch(error => {
    console.error('Erro ao processar webhook:', error);
    // Implementar retry ou alertas
  });
});

async function processWebhookAsync(event) {
  // Lógica de processamento demorada
  await updateDatabase(event);
  await sendEmailToCustomer(event);
  await updateInventory(event);
}

Validação

Valide sempre os dados recebidos:
function validateWebhook(event) {
  // Verificar campos obrigatórios
  if (!event.event || !event.transaction_id) {
    throw new Error('Webhook inválido: campos obrigatórios faltando');
  }
  
  // Verificar tipo de evento
  const validEvents = ['payment.approved', 'payment.failed', 'payment.refunded'];
  if (!validEvents.includes(event.event)) {
    throw new Error(`Evento desconhecido: ${event.event}`);
  }
  
  // Verificar valores
  if (event.amount && event.amount < 0) {
    throw new Error('Valor inválido');
  }
  
  return true;
}

app.post('/webhooks/econpay', (req, res) => {
  try {
    const event = req.body;
    validateWebhook(event);
    processWebhook(event);
    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook inválido:', error);
    res.status(400).json({ error: error.message });
  }
});

Retry e Timeout

Comportamento da EconPay

  • Timeout: 30 segundos
  • Retries: 3 tentativas
  • Intervalo: 1 minuto entre tentativas
Se seu servidor não responder com 200 OK em 30 segundos, tentaremos novamente.

Boas Práticas

Retorne 200 OK em menos de 5 segundos. Processe tarefas pesadas de forma assíncrona.
Se falhar ao processar, implemente sua própria lógica de retry.
Registre todos os webhooks recebidos para debug e auditoria.
Configure alertas para webhooks que falharem repetidamente.

Testando Webhooks

Em Desenvolvimento

Use ngrok para receber webhooks localmente:
# Terminal 1: Iniciar sua aplicação
npm start

# Terminal 2: Expor com ngrok
ngrok http 3000

# Copiar URL gerada e cadastrar no dashboard
https://abc123.ngrok.io/webhooks/econpay

Ferramentas de Teste

Simular Webhook Manualmente

curl --request POST \
  --url http://localhost:3000/webhooks/econpay \
  --header 'Content-Type: application/json' \
  --data '{
    "event": "payment.approved",
    "transaction_id": 123,
    "order_number": "ORD-TEST-001",
    "status": "APPROVED",
    "amount": 10000,
    "payment_type": "pix",
    "paid_at": "2024-01-22T10:35:00Z"
  }'

Segurança

Importante: Sempre valide que o webhook veio realmente da EconPay.

Validar IP de Origem

const ECONPAY_IPS = ['IP_DA_ECONPAY_1', 'IP_DA_ECONPAY_2'];

app.post('/webhooks/econpay', (req, res) => {
  const clientIp = req.ip || req.connection.remoteAddress;
  
  if (!ECONPAY_IPS.includes(clientIp)) {
    console.warn('Webhook de IP não autorizado:', clientIp);
    return res.status(403).json({ error: 'Forbidden' });
  }
  
  // Processar webhook
  processWebhook(req.body);
  res.status(200).json({ received: true });
});

Verificar Dados

Sempre consulte a API para confirmar o status:
async function processPaymentApproved(event) {
  // Consultar API para confirmar
  const transaction = await fetch(
    `https://api.econpay.com.br/transactions/${event.transaction_id}`,
    {
      headers: { 'Authorization': `Bearer ${token}` }
    }
  ).then(r => r.json());
  
  // Verificar se realmente está aprovado
  if (transaction.status !== 'APPROVED') {
    console.warn('Status divergente no webhook');
    return;
  }
  
  // Processar pagamento
  await markOrderAsPaid(event.order_number);
}

Troubleshooting

Webhook não está chegando

1

Verifique a URL

Certifique-se de que a URL está correta e acessível
2

Teste manualmente

Use cURL para testar se seu endpoint responde
3

Verifique firewall

Certifique-se de que não há firewall bloqueando
4

Veja os logs

Consulte logs no dashboard para ver tentativas de envio

Webhook chegando mas não processando

  • Verifique logs da sua aplicação
  • Certifique-se de retornar 200 OK
  • Valide o formato do JSON recebido
  • Teste com dados mockados

Próximos Passos