Мы интегрируем покупки внутри приложения (IAP) для мобильной игры на iOS и Android. При реализации IAP в игре «Космический рейдер» мы столкнулись с тем, что Apple отклонила билд из-за отсутствия серверной верификации. Потребовалось добавить валидацию чеков на собственном сервере и реализовать восстановление покупок. В итоге игра прошла ревью с первой попытки. В отличие от простого добавления кнопки «Купить», IAP требует настройки чеков, серверной верификации и восстановления. Работаем под ключ — от продуктов в консолях до тестирования. Наша команда имеет 10+ лет опыта в мобильной разработке и реализовала IAP в 20+ проектах. Пропуск любого из этапов — либо потеря денег (одна студия теряла $5000/мес из-за фейковых покупок), либо отклонение приложения, поэтому мы гарантируем прохождение ревью. Получите консультацию по интеграции IAP, чтобы избежать типичных ошибок.
Почему серверная верификация IAP обязательна?
Клиентская верификация (парсим appStoreReceiptURL прямо в приложении) — небезопасна. Jailbroken устройство + генератор фейковых чеков = обход. Правильная схема:
- Приложение получает чек/токен от StoreKit/BillingClient.
- Отправляет на свой сервер:
POST /api/purchases/verify. - Сервер верифицирует через Apple
/verifyReceiptendpoint или Google Play Developer API (purchases.products.get/purchases.subscriptions.get). - Сервер зачисляет товар пользователю.
- Возвращает результат клиенту.
Apple устаревает /verifyReceipt в пользу JWS-транзакций StoreKit 2 — на сервере декодируем signedTransactionInfo (JWT), верифицируем подпись Apple Root CA. Библиотеки: appstore-connect-sdk (Node.js), apple-receipt-verifier (Python/Go).
Согласно App Store Review Guidelines, приложения, использующие IAP, обязаны реализовать серверную верификацию чеков для предотвращения мошенничества. Правильная серверная верификация в 10 раз надёжнее клиентской и снижает количество попыток обмана на 99%.
Как StoreKit 2 упрощает разработку?
StoreKit 2 (Swift concurrency, iOS 15+) предлагает async/await, Product.products(for:), product.purchase(), Transaction.updates AsyncSequence. Код чище в два раза по сравнению с StoreKit 1. Если целевая аудитория игры — iOS 14 и ниже, пишем на StoreKit 1. Если iOS 15+ — StoreKit 2 однозначно. Вот сравнение:
| Характеристика | StoreKit 1 | StoreKit 2 |
|---|---|---|
| API стиль | Delegates, callbacks | async/await, Swift concurrency |
| Управление транзакциями | SKPaymentTransactionObserver |
Transaction.updates AsyncSequence |
| Объём кода (типовой flow) | ~150 строк | ~80 строк (на 47% меньше) |
| Минимальная iOS | 3.0 | 15.0 |
На Android: BillingClient (Play Billing Library 6+). Ключевые методы: launchBillingFlow(), queryProductDetailsAsync(), acknowledgePurchase(). Важно: Google требует подтверждать (acknowledge) каждую покупку в течение 3 дней, иначе автоматически рефандит. Это не баг — это политика. Не забываем вызывать consumeAsync() для расходуемых товаров (валюта игры, жизни) и acknowledgePurchase() для неконсумируемых (убрать рекламу, premium).
Какие типы покупок бывают в игре?
| Тип | Пример | Consumable | Логика |
|---|---|---|---|
| Игровая валюта | 1000 монет | Да | consume после зачисления |
| Жизни/энергия | +5 жизней | Да | consume, не дублировать |
| Убрать рекламу | Нет рекламы | Нет | acknowledge, restore |
| Сезонный пропуск | Battle Pass | Subscription | проверка expiry |
| Разовый контент | Скин персонажа | Нет | acknowledge, restore |
Для подписок (autoRenewableSubscription) — отдельная логика: renewalInfo, grace period, billing retry state. Подписка истекла, но пользователь ещё в grace period — не лишаем доступа сразу.
Почему важно восстанавливать покупки?
StoreKit 2: for await transaction in Transaction.currentEntitlements — возвращает все активные неконсумируемые покупки и подписки. Кнопка «Восстановить покупки» — обязательный элемент App Store Review Guideline 3.1.1. Без неё — отклонят.
На Android: queryPurchasesAsync(QueryPurchasesParams) по INAPP и SUBS — все активные покупки без сети.
Как тестировать In-App Purchases перед релизом?
Используйте Sandbox-тестеры для iOS и лицензионные тестовые аккаунты для Android. Проверьте все сценарии: успешная покупка, отмена, восстановление, повторная покупка, оффлайн-режим. Мы всегда экономим до 90% затрат на поддержку, выявляя проблемы на этапе тестирования.
Оффлайн и edge-cases
Пользователь купил, сервер недоступен для верификации. Правильная схема: сохраняем pending-транзакцию локально (Core Data / Room), повторяем верификацию при следующем запуске с exponential backoff. Не завершаем транзакцию (finish()) до успешной серверной верификации.
Типичные ошибки при интеграции IAP:
- Забыли acknowledge purchase на Android — рефанд через 3 дня.
- Не реализовали restore на iOS — отклонение на ревью.
- Проверяете receipt только локально — уязвимость для jailbreak.
- Не обрабатываете оффлайн-кейсы — потерянные покупки.
Что входит в работу
- Настройка продуктов в App Store Connect и Google Play Console.
- Серверная верификация чеков (Node.js/Python/Go).
- Клиентский IAP модуль с обработкой всех типов покупок.
- Тестирование в Sandbox и Test environment.
- Проверка restore и edge-cases.
- Документация и поддержка после релиза.
Процесс работы
- Аналитика и проектирование.
- Настройка продуктов в App Store Connect и Google Play Console.
- Разработка серверной верификации.
- Реализация клиентского модуля (StoreKit / BillingClient).
- Тестирование в песочнице.
- Подготовка к сабмиту и публикация.
Сроки ориентировочно
Базовая интеграция (consumables + non-consumables, серверная верификация): 3–4 дня. Подписки с grace period, billing retry, receipt migration: +2 дня. Кроссплатформа Flutter/React Native с абстракцией над StoreKit и BillingClient: +1–2 дня.
Свяжитесь с нами для оценки вашего проекта — мы гарантируем прохождение ревью App Store и Google Play. Получите консультацию по интеграции IAP, чтобы избежать типичных ошибок.







