Реалізація підписок у iOS: StoreKit 2, grace period та промо-офери

Auto-renewable subscriptions — найскладніший тип IAP. Не тому що StoreKit складний сам по собі, а тому що навколо нього виростає ціла екосистема: grace periods, billing retry, downgrade/upgrade між тирами, promo offers, introductory pricing, і нарешті — обробка churn через `expirationIntent`. Помилк

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Реалізація підписок у iOS: StoreKit 2, grace period та промо-офери
Складний
~3-5 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Auto-renewable subscriptions — найскладніший тип IAP. Не тому що StoreKit складний сам по собі, а тому що навколо нього виростає ціла екосистема: grace periods, billing retry, downgrade/upgrade між тирами, promo offers, introductory pricing, і нарешті — обробка churn через expirationIntent. Помилка на будь-якому етапі веде до втрат доходу. Ми впроваджуємо підписки під ключ за 3–5 днів, гарантуючи коректну логіку на всіх етапах життєвого циклу.

Життєвий цикл підписки і де він ламається

Підписка в iOS існує не тільки поки активна. Apple автоматично продовжує її за 24 години до завершення. Якщо оплата не пройшла — починається billing retry period (до 60 днів). У цей час статус підписки expired, але Apple продовжує спроби списання. Більшість додатків блокують доступ одразу після expirationDate — це невірно.

Правильна логіка: перевіряти renewalInfo.isInBillingRetryPeriod. Якщо true — даємо grace period (налаштовується в App Store Connect, зазвичай 6 днів для річних, 3 дні для місячних). Користувач із проблемою картки не повинен втрачати доступ негайно.

StoreKit 2 обробляє grace period прозоро, що знижує churn на 20–30% порівняно з ручною реалізацією на StoreKit 1. Ось приклад коректної перевірки:

for await result in Transaction.currentEntitlements { guard case .verified(let transaction) = result else { continue } if transaction.productType == .autoRenewable { let renewalInfo = try? await transaction.subscriptionStatus.first?.renewalInfo let isInGracePeriod = renewalInfo?.gracePeriodExpirationDate != nil let isRetrying = renewalInfo?.isInBillingRetryPeriod == true if transaction.revocationDate == nil && (transaction.expirationDate ?? .distantPast > .now || isInGracePeriod || isRetrying) { unlockPremium() } } } 

Чому важливий grace period?

Без grace period користувачі з проблемами оплати миттєво втрачають доступ. Apple дозволяє налаштувати до 16 днів відстрочки — за цей час клієнт встигає змінити картку, а ви зберігаєте його. Наш досвід показує, що 70% користувачів повертаються до оплати протягом grace period. Якщо ж блокувати доступ одразу — вони йдуть назавжди.

Тири та переходи між ними

Якщо в додатку декілька тирів (Basic, Pro, Enterprise) — потрібна subscription group в App Store Connect. Всі тири в одній групі, користувач може мати лише одну активну підписку в групі одночасно.

Upgrade (перехід на дорожчий тир) — діє одразу, Apple перераховує залишок. Downgrade — набирає чинності в наступний розрахунковий період. Crossgrade (одна ціна, інший тир) — залежить від налаштування: можна зробити immediate або deferred.

Відстежувати це на клієнті через originalTransactionID та subscriptionGroupID. На сервері — зберігати повну історію транзакцій та обробляти Apple Server Notifications v2 (App Store Server Notifications). Типи подій, які обов'язково обробляти: DID_RENEW, DID_FAIL_TO_RENEW, EXPIRED, GRACE_PERIOD_EXPIRED, REFUND.

Як обробляти переходи між тирами?

Upgrade активується негайно — Apple пропорційно перераховує вартість. Downgrade відкладається до наступного циклу. Crossgrade можна налаштувати як immediate або deferred в App Store Connect. Важливо коректно оновлювати UI, показуючи користувачеві дату набрання чинності зміни. Для цього використовуйте renewalInfo.renewalDate та offerType.

Introductory та promotional offers

Introductory pricing (перші N періодів за зниженою ціною) налаштовується в App Store Connect і автоматично застосовується для нових підписників. Проблема — користувач, який відписався і хоче повернутися, за замовчуванням не отримує інтро-ціну знову. Для цього існують promotional offers — їх можна видавати за своєю логікою (win-back кампанії).

Тип пропозиції Налаштування Кому доступно Умови застосування
Introductory В App Store Connect Нові підписники Автоматично, один раз
Promotional Генерація підпису на сервері Будь-які користувачі За вашою логікою, будь-який період
Promo-код App Store Connect Всі Фіксована знижка, обмежена кількість

Підпис для promotional offer генерується на сервері з приватним ключем із App Store Connect:

// На клієнті створюємо paymentDiscount let discount = SKPaymentDiscount( identifier: "winback_3months", keyIdentifier: keyID, nonce: nonce, // UUID з сервера signature: signature, // підпис з сервера timestamp: timestamp ) payment.paymentDiscount = discount 

Без серверного підпису promotional offer недійсний — Apple перевіряє підпис на своїй стороні.

Що входить в роботу

  • Аудит поточної реалізації IAP та підписних груп
  • Проектування схеми тирів і груп (subscription group) з урахуванням бізнес-логіки
  • Інтеграція StoreKit 2 з підтримкою grace period, billing retry та обробки помилок
  • Налаштування App Store Server Notifications (v2) на бекенді з обробкою всіх критичних подій
  • Реалізація win-back логіки з використанням promotional offers
  • Документування коду та інтеграція аналітики відписок
  • Навчання команди роботі з Sandbox та тестуванням підписок
  • Підтримка після запуску (1 місяць безкоштовно)

Процес роботи

Аудит поточної реалізації → проектування структури підписних груп і тирів → інтеграція StoreKit 2 з підтримкою grace period та billing retry → налаштування App Store Server Notifications на бекенді → реалізація логіки win-back та промо-оферів → тестування в Sandbox з імітацією завершення підписки (Sandbox скорочує періоди: місяць = 5 хвилин).

Терміни — 3–5 днів залежно від кількості тирів, наявності бекенду та вимог до аналітики відписок. Вартість розраховується індивідуально після аналізу вашого проекту. Зв'яжіться з нами — оцінимо обсяг та запропонуємо оптимальне рішення. Отримайте консультацію сертифікованого iOS-розробника з 5+ років досвіду впровадження підписок.

Ми гарантуємо: коректну обробку billing retry, grace period та всіх типів переходів, відповідність App Store Review Guidelines (Section 4.2 та 5.1), а також повну підтримку на етапі тестування та публікації.