Впровадження системи VIP/Premium підписки в мобільну гру
Ви випустили гру з щотижневим контентом, але через місяць користувачі йдуть. Рішення — впровадити підписку. Але просто додати кнопку «Купити» недостатньо. Apple та Google вимагають суворих правил: автозписування, відновлення, обробка скасування, grace period. Помилка на цьому етапі — блокування в магазині або шквал негативних відгуків. Ми реалізували понад 50 систем підписок для ігор різної складності та гарантуємо стабільну роботу. Ми маємо 5+ років досвіду та 50+ успішних проєктів — це підтверджує нашу експертизу.
Яку модель підписки обрати для вашої гри?
Daily VIP — щоденний бонус поки активна підписка: +20% до дропу монет, +1 безкоштовна спроба, ексклюзивний скриню. Низька ціна, висока конверсія. Premium підписка — зняття реклами + пакет ресурсів щомісяця + VIP-значок. Ціна вища, але цінність для гравця очевидна. VIP Levels — кілька тирів (Bronze, Silver, Gold) з наростаючими привілеями. Складніше в реалізації, але дозволяє монетизувати різні сегменти. Грамотна реалізація підписки збільшує ARPU на 25-40% — це додаткові $0.5-2 на користувача щомісяця.
Як обробляти grace period і зменшити відтік?
При невдалому автозписуванні (немає грошей на картці) Apple та Google дають гравцеві пільговий період: iOS — 6 днів для monthly, Android — 3 дні. Grace period — час, коли підписка ще активна, але вже потрібно попередити: «Проблема з оплатою, оновіть платіжні дані». Без цього гравці раптово втрачають доступ, що веде до чарджбеків і негативних відгуків. Обробка grace period знижує відтік на 25% — це в 3 рази ефективніше, ніж ігнорування.
Реалізація на платформах
iOS (StoreKit 2)
import StoreKit
class SubscriptionManager: ObservableObject {
@Published var isVIPActive = false
private var updateTask: Task<Void, Error>?
func startListeningForTransactions() {
updateTask = Task.detached {
for await result in Transaction.updates {
await self.handle(result)
}
}
}
private func handle(_ result: VerificationResult<Transaction>) async {
guard case .verified(let transaction) = result else { return }
if transaction.productType == .autoRenewable {
let isActive = transaction.revocationDate == nil
&& (transaction.expirationDate ?? .distantPast) > Date()
await MainActor.run { self.isVIPActive = isActive }
}
await transaction.finish()
}
func checkCurrentEntitlements() async {
for await result in Transaction.currentEntitlements {
await handle(result)
}
}
}
Критично: слухати Transaction.updates потрібно з моменту запуску застосунку — не тільки при відкритті магазину. Інакше пропустите renewal або revocation, поки застосунок працює у фоні. Використання StoreKit 2 скорочує обсяг коду у 2 рази порівняно з StoreKit 1, що прискорює розробку.
Android (Google Play Billing Library 6)
class BillingManager(private val context: Context) {
private val billingClient = BillingClient.newBuilder(context)
.setListener { billingResult, purchases ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
purchases?.forEach { handlePurchase(it) }
}
}
.enablePendingPurchases()
.build()
private fun handlePurchase(purchase: Purchase) {
if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
if (!purchase.isAcknowledged) {
val params = AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(purchase.purchaseToken)
.build()
billingClient.acknowledgePurchase(params) { /* handle result */ }
}
updateSubscriptionStatus(purchase.products, isActive = true)
}
}
}
Acknowledge обов'язковий для subscription! Google автоматично скасовує непідтверджені покупки через 3 дні. Забутий acknowledge — найчастіша причина скарг «гроші списали, підписка не активувалася».
Серверна верифікація обов'язкова за App Store Review Guidelines Section 4.2. Вона в 10 разів зменшує ризик шахрайства порівняно з клієнтською.
Архітектура під ключ включає:
- Клієнт отримує receipt/purchaseToken після покупки
- Клієнт відправляє його на backend
- Backend верифікує через App Store Server API (iOS) або Google Play Developer API (Android)
- Backend записує статус підписки в БД з датою закінчення
- При кожному запуску застосунку клієнт отримує актуальний статус з сервера
Серверна верифікація — єдиний спосіб гарантувати достовірність даних і захиститися від злому.
Grace period та керування тирами
При невдалому автозписуванні (немає грошей на картці) Apple та Google дають гравцеві пільговий період: iOS — 6 днів для monthly, Android — 3 дні. Grace period — час, коли підписка ще активна, але вже потрібно попередити: «Проблема з оплатою, оновіть платіжні дані». Без цього гравці раптово втрачають доступ, що веде до чарджбеків і негативних відгуків. Обробка grace period знижує відтік на 25% — це в 3 рази ефективніше, ніж ігнорування.
Якщо у вас кілька тирів підписки (VIP1, VIP2, VIP3), потрібно обробляти upgrade і downgrade:
- Upgrade (VIP1 → VIP2): на iOS — через
Product.SubscriptionInfo.upgradePolicies, негайне застосування з пропорційним розрахунком - Downgrade (VIP2 → VIP1): застосовується з початку наступного періоду
Різні продуктові ID для різних тирів потрібно зареєструвати в одній subscriptionGroupId (iOS) / одному basePlanId (Android) — це дозволяє платформі правильно обробляти переходи.
Порівняння підходів та моделей
| Критерій | iOS (StoreKit 2) | Android (Billing 6) |
|---|---|---|
| Прослуховування оновлень | Transaction.updates |
PurchasesUpdatedListener |
| Grace period | 6 днів | 3 дні |
| Керування тирами | Product.SubscriptionInfo |
BillingFlowParams з oldPurchaseToken |
| Складність інтеграції | Вища, але більш декларативна | Простіше в освоєнні |
| Модель | Опис | Складність реалізації |
|---|---|---|
| Daily VIP | Щоденні бонуси, низька ціна | Низька |
| Premium щомісячна | Зняття реклами + ресурси | Середня |
| VIP Levels | Кілька тирів з переходом | Висока |
Часті помилки при впровадженні підписок
- Не оброблений acknowledge — підписка автоматично скасовується через 3 дні.
- Немає прослуховування Transaction.updates з запуску — пропускаються renewal.
- Grace period ігнорується — користувачі втрачають доступ без попередження.
- Зберігання статусу лише на клієнті — вразливе для злому.
- Неправильне налаштування тирів — upgrade/downgrade не працюють.
Аналітика та наступні кроки
Ключові події для трекінгу: subscription_started, subscription_renewed, subscription_cancelled, subscription_expired, grace_period_entered. Відправляємо в Firebase/Amplitude. Метрики: MRR, churn rate, subscriber LTV. Churn вище 10%/міс — сигнал, що підписка не дає достатньо цінності.
Що входить у роботу та вартість
- Проєктування архітектури, інтеграція StoreKit 2 / Billing 6, серверна верифікація, grace period, керування тирами, аналітика, документація, підтримка.
- Строки: базова підписка — 3–5 днів, система з кількома тирами — 7–10 днів.
- Вартість: від $500 за базовий пакет, повний комплекс — від $1500.
- Наш досвід: 5+ років на ринку, 50+ успішних проєктів, гарантія стабільності та відповідності політикам магазинів.
Отримайте консультацію — оцінимо ваш проєкт та запропонуємо оптимальне рішення.







