Quiz: Webhooks y Eventos en Tiempo Real

Quiz
15 min~5 min lectura

Quiz Interactivo

Pon a prueba tus conocimientos

Concepto clave

Los webhooks son notificaciones HTTP que Stripe envía a tu servidor cuando ocurren eventos importantes en tu cuenta. Imagina que contratas un servicio de vigilancia para tu casa: en lugar de revisar constantemente las cámaras (polling), el sistema te llama automáticamente cuando detecta movimiento (evento). En Stripe, eventos como payment_intent.succeeded o invoice.payment_failed activan estos webhooks.

Los eventos en tiempo real permiten que tu aplicación reaccione inmediatamente a cambios en el estado de pagos, suscripciones o facturas. Esto es crucial para mantener la sincronización entre Stripe y tu base de datos, enviar confirmaciones automáticas o gestionar fallos en pagos recurrentes. Sin webhooks, tendrías que consultar constantemente la API de Stripe, lo que es ineficiente y puede causar retrasos.

Cómo funciona en la práctica

El flujo típico de un webhook de Stripe sigue estos pasos:

  1. Configuras un endpoint HTTPS en tu servidor (ej: https://tudominio.com/stripe-webhook)
  2. Registras este endpoint en el Dashboard de Stripe o vía API
  3. Cuando ocurre un evento relevante, Stripe envía una petición POST a tu endpoint
  4. Tu servidor verifica la firma del webhook para asegurar autenticidad
  5. Procesas el evento según su tipo y actualizas tu sistema
  6. Respondes con HTTP 200 para confirmar recepción

Por ejemplo, cuando un cliente cancela su suscripción, Stripe envía un evento customer.subscription.deleted. Tu servidor recibe este evento, actualiza el estado del usuario en tu base de datos a "inactivo" y posiblemente envía un email de confirmación.

Código en acción

Configuración básica de un endpoint de webhook en Node.js:

const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const app = express();

// Middleware para parsear JSON
app.use(express.json());

app.post('/stripe-webhook', async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

  try {
    // Verificar la firma del webhook
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    console.error(`⚠️  Error de verificación: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Manejar diferentes tipos de eventos
  switch (event.type) {
    case 'payment_intent.succeeded':
      const paymentIntent = event.data.object;
      console.log(`Pago exitoso: ${paymentIntent.id}`);
      // Actualizar base de datos aquí
      break;
    case 'invoice.payment_failed':
      const invoice = event.data.object;
      console.log(`Pago fallido para factura: ${invoice.id}`);
      // Enviar notificación al cliente
      break;
    default:
      console.log(`Evento no manejado: ${event.type}`);
  }

  res.json({received: true});
});

app.listen(3000, () => {
  console.log('Servidor escuchando en puerto 3000');
});

Mejora con manejo de reintentos y logging:

// ANTES: Sin manejo de errores robusto
// Solo console.log básico

// DESPUÉS: Con manejo profesional
try {
  switch (event.type) {
    case 'customer.subscription.created':
      await handleSubscriptionCreated(event.data.object);
      break;
    case 'charge.refunded':
      await handleRefund(event.data.object);
      break;
  }
  
  // Registrar éxito para monitoreo
  console.log(`✅ Evento procesado: ${event.type} (ID: ${event.id})`);
  
} catch (error) {
  // Log detallado para debugging
  console.error(`❌ Error procesando ${event.type}:`, {
    error: error.message,
    eventId: event.id,
    timestamp: new Date().toISOString()
  });
  
  // IMPORTANTE: Siempre responder 200 para evitar reintentos infinitos
  // Stripe reintentará automáticamente en caso de error
}

Errores comunes

  • No verificar la firma del webhook: Cualquiera podría enviar peticiones falsas a tu endpoint. Siempre usa stripe.webhooks.constructEvent() con tu webhook secret.
  • No manejar eventos duplicados: Stripe puede enviar el mismo evento múltiples veces. Implementa idempotencia almacenando event.id procesados.
  • No responder rápidamente: Tu endpoint debe responder en menos de 10 segundos. Stripe reintentará si no responde a tiempo.
  • Procesar eventos en orden incorrecto: Algunos eventos deben procesarse en secuencia (ej: invoice.created antes de invoice.paid). Implementa colas si es necesario.
  • No probar webhooks localmente: Usa la CLI de Stripe (stripe listen --forward-to localhost:3000) para probar en desarrollo.

Checklist de dominio

  1. Configuré un endpoint HTTPS seguro para recibir webhooks
  2. Implementé verificación de firmas con stripe.webhooks.constructEvent()
  3. Manejo correctamente al menos 5 tipos de eventos diferentes
  4. Mi endpoint responde en menos de 5 segundos siempre
  5. Implementé logging detallado para todos los eventos procesados
  6. Probé webhooks en ambiente local usando stripe CLI
  7. Configuré reintentos automáticos para eventos fallidos

Implementa un sistema de notificaciones por email basado en webhooks

En este ejercicio práctico, crearás un sistema que envía emails automáticos basado en eventos de Stripe. Esto simula un escenario real donde necesitas notificar a clientes sobre cambios en sus suscripciones.

  1. Configura tu entorno:
    • Crea un proyecto Node.js con Express
    • Instala las dependencias: stripe, nodemailer, dotenv
    • Configura variables de entorno para STRIPE_SECRET_KEY y STRIPE_WEBHOOK_SECRET
  2. Crea el endpoint de webhook:
    • Implementa un endpoint POST en /api/stripe-webhook
    • Agrega verificación de firma usando stripe.webhooks.constructEvent()
    • Responde con HTTP 200 inmediatamente después de recibir el evento
  3. Implementa el manejo de eventos:
    • Procesa estos 3 eventos: invoice.payment_succeeded, invoice.payment_failed, customer.subscription.deleted
    • Para cada evento, llama a una función sendNotificationEmail() con los datos relevantes
    • Usa nodemailer para enviar emails (puedes usar un servicio como Mailtrap para testing)
  4. Agrega idempotencia:
    • Crea una tabla en tu base de datos o usa un array en memoria para almacenar event.id procesados
    • Antes de procesar cualquier evento, verifica que no haya sido procesado antes
    • Si ya fue procesado, responde 200 pero no ejecutes acciones duplicadas
  5. Prueba tu implementación:
    • Usa stripe CLI para enviar eventos de prueba a tu endpoint local
    • Verifica que los emails se envíen correctamente para cada tipo de evento
    • Prueba enviando el mismo evento dos veces y verifica que no se dupliquen emails
Pistas
  • Usa el método stripe.webhooks.generateTestHeaderString() para crear firmas de prueba en desarrollo
  • Implementa un sistema de colas simple con arrays si necesitas procesar eventos en orden específico
  • Para testing, configura nodemailer con Mailtrap (es gratuito y no envía emails reales)

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.