Реализация In-App Purchases (одноразовые покупки) для iOS

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация In-App Purchases (одноразовые покупки) для iOS
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация In-App Purchases (одноразовые покупки) для iOS

Non-consumable IAP — категория, где каждая ошибка в логике восстановления покупок превращается в жалобу в App Store и чарджбек. Пользователь купил «безлимитный режим» или «убрать рекламу», переустановил приложение — и не получил своё. Поддержка Apple не поможет: восстановление non-consumable это ответственность разработчика.

Что чаще всего идёт не так

Самая распространённая ошибка — вызывать SKPaymentQueue.default().restoreCompletedTransactions() только по нажатию кнопки «Восстановить». Правильно: при каждом запуске проверять originalTransaction через SKReceiptRefreshRequest или серверную валидацию. Без этого пользователь, вернувшийся через полгода с новым iPhone, окажется без оплаченного контента.

Второй кейс — неправильная обработка SKPaymentTransactionObserver. Если updatedTransactions не вызывает finishTransaction(_:) для всех состояний (.purchased, .restored, .failed), транзакция зависает в очереди и при следующем запуске приложения повторно триггерит observer. Видел проекты, где это приводило к двойному открытию paid-контента после рестарта.

Как устроена правильная реализация

Архитектура non-consumable IAP в 2024 году строится вокруг StoreKit 2 (iOS 15+) или StoreKit 1 с поддержкой iOS 13–14.

StoreKit 2 радикально упрощает код:

// Запрос продуктов
let products = try await Product.products(for: ["com.app.premium_unlock"])

// Покупка
let result = try await products.first?.purchase()

switch result {
case .success(let verification):
    switch verification {
    case .verified(let transaction):
        // unlock контент
        await transaction.finish()
    case .unverified:
        // receipt подделан — не разблокируем
        break
    }
case .pending:
    // SCA или родительский контроль — ждём
    break
case .userCancelled:
    break
}

Transaction.currentEntitlements — async sequence, который при каждом запуске приложения возвращает все активные покупки. Итерируем его в @main или в AppDelegate.applicationDidFinishLaunching и восстанавливаем состояние без кнопки «Восстановить».

Для iOS 13–14 остаётся StoreKit 1 с SKPaymentTransactionObserver. Там нужен отдельный ReceiptValidator — либо локальная верификация через openssl (сложно, но без сетевых запросов), либо серверная через Apple /verifyReceipt endpoint (deprecated с 2023, но работает). Рекомендую серверную: локальная требует embedding Apple root certificate и корректной ASN.1-парсинга.

Серверная валидация

Для приложений с бэкендом: при покупке клиент отправляет appStoreReceiptURL на сервер, сервер запрашивает Apple Sandbox/Production и сохраняет original_transaction_id в базе. При восстановлении на новом устройстве — запрос к своему API по apple_id пользователя.

Без этого невозможно реализовать «покупка на одном устройстве, доступ на другом» в рамках одного Apple ID — а пользователи этого ожидают.

Тестирование

В Xcode Simulator StoreKit работает через локальный .storekit файл — можно тестировать без реальных продуктов. Для device-тестирования нужен Sandbox Account в App Store Connect. Важно проверять сценарий: покупка → удаление → переустановка → восстановление. Этот путь ломается чаще всего.

Сроки реализации — 2–3 дня: настройка продуктов в App Store Connect, интеграция StoreKit 2 с fallback на StoreKit 1, покрытие тестами на Sandbox, прохождение ревью (App Review требует кнопку «Restore Purchases» в интерфейсе).