Skip to main content

🔔 Visão Geral

Webhooks são notificações HTTP enviadas pela UPay Gateway API para sua aplicação quando eventos importantes ocorrem. Isso permite que você reaja em tempo real a mudanças de status, pagamentos confirmados e outros eventos sem precisar fazer polling constante.

✨ Funcionalidades

  • Eventos em Tempo Real: Receba notificações instantâneas
  • Múltiplos Eventos: Configure webhooks para diferentes tipos de eventos
  • Retry Automático: Tentativas automáticas em caso de falha
  • Segurança: Assinatura HMAC para validar requisições
  • Histórico: Visualize todos os eventos enviados
  • Múltiplas URLs: Configure diferentes endpoints para diferentes eventos

🚀 Criando uma Assinatura de Webhook

Requisição Básica

curl -X POST "https://https://upay-sistema-api.onrender.com//api/webhooks/subscriptions" \
  -H "Authorization: Bearer SUA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://meusite.com.br/webhooks/upay",
    "events": ["payment.completed", "payment.failed"],
    "description": "Webhook para notificações de pagamento"
  }'

Resposta

{
  "success": true,
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "url": "https://meusite.com.br/webhooks/upay",
    "events": ["payment.completed", "payment.failed"],
    "description": "Webhook para notificações de pagamento",
    "status": "ACTIVE",
    "secret": "whsec_abc123...",
    "createdAt": "2025-12-30T00:00:00.000Z"
  }
}
Guarde o secret em local seguro. Ele será usado para validar as requisições do webhook.

📋 Eventos Disponíveis

Eventos de Pagamento

  • payment.completed - Pagamento confirmado
  • payment.failed - Pagamento falhou
  • payment.pending - Pagamento pendente
  • payment.refunded - Pagamento reembolsado
  • payment.cancelled - Pagamento cancelado
  • payment_link.created - Link de pagamento criado
  • payment_link.updated - Link de pagamento atualizado
  • payment_link.deleted - Link de pagamento deletado

Eventos de Produto

  • product.created - Produto criado
  • product.updated - Produto atualizado
  • product.deleted - Produto deletado

Eventos de Cupom

  • coupon.created - Cupom criado
  • coupon.used - Cupom utilizado
  • coupon.expired - Cupom expirado

📖 Exemplo Completo

const response = await fetch('https://https://upay-sistema-api.onrender.com//api/webhooks/subscriptions', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    url: 'https://meusite.com.br/webhooks/upay',
    events: [
      'payment.completed',
      'payment.failed',
      'payment.refunded'
    ],
    description: 'Webhook para processar notificações de pagamento'
  })
});

const { data } = await response.json();
console.log('Webhook Secret:', data.secret);

🔍 Listando Assinaturas

Listar Todas as Assinaturas

curl -X GET "https://https://upay-sistema-api.onrender.com//api/webhooks/subscriptions" \
  -H "Authorization: Bearer SUA_API_KEY"

Listar Eventos Enviados

curl -X GET "https://https://upay-sistema-api.onrender.com//api/webhooks/events?page=1&limit=20" \
  -H "Authorization: Bearer SUA_API_KEY"

✏️ Atualizando uma Assinatura

curl -X PUT "https://https://upay-sistema-api.onrender.com//api/webhooks/subscriptions/{id}" \
  -H "Authorization: Bearer SUA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://meusite.com.br/webhooks/upay-v2",
    "events": ["payment.completed", "payment.failed", "payment.refunded"],
    "status": "ACTIVE"
  }'

🗑️ Deletando uma Assinatura

curl -X DELETE "https://https://upay-sistema-api.onrender.com//api/webhooks/subscriptions/{id}" \
  -H "Authorization: Bearer SUA_API_KEY"

🔐 Validando Webhooks

Assinatura HMAC

Todas as requisições de webhook incluem um header X-Upay-Signature com uma assinatura HMAC-SHA256. Use o secret da assinatura para validar que a requisição veio da UPay.

Exemplo de Validação (Node.js)

const crypto = require('crypto');

function validateWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// No seu endpoint de webhook
app.post('/webhooks/upay', express.json(), (req, res) => {
  const signature = req.headers['x-upay-signature'];
  const secret = process.env.UPAY_WEBHOOK_SECRET;
  
  if (!validateWebhookSignature(req.body, signature, secret)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }
  
  // Processar webhook
  const event = req.body;
  console.log('Evento recebido:', event.type);
  
  res.status(200).json({ received: true });
});

Exemplo de Validação (Python)

import hmac
import hashlib
import json

def validate_webhook_signature(payload, signature, secret):
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        json.dumps(payload).encode('utf-8'),
        hashlib.sha256
    ).hexdigest()
    
    return hmac.compare_digest(signature, expected_signature)

# No seu endpoint de webhook
@app.route('/webhooks/upay', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Upay-Signature')
    secret = os.getenv('UPAY_WEBHOOK_SECRET')
    
    if not validate_webhook_signature(request.json, signature, secret):
        return jsonify({'error': 'Invalid signature'}), 401
    
    # Processar webhook
    event = request.json
    print(f"Evento recebido: {event['type']}")
    
    return jsonify({'received': True}), 200

📨 Estrutura do Payload

Exemplo: payment.completed

{
  "id": "evt_abc123",
  "type": "payment.completed",
  "createdAt": "2025-12-30T00:00:00.000Z",
  "data": {
    "transactionId": "550e8400-e29b-41d4-a716-446655440000",
    "paymentLinkId": "550e8400-e29b-41d4-a716-446655440001",
    "amount": 199.00,
    "amountCents": 19900,
    "currency": "BRL",
    "paymentMethod": "pix",
    "status": "COMPLETED",
    "client": {
      "id": "550e8400-e29b-41d4-a716-446655440002",
      "name": "João Silva",
      "email": "[email protected]"
    }
  }
}

Exemplo: payment.failed

{
  "id": "evt_def456",
  "type": "payment.failed",
  "createdAt": "2025-12-30T00:00:00.000Z",
  "data": {
    "transactionId": "550e8400-e29b-41d4-a716-446655440000",
    "paymentLinkId": "550e8400-e29b-41d4-a716-446655440001",
    "amount": 199.00,
    "amountCents": 19900,
    "currency": "BRL",
    "paymentMethod": "credit_card",
    "status": "FAILED",
    "error": "Cartão recusado",
    "errorCode": "CARD_DECLINED"
  }
}

🔄 Retry e Confiabilidade

A UPay tenta entregar webhooks automaticamente:
  1. Primeira tentativa: Imediata
  2. Retry 1: Após 1 minuto
  3. Retry 2: Após 5 minutos
  4. Retry 3: Após 15 minutos
  5. Retry 4: Após 1 hora
Seu endpoint deve responder com status HTTP 200-299 para confirmar o recebimento. Respostas com erro ou timeout resultarão em retry.

✅ Boas Práticas

  1. Responda rapidamente: Processe webhooks de forma assíncrona quando possível
  2. Valide a assinatura: Sempre valide o X-Upay-Signature
  3. Idempotência: Processe eventos de forma idempotente usando o id do evento
  4. Logs: Mantenha logs de todos os webhooks recebidos
  5. Testes: Use webhooks de teste para validar sua implementação

🧪 Testando Webhooks

Usando ngrok (Desenvolvimento Local)

# Instale o ngrok
npm install -g ngrok

# Exponha sua aplicação local
ngrok http 3000

# Use a URL do ngrok na assinatura do webhook
# Ex: https://abc123.ngrok.io/webhooks/upay

Endpoint de Teste

app.post('/webhooks/upay', express.json(), (req, res) => {
  console.log('Webhook recebido:', JSON.stringify(req.body, null, 2));
  res.status(200).json({ received: true });
});

📚 Próximos Passos