Mensual y anual
Varios ciclos de cobro en un mismo plan, elegir uno al comprar y cambiarlo después.
Para un producto que cobra el mismo plan por mes o por año, con descuento por pagar más tiempo de una vez. El ejemplo es Pro a 10 USD al mes, 27 al trimestre y 100 al año.
El modelo
| En tu aplicación | En Billete |
|---|---|
| Pro mensual, trimestral y anual | Un solo plan con un precio por ciclo en prices |
| El ciclo que eligió el cliente | months de su suscripción |
| Pasar de mensual a anual | Un cambio con months |
- Un plan, varios precios. Los ciclos son de 1, 3, 6, 9 o 12 meses y cada uno aparece una vez. Las cuotas y los puestos son los del plan, así que Pro mensual y Pro anual dan lo mismo y tu aplicación no los distingue.
- No crees un plan por ciclo. Con dos planes, pasar de mensual a anual sería un cambio de plan, el respaldo y los cupones limitados a un plan tendrían que nombrar a los dos, y un cliente podría terminar con ambos.
- Cada periodo se paga completo y por adelantado. El anual se paga de una vez y su renovación llega al año; no hay cuotas mensuales de un ciclo anual.
1. Crea el plan con sus ciclos
const pro = await billete.plans.create({
name: "Pro",
lookupKey: "pro",
currency: "USD",
prices: [
{ months: 1, amount: 1000 },
{ months: 3, amount: 2700 },
{ months: 12, amount: 10000 },
],
features: { mensajes: 5000 },
});Cada amount es el precio del periodo completo, en céntimos. Si muestras «equivale a 8,33 USD al mes», ese número es solo de tu página: Billete cobra el precio del ciclo. Cambiar los precios después solo afecta a las suscripciones nuevas.
2. Deja que el cliente elija el ciclo
Un enlace de pago del plan ofrece todos sus ciclos, o solo los que listes en months, y el cliente elige en el checkout:
const link = await billete.paymentLinks.create({
type: "plan",
plan: PLANS.pro,
months: [1, 12],
});
// Abre el checkout con el anual ya elegido; el cliente puede cambiarlo.
const annualUrl = `${link.url}?months=12`;Un checkout que crea tu servidor cobra el ciclo que envías y el cliente no lo cambia. Si el selector está en tu página, crea el checkout con lo que eligió:
const checkout = await billete.checkouts.create({
plan: PLANS.pro,
months: form.months,
customer: { externalId: user.id, email: user.email },
successUrl: "https://tuapp.com/ajustes/plan?checkout={CHECKOUT_ID}",
});
return redirect(checkout.url);3. Cambia el ciclo
De mensual a anual, ahora. El cliente paga el año menos lo que le queda del mes, y el periodo anual empieza al confirmarse el pago:
const quote = await billete.subscriptions.changes.preview(user.subscriptionId, { months: 12 });
// quote.credit: lo que vale el resto del mes; quote.total: lo que pagará hoy.
const result = await billete.subscriptions.changes.create(user.subscriptionId, {
months: 12,
when: "now",
successUrl: "https://tuapp.com/ajustes/plan",
});
if (result.type === "checkout") return redirect(result.checkout.url);De anual a mensual, en la renovación. Hacerlo ahora perdería el resto del año pagado, porque no hay saldo a favor: sin acceptUnusedCredit: true responde unused_credit_not_accepted. Prográmalo:
await billete.subscriptions.changes.create(user.subscriptionId, { months: 1, when: "renewal" });El cambio queda en pendingChange y renewal.amount ya muestra el precio mensual. El cliente conserva el ciclo anual hasta el final del año y la renovación cobra el mes.
Durante los 3 días previos a la renovación, o en la gracia, un cambio now responde subscription_renewal_open: ofrece pagar la renovación o programar el cambio. El portal también deja cambiar el ciclo si lo activas, siempre desde la próxima renovación.
4. Escucha los eventos
| Evento | Qué pasó | Qué hace tu aplicación |
|---|---|---|
subscription.updated | Se aplicó un cambio pagado o se programó uno. | Muestra el ciclo actual y, si lo hay, pendingChange. |
subscription.renewed | Pagó la renovación; un cambio programado ya rige. | Muestra el periodo nuevo. |
subscription.change_failed | El pago del cambio llegó cuando la suscripción ya era otra; se reembolsa. | Dile que sigue en su ciclo y que lo intente otra vez. |
Referencia de suscripciones · Referencia de planes · Enlaces de pago