Manejar Cambios y Cancelaciones de Suscripciones

Lectura
25 min~5 min lectura

Concepto clave

Manejar cambios y cancelaciones de suscripciones es como gestionar una membresía de gimnasio. Cuando un cliente quiere cambiar de plan (por ejemplo, de básico a premium), necesitas procesar esa transición sin interrumpir su acceso. Si cancela, debes asegurar que los servicios se detengan correctamente al final del período pagado, similar a cómo un gimnasio permite usar las instalaciones hasta el último día del mes pagado.

En Stripe, esto se maneja a través de subscriptions y webhooks. Las suscripciones representan acuerdos de pago recurrentes, mientras que los webhooks son notificaciones que Stripe envía a tu servidor cuando ocurren eventos importantes, como una cancelación o cambio. Es crucial procesar estos eventos en tiempo real para mantener la sincronización entre Stripe y tu base de datos.

Cómo funciona en la práctica

Imagina que tienes una plataforma SaaS con planes básico ($10/mes) y premium ($30/mes). Un cliente en el plan básico decide actualizar a premium. El proceso paso a paso es:

  1. El cliente solicita el cambio en tu interfaz.
  2. Tu backend llama a la API de Stripe para actualizar la suscripción.
  3. Stripe calcula un prorrateo: cobra la diferencia proporcional hasta el próximo ciclo de facturación.
  4. Stripe envía un webhook customer.subscription.updated a tu servidor.
  5. Tu servidor procesa el webhook y actualiza el estado del usuario en tu base de datos.

Para cancelaciones, el flujo es similar, pero Stripe mantiene la suscripción activa hasta el final del período pagado, enviando un webhook customer.subscription.deleted cuando finaliza.

Codigo en accion

Actualizar una suscripción con la API de Stripe

Este ejemplo muestra cómo cambiar un cliente del plan básico al premium usando Node.js y la librería stripe.

const stripe = require('stripe')('sk_test_tu_clave_secreta');

async function updateSubscription(subscriptionId, newPriceId) {
  try {
    const subscription = await stripe.subscriptions.update(subscriptionId, {
      items: [{
        id: subscriptionId,
        price: newPriceId, // ID del precio premium
      }],
      proration_behavior: 'create_prorations', // Prorratea automáticamente
    });
    console.log('Suscripción actualizada:', subscription.id);
    return subscription;
  } catch (error) {
    console.error('Error actualizando suscripción:', error);
    throw error;
  }
}

// Uso: updateSubscription('sub_123', 'price_premium_456');

Procesar webhooks para cambios y cancelaciones

Este código maneja los webhooks de Stripe en un servidor Express para mantener tu base de datos sincronizada.

const express = require('express');
const stripe = require('stripe')('sk_test_tu_clave_secreta');
const app = express();
app.use(express.json());

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

  try {
    event = stripe.webhooks.constructEvent(req.body, sig, 'whsec_tu_webhook_secret');
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  switch (event.type) {
    case 'customer.subscription.updated':
      const subscriptionUpdated = event.data.object;
      // Actualiza tu base de datos con el nuevo plan
      await updateUserPlan(subscriptionUpdated.customer, subscriptionUpdated.items.data[0].price.id);
      console.log('Suscripción actualizada procesada');
      break;
    case 'customer.subscription.deleted':
      const subscriptionDeleted = event.data.object;
      // Marca al usuario como cancelado en tu base de datos
      await cancelUserSubscription(subscriptionDeleted.customer);
      console.log('Suscripción cancelada procesada');
      break;
    default:
      console.log(`Evento no manejado: ${event.type}`);
  }

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

app.listen(3000, () => console.log('Webhook server running on port 3000'));

Errores comunes

  • No validar webhooks: Si no verificas la firma de Stripe, podrías procesar eventos falsos. Siempre usa stripe.webhooks.constructEvent como en el ejemplo.
  • Ignorar el prorrateo: Al cambiar planes, Stripe prorratea por defecto. Si no lo manejas, los clientes pueden ver cargos inesperados. Explica esto claramente en tu UI.
  • No sincronizar la base de datos: Si solo actualizas en Stripe pero no en tu base de datos, los usuarios podrían perder acceso o mantenerlo indebidamente. Usa webhooks para mantener ambos sistemas alineados.
  • Cancelar inmediatamente en lugar de al final del período: Por defecto, Stripe cancela al final del ciclo. Si cancelas inmediatamente, podrías reembolsar un período no usado sin necesidad.
  • No manejar fallos en webhooks: Si tu servidor falla al procesar un webhook, Stripe reintentará, pero debes registrar errores y tener un plan de recuperación.

Checklist de dominio

  1. Puedo actualizar una suscripción usando la API de Stripe con prorrateo automático.
  2. He implementado un endpoint de webhooks que valida firmas y procesa eventos de actualización y cancelación.
  3. Sincronizo los cambios de suscripción entre Stripe y mi base de datos en tiempo real.
  4. Comprendo la diferencia entre cancelar inmediatamente y al final del período de facturación.
  5. Manejo errores en webhooks con logs y reintentos.
  6. Proporciono retroalimentación clara a los usuarios sobre cambios y cargos prorrateados.
  7. He probado flujos completos de cambio y cancelación en modo de prueba de Stripe.

Implementa un sistema de cambios y cancelaciones de suscripciones con Stripe

En este ejercicio, crearás un backend básico para manejar cambios y cancelaciones de suscripciones usando Stripe. Sigue estos pasos:

  1. Configura el entorno: Crea un proyecto Node.js e instala la librería stripe. Usa claves de prueba de Stripe.
  2. Implementa la actualización de suscripción: Escribe una función que tome un subscriptionId y un newPriceId, y llame a stripe.subscriptions.update para cambiar el plan. Incluye prorrateo.
  3. Configura webhooks: Crea un servidor Express con un endpoint POST /webhook que valide eventos de Stripe y maneje customer.subscription.updated y customer.subscription.deleted.
  4. Sincroniza con una base de datos simulada: Usa un objeto en memoria para representar usuarios. Al procesar webhooks, actualiza el plan del usuario o márcalo como cancelado.
  5. Prueba el flujo: Usa la CLI de Stripe o el dashboard para simular cambios y cancelaciones. Verifica que tu base de datos simulada se actualice correctamente.
Pistas
  • Usa stripe.webhooks.constructEvent para validar webhooks; necesitarás el secreto de tu webhook.
  • Para prorrateo, el parámetro proration_behavior en stripe.subscriptions.update puede ser 'create_prorations' (por defecto).
  • En pruebas, configura un túnel (por ejemplo, con ngrok) para que Stripe pueda enviar webhooks a tu servidor local.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.