Cargando…

Esto está tardando más de lo esperado.

Volver al centro de ayuda

Crea y pon precio a un plan

Arma un plan en el panel de administración, ponle precio por país e intervalo, y sigue lo que un suscriptor puede hacer con él.

Un plan es aquello a lo que un usuario se suscribe. Esta guía cubre crear uno desde el panel de administración, sus precios, cómo se retira de la venta, y cada movimiento que un suscriptor puede hacer: suscribirse, subir, bajar, cancelar, volver. Da por hecho que el cobro está encendido; si la barra lateral del panel no tiene grupo Planes, empieza por Activa los planes y el cobro.

Cómo se guarda un plan

Un plan es una fila en billing_plans y un Stripe Product, nombrado APP_NAME - Nombre del plan. Sus precios son filas en billing_prices, una por país y moneda, y cada una tiene una fila en billing_price_variations por intervalo de cobro, con el monto y el id del Stripe Price. Una suscripción apunta a un Stripe Price, así que el plan actual de un usuario se resuelve a partir del precio del elemento de la suscripción, nunca de un id de plan guardado en la suscripción.

Un usuario tiene una suscripción, llamada default, con exactamente un precio de plan y cero o más precios de complementos. Todos los helpers asumen esa forma.

Crea el plan

Ve a Planes, Planes, Crear. El formulario tiene cinco bloques.

Bloque Campos Notas
Información del plan Nombre, Descripción Ambos obligatorios. Son lo que muestra la tarjeta del plan. Un selector Contexto aparece sólo cuando hay un segundo adaptador de cobro registrado, para restringir el plan a usuarios o al otro dueño.
Características Líneas de texto libre Cada línea se vuelve una palomita en la tarjeta. Puramente descriptivas; nada las lee.
Precios Una variación de precio por país Detallado abajo. Obligatorio: al menos una variación con al menos un monto.
Complementos incluidos Selección múltiple de los complementos Capacidades que el plan otorga sin línea extra en la suscripción. Ver Vende complementos.
Límites Llave de límite, Valor del límite Una fila por cuota. Las llaves son los métodos públicos de App\Classes\PlanLimits; cada llave una vez. Ver Límites de plan y consumo.

Guardar crea el Stripe Product y un Stripe Price por cada monto, y redirige a la lista de planes. Si falta STRIPE_SECRET el formulario lo dice en una advertencia arriba; ponlo antes de crear planes, porque cada precio es un objeto de Stripe.

El plan también recibe un slug a partir de su nombre. Es metadato interno que se escribe en el Stripe Product y no se muestra en ningún lado.

Precios

Haz clic en Agregar variación de precios. Cada variación es un País y una Moneda, con un campo de monto por intervalo. Un plan que se vende a 199 MXN al mes en México y a 12 USD al mes en todos lados son dos variaciones: MX - Mexico en MXN, y Todo en USD. Cada país puede aparecer una vez por plan.

  • País es Todo (guardado como default) o uno de los países listados. El usuario ve la variación de su país cuando existe, y Todo en caso contrario. El país sale del country_code del usuario, luego de la detección de país, luego de default.
  • Moneda es uno de los códigos ISO listados. Es la moneda en la que cobra Stripe; no hay conversión al momento de la venta.
  • Cada monto crea un Stripe Price recurrente para ese intervalo. Los Stripe Price son inmutables, así que una vez guardado el campo queda deshabilitado. Para cambiar un monto, quita el precio con la cruz arriba del campo y escribe el nuevo: el Stripe Price viejo se archiva y se crea uno nuevo. La cruz sólo se ofrece mientras ninguna suscripción usa ese precio.
  • El botón de basura quita la variación completa; sólo se ofrece cuando ninguno de sus precios tiene suscriptores.
  • Un monto de 0 es un plan gratuito. Mantén exactamente un plan gratuito por país: con dos, la suscripción gratuita automática al registrarse no hace nada, porque no puede elegir.

Las columnas de intervalo salen de config/pricing.php, monthly y yearly por omisión; agregar una entrada ahí agrega una columna aquí, y la lista de monedas, la de países y los tipos de cambio se explican en Monedas, intervalos y tipos de cambio.

Una vez guardada una variación, el botón de ojo junto a ella abre un modal con su número de suscriptores, sus precios y una gráfica, y un enlace Abrir página completa a /admin/billing-plans/{id}/pricing/{country}.

Dónde aparece el plan

Un plan está en venta en el momento en que se guarda con un Stripe Price. Se muestra en /account/plans para usuarios con sesión y en la sección de precios de la página de inicio, bajo el selector de intervalo. El selector lista sólo los intervalos que al menos un plan tiene con precio y que están marcados como activos en config/pricing.php; un usuario que ya está suscrito ve seleccionado su propio intervalo.

Retira un plan de la venta

No hay un interruptor de "en venta" en los planes; el catálogo es lo que tiene un Stripe Price. Existen tres operaciones, y cada una se niega cuando rompería a un suscriptor:

  • Quitar un precio: la cruz sobre el monto, sólo mientras nadie está suscrito a él. El Stripe Price se archiva, así que ya no puede comprarse, y el plan deja de mostrarse para ese intervalo o país.
  • Borrar el plan: desde la lista de planes, sólo cuando ya no le quedan precios. El Stripe Product se archiva y la fila se borra de forma suave.
  • Migrar a los suscriptores: en la página de precios, Migrar suscriptores abre un modal donde marcas las suscripciones a mover, o ninguna para moverlas todas, y eliges un plan destino y uno de sus precios. El movimiento corre en un job encolado, MigrateUsersToPlan, así que la cola debe estar corriendo; cada suscripción se cambia al precio destino, conservando los complementos que existen en la misma moneda e intervalo, con el prorrateo por omisión de Stripe. No se envía ningún correo a los suscriptores.

Así que la secuencia para retirar un plan que la gente usa es: crea el reemplazo, migra los suscriptores a él, quita los precios viejos, borra el plan viejo. Las suscripciones y las facturas siguen referenciando los Stripe Price archivados, y por eso el borrado está protegido.

Sigue a los suscriptores

La página de precios de cada variación lista a sus suscriptores con nombre, correo, estatus y fecha de inicio, y grafica Nuevas suscripciones por día, Suscripciones acumuladas e Ingresos estimados por día, esta última siendo nuevas suscripciones por el monto promedio de esa variación. La lista de usuarios tiene una columna Plan actual y un filtro Plan. El tablero del panel tiene las métricas globales de ingresos y suscripciones descritas en Activa los planes y el cobro.

Qué puede hacer el suscriptor

Toda acción vive en las tarjetas de planes de /account/plans; el botón de cada tarjeta depende de la suscripción del usuario. La lógica es PlanService en el paquete, que desde tu propio código alcanzas como $user->subscribeToPlan($variation), $user->changeSubscriptionPlan($variation) y $user->subscription()->cancel().

Suscribirse

Sin suscripción cada tarjeta dice Suscribirse. Un plan gratuito se suscribe al instante, sin tarjeta. Un plan de pago abre Stripe Checkout; al terminar, Stripe devuelve al usuario a /account/plans?checkout=success, que muestra "Pago exitoso" y lo manda al tablero mientras el webhook crea la suscripción local. Checkout muestra un campo de código promocional cuando los cupones están encendidos; ver Pruebas gratuitas y cupones.

Un usuario nuevo queda suscrito al plan gratuito de su país al registrarse, cuando hay exactamente uno. Abrir /account/plans repite esa revisión, y además mueve a un usuario en plan gratuito al plan gratuito de su país actual si es distinto.

Cambiar de plan

Todas las demás tarjetas dicen Cambiar plan. Antes de enviar nada a Stripe, los límites del plan destino se comparan con el consumo actual del usuario; exceder uno detiene el cambio con el mensaje "Has excedido el límite para ...". Después:

De A Qué pasa
Gratuito Gratuito Se intercambia el precio.
Gratuito De pago, sin tarjeta guardada La suscripción gratuita se cancela de inmediato y se abre Checkout con el nuevo plan más los complementos actuales.
De pago De pago, más caro, mismo intervalo swapAndInvoice: la diferencia prorrateada se cobra ahora.
De pago De pago, más barato, mismo intervalo swap sin prorrateo: el nuevo precio aplica en la siguiente renovación, no se emite crédito.
De pago Gratuito Se cancela al final del periodo; el usuario conserva el plan de pago hasta entonces y no se le cobra de nuevo.
Cualquiera Intervalo distinto La suscripción de Stripe se actualiza directamente con proration_behavior: always_invoice, con cada complemento mapeado a su precio en el nuevo intervalo. Falla si un complemento no tiene precio en ese intervalo, o si no hay un método de pago válido registrado.

Los complementos de la suscripción se conservan en todos los cambios. Las bajadas se miden por monto: un destino más barato que el precio del plan actual es una bajada.

Cancelar y el periodo de gracia

La tarjeta del plan de pago actual dice Cancelar. Cancelar programa la suscripción para terminar al final del periodo, así que el usuario conserva el acceso hasta la fecha que pagó. Durante ese periodo de gracia la tarjeta dice Cancelado con "Su suscripción permanecerá activa hasta ...", la pantalla de cobro muestra Cancelación programada, y:

  • Elegir otro plan de pago está permitido y reactiva la suscripción, porque Stripe descarta la cancelación pendiente cuando cambian los elementos. Así es como un usuario reanuda.
  • Elegir un plan gratuito se rechaza: la suscripción ya está terminando.
  • Cuando pasa la fecha, la suscripción termina, todas las tarjetas vuelven a decir Suscribirse y la pantalla de cobro muestra cuándo se canceló y quién lo hizo.

La fecha de cancelación, su motivo y el usuario que hizo clic se guardan en la suscripción (canceled_at, cancellation_reason, canceled_by). Una cancelación hecha en el Dashboard de Stripe llega por el webhook y se muestra como "vía Stripe".

Pagos fallidos

Cuando Stripe no pudo cobrar una renovación, la suscripción queda past_due; cuando el primer pago nunca se completó, incomplete. Ambas cuentan como no activas: la barra lateral dice "Sin plan", /app redirige a los planes, y la tarjeta dice Reintentar pago. Reintentar paga la factura abierta con la tarjeta predeterminada, o manda al usuario a la página de factura alojada de Stripe cuando el banco pide autenticación.

La pantalla de cobro

/account/billing muestra el estado de la suscripción como una etiqueta, el nombre del plan, el número de complementos activos, el inicio del periodo actual y la fecha del siguiente pago leídos en vivo desde Stripe, una lista plegable de los complementos con sus precios, y las últimas diez facturas pagadas con fecha, monto y estatus. No hay enlace a PDF; los montos se formatean con CASHIER_CURRENCY_LOCALE.

/account/payment-methods lista las tarjetas guardadas con marca, últimos cuatro dígitos y vencimiento. Una tarjeta se agrega mediante Stripe Elements contra un SetupIntent, así que ningún número de tarjeta llega a tu servidor; la primera tarjeta se vuelve predeterminada automáticamente. Una tarjeta puede volverse predeterminada cuando hay más de una, y eliminarse salvo que sea la última o la predeterminada de una suscripción activa.

Eventos para tu código

Dos eventos dejan que el resto de la aplicación reaccione sin tocar el cobro:

  • WeblaborMx\BillingCore\Events\SubscriptionPaid en cada factura pagada, con el monto, la moneda, el id de la factura y el id de la suscripción. El kit lo escucha para pagar recompensas de referidos y registrar un evento de tracking.
  • WeblaborMx\BillingCore\Events\PlanChanged cuando un usuario cambia a un plan de pago.

Ambos llevan el contexto de cobro; revisa $event->adapterKey() === 'user' antes de actuar sobre un usuario, para que un listener siga siendo correcto si más adelante se agrega otro dueño de cobro.