Integración de webhooks

Configuración y gestión de los webhooks del proveedor de pagos para eventos de suscripción.

Nota: Este es contenido de ejemplo/marcador de posición con fines de demostración.

Los webhooks notifican a su aplicación cuando se producen eventos de facturación, lo que garantiza que su aplicación se mantenga sincronizada con su proveedor de pagos.

¿Por qué webhooks?

Los webhooks son esenciales para:

  • Actualizaciones en tiempo real - Notificación instantánea de los eventos de pago
  • Fiabilidad - Gestiona los eventos incluso si los usuarios cierran el navegador
  • Seguridad - Comunicación de servidor a servidor
  • Automatización - Actualizaciones automáticas del estado de la suscripción

Endpoint de webhooks

Su endpoint de webhooks recibe los eventos del proveedor de pagos:

// app/api/billing/webhook/route.ts
export async function POST(request: Request) {
  const body = await request.text();
  const signature = request.headers.get('stripe-signature');

  // Verificar la firma del webhook
  const event = stripe.webhooks.constructEvent(
    body,
    signature,
    process.env.STRIPE_WEBHOOK_SECRET
  );

  // Gestionar el evento
  await handleBillingEvent(event);

  return new Response('OK', { status: 200 });
}

Eventos habituales

Suscripción creada

case 'customer.subscription.created':
  await prisma.subscription.create({
    data: {
      id: event.data.object.id,
      accountId: event.data.object.metadata.accountId,
      status: 'active',
      planId: event.data.object.items.data[0].price.id,
      currentPeriodEnd: new Date(event.data.object.current_period_end * 1000),
    },
  });
  break;

Suscripción actualizada

case 'customer.subscription.updated':
  await prisma.subscription.update({
    where: { id: event.data.object.id },
    data: {
      status: event.data.object.status,
      planId: event.data.object.items.data[0].price.id,
      currentPeriodEnd: new Date(event.data.object.current_period_end * 1000),
    },
  });
  break;

Suscripción eliminada

case 'customer.subscription.deleted':
  await prisma.subscription.update({
    where: { id: event.data.object.id },
    data: {
      status: 'canceled',
      canceledAt: new Date(),
    },
  });
  break;

Pago fallido

case 'invoice.payment_failed':
  const subscription = await prisma.subscription.findUnique({
    where: { id: event.data.object.subscription },
  });

  // Enviar notificación de pago fallido
  await sendPaymentFailureEmail(subscription.accountId);
  break;

Configuración de webhooks

Stripe

  1. Desarrollo local (con la CLI de Stripe):
stripe listen --forward-to localhost:3000/api/billing/webhook
  1. Producción:
  • Vaya a Stripe Dashboard → Developers → Webhooks
  • Añada el endpoint: https://yourdomain.com/api/billing/webhook
  • Seleccione los eventos que desea escuchar
  • Copie el secreto de firma del webhook en su .env

Paddle

  1. Configure la URL del webhook en el panel de Paddle
  2. Añada el secreto del webhook a las variables de entorno
  3. Verifique la firma del webhook:
const signature = request.headers.get('paddle-signature');
const verified = paddle.webhooks.verify(body, signature);

if (!verified) {
  return new Response('Invalid signature', { status: 401 });
}

Buenas prácticas de seguridad

  1. Verifique siempre las firmas - Evita solicitudes no autorizadas
  2. Use HTTPS - Cifra los datos del webhook en tránsito
  3. Valide los datos del evento - Compruebe los campos obligatorios
  4. Procese de forma idempotente - Gestione los eventos duplicados de forma segura
  5. Devuelva 200 rápidamente - Confirme la recepción y procese de forma asíncrona

Gestión de errores

async function handleBillingEvent(event: Event) {
  try {
    await processEvent(event);
  } catch (error) {
    // Registrar el error para la depuración
    console.error('Webhook error:', error);

    // Almacenar el evento fallido para reintentarlo
    await prisma.failedWebhook.create({
      data: {
        eventId: event.id,
        type: event.type,
        payload: event,
        error: error.message,
      },
    });

    // Lanzar el error para que el proveedor reintente
    throw error;
  }
}

Pruebas de webhooks

Uso de las herramientas CLI del proveedor

# Stripe
stripe trigger customer.subscription.created

# Probar escenarios específicos
stripe trigger payment_intent.payment_failed

Pruebas manuales

curl -X POST https://your-app.com/api/billing/webhook \
  -H "Content-Type: application/json" \
  -H "stripe-signature: test_signature" \
  -d @test-event.json

Monitorización

Haga un seguimiento de la entrega de webhooks:

  • Tiempos de respuesta
  • Tasas de éxito/fallo
  • Duración del procesamiento de eventos
  • Eventos fallidos que requieren intervención manual

La mayoría de los proveedores ofrecen paneles de monitorización de webhooks que muestran los intentos de entrega y los fallos.