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ónEn Billete
Pro mensual, trimestral y anualUn solo plan con un precio por ciclo en prices
El ciclo que eligió el clientemonths de su suscripción
Pasar de mensual a anualUn 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

EventoQué pasóQué hace tu aplicación
subscription.updatedSe aplicó un cambio pagado o se programó uno.Muestra el ciclo actual y, si lo hay, pendingChange.
subscription.renewedPagó la renovación; un cambio programado ya rige.Muestra el periodo nuevo.
subscription.change_failedEl 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