Совершение покупок в мобильном приложении с помощью Kotlin Multiplatform SDK
Отображение пейволов в мобильном приложении — важный шаг для предоставления пользователям доступа к премиум-контенту или сервисам. Однако просто показать пейвол достаточно для проведения покупок лишь в том случае, если вы используете Paywall Builder для его настройки.
Если вы не используете Paywall Builder, для завершения покупки и открытия нужного контента необходимо вызвать отдельный метод .makePurchase(). Именно через него пользователи взаимодействуют с пейволами и совершают нужные транзакции.
Если для продукта, который пользователь пытается купить, настроен активный promotional offer, Adapty автоматически применит его в момент покупки.
Обратите внимание: introductory offer применяется автоматически только при использовании пейволов, настроенных через Paywall Builder.
В остальных случаях нужно проверить право пользователя на introductory offer на iOS. Пропуск этого шага может привести к отклонению приложения при релизе, а также к списанию полной цены с пользователей, которым доступен introductory offer.
Убедитесь, что вы выполнили начальную настройку, не пропустив ни одного шага. Без неё валидация покупок невозможна.
Совершение покупки
Используете Paywall Builder? Покупки обрабатываются автоматически — этот шаг можно пропустить.
Нужны пошаговые инструкции? Смотрите гайд по быстрому старту с полным описанием реализации.
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
}
Параметры запроса:
| Параметр | Обязательность | Описание |
|---|---|---|
| Product | обязательный | Объект AdaptyPaywallProduct, полученный из пейвола. |
Параметры ответа:
| Параметр | Описание |
|---|---|
| Profile | При успешном запросе ответ содержит этот объект. Объект AdaptyProfile предоставляет исчерпывающую информацию об уровнях доступа пользователя, подписках и разовых покупках внутри приложения. Проверьте статус уровня доступа, чтобы определить, есть ли у пользователя необходимый доступ к приложению. |
Примечание: если вы всё ещё используете StoreKit версии ниже 2.0 и Adapty SDK версии ниже 2.9.0, вам нужно указать общий секрет Apple App Store. Этот метод в настоящее время признан устаревшим компанией Apple.
Смена подписки при совершении покупки
Когда пользователь выбирает новую подписку вместо продления текущей, поведение зависит от магазина приложений. В Google Play подписка не обновляется автоматически — переключение нужно реализовать в коде мобильного приложения, как описано ниже.
Чтобы заменить подписку на другую в Android, вызовите метод .makePurchase() с дополнительным параметром:
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
}
Дополнительный параметр запроса:
| Параметр | Обязательность | Описание |
|---|---|---|
| parameters | необязательный | Объект AdaptyAndroidSubscriptionUpdateParameters, передаваемый через AdaptyPurchaseParameters. |
Подробнее о подписках и режимах замены можно прочитать в документации Google для разработчиков:
- О режимах замены
- Рекомендации Google по режимам замены
- Режим замены
CHARGE_PRORATED_PRICE. Примечание: этот метод доступен только при повышении уровня подписки. Понижение не поддерживается. - Режим замены
DEFERRED. Примечание: реальная смена подписки произойдёт только по окончании текущего расчётного периода.
Погашение промокодов в iOS
Об офферных кодах
Офферные коды позволяют предоставлять скидки или бесплатные пробные периоды конкретным пользователям. В отличие от обычных офферов, которые применяются автоматически, офферные коды распространяются за пределами приложения — через email-рассылки, социальные сети или печатные материалы. Пользователи активируют их, вводя код в App Store, переходя по ссылке для активации или через диалог внутри приложения.
Чтобы настроить офферные коды, откройте подписку в App Store Connect и перейдите в раздел Offer Codes. Вы можете создать три вида офферных кодов:
- Free — подписка бесплатна на заданный период, следующее продление — по полной цене.
- Pay as you go — пользователь платит сниженную цену в каждом расчётном периоде на протяжении заданного срока, после чего подписка продлевается по полной цене.
- Pay up front — пользователь единовременно платит сниженную цену за весь срок оффера, после чего подписка продлевается по полной цене.
Добавлять офферные коды в Adapty не нужно. Apple помечает каждую транзакцию в период действия оффера категорией офферного кода. Это касается как первоначальной активации, так и всех последующих продлений со скидкой. Adapty обнаруживает метку и записывает каждую транзакцию с категорией оффера offer_code. Как только период оффера заканчивается и подписка продлевается по полной цене, метка исчезает. Вы можете фильтровать аналитику по типу оффера Offer Code в дашборде Adapty.
Устранение расхождений в выручке
Если транзакция по офферному коду отображается в Adapty по полной цене продукта вместо сниженной цены оффера, проверьте следующее в App Store Connect:
- Для офферного кода настроены корректные цены для всех регионов, где пользователи могут его активировать.
- Цена оффера задана для конкретной страны или региона пользователя. Apple передаёт региональную цену в транзакции. Если для оффера не настроена региональная цена, Apple может передать полную цену продукта.
Вы можете фильтровать и проверять транзакции по офферным кодам в дашборде Adapty по фильтрам типа оффера Offer Code и Offer Discount Type.
Устаревшие промокоды (deprecated)
Apple прекратила поддержку промокодов для встроенных покупок в марте 2026 года. Офферные коды заменяют их с расширенными возможностями: настраиваемые условия применения, сроки действия и до 1 миллиона кодов в квартал. Если вы ранее использовали промокоды для встроенных покупок, перейдите на офферные коды в App Store Connect.
Устаревшие промокоды (не более 100 на приложение на версию) предоставляли бесплатный доступ к подписке. В отличие от офферных кодов, Apple не включала информацию о скидке в транзакции по промокодам — в чеке указывалась полная цена продукта. В результате Adapty записывал эти транзакции по полной цене, что приводило к расхождениям в выручке между аналитикой Adapty и App Store Connect.
Если вы видите исторические транзакции по полной цене, которые должны были быть бесплатными, скорее всего, они связаны с устаревшими промокодами. Поскольку эти коды больше не поддерживаются, перейдите на офферные коды для точного учёта выручки.
Чтобы отобразить в приложении экран погашения кода:
Adapty.presentCodeRedemptionSheet()
.onSuccess {
// code redemption sheet presented successfully
}
.onError { error ->
// handle the error
}
По нашим наблюдениям, экран погашения промокодов в некоторых приложениях может работать нестабильно. Рекомендуем направлять пользователя напрямую в App Store.
Для этого откройте URL следующего формата:
https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}
Управление предоплаченными планами (Android)
Если пользователи вашего приложения могут приобретать предоплаченные планы (например, покупать неавтопродлевающуюся подписку на несколько месяцев), вы можете включить отложенные транзакции для таких планов.
Adapty.activate(
AdaptyConfig.Builder("PUBLIC_SDK_KEY")
.withGoogleEnablePendingPrepaidPlans(true)
.build()
).onSuccess {
// successful activation
}.onError { error ->
// handle the error
}