
Apple ha incorporado en 2026 (SDK de Xcode 26.5 / iOS, iPadOS, macOS, tvOS y visionOS 26.4) un nuevo modelo de suscripción nativo: la suscripción mensual con un compromiso de 12 meses, conocida como commitment plan. Resuelve por fin, sin trucos, el caso de uso de toda la vida: una suscripción anual que el cliente paga mes a mes.
En esta entrada lo vemos de forma visual y resumida: qué es, dónde está disponible, qué API necesitas y, sobre todo, los dos puntos que más fallos provocan: qué fecha usar para dar acceso y qué pasa cuando el cliente cancela.
1. El concepto de un vistazo
Suscripción anual clásica
- Plan de facturación
.upFront - Un único pago inicial
- Renueva una vez al año
Commitment plan (nuevo)
- Plan de facturación
.monthly - El cliente se compromete a los 12 pagos
- Al terminar, renueva otro compromiso de 12 meses salvo cancelación
Cada periodo mensual se comporta exactamente como una suscripción mensual normal: genera una transacción independiente y concede un mes de acceso. La diferencia es que el cliente se ha comprometido al año completo.
2. Disponibilidad y límites
Requisitos técnicos
- SDK mínimo: Xcode 26.5
- SO mínimo: iOS, iPadOS, macOS, tvOS y visionOS 26.4
Restricción geográfica
Disponible en todo el mundo EXCEPTO EE. UU. y Singapur.
No es un producto nuevo: es un plan de facturación mensual que activas sobre tu suscripción anual existente desde App Store Connect. Esto significa que el grupo de suscripción y el product ID no cambia.
3. Mapa de la API
| Elemento | Para qué sirve |
|---|---|
Product.SubscriptionInfo.BillingPlanType | Distingue el plan: .upFront (anual clásico) o .monthly (commitment plan). |
Product.SubscriptionInfo.PricingTerms | Array con los planes disponibles. Si hay commitment plan, tiene dos entradas (la .upFront y la .monthly). |
Transaction.CommitmentInfo | Datos para mostrar el progreso del compromiso con tu propia UI personalizada: billingPeriodNumber, totalBillingPeriods, expirationDate y price. Si no quieres complicarte con UI custom, abre la pantalla del sistema llamando a showManageSubscriptions(in:) o showManageSubscriptions(in:subscriptionGroupID:). |
billingPlanType (Transaction) | Indica si la transacción es de un commitment plan (.monthly). Compruébalo antes de ramificar lógica. |
.billingPlanType(.monthly) | PurchaseOption que pasas a product.purchase(options:) para comprar el plan mensual. |
Comprar el plan
let result = try await product.purchase(options: [.billingPlanType(.monthly)])
Sin esa opción, se compra el plan estándar .upFront. Las renovaciones mensuales posteriores no pasan por purchase(): llegan por Transaction.updates, igual que cualquier suscripción mensual.
Importante
Antes de la compra debes mostrar al cliente los dos importes: el precio mensual y el precio total del compromiso. Es un requisito de Apple, no una recomendación.
4. Las DOS fechas importantes
Es el error número uno. Una transacción de commitment plan lleva dos fechas distintas y usar la equivocada rompe el control de acceso.
Para dar acceso (entitlement)
expirationDate en Transaction
Ej.: 30 de junio de 2026, el final del periodo mensual en curso.
ÚSALA para conceder acceso
Solo para mostrar progreso
expirationDate en Transaction.CommitmentInfo
Ej.: 31 de diciembre de 2026, el final de todo el compromiso.
NUNCA para acceso
Cuidado con la fecha
Si las confundes, o concedes 12 meses de acceso con un solo pago, o revocas el acceso meses antes de tiempo. Lee siempre estas fechas de la transacción más reciente, porque pueden desplazarse tras recuperar un fallo de pago.
Lógica de acceso (igual que una mensual normal)
Recorre currentEntitlements (Transaction.Transactions) y concede acceso cuando, en cada transacción:
expirationDateestá en el futuro, YrevocationDateesnil, YisUpgradedesfalse.
Si tu app ya gestiona bien las suscripciones mensuales, esta misma lógica funciona sin cambios.
5. ¿Qué pasa cuando el cliente cancela?
El segundo concepto contraintuitivo: cancelar significa cancelar la renovación del compromiso, no los pagos que quedan del compromiso actual. El cobro mensual continúa hasta completar los 12 periodos.
willAutoRenew (Product.SubscriptionInfo.RenewalInfo.CommitmentInfo) cambia a 0.El compromiso NO se renovará al terminar el año.
willAutoRenew en la información de renovación de la suscripción (renewalInfo) sigue en 1.La facturación mensual continúa por los periodos que quedan.
DID_CHANGE_RENEWAL_STATUS (AUTO_RENEW_DISABLED).Y siguen llegando
DID_RENEW cada mes hasta el final.EXPIRED.Aquí, y solo aquí, termina el acceso.
Comportamiento crítico
Sigue dando acceso durante los 12 periodos. Cancelar no revoca el servicio; solo lo hace EXPIRED (o una revocación).
No confundas los dos. El primer willAutoRenew responde a "¿se renovará el compromiso anual?"; mietras que el segundo willAutoRenew responde a "¿se cobrará el mes que viene?".
Fallo de pago: ojo, no hay periodo de gracia
Sin periodo de gracia
La mayor diferencia con una suscripción normal: el Billing Grace Period NO se aplica a los commitment plans. Revoca el acceso en cuanto veas DID_FAIL_TO_RENEW y restáuralo con DID_RENEW (subtipo BILLING_RECOVERY). App Store reintenta el cobro hasta 90 días.
6. Conclusión
Los commitment plans hacen nativo el clásico "anual pagado a plazos". Si tu app ya gestiona suscripciones mensuales, el 90 % del trabajo está hecho: la lógica de acceso es la misma. Solo tienes que recordar tres cosas: usar expirationDate (Transaction) para el acceso, seguir dando servicio tras una cancelación hasta EXPIRED y revocar de inmediato si falla un pago (sin periodo de gracia). Pruébalo de principio a fin en el sandbox con renovación acelerada (puedes configurarlo desde el apartado Developer, dentro del apartado de configuración de tu dispostivo de prueba).
Bibliografía y fuentes consultadas
- Apple Developer. Supporting monthly subscriptions with a 12-month commitment.
- Apple Developer. Managing the life cycle of monthly subscriptions with a 12-month commitment.