Saltar al contenido principal

¿Qué es una actualización o downgrade de suscripción?

Cambiar de plan te permite mover a un cliente entre niveles o cantidades de suscripción. Úsalo para:
  • Alinear precios con uso o características
  • Pasar de mensual a anual (o viceversa)
  • Ajustar la cantidad para productos basados en asientos
Los cambios de plan pueden desencadenar un cargo inmediato dependiendo del modo de prorrata que elijas.

Cuándo usar cambios de plan

  • Actualiza cuando un cliente necesita más características, uso o asientos
  • Downgrade cuando el uso disminuye
  • Migra usuarios a un nuevo producto o precio sin cancelar su suscripción

Requisitos previos

Antes de implementar cambios en el plan de suscripción, asegúrate de tener:
  • Una cuenta de comerciante de Dodo Payments con productos de suscripción activos
  • Credenciales de API (clave de API y clave secreta de webhook) desde el panel de control
  • Una suscripción activa existente para modificar
  • Un endpoint de webhook configurado para manejar eventos de suscripción
Para instrucciones de configuración detalladas, consulta nuestra Guía de Integración.

Guía de Implementación Paso a Paso

Sigue esta guía completa para implementar cambios en el plan de suscripción en tu aplicación:
1

Entender los Requisitos de Cambio de Plan

Antes de implementar, determina:
  • Qué productos de suscripción se pueden cambiar a cuáles otros
  • Qué modo de prorrata se ajusta a tu modelo de negocio
  • Cómo manejar los cambios de plan fallidos de manera elegante
  • Qué eventos de webhook rastrear para la gestión de estado
Prueba los cambios de plan a fondo en modo de prueba antes de implementarlos en producción.
2

Elige tu Estrategia de Prorrata

Selecciona el enfoque de facturación que se alinee con las necesidades de tu negocio:
Mejor para: aplicaciones SaaS que desean cobrar de manera justa por el tiempo no utilizado
  • Calcula el monto prorrateado exacto basado en el tiempo restante del ciclo
  • Cobra un monto prorrateado basado en el tiempo no utilizado restante en el ciclo
  • Proporciona facturación transparente a los clientes
3

Implementar la API de Cambio de Plan

Usa la API de Cambio de Plan para modificar los detalles de la suscripción:
subscription_id
string
required
El ID de la suscripción activa a modificar.
product_id
string
required
El nuevo ID de producto al que cambiar la suscripción.
quantity
integer
default:"1"
Número de unidades para el nuevo plan (para productos basados en asientos).
proration_billing_mode
string
required
Cómo manejar la facturación inmediata: prorated_immediately, full_immediately, o difference_immediately.
addons
array
Addons opcionales para el nuevo plan. Dejar esto vacío elimina cualquier addon existente.
4

Manejar Eventos de Webhook

Configura el manejo de webhooks para rastrear los resultados del cambio de plan:
  • subscription.active: Cambio de plan exitoso, suscripción actualizada
  • subscription.plan_changed: Plan de suscripción cambiado (actualización/downgrade/actualización de addon)
  • subscription.on_hold: El cargo por cambio de plan falló, suscripción pausada
  • payment.succeeded: Cargo inmediato por cambio de plan exitoso
  • payment.failed: Cargo inmediato fallido
Siempre verifica las firmas de los webhooks e implementa el procesamiento de eventos idempotentes.
5

Actualizar el Estado de tu Aplicación

Basado en eventos de webhook, actualiza tu aplicación:
  • Concede/revoca características basadas en el nuevo plan
  • Actualiza el panel del cliente con los nuevos detalles del plan
  • Envía correos electrónicos de confirmación sobre cambios de plan
  • Registra cambios de facturación para fines de auditoría
6

Probar y Monitorear

Prueba a fondo tu implementación:
  • Prueba todos los modos de prorrata con diferentes escenarios
  • Verifica que el manejo de webhooks funcione correctamente
  • Monitorea las tasas de éxito de los cambios de plan
  • Configura alertas para cambios de plan fallidos
Tu implementación de cambio de plan de suscripción ahora está lista para su uso en producción.

Vista Previa de Cambios de Plan

Antes de comprometerte a un cambio de plan, usa la API de Vista Previa para mostrar a los clientes exactamente lo que se les cobrará:
const preview = await client.subscriptions.previewChangePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
});

// Show customer the charge before confirming
console.log('Immediate charge:', preview.immediate_charge.summary);
console.log('New plan details:', preview.new_plan);
Usa la API de vista previa para construir diálogos de confirmación que muestren a los clientes el monto exacto que se les cobrará antes de que confirmen un cambio de plan.

API de Cambio de Plan

Usa la API de Cambio de Plan para modificar el producto, la cantidad y el comportamiento de prorrata para una suscripción activa.

Ejemplos de inicio rápido

import DodoPayments from 'dodopayments';

const client = new DodoPayments({
  bearerToken: process.env.DODO_PAYMENTS_API_KEY,
  environment: 'test_mode', // defaults to 'live_mode'
});

async function changePlan() {
  const result = await client.subscriptions.changePlan('sub_123', {
    product_id: 'prod_new',
    quantity: 3,
    proration_billing_mode: 'prorated_immediately',
  });
  console.log(result.status, result.invoice_id, result.payment_id);
}

changePlan();
Success
{
  "status": "processing",
  "subscription_id": "sub_123",
  "invoice_id": "inv_789",
  "payment_id": "pay_456",
  "proration_billing_mode": "prorated_immediately"
}
Campos como invoice_id y payment_id se devuelven solo cuando se crea un cargo inmediato y/o una factura durante el cambio de plan. Siempre confía en los eventos de webhook (por ejemplo, payment.succeeded, subscription.plan_changed) para confirmar resultados.
Si el cargo inmediato falla, la suscripción puede pasar a subscription.on_hold hasta que el pago tenga éxito.

Gestión de Addons

Al cambiar planes de suscripción, también puedes modificar addons:
// Add addons to the new plan
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [
    { addon_id: 'addon_123', quantity: 2 }
  ]
});

// Remove all existing addons
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'difference_immediately',
  addons: [] // Empty array removes all existing addons
});
Los addons se incluyen en el cálculo de prorrata y se cobrarán de acuerdo con el modo de prorrata seleccionado.

Modos de Prorrata

Elige cómo facturar al cliente al cambiar de planes:

prorated_immediately

  • Cobra por la diferencia parcial en el ciclo actual
  • Si está en prueba, cobra de inmediato y cambia al nuevo plan ahora
  • Downgrade: puede generar un crédito prorrateado aplicado a futuras renovaciones

full_immediately

  • Cobra el monto total del nuevo plan de inmediato
  • Ignora el tiempo restante del antiguo plan
Los créditos creados por downgrades usando difference_immediately son específicos de la suscripción y distintos de Créditos de Clientes. Se aplican automáticamente a futuras renovaciones de la misma suscripción y no son transferibles entre suscripciones.

difference_immediately

  • Actualización: cobra inmediatamente la diferencia de precio entre los planes antiguo y nuevo
  • Downgrade: agrega el valor restante como crédito interno a la suscripción y se aplica automáticamente en las renovaciones

Escenarios de Ejemplo

await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_pro',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
// Immediate charge: $50
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_starter',
  quantity: 1,
  proration_billing_mode: 'difference_immediately'
})
// Credit added: $30 (auto-applied to future renewals for this subscription)
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'prorated_immediately'
})
// Immediate prorated charge based on remaining days in cycle
await client.subscriptions.changePlan('sub_123', {
  product_id: 'prod_new',
  quantity: 1,
  proration_billing_mode: 'full_immediately'
})
// Immediate full charge for new plan; no credits calculated
Elige prorated_immediately para una contabilidad justa; elige full_immediately para reiniciar la facturación; usa difference_immediately para actualizaciones simples y crédito automático en downgrades.

Manejo de webhooks

Rastrea el estado de la suscripción a través de webhooks para confirmar cambios de plan y pagos.

Tipos de eventos a manejar

  • subscription.active: suscripción activada
  • subscription.plan_changed: plan de suscripción cambiado (actualización/downgrade/cambios de addon)
  • subscription.on_hold: cargo fallido, suscripción pausada
  • subscription.renewed: renovación exitosa
  • payment.succeeded: pago por cambio de plan o renovación exitoso
  • payment.failed: pago fallido
Recomendamos impulsar la lógica empresarial a partir de eventos de suscripción y usar eventos de pago para confirmación y conciliación.

Verificar firmas y manejar intenciones

import { NextRequest, NextResponse } from 'next/server';

export async function POST(req) {
  const webhookId = req.headers.get('webhook-id');
  const webhookSignature = req.headers.get('webhook-signature');
  const webhookTimestamp = req.headers.get('webhook-timestamp');
  const secret = process.env.DODO_WEBHOOK_SECRET;

  const payload = await req.text();
  // verifySignature is a placeholder – in production, use a Standard Webhooks library
  const { valid, event } = await verifySignature(
    payload,
    { id: webhookId, signature: webhookSignature, timestamp: webhookTimestamp },
    secret
  );
  if (!valid) return NextResponse.json({ error: 'Invalid signature' }, { status: 400 });

  switch (event.type) {
    case 'subscription.active':
      // mark subscription active in your DB
      break;
    case 'subscription.plan_changed':
      // refresh entitlements and reflect the new plan in your UI
      break;
    case 'subscription.on_hold':
      // notify user to update payment method
      break;
    case 'subscription.renewed':
      // extend access window
      break;
    case 'payment.succeeded':
      // reconcile payment for plan change
      break;
    case 'payment.failed':
      // log and alert
      break;
    default:
      // ignore unknown events
      break;
  }

  return NextResponse.json({ received: true });
}
Para esquemas de carga útil detallados, consulta los cargas útiles de webhook de suscripción y las cargas útiles de webhook de pago.

Mejores Prácticas

Sigue estas recomendaciones para cambios de plan de suscripción confiables:

Estrategia de Cambio de Plan

  • Prueba a fondo: Siempre prueba los cambios de plan en modo de prueba antes de producción
  • Elige prorrata cuidadosamente: Selecciona el modo de prorrata que se alinee con tu modelo de negocio
  • Maneja fallos de manera elegante: Implementa un manejo de errores adecuado y lógica de reintento
  • Monitorea tasas de éxito: Rastrea las tasas de éxito/fallo de cambios de plan e investiga problemas

Implementación de Webhook

  • Verifica firmas: Siempre valida las firmas de los webhooks para asegurar autenticidad
  • Implementa idempotencia: Maneja eventos de webhook duplicados de manera elegante
  • Procesa de manera asíncrona: No bloquees las respuestas de webhook con operaciones pesadas
  • Registra todo: Mantén registros detallados para depuración y fines de auditoría

Experiencia del Usuario

  • Comunica claramente: Informa a los clientes sobre cambios de facturación y tiempos
  • Proporciona confirmaciones: Envía correos electrónicos de confirmación para cambios de plan exitosos
  • Maneja casos extremos: Considera períodos de prueba, prorratas y pagos fallidos
  • Actualiza la UI de inmediato: Refleja los cambios de plan en la interfaz de tu aplicación

Problemas Comunes y Soluciones

Resuelve problemas típicos encontrados durante cambios de plan de suscripción:
Síntomas: La llamada a la API tiene éxito pero la suscripción permanece en el antiguo planCausas comunes:
  • El procesamiento del webhook falló o se retrasó
  • El estado de la aplicación no se actualizó después de recibir webhooks
  • Problemas de transacción en la base de datos durante la actualización del estado
Soluciones:
  • Implementa un manejo robusto de webhooks con lógica de reintento
  • Usa operaciones idempotentes para actualizaciones de estado
  • Agrega monitoreo para detectar y alertar sobre eventos de webhook perdidos
  • Verifica que el endpoint de webhook sea accesible y responda correctamente
Síntomas: El cliente hace un downgrade pero no ve el saldo de créditoCausas comunes:
  • Expectativas del modo de prorrata: los downgrades acreditan la diferencia total del precio del plan con difference_immediately, mientras que prorated_immediately crea un crédito prorrateado basado en el tiempo restante en el ciclo
  • Los créditos son específicos de la suscripción y no se transfieren entre suscripciones
  • El saldo de crédito no es visible en el panel del cliente
Soluciones:
  • Usa difference_immediately para downgrades cuando desees créditos automáticos
  • Explica a los clientes que los créditos se aplican a futuras renovaciones de la misma suscripción
  • Implementa un portal para clientes para mostrar saldos de crédito
  • Verifica la vista previa de la próxima factura para ver los créditos aplicados
Síntomas: Eventos de webhook rechazados debido a firma inválidaCausas comunes:
  • Clave secreta de webhook incorrecta
  • Cuerpo de la solicitud en bruto modificado antes de la verificación de la firma
  • Algoritmo de verificación de firma incorrecto
Soluciones:
  • Verifica que estés usando el correcto DODO_WEBHOOK_SECRET desde el panel de control
  • Lee el cuerpo de la solicitud en bruto antes de cualquier middleware de análisis JSON
  • Usa la biblioteca estándar de verificación de webhook para tu plataforma
  • Prueba la verificación de la firma del webhook en el entorno de desarrollo
Síntomas: La API devuelve un error 422 Entidad No ProcesableCausas comunes:
  • ID de suscripción o ID de producto inválidos
  • Suscripción no en estado activo
  • Parámetros requeridos faltantes
  • Producto no disponible para cambios de plan
Soluciones:
  • Verifica que la suscripción exista y esté activa
  • Verifica que el ID de producto sea válido y esté disponible
  • Asegúrate de que se proporcionen todos los parámetros requeridos
  • Revisa la documentación de la API para los requisitos de parámetros
Síntomas: Cambio de plan iniciado pero el cargo inmediato fallaCausas comunes:
  • Fondos insuficientes en el método de pago del cliente
  • Método de pago expirado o inválido
  • El banco rechazó la transacción
  • La detección de fraude bloqueó el cargo
Soluciones:
  • Maneja los eventos de webhook payment.failed de manera apropiada
  • Notifica al cliente para que actualice su método de pago
  • Implementa lógica de reintento para fallos temporales
  • Considera permitir cambios de plan con cargos inmediatos fallidos
Síntomas: El cargo por cambio de plan falla y la suscripción pasa al estado on_holdQué sucede: Cuando un cargo por cambio de plan falla, la suscripción se coloca automáticamente en estado on_hold. La suscripción no se renovará automáticamente hasta que se actualice el método de pago.Solución: Actualiza el método de pago para reactivar la suscripciónPara reactivar una suscripción desde el estado on_hold después de un cambio de plan fallido:
  1. Actualiza el método de pago usando la API de Actualización de Método de Pago
  2. Creación automática de cargo: La API crea automáticamente un cargo por los saldos pendientes
  3. Generación de factura: Se genera una factura para el cargo
  4. Procesamiento de pago: El pago se procesa utilizando el nuevo método de pago
  5. Reactivación: Tras el pago exitoso, la suscripción se reactiva al estado active
// Reactivate subscription from on_hold after failed plan change
async function reactivateAfterFailedPlanChange(subscriptionId) {
  // Update payment method - automatically creates charge for remaining dues
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'new',
    return_url: 'https://example.com/return'
  });
  
  if (response.payment_id) {
    console.log('Charge created for remaining dues:', response.payment_id);
    console.log('Payment link:', response.payment_link);
    
    // Redirect customer to payment_link to complete payment
    // Monitor webhooks for:
    // 1. payment.succeeded - charge succeeded
    // 2. subscription.active - subscription reactivated
  }
  
  return response;
}

// Or use existing payment method if available
async function reactivateWithExistingPaymentMethod(subscriptionId, paymentMethodId) {
  const response = await client.subscriptions.updatePaymentMethod(subscriptionId, {
    type: 'existing',
    payment_method_id: paymentMethodId
  });
  
  // Monitor webhooks for payment.succeeded and subscription.active
  return response;
}
Eventos de webhook a monitorear:
  • subscription.on_hold: Suscripción colocada en espera (recibido cuando falla el cargo por cambio de plan)
  • payment.succeeded: Pago por saldos pendientes exitoso (después de actualizar el método de pago)
  • subscription.active: Suscripción reactivada después de un pago exitoso
Mejores prácticas:
  • Notifica a los clientes de inmediato cuando falle un cargo por cambio de plan
  • Proporciona instrucciones claras sobre cómo actualizar su método de pago
  • Monitorea eventos de webhook para rastrear el estado de reactivación
  • Considera implementar lógica de reintento automática para fallos temporales de pago

Referencia de API para Actualizar Método de Pago

Consulta la documentación completa de la API para actualizar métodos de pago y reactivar suscripciones.

Probando tu Implementación

Sigue estos pasos para probar a fondo tu implementación de cambio de plan de suscripción:
1

Configurar entorno de prueba

  • Usa claves de API de prueba y productos de prueba
  • Crea suscripciones de prueba con diferentes tipos de plan
  • Configura un endpoint de webhook de prueba
  • Establece monitoreo y registro
2

Probar diferentes modos de prorrata

  • Prueba prorated_immediately con varias posiciones del ciclo de facturación
  • Prueba difference_immediately para actualizaciones y downgrades
  • Prueba full_immediately para reiniciar ciclos de facturación
  • Verifica que los cálculos de crédito sean correctos
3

Probar manejo de webhook

  • Verifica que se reciban todos los eventos de webhook relevantes
  • Prueba la verificación de la firma del webhook
  • Maneja eventos de webhook duplicados de manera elegante
  • Prueba escenarios de fallo en el procesamiento de webhooks
4

Probar escenarios de error

  • Prueba con IDs de suscripción inválidos
  • Prueba con métodos de pago expirados
  • Prueba fallos de red y tiempos de espera
  • Prueba con fondos insuficientes
5

Monitorear en producción

  • Configura alertas para cambios de plan fallidos
  • Monitorea los tiempos de procesamiento de webhooks
  • Rastrea tasas de éxito de cambios de plan
  • Revisa tickets de soporte al cliente para problemas de cambios de plan

Manejo de Errores

Maneja errores comunes de la API de manera elegante en tu implementación:

Códigos de Estado HTTP

Solicitud de cambio de plan procesada con éxito. La suscripción se está actualizando y el procesamiento de pagos ha comenzado.
Parámetros de solicitud inválidos. Verifica que todos los campos requeridos estén proporcionados y correctamente formateados.
Clave de API inválida o faltante. Verifica que tu DODO_PAYMENTS_API_KEY sea correcto y tenga los permisos adecuados.
ID de suscripción no encontrado o no pertenece a tu cuenta.
La suscripción no se puede cambiar (por ejemplo, ya cancelada, producto no disponible, etc.).
Ocurrió un error en el servidor. Reintenta la solicitud después de un breve retraso.

Formato de Respuesta de Error

{
  "error": {
    "code": "subscription_not_found",
    "message": "The subscription with ID 'sub_123' was not found",
    "details": {
      "subscription_id": "sub_123"
    }
  }
}

Próximos pasos