🚧 La documentacion de Bloque está en desarrollo

Configuración de Webhooks

Los webhooks te permiten recibir notificaciones en tiempo real sobre eventos de pago desde Bloque.

¿Qué son los Webhooks?

Los webhooks son callbacks HTTP que notifican a tu servidor cuando ocurren eventos específicos, como pagos exitosos, transacciones fallidas o actualizaciones de estado.

Configurando Webhooks

1. Crear Endpoint de Webhook

Crea un endpoint en tu backend para recibir eventos de webhook:

import { Bloque } from '@bloque/payments';
import express from 'express';

const app = express();

// Inicializar SDK con secreto de webhook
const bloque = new Bloque({
  accessToken: process.env.BLOQUE_ACCESS_TOKEN!,
  mode: 'production',
  webhookSecret: process.env.BLOQUE_WEBHOOK_SECRET,
});

// Endpoint de webhook
app.post('/webhooks/bloque', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-bloque-signature'] as string;

  try {
    // Verificar firma del webhook
    const isValid = bloque.webhooks.verify(req.body, signature);

    if (!isValid) {
      return res.status(400).send('Firma inválida');
    }

    // Parsear evento
    const event = JSON.parse(req.body.toString());

    // Manejar evento
    handleWebhookEvent(event);

    res.json({ received: true });
  } catch (error) {
    console.error('Error de webhook:', error);
    res.status(400).send('Error de webhook');
  }
});

app.listen(3000);

2. Verificar Firmas de Webhook

Siempre verifica las firmas de webhook para asegurar que provienen de Bloque:

const isValid = bloque.webhooks.verify(
  requestBody,
  signatureHeader,
  { secret: process.env.BLOQUE_WEBHOOK_SECRET }
);

if (!isValid) {
  // Rechazar webhook
  return res.status(400).send('Firma inválida');
}

3. Manejar Eventos de Webhook

Procesa diferentes tipos de eventos:

function handleWebhookEvent(event) {
  switch (event.type) {
    case 'payment.succeeded':
      handlePaymentSucceeded(event.data);
      break;

    case 'payment.failed':
      handlePaymentFailed(event.data);
      break;

    case 'checkout.completed':
      handleCheckoutCompleted(event.data);
      break;

    case 'checkout.expired':
      handleCheckoutExpired(event.data);
      break;

    default:
      console.log('Tipo de evento no manejado:', event.type);
  }
}

Eventos de Webhook

payment.succeeded

Se dispara cuando un pago se procesa exitosamente.

{
  type: 'payment.succeeded',
  data: {
    id: 'pay_123',
    status: 'succeeded',
    amount: 2999,
    currency: 'USD',
    payment_method: 'card',
    created_at: '2024-01-15T10:30:00Z'
  }
}

payment.failed

Se dispara cuando un pago falla.

{
  type: 'payment.failed',
  data: {
    id: 'pay_123',
    status: 'failed',
    error: 'insufficient_funds',
    error_message: 'Fondos insuficientes'
  }
}

checkout.completed

Se dispara cuando una sesión de checkout se completa.

{
  type: 'checkout.completed',
  data: {
    id: 'checkout_123',
    status: 'completed',
    payment_id: 'pay_123'
  }
}

checkout.expired

Se dispara cuando una sesión de checkout expira.

{
  type: 'checkout.expired',
  data: {
    id: 'checkout_123',
    status: 'expired'
  }
}

Ejemplo Completo

import { Bloque } from '@bloque/payments';
import express from 'express';

const app = express();

const bloque = new Bloque({
  accessToken: process.env.BLOQUE_ACCESS_TOKEN!,
  mode: 'production',
  webhookSecret: process.env.BLOQUE_WEBHOOK_SECRET,
});

app.post('/webhooks/bloque', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.headers['x-bloque-signature'] as string;

  try {
    // Verificar firma
    const isValid = bloque.webhooks.verify(req.body, signature);

    if (!isValid) {
      return res.status(400).send('Firma inválida');
    }

    // Parsear evento
    const event = JSON.parse(req.body.toString());
    console.log('Webhook recibido:', event.type);

    // Manejar eventos
    switch (event.type) {
      case 'payment.succeeded':
        // Actualizar estado de orden
        await updateOrderStatus(event.data.id, 'paid');
        // Enviar email de confirmación
        await sendConfirmationEmail(event.data);
        break;

      case 'payment.failed':
        // Registrar fallo
        console.error('Pago fallido:', event.data);
        // Notificar al cliente
        await sendFailureNotification(event.data);
        break;

      case 'checkout.completed':
        // Marcar checkout como completo
        await markCheckoutComplete(event.data.id);
        break;
    }

    res.json({ received: true });
  } catch (error) {
    console.error('Error de webhook:', error);
    res.status(400).send('Error de webhook');
  }
});

app.listen(3000);

Mejores Prácticas

1. Responder Rápidamente

Siempre responde con 200 OK rápidamente. Procesa eventos de forma asíncrona:

app.post('/webhooks/bloque', async (req, res) => {
  const signature = req.headers['x-bloque-signature'] as string;

  // Verificar
  const isValid = bloque.webhooks.verify(req.body, signature);
  if (!isValid) {
    return res.status(400).send('Firma inválida');
  }

  // Responder inmediatamente
  res.json({ received: true });

  // Procesar de forma asíncrona
  const event = JSON.parse(req.body.toString());
  processWebhookAsync(event).catch(console.error);
});

2. Manejar Idempotencia

Los webhooks pueden enviarse múltiples veces. Almacena IDs de eventos procesados:

const processedEvents = new Set();

function handleWebhookEvent(event) {
  if (processedEvents.has(event.id)) {
    console.log('Evento ya procesado:', event.id);
    return;
  }

  // Procesar evento
  processEvent(event);

  // Marcar como procesado
  processedEvents.add(event.id);
}

3. Lógica de Reintento

Bloque reintentará webhooks si tu endpoint falla. Asegura que tu endpoint sea idempotente.

4. Asegurar tu Endpoint

  • Siempre verifica firmas de webhook
  • Usa HTTPS en producción
  • Mantén los secretos de webhook seguros
  • Limita la tasa de requests a endpoints de webhook

Probando Webhooks

Prueba webhooks localmente usando herramientas como ngrok:

# Iniciar ngrok
ngrok http 3000

# Usa la URL de ngrok en el dashboard de Bloque
https://tu-url-ngrok.ngrok.io/webhooks/bloque

Próximos Pasos