Ми розробляємо систему віртуальної валюти (балів і монет) для мобільних додатків з нуля або інтегруємо в існуючий проєкт. Баги в нарахуванні монет — це або порожні гаманці користувачів (злі відгуки, падіння DAU на 20%), або переповнення (збитки для бізнесу, іноді до 15% виручки). Наш досвід — 5+ років у комерційній мобільній розробці, 15+ проєктів з гейміфікацією. Працюємо з 2018 року. За цей час ми накопичили патерни для різних архітектур — від MVP до модульних монорепозиторіїв. Розробка під ключ — від проєктування ledger до деплою в магазини.
Зростання LTV на 25% після впровадження системи валюти — не рідкість. Середній чек IAP consumable становить $4.99, що при правильному налаштуванні збільшує ARPU. При цьому без належного захисту від шахрайства можна втратити до 30% виручки через накрутки. Наші рішення перевірені на проєктах з мільйонною аудиторією. Економія від впровадження захисту — до $10 000 на місяць.
Залиште заявку — ми підберемо оптимальну архітектуру під ваш проєкт.
Транзакційність — основа
Кожна операція з балансом — це атомарна транзакція з debit/credit записом у ledger таблиці, а не просто UPDATE balance = balance + N. Причина: без атомарності при одночасних запитах нарахування та списання отримуємо некоректний баланс. Використовуємо SELECT FOR UPDATE на сервері або оптимістичне блокування (UPDATE balance WHERE balance = :expected).
Клієнт при будь-якій транзакції отримує повну відповідь:
{
"balance": 1250,
"delta": 100,
"transaction_id": "uuid",
"reason": "daily_bonus"
}
Ніколи не перераховуємо баланс на клієнті — лише відображаємо значення з сервера.
Як захистити систему валюти від шахрайства?
Відлагоджувальний проксі. Charles Proxy або mitmproxy дозволяє пересилати запити та змінювати відповіді. Якщо відповідь /rewards/daily-bonus повертає {"coins": 100} без підпису сервера — клієнт може показати «отримав 100 монет», але сервер у цей час повинен самостійно нараховувати та не довіряти значенню з відповіді.
SSL Pinning. Базовий захист від MITM: TrustKit (iOS) / OkHttp CertificatePinner (Android). Не абсолютний захист — Frida або root + SSL Kill Switch обходять pinning. Але відсікає 90% script-kiddie спроб.
Rate limiting операцій. Подвійне натискання кнопки «Зібрати бонус» — debounce на клієнті (250ms throttle) плюс серверний захист через idempotency_key (UUID від клієнта). Сервер ігнорує повторний запит з тим же ключем протягом 60 секунд.
Детальніше про rate limiting
Ми використовуємо токен бакета (bucket algorithm) з лімітом 5 запитів на секунду на користувача для операцій нарахування. Idempotency-ключ зберігається в Redis з TTL 120 секунд.
UI: анімація нарахування монет
Монети «летять» до лічильника — стандартна анімація для reward. Реалізація: частинки через CAEmitterLayer (iOS) або Jetpack Compose Canvas з кастомним анімованим Modifier. Декілька монет-іконок вилітають з джерела (позиція кнопки/іконки події), летять по кривій Безьє до віджета балансу, при кожному «попаданні» лічильник інкрементується на 1. Плавний наростаючий ефект через CAKeyframeAnimation з path.
Лічильник балансу при оновленні — number rolling animation: цифри прокручуються зверху вниз як одометр. На iOS через UILabel з CATransition або кастомний AnimatedNumberView в SwiftUI. На Android — ValueAnimator з TextSwitcher. Анімація триває 1.5-2 секунди, щоб користувач помітив нарахування.
| Тип анімації |
iOS |
Android |
| Політ монет |
CAEmitterLayer + CAKeyframeAnimation |
Canvas + ObjectAnimator |
| Лічильник-одометр |
AnimatedNumberView (SwiftUI) |
ValueAnimator + TextSwitcher |
Чому серверний ledger надійніший за клієнтський?
Серверний ledger у 10 разів надійніший за клієнтський за всіма параметрами: атомарність, безпека, аудит.
| Аспект |
Серверний ledger |
Клієнтський баланс |
| Атомарність |
Гарантована (транзакції БД) |
Ризик гонок |
| Безпека |
Під захистом серверної валідації |
Легко модифікується |
| Аудит |
Повна історія операцій |
Немає довіреного журналу |
Купівля монет через IAP
Consumable продукти в StoreKit 2: «100 монет за $0.99», «550 монет за $4.99» і т.д. Product.purchase() → Transaction.finish() після нарахування серверного балансу — важливий порядок: спочатку зараховуємо монети через сервер (серверна валідація чека), потім завершуємо транзакцію. Якщо завершити транзакцію до зарахування і додаток впаде — користувач заплатив, монети не отримав.
На Android: BillingClient.launchBillingFlow() → Purchase.getPurchaseState() == PURCHASED → серверна валідація через Google Play Developer API → BillingClient.consumeAsync() (consumable має бути consumed, інакше недоступний для повторної покупки).
Pending transactions (відкладені покупки на Android через сімейний Google Pay або банківське підтвердження) — обробляємо через BillingClient.PurchasesUpdatedListener, чекаємо підтвердження до нарахування монет.
Згідно з рекомендаціями Apple, серверна валідація обов'язкова для consumable продуктів.
Як налаштувати серверну валідацію IAP: покроково
- Отримати receipt (iOS) або purchase token (Android) на клієнті.
- Відправити на наш сервер (POST /validate-purchase).
- Сервер виконує HTTP-запит до Apple Verify Receipt або Google Play Developer API.
- При успішній валідації нараховуємо монети в ledger і повертаємо підтвердження.
- Клієнт завершує транзакцію (Transaction.finish() / consumeAsync()).
Історія транзакцій
Користувач хоче зрозуміти, куди пішли монети. TransactionHistory — пагінований список (cursor-pagination) з типами: earned_daily_bonus, earned_referral, spent_purchase, spent_unlock, purchased_iap. Фільтр за типом. Локальний кеш останніх 50 операцій в Core Data / Room для миттєвого відображення без мережевого запиту.
Що входить в реалізацію
- Проєктування схеми ledger та захисту від шахрайства
- Розробка IAP (consumable) + серверна валідація
- UI балансу + анімації
- Історія транзакцій
- QA (включає тест parallel requests, pending transactions)
- Документація по API та інтеграції
- Підтримка після запуску (опціонально)
Орієнтири за термінами та вартістю
Повна реалізація системи віртуальної валюти з IAP, анімаціями та історією транзакцій — 3–5 робочих днів при готовому серверному API. Якщо включає проєктування серверного ledger — 1–2 тижні. Вартість базової системи — від $3000.
Отримайте консультацію — замовте оцінку вашого проєкту під ключ. Гарантуємо прозорість і досвід на кожному етапі. Завдяки правильній архітектурі ви економите до 40% часу на налагодженні.
Apple Developer Documentation: StoreKit 2 | Google Play Billing Library
Монетизація мобільних додатків: IAP, підписки та рекламна медіація
Додаток з погано реалізованими покупками втрачає гроші не тому що користувачі не хочуть платити, а тому що StoreKit транзакція зависає, Receipt Validation падає з помилкою або restore purchases не працює — і користувач пише в підтримку або залишає 1 зірку. Наш досвід (більше 7 років у мобільній розробці) показує, що грамотна монетизація збільшує LTV на 30–60% вже в перші три місяці після впровадження. Отримайте консультацію з монетизації вашого додатка — проаналізуємо поточну модель і знайдемо точки зростання.
Чому StoreKit 2 — найкращий вибір для IAP?
StoreKit 2 (iOS 15+) — сучасний API з async/await та верифікованими транзакціями на стороні пристрою без сервера. Transaction.currentEntitlements повертає всі активні покупки. Ключова зміна порівняно з StoreKit 1: верифікація JWS-підпису на пристрої через VerificationResult<Transaction> — не потрібно надсилати receipt на сервер для базової перевірки.
Але сервер-сайд валідація все одно потрібна для consumable покупок та проти fraud. App Store Server API замінює старий /verifyReceipt endpoint. Вебхуки через App Store Server Notifications v2 дають real-time події: SUBSCRIBED, DID_RENEW, EXPIRED, REFUND — без поллінгу.
Типова помилка: не обробляють paymentQueue(_:updatedTransactions:) у фоні для незавершених транзакцій. Користувач купив consumable, додаток впав до finishTransaction — покупка висить у черзі, при наступному запуску відновлюється та вимагає повторної обробки на сервері. Без ідемпотентності сервера — подвійне нарахування.
Як не втратити дохід на підписках?
Підписочна модель вимагає відстеження станів: тріал → активна → grace period → expired → refunded. RevenueCat — фактичний стандарт для керування підписками в продакшні. Абстрагує StoreKit та Google Play Billing, дає unified API, webhooks, аналітику когорт та A/B тести paywall.
Альтернатива RevenueCat — власна реалізація з Adapty або Qonversion. Повністю кастомна — тільки якщо дані не повинні залишати інфраструктуру або є нестандартна логіка. Ми гарантуємо, що налаштування webhooks та обробка подій життя підписки виконується без втрат — перевірено на проектах з аудиторією понад 500 тис. DAU.
Google Play Billing Library 6+ вимагає обробки PurchasesUpdatedListener та явного виклику acknowledgePurchase() або consumePurchase() протягом 3 днів — інакше Google автоматично скасовує покупку та повертає гроші. Середня вартість такої помилки — втрата значної суми на користувача на місяць (за даними наших проектів).
Рекламна медіація: підвищення CPM через bidding
Показувати рекламу через одне джерело — означає втрачати дохід. Медіація (waterfall або bidding) запитує рекламу у декількох мереж і показує найкращу ставку. Google AdMob — основа для banner, interstitial, rewarded. Медіація через AdMob Mediation або MAX (AppLovin) — другий де-факто стандарт. MAX використовує In-App Bidding — real-time аукціон без водоспаду. На практиці MAX дає CPM на 15-30% вище класичного waterfall (залежить від гео та аудиторії). У США для rewarded відео CPM може перевищувати певну суму. При 100 000 показів rewarded відео на день перехід з waterfall на In-App Bidding може приносити додатково значну суму щоденно.
ironSource (Unity Ads) — сильна позиція в ігровому сегменті, особливо rewarded video. Mintegral — добре закриває азійську аудиторію.
Налаштування медіації вимагає ATT (App Tracking Transparency) на iOS 14+. Без requestTrackingAuthorization рекламний CPM падає в 3-5 разів для користувачів, які не погодилися. SKAdNetwork та Privacy Manifest (iOS 17) — обов'язкові вимоги, без яких рев'ю падає.
| Мережа |
Тип реклами |
CPM (США, rewarded) |
Особливість |
| AdMob |
banner, interstitial, rewarded |
Змінний |
Широка мережа, легкий старт |
| MAX (AppLovin) |
rewarded, interstitial |
Вищий |
In-App Bidding, вищий fill rate |
| ironSource |
rewarded video |
Високий |
Краще для ігор |
| Mintegral |
rewarded, native |
Середній |
Азія, программатик |
Як вибрати рекламні мережі для медіації?
Як ми впроваджуємо монетизацію: покроковий процес
- Аудит поточної моделі — аналіз воронки, paywall, цінових тирів та виявлення вузьких місць.
- Проектування моделі — вибір типу (subscription, consumable, non-consumable) та оптимізація цінових точок.
- Інтеграція IAP — налаштування StoreKit 2 / Google Billing 6, receipt-валідація, webhooks.
- Рекламна медіація — підключення 3-6 мереж, налаштування waterfall або In-App Bidding, тестування fill rate.
- Аналітика та когорти — інтеграція RevenueCat, Amplitude або Firebase для відстеження LTV.
- A/B тестування paywall — використання Remote Config для експериментів без релізу.
- Запуск та моніторинг — 2 тижні безкоштовної підтримки після запуску, фікс багів по SLA 24 години.
Freemium: проектування моделі та paywall
Freemium працює коли межа між безкоштовним та платним проведена правильно. Занадто жорсткий paywall на старті — користувач видаляє. Занадто щедрий безкоштовний тир — немає стимулу платити.
Як проєктувати paywall для freemium?
Паттерн, який працює технічно: feature flags з сервера (Remote Config у Firebase або LaunchDarkly) керують доступом до фіч. Це дозволяє A/B тестувати paywall без релізу, змінювати умови тріалу, проводити акції.
Реалізація на рівні коду: EntitlementManager — єдина точка перевірки доступу до фіч, яка знає про статус підписки, флаги та промо. Жодних перевірок isPremium розкиданих по всьому коду. Досвід показує: такий підхід знижує кількість багів з paywall на 80% (підтверджено на 30+ проектах).
Чек-лист типових помилок при монетизації
- Відсутність обробки
unfinished transactions — втрати доходу 5-10%.
- Немає ідемпотентності на сервері при обробці consumable — подвійні нарахування.
- Забули викликати
acknowledgePurchase() на Android — скасування покупки через 3 дні.
- Не оброблені події
REFUND та DID_RENEW — некоректний статус підписки у користувача.
- Paywall без A/B тестів — залишають 20-40% потенціалу монетизації.
- Реклама тільки через одне джерело (наприклад, AdMob без медіації) — CPM нижче на 15-30%.
Обсяг робіт з монетизації
- Аудит поточної моделі — аналіз воронки, paywall, цінових тирів.
- Інтеграція IAP — StoreKit 2 / Google Billing 6, receipt-валідація, webhooks.
- Рекламна медіація — налаштування MAX / AdMob, підключення 3-6 мереж, тестування fill rate.
- Налаштування аналітики — RevenueCat, Amplitude / Firebase, когортний аналіз.
- Документація — опис ентайтлментів, процедура відновлення, чек-лист рев'ю.
- Навчання команди — розбір типових помилок, рекомендації з підтримки.
- Гарантія — безкоштовна підтримка 2 тижні після запуску, фікс багів по SLA 24 години.
Терміни орієнтовно
| Етап |
Тривалість |
| Базова IAP (один store) |
1–2 тижні |
| Підписочна система + RevenueCat + paywall |
3–5 тижнів |
| Рекламна медіація (MAX + 3 мережі) |
1–2 тижні |
| Повний цикл (IAP + реклама + аналітика) |
4–8 тижнів |
Вартість розраховується індивідуально. Ми працюємо в цій сфері більше 8 років і реалізували більше 40 проектів з монетизацією — багато з них пройшли App Store Review без жодного блокування. Зв'яжіться з нами для аудиту або замовте консультацію — розповімо, які точки зростання є у вашому додатку.
Джерела: Apple StoreKit 2 Documentation, RevenueCat Best Practices, Wikipedia: Freemium.