Realizar compras in-app en una aplicación móvil con el SDK de Kotlin Multiplatform
Mostrar paywalls en tu aplicación móvil es un paso esencial para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, presentar un paywall solo gestiona las compras de forma autónoma cuando Adapty renderiza la pantalla — es decir, un flow, o un paywall del antiguo Paywall Builder.
Si renderizas la pantalla con tu propio código, debes usar un método independiente llamado .makePurchase() para completar una compra y desbloquear el contenido deseado. Este método es la puerta de entrada para que los usuarios interactúen con los paywalls y lleven a cabo sus transacciones.
Si tu paywall tiene una oferta promocional activa para el producto que un usuario intenta comprar, Adapty la aplicará automáticamente en el momento de la compra.
Ten en cuenta que la oferta introductoria se aplicará automáticamente solo si Adapty renderiza la pantalla.
En otros casos, deberás verificar la elegibilidad del usuario para una oferta introductoria en iOS. Omitir este paso puede provocar que tu app sea rechazada durante la revisión. Además, podría llevar a cobrar el precio completo a usuarios que son elegibles para una oferta introductoria.
Asegúrate de haber completado la configuración inicial sin saltarte ningún paso. Sin ella, no podemos validar las compras.
Realizar una compra
¿Adapty renderiza tu pantalla? Para un flow o un paywall de Paywall Builder, las compras se procesan automáticamente; puedes saltarte este paso.
¿Buscas orientación paso a paso? Consulta la guía de inicio rápido para obtener instrucciones de implementación completas con todo el contexto.
Adapty.makePurchase(product = product).onSuccess { purchaseResult ->
when (purchaseResult) {
is AdaptyPurchaseResult.Success -> {
val profile = purchaseResult.profile
if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) {
// Grant access to the paid features
}
}
is AdaptyPurchaseResult.UserCanceled -> {
// Handle the case where the user canceled the purchase
}
is AdaptyPurchaseResult.Pending -> {
// Handle deferred purchases (e.g., the user will pay offline with cash)
}
}
}.onError { error ->
// Handle the error
}
| Parámetro | Presencia | Descripción |
|---|---|---|
| Product | required | Un objeto AdaptyPaywallProduct obtenido del paywall. |
Parámetros de respuesta:
| Parámetro | Descripción |
|---|---|
| Profile | Si la solicitud se ha completado correctamente, la respuesta contiene este objeto. Un objeto AdaptyProfile proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas de un usuario dentro de la app. Comprueba el estado del nivel de acceso para determinar si el usuario tiene el acceso requerido a la app. |
Nota: si todavía usas una versión de StoreKit de Apple inferior a v2.0 y una versión del SDK de Adapty inferior a v2.9.0, debes proporcionar el secreto compartido de Apple App Store en su lugar. Apple ha declarado este método como obsoleto.
Cambiar la suscripción al realizar una compra
Cuando un usuario elige una nueva suscripción en lugar de renovar la actual, el funcionamiento depende del store. En Google Play, la suscripción no se actualiza automáticamente. Tendrás que gestionar el cambio en el código de tu aplicación móvil como se describe a continuación.
Para reemplazar la suscripción por otra en Android, llama al método .makePurchase() con el parámetro adicional:
val subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters(
oldSubVendorProductId = "old_subscription_product_id",
replacementMode = AdaptyAndroidSubscriptionUpdateReplacementMode.CHARGE_FULL_PRICE
)
val purchaseParams = AdaptyPurchaseParameters.Builder()
.setSubscriptionUpdateParams(subscriptionUpdateParams)
.build()
Adapty.makePurchase(
product = product,
parameters = purchaseParams
).onSuccess { purchaseResult ->
when (purchaseResult) {
is AdaptyPurchaseResult.Success -> {
val profile = purchaseResult.profile
// successful cross-grade
}
is AdaptyPurchaseResult.UserCanceled -> {
// user canceled the purchase flow
}
is AdaptyPurchaseResult.Pending -> {
// the purchase has not been finished yet, e.g. user will pay offline by cash
}
}
}.onError { error ->
// Handle the error
}
Parámetro de solicitud adicional:
| Parámetro | Presencia | Descripción |
|---|---|---|
| parameters | opcional | un objeto AdaptyAndroidSubscriptionUpdateParameters pasado a través de AdaptyPurchaseParameters. |
Puedes leer más sobre suscripciones y modos de reemplazo en la documentación de Google Developer:
- Acerca de los modos de reemplazo
- Recomendaciones de Google para los modos de reemplazo
- Modo de reemplazo
CHARGE_PRORATED_PRICE. Nota: este método solo está disponible para actualizaciones de suscripción. No se admiten cambios a planes inferiores. - Modo de reemplazo
DEFERRED. Nota: el cambio de suscripción real solo se producirá cuando finalice el período de facturación de la suscripción actual.
Canjear códigos de oferta en iOS
Acerca de los códigos de oferta
Los códigos de oferta te permiten dar descuentos o períodos de prueba gratuitos a usuarios específicos. A diferencia de las ofertas regulares que se aplican automáticamente, los códigos de oferta se distribuyen fuera de la app — a través de campañas de correo electrónico, redes sociales o materiales impresos. Los usuarios los canjean introduciendo el código en el App Store, siguiendo una URL de canje o a través de un diálogo dentro de la app.
Para configurar códigos de oferta, abre una suscripción en App Store Connect y ve a su sección Offer Codes. Puedes crear tres tipos de códigos de oferta:
- Free — la suscripción es gratuita durante un período determinado, y la siguiente renovación se realiza al precio completo.
- Pay as you go — el usuario paga un precio con descuento en cada ciclo de facturación durante un período determinado, luego la suscripción se renueva al precio completo.
- Pay up front — el usuario paga un precio único con descuento por toda la duración de la oferta, luego la suscripción se renueva al precio completo.
No es necesario añadir los códigos de oferta a Adapty. Apple etiqueta cada transacción durante el período de la oferta con la categoría del código de oferta. Esto incluye el canje inicial y todas las renovaciones con descuento posteriores. Adapty detecta la etiqueta y registra cada transacción con la categoría de oferta offer_code. Una vez que el período de oferta termina y la suscripción se renueva al precio completo, la etiqueta ya no está presente. Puedes filtrar los análisis por el tipo de oferta Offer Code en el Adapty Dashboard.
Solución de problemas de discrepancias en ingresos
Si observas que una transacción con código de oferta aparece en Adapty al precio completo del producto en lugar del precio con descuento de la oferta, verifica lo siguiente en App Store Connect:
- El código de oferta tiene el precio correcto configurado para todas las regiones donde los usuarios pueden canjearlo.
- El precio de la oferta está establecido para el país o región específico del usuario. Apple envía el precio regional en la transacción. Si no hay ningún precio regional configurado para la oferta, Apple puede enviar el precio completo del producto en su lugar.
Puedes filtrar y verificar las transacciones con códigos de oferta en el Adapty Dashboard mediante los filtros de tipo de oferta Offer Code y Offer Discount Type.
Códigos promocionales heredados (obsoletos)
Apple dejó obsoletos los códigos promocionales para compras in-app en marzo de 2026. Los códigos de oferta los reemplazan con más funcionalidades: elegibilidad configurable, fechas de vencimiento y hasta 1 millón de códigos por trimestre. Si anteriormente usabas códigos promocionales para compras in-app, haz la transición a los códigos de oferta en App Store Connect.
Los códigos promocionales heredados (limitados a 100 por app por versión) otorgaban acceso gratuito a una suscripción. A diferencia de los códigos de oferta, Apple no incluía información de descuento en las transacciones con códigos promocionales — enviaba el precio completo del producto en el recibo. Como resultado, Adapty registraba estas transacciones al precio completo, lo que causaba discrepancias de ingresos entre los análisis de Adapty y App Store Connect.
Si ves transacciones históricas al precio completo que deberían haber sido gratuitas, es probable que provengan de códigos promocionales heredados. Dado que estos códigos están ahora obsoletos, haz la transición a los códigos de oferta para un seguimiento preciso de los ingresos.
Para mostrar la pantalla de canje de códigos en tu app:
Adapty.presentCodeRedemptionSheet()
.onSuccess {
// code redemption sheet presented successfully
}
.onError { error ->
// handle the error
}
Según nuestras observaciones, la pantalla de canje de códigos de oferta puede no funcionar de forma fiable en algunas apps. Recomendamos redirigir al usuario directamente a la App Store.
Para hacerlo, debes abrir la URL con el siguiente formato:
https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}
Gestionar planes prepago (Android)
Si los usuarios de tu app pueden comprar planes prepago (por ejemplo, comprar una suscripción no renovable por varios meses), puedes habilitar transacciones pendientes para los planes prepago.
Adapty.activate(
AdaptyConfig.Builder("PUBLIC_SDK_KEY")
.withGoogleEnablePendingPrepaidPlans(true)
.build()
).onSuccess {
// successful activation
}.onError { error ->
// handle the error
}
Compras in-app promocionadas desde la App Store
Tu app recibe compras in-app promocionadas a partir de la versión 4.1 del SDK, en iOS 16.4 o posterior. Por debajo de iOS 16.4, el listener no se activa y las compras promocionadas se completan por sí solas. Esta es una función exclusiva de iOS: en Android el listener tampoco se activa, y makePromotedPurchase devuelve un AdaptyErrorCode.DEVELOPER_ERROR.
Cuando un usuario inicia una compra desde la página de tu producto en la App Store y la transacción llega a tu app, el SDK te entrega el producto a través de un OnPromotedPurchaseListener. Completar la compra depende de tu app: pasa el producto a makePromotedPurchase. Como tú controlas cuándo ocurre esto, puedes mostrar tu propia pantalla antes de que comience la compra.
Para admitir compras promocionadas, registra el listener y completa la compra desde él:
Adapty.setOnPromotedPurchaseListener(OnPromotedPurchaseListener { product ->
scope.launch {
Adapty.makePromotedPurchase(product)
.onSuccess { result -> /* process the purchase result */ }
.onError { error -> /* handle the error */ }
}
})
Sin un listener registrado, una compra promocionada nunca se completa: el App Store entrega el producto a tu app y espera. Pasar null a setOnPromotedPurchaseListener también impide que las compras promocionadas funcionen.
Registra el listener al iniciar la app, justo después de Adapty.activate. Una compra promocionada normalmente lanza la app en frío, por lo que suele llegar al SDK antes de que tu registro se ejecute. El SDK retiene una de estas compras y la entrega en cuanto te registras, conservando solo la más reciente, y escribe una advertencia en la consola cada vez que retiene una compra.
Si el producto promocionado incluye una oferta de suscripción, el SDK la aplica automáticamente en el momento de la compra. La oferta se lee desde el intent de compra del App Store, que la expone en iOS 18.0 y versiones posteriores. En iOS 16.4–17.x, la compra se realiza al precio base.
makePromotedPurchase no acepta parámetros de compra — un producto promocionado proviene del App Store y no de un paywall, por lo que no lleva contexto de paywall. Devuelve el mismo AdaptyPurchaseResult que makePurchase.
AdaptyPromotedProduct incluye vendorProductId, localizedTitle, localizedDescription, price, regionCode, isFamilyShareable y una subscription de tipo AdaptyProductSubscription.