EN Прислать проект
Все статьи

Встроенные покупки и подписки: как сделать правильно

Встроенные покупки и подписки в мобильном приложении: правила магазинов, проверка покупок на сервере, восстановление и частые ошибки.

· 5 минМобильныеКод

Встроенные покупки — это оплата цифрового внутри мобильного приложения через систему магазина: StoreKit у Apple и Google Play Billing у Google. Деньги списывает магазин, он же отвечает за возвраты и отмену подписок, а твоя задача — правильно понять, что человек купил, и выдать ему доступ.

На демо покупка выглядит просто: нажал кнопку, увидел системное окно, получил премиум. В жизни подписки продлеваются, не продлеваются, возвращаются, переходят на другой телефон, и всё это должно попасть в твою базу.

Что продаётся через встроенные покупки

Правило в общих чертах: всё цифровое, что потребляется внутри приложения, идёт через магазин. Подписки, премиум-функции, кредиты, внутриигровая валюта, контент. Физические товары и услуги в реальном мире — доставка, такси, билеты на концерт — оплачиваются обычным платёжным провайдером.

Видов покупок три:

  • расходуемые — кредиты, монеты: купил, потратил, можно купить снова;
  • нерасходуемые — разблокировка навсегда: покупается один раз;
  • подписки с автопродлением — доступ на период, который продлевается сам.

Цены задаются в консоли магазина, а не в коде. На экране покупки показывай цену, которую вернул магазин: она уже в валюте и формате страны пользователя. Для подписки рядом должны быть срок, цена и честная фраза о том, что она продлевается автоматически. Отменить подписку человек может только в настройках магазина — ты сделать это за него не можешь, но можешь показать, где это делается.

Проверка покупки на сервере

Главное правило: приложение не решает, что человек премиум. Это решает сервер.

После покупки приложение получает от магазина подтверждение — подписанную транзакцию у Apple, токен покупки у Google. Оно отправляет его на твой сервер, а сервер проверяет его у самого магазина через серверный API: настоящая ли покупка, для какого продукта, до какого числа действует. Только после этого сервер записывает доступ.

Хранить доступ удобно в одной таблице, независимо от того, откуда пришли деньги:

create table entitlements (
  user_id      bigint not null,
  product      text   not null,
  source       text   not null,  -- apple, google, web
  expires_at   timestamptz,
  original_txn text   not null unique
);

Уникальный идентификатор исходной транзакции защищает от двойного начисления, когда одну и ту же покупку прислали и приложение, и уведомление магазина.

Серверные уведомления магазинов

Продление, отмена, возврат денег, проблема с картой — всё это происходит без участия приложения, иногда когда оно не открывалось неделями. Узнать об этом можно только из уведомлений, которые магазин присылает на твой сервер: App Store Server Notifications у Apple и Real-time developer notifications у Google.

Подключи их с первого дня. Без них подписка, за которую вернули деньги, останется активной навсегда, а продлённая будет выглядеть истёкшей, пока человек не откроет приложение. Учти и льготный период: если карта не прошла, магазин какое-то время пытается списать снова, и обрывать доступ в первую же минуту не стоит.

Восстановление покупок

Кнопка «Восстановить покупки» обязательна — без неё Apple отклонит приложение. Она нужна человеку, который сменил телефон или переустановил приложение: магазин отдаёт его прошлые покупки, а ты снова выдаёшь доступ.

Заранее реши, что делать, если покупка сделана с одного аккаунта в приложении, а восстанавливают её из-под другого. Перенести доступ на текущий аккаунт или сказать «эта подписка привязана к другому входу» — оба варианта нормальны, плохо не решить никак.

Частые ошибки

  • Доступ выдаётся по флагу из приложения, без проверки на сервере.
  • Доступ выдаётся в момент нажатия, а не после подтверждения покупки.
  • На iOS транзакция не завершается после выдачи доступа, и магазин присылает её снова при каждом запуске.
  • На Android покупка не подтверждается (acknowledge) в течение нескольких дней, и Google автоматически возвращает деньги.
  • Возвраты не обрабатываются, и доступ остаётся у тех, кто получил деньги назад.
  • Цена зашита в интерфейс текстом и расходится с реальной.
  • Продукты не отправлены на проверку вместе со сборкой, и проверяющий не может ничего купить.

Тестируй в песочнице: у Apple есть тестовые аккаунты, у Google — лицензионные тестировщики, и в обоих случаях подписки продлеваются ускоренно, так что месяц проходит за минуты.

Можно не писать всё это самому — есть сервисы, которые берут на себя проверку покупок и уведомления. Это экономит время, но добавляет зависимость, так что таблица доступов на твоей стороне всё равно нужна.

Коротко

  • Цифровое в приложении продаётся через встроенные покупки, физическое — обычной оплатой.
  • Доступ выдаёт сервер после проверки покупки у магазина, а не приложение.
  • Серверные уведомления магазинов нужны с первого дня: продления, отмены, возвраты.
  • Кнопка восстановления покупок обязательна, и правило для смены аккаунта решается заранее.
  • Завершай транзакции на iOS и подтверждай покупки на Android.

SUBXCAT может собрать покупки и подписки так, чтобы доступ в базе совпадал с тем, за что люди заплатили.

Хочешь, сделаем это за тебя?

Расскажи о проекте ассистенту — через пять минут будет примерная смета, через 48 часов разбор.

Созвон с командой 20 минут: инженер, дизайнер и маркетолог посмотрят на проект вместе с тобой.
Записаться на звонок