Настройка плана с 12-месячным обязательством

Important

Чтобы предложить тарифный план с обязательством, вам нужна годовая подписка в App Store и флоу или кастомный пейвол. Флоу требуют Adapty SDK v4.3.1 или новее на iOS, v4.3 или новее на Android, а также v4.3.0 или новее на React Native или Flutter. Кастомные пейволы требуют Adapty SDK v4.3 или новее на iOS, React Native или Flutter.

Чтобы подписчики брали на себя обязательство на полный год, но платили ежемесячно, добавьте 12-месячный план с обязательством к вашему годовому продукту в App Store Connect и в Adapty.

Прежде чем начать

Прежде чем внедрять планы с обязательством, убедитесь, что вы:

  • Выбирайте правильный рынок: Планы с обязательством недоступны в США. В Германии, Израиле, Южной Африке и Турции подписчики могут отменить подписку с немедленным вступлением в силу через Apple Support.
  • Учитывайте версию ОС: Подписчикам нужен iOS 26.4 или выше, либо аналогичная версия iPadOS, macOS, tvOS или visionOS. Соберите приложение с помощью Xcode 26.5 или выше.
  • Учитывайте ценовой диапазон: Сумма 12 ежемесячных платежей должна составлять от 1x до 1,5x стоимости годовой подписки с единовременной оплатой.
  • Используйте поддерживаемую версию Adapty SDK: Флоу требуют Adapty SDK v4.3.1 или выше на iOS, v4.3 или выше на Android и v4.3.0 или выше на React Native или Flutter. Кастомные пейволы требуют Adapty SDK v4.3 или выше на iOS, React Native или Flutter: в версиях приложения с более ранним SDK пользователи смогут купить только план с единовременной оплатой.
  • Обновите код, обрабатывающий идентификаторы продуктов: Вебхуки, интеграции, экспорт данных и Server-side API передают покупки плана с обязательством как <product_id>:monthly. Если ваш код обрабатывает идентификаторы продуктов, обновите логику до первой покупки плана с обязательством.

1. Настройка App Store Connect

  1. Откройте годовую подписку в App Store Connect или создайте новую подписку с длительностью 1 Year.
  2. В разделе Availability добавьте одни и те же страны в разделах 1 Year Upfront и Monthly with 12-Month Commitment. Apple предлагает тарификацию с обязательным сроком только там, где доступна авансовая тарификация. Обратное не обязательно: вы можете предлагать план с единовременной оплатой в странах без плана с обязательным сроком.
  3. В разделе Subscription Prices установите авансовую цену для базовой территории, если у подписки её ещё нет. Apple требует авансовую цену, даже если пользователям отображается только план с обязательным сроком.
  4. Установите ежемесячную цену для базовой территории. Ежемесячная цена должна составлять от 1/12 до 1/8 авансовой цены. Например, при авансовой цене €59,99 ежемесячная цена может быть от €5,00 до €7,49.

App Store Connect рассчитывает цены для других стран на основе цен базовой территории.

Подробные инструкции можно найти в гайде Apple по предложению ежемесячных подписок с обязательством на 12 месяцев.

2. Настройка Adapty

Чтобы commitment plan отображался во флоу или в кастомных пейволах, включите его для годового продукта в Adapty. Если вы не используете ни то ни другое, этот шаг можно пропустить.

  1. Откройте годовой продукт. Если его ещё нет, создайте его и подключите подписку, которую вы настроили в App Store Connect. Не создавайте новый продукт через Adapty: это создаст отдельную подписку без commitment plan.

  2. Откройте вкладку App Store и выберите Offer monthly payments with a 12-month commitment.

    App Store tab of a yearly product with the Offer monthly payments with a 12-month commitment checkbox
  3. Во всплывающем окне из списка Monthly price, USD выберите цену рассрочки, соответствующую значению в App Store Connect. Список содержит только ценовые точки App Store в допустимом диапазоне. Эта цена является справочным значением: Adapty не отправляет её в App Store Connect.

    Monthly with 12-month commitment pop-up with the Monthly price, USD field

3. Настройте офферы

В App Store Connect у каждого тарифного плана есть собственные introductory offer, promotional offer, win-back offer и коды офферов. Оффер для авансового плана не применяется к плану с обязательством.

  • Бесплатные пробные периоды и другие introductory offers: Настройте предложение для тарифного плана с обязательством в App Store Connect. Adapty применяет introductory offers автоматически. Когда introductory offer заканчивается, начинается 12-месячное обязательство подписчика.
  • Promotional и win-back offers: Настройте promotional или win-back offers для тарифного плана с обязательством в App Store Connect. Затем добавьте предложения в Adapty и установите для них App Store plan — Monthly with 12-month commitment. Флоу или продукт пейвола показывает только предложения для своего тарифного плана. Если вы не используете ни флоу, ни кастомные пейволы, добавлять предложения в Adapty не нужно.
  • Промокоды: Настройте промокоды для тарифного плана с обязательством в App Store Connect.

4. Добавьте на пейвол или во флоу

Warning

Apple требует отображать и цену в рассрочку, и годовую сумму до совершения покупки.

Флоу

  1. В конструкторе флоу откройте панель Products и добавьте годовой продукт с тегом Monthly на экран. Чтобы также продавать план с единовременной оплатой на том же экране, добавьте продукт с тегом Upfront.
    • Чтобы предложить единовременный оффер пользователям, которые покупают план с полной оплатой, — на более ранней версии SDK или там, где рассрочный план недоступен, — выберите его в поле Fallback offer.
  2. Назначьте продукт Monthly на карточку продукта или на действие Purchase.
  3. Чтобы отобразить цену за рассрочку, вставьте переменные prod_billing_price и prod_billing_period. Чтобы показать общую годовую сумму, вставьте prod_price. Переменные рассрочки требуют Adapty SDK v4.3.1 или выше для iOS, либо v4.3.0 или выше для React Native или Flutter.
  4. Чтобы предварительно просмотреть экран для пользователей, которые не могут купить рассрочный план, откройте в панели Products меню продукта Monthly и выберите Offer > Monthly plan unavailable.

Пользовательский пейвол

  1. В кастомном пейволе добавьте годовой продукт и укажите для него Billing plan → Monthly. Чтобы на том же пейволе продавать и предоплатный план, добавьте годовой продукт ещё раз с планом Upfront.
    • Если вы хотите предложить предоплатный оффер пользователям, которые приобретают предоплатный план, но на более старой версии SDK или там, где план с обязательством не применяется, — выберите его в поле Fallback offer.
  2. В приложении отображайте цену из product.subscriptionPricingTerms. Для пользователей, которым доступен план с обязательством, Adapty SDK вернёт его условия. Для всех остальных SDK вернёт условия предоплатного плана:
    • Чтобы определить, какой план вернул SDK, проверьте product.subscriptionPricingTerms?.billingPlan. Значение .monthly соответствует плану с обязательством, .upFront — предоплатному плану.
    • Для отображения цены за период используйте subscriptionPricingTerms.localizedBillingPrice и subscriptionPricingTerms.billingPeriod.
    • Для отображения итоговой годовой суммы используйте subscriptionPricingTerms.commitmentInfo.localizedPrice и subscriptionPricingTerms.commitmentInfo.period. Для плана с обязательством product.localizedPrice и product.subscriptionPeriod возвращают те же годовые значения.
    • В React Native читайте условия из product.subscription?.ios?.pricingTerms. Значение billingPlan равно 'monthly' для плана с обязательством и 'up_front' для предоплатного плана. Для цены за период используйте billingPrice.localizedString и billingPeriod. Для итоговой годовой суммы — commitmentInfo.price.localizedString и commitmentInfo.period.
    • В Flutter читайте условия из product.subscription?.pricingTerms. Значение billingPlan равно AdaptySubscriptionBillingPlan.monthly для плана с обязательством и AdaptySubscriptionBillingPlan.upFront для предоплатного плана. Для цены за период используйте billingPrice.localizedString и billingPeriod. Для итоговой годовой суммы — commitmentInfo.price.localizedString и commitmentInfo.period.

Пользователи не могут приобрести план с обязательным периодом в следующих случаях:

  • Неподдерживаемая версия ОС или страна: На устройстве пользователя установлена версия системы ниже 26.4, либо план недоступен в его App Store по стране. SDK Adapty возвращает цену обычного плана без рассрочки.
  • Существующая подписка без рассрочки: StoreKit сообщает, что пользователь уже подписан. Для смены плана подписчики используют настройки подписки Apple.
  • Встроенная покупка через App Store: Пользователь выбирает продукт в App Store, после чего SDK Adapty инициирует покупку в вашем приложении. Для таких покупок SDK поддерживает только обычный план без рассрочки.

Чтобы прекратить предлагать тарифный план с обязательством, в своих флоу замените или удалите продукт Monthly. В пользовательских пейволах установите для годового продукта значение Billing plan → Upfront или удалите строку Monthly. Снять флажок Offer monthly payments with a 12-month commitment в Adapty невозможно. Текущие подписчики по-прежнему продлеваются с новым обязательством каждый год — если только вы не нажмёте Remove Monthly Billing для годовой подписки в App Store Connect. Подписчики, уже взявшие на себя обязательство, продолжают платить до его окончания.

5. Протестируйте план в песочнице

Следуйте гайду по тестированию в песочнице, используя два аккаунта песочницы:

  • Аккаунт из страны, где доступен план с рассрочкой: пейвол должен отображать план с рассрочкой с ежемесячной ценой и общей суммой. После покупки в профиле пользователя песочницы должен появиться уровень доступа годового продукта.
  • Аккаунт из США: пейвол должен отображать только план с единовременной оплатой.

Если ваш код обрабатывает идентификаторы продуктов из вебхуков или Server-side API, убедитесь, что он получает покупки commitment-plan как <product_id>:monthly.

Для локального тестирования логики покупок используйте StoreKit Testing в Xcode версии 26.5 или новее. Покупки в StoreKit Testing не попадают в Adapty.

Отображение прогресса обязательства в приложении

Чтобы показывать подписчикам, насколько они продвинулись в рамках обязательства, считайте уровень доступа из профиля пользователя. Свойства billingPlan и commitmentInfo доступны начиная с Adapty SDK v4.3 для iOS и v4.3.0 для React Native и Flutter.

  • Чтобы определить, находится ли подписчик на тарифе с обязательным периодом, сравните billingPlan с ежемесячным значением. Не проверяйте, установлено ли свойство: оно также может содержать значение upfront.
  • Для отображения прогресса используйте commitmentInfo.billingPeriodNumber для текущего платежа и commitmentInfo.totalBillingPeriods для количества платежей.
  • Чтобы отобразить дату окончания обязательного периода, используйте commitmentInfo.expiresAt, а не свойство expiresAt уровня доступа.

Устранение неполадок

  • Отсутствует флажок для ежемесячных платежей: флажок Offer monthly payments with a 12-month commitment появляется только для продукта типа Annual с идентификатором продукта App Store. Он остаётся неактивным, пока у продукта не указана Price (USD).
  • Пользователи не видят бесплатный пробный период или другое предложение для тарифа с обязательством: в App Store Connect каждое предложение привязано к одному тарифному плану. Настройте предложение для тарифа с обязательством. Для promotional offer или win-back offer также задайте App Store plan предложения в Adapty как Monthly with 12-month commitment.
  • Все пользователи видят единовременную цену: проверьте оба условия:
    • Приложение собрано с Xcode 26.5 или более новой версией. При использовании более ранней версии Xcode SDK Adapty всегда возвращает цену единовременного тарифа.
    • В флоу экран использует годовой продукт с тегом Monthly. В кастомном пейволе для годового продукта Billing plan установлен как Monthly.
  • Часть пользователей видит единовременную цену: эти пользователи не могут купить тариф с обязательством.
  • Пейвол показывает годовую сумму вместо суммы рассрочки:
    • В флоу prod_price возвращает годовую сумму. Чтобы отобразить сумму рассрочки, используйте prod_billing_price. В Adapty iOS SDK v4.3.0 prod_billing_price также показывает годовую сумму: обновите SDK до v4.3.1 или более новой версии.
    • В кастомном пейволе product.localizedPrice возвращает годовую сумму. Чтобы отобразить сумму рассрочки, используйте subscriptionPricingTerms.localizedBillingPrice. В React Native используйте product.subscription?.ios?.pricingTerms?.billingPrice.localizedString. В Flutter используйте product.subscription?.pricingTerms?.billingPrice.localizedString.