Concepto clave
Implementar un sistema completo de suscripciones con Stripe es como construir una fábrica automatizada de ingresos recurrentes. En lugar de cobrar manualmente cada mes, configuras un motor de facturación que gestiona automáticamente pagos, renovaciones, cambios de plan y cancelaciones. El corazón de este sistema son los webhooks, que actúan como mensajeros en tiempo real que notifican a tu backend sobre eventos importantes (como un pago exitoso o una suscripción cancelada).
Imagina que gestionas un gimnasio digital: los clientes se suscriben a diferentes planes (básico, premium), pagan mensualmente, y a veces cambian de plan o dan de baja su membresía. Stripe maneja la parte financiera y de cumplimiento normativo, mientras tu aplicación se enfoca en entregar el servicio y sincronizar el estado de cada usuario. La clave está en mantener una fuente única de verdad entre Stripe y tu base de datos, evitando desincronizaciones que podrían causar que usuarios accedan a contenido sin pagar o viceversa.
Cómo funciona en la práctica
Vamos a construir el flujo completo desde cero. Primero, configuras productos y precios en el dashboard de Stripe o mediante API. Luego, en tu aplicación:
- El usuario selecciona un plan y proporciona información de pago en un formulario seguro.
- Tu backend crea un Customer en Stripe (si no existe) y una Subscription asociada a un precio recurrente.
- Stripe procesa el pago inicial y genera la primera factura.
- Configuras endpoints de webhook para escuchar eventos como
invoice.paidocustomer.subscription.updated. - Cuando llega un webhook, tu backend actualiza el estado del usuario en tu base de datos (por ejemplo, activando su acceso premium).
Un ejemplo práctico: para un servicio de streaming, cuando un usuario actualiza de plan básico a familiar, Stripe maneja el prorrateo de la factura y envía un webhook customer.subscription.updated. Tu backend recibe este evento, actualiza los límites de pantallas simultáneas en tu base de datos, y notifica al usuario.
Código en acción
Aquí tienes un ejemplo funcional en Node.js para crear una suscripción y manejar webhooks. Primero, instala Stripe: npm install stripe.
// Configuración inicial
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const express = require('express');
const app = express();
app.use(express.json());
// Crear un cliente y suscripción
app.post('/create-subscription', async (req, res) => {
try {
const { email, paymentMethodId, priceId } = req.body;
// Paso 1: Crear o recuperar cliente
const customer = await stripe.customers.create({
email: email,
payment_method: paymentMethodId,
invoice_settings: {
default_payment_method: paymentMethodId
}
});
// Paso 2: Crear suscripción
const subscription = await stripe.subscriptions.create({
customer: customer.id,
items: [{ price: priceId }],
expand: ['latest_invoice.payment_intent']
});
res.json({ subscriptionId: subscription.id, status: subscription.status });
} catch (error) {
res.status(400).json({ error: error.message });
}
});Ahora, el endpoint para webhooks (usa el middleware de Stripe para verificar la firma):
// Manejo de webhooks
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
} catch (err) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
// Manejar eventos específicos
switch (event.type) {
case 'invoice.paid':
const invoice = event.data.object;
// Actualizar usuario en tu BD: marcar como activo
console.log(`Factura ${invoice.id} pagada para cliente ${invoice.customer}`);
break;
case 'customer.subscription.updated':
const subscription = event.data.object;
// Sincronizar cambios de plan en tu BD
console.log(`Suscripción ${subscription.id} actualizada a estado ${subscription.status}`);
break;
case 'invoice.payment_failed':
// Notificar al usuario o desactivar acceso
console.log('Pago fallido, manejar retry logic');
break;
default:
console.log(`Evento no manejado: ${event.type}`);
}
res.json({received: true});
});Errores comunes
- No verificar webhooks: Si no validas la firma de Stripe, podrías aceptar eventos falsificados. Siempre usa
stripe.webhooks.constructEventcomo en el código anterior. - Desincronización de estados: Confiar solo en el estado de Stripe sin reflejarlo en tu BD puede causar que usuarios tengan acceso incorrecto. Sincroniza tras cada webhook relevante.
- Manejo inadecuado de fallos de pago: Ignorar eventos como
invoice.payment_failedlleva a pérdida de ingresos. Configura reintentos automáticos y notificaciones. - Exponer claves secretas: Nunca hardcodees
STRIPE_SECRET_KEYen el frontend. Úsala solo en el backend con variables de entorno. - Olvidar el prorrateo: Al cambiar planes, Stripe ajusta facturas automáticamente, pero debes reflejar estos cambios en tu lógica de negocio (ej., actualizar límites de uso).
Checklist de dominio
- ¿Puedes crear un producto y precio recurrente mediante API de Stripe?
- ¿Implementaste un flujo completo de suscripción (cliente + pago + factura inicial)?
- ¿Configuraste y probaste al menos 3 webhooks críticos (pago exitoso, fallido, actualización)?
- ¿Sincronizas el estado de suscripciones entre Stripe y tu base de datos tras cada evento?
- ¿Manejas correctamente errores como tarjetas declinadas o cancelaciones?
- ¿Protegiste tus endpoints con verificación de firma de webhooks?
- ¿Documentaste el flujo para otros desarrolladores o stakeholders?
Implementa un sistema de suscripciones para una plataforma de cursos online
Desarrolla un backend que permita a usuarios suscribirse a planes mensuales (básico o premium), maneje renovaciones automáticas y sincronice el acceso a cursos. Sigue estos pasos:
- Configura dos productos en Stripe: Curso Básico (precio mensual de $10) y Curso Premium (precio mensual de $25). Usa la API o el dashboard.
- Crea un endpoint
/subscribeque reciba email, paymentMethodId y planId. Debe crear un cliente en Stripe (si es nuevo) y una suscripción al plan correspondiente. - Implementa un endpoint
/webhookque escuche eventos de Stripe. Cuando llegueinvoice.paid, actualiza un camposubscriptionStatusen tu base de datos (simula con un objeto en memoria). - Añade lógica para
customer.subscription.updated: si el plan cambia, registra el nuevo plan en tu base de datos. - Prueba el flujo completo: suscripción inicial, pago exitoso, cambio de plan y cancelación. Usa claves de prueba de Stripe y tarjetas como
4242 4242 4242 4242.
Entrega el código funcional y una explicación de cómo probarlo localmente.
Pistas- Usa la biblioteca oficial de Stripe para tu lenguaje (ej., stripe-node) para simplificar llamadas API.
- Simula una base de datos con un objeto JavaScript como
let users = {};para almacenar estados. - Prueba webhooks localmente con Stripe CLI: ejecuta
stripe listen --forward-to localhost:3000/webhook.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.