Сергей Журавель | 22 ноября 2022 г.

Всем привет! Меня зовут Сергей. Уже более шести лет я работаю iOS Team Leader в Futurra Group.

Я работаю с In‑App Purchases (или IAP — Встроенные Покупки) каждый день, и за эти годы я нарастил опыт правильного и эффективного управления IAP. В этом руководстве, состоящем из нескольких статей, я покажу, как без лишних проблем добавлять покупки в приложение, начиная с настроек конфигурации покупки в App Store Connect и заканчивая обработкой покупок в приложении c примерами исходного кода. К сожалению, Apple не дает нам пошаговых инструкций. В следствии этого, у многих возникают трудности с внедрением IAP. Я хочу исправить эту ситуацию.

Ссылки на все мои статьи об IAP:

IAP позволяет разработчикам взимать плату с пользователей за определенную функциональность или контент при использовании приложения. Внедрение IAP особенно привлекательно по нескольким причинам:

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

  • Приложение может быть предложено бесплатно, становясь доступной загрузкой для большинства людей. Бесплатные приложения, как правило, загружаются намного чаще, чем платные. Если пользователям понравится ваше приложение, позже они смогут приобрести дополнительный контент или функциональность.

  • Следом за первоначальным релизом приложения, вы можете добавить новый платный контент в то же самое приложение вместо того, чтобы, с целью заработать больше денег, разрабатывать совершенно новое.

  • Вы можете показывать пользователю рекламу в бесплатном приложении с возможностью удалить ее, купив IAP.

Реализации IAP требует, чтобы приложение использовало API StoreKit на устройстве. StoreKit управляет всей коммуникацией с серверами Apple iTunes для получения информации о продукте и выполнения транзакций. Для IAP должен быть настроен профиль обеспечения (provisioning profile), а информация о продукте должна быть введена в App Store Connect.

Правила IAP

Вы не можете принимать другие формы оплаты цифровых продуктов или услуг, имеющихся в вашем приложении, а также упоминать их или направлять к ним своих пользователей из приложения. Это означает, что вы не сможете принимать кредитные карты или PayPal, когда наиболее подходящим механизмом оплаты будет IAP. Существует особый случай для покупок цифровых продуктов вне приложения, но используемых внутри приложения. Например, покупка книг на веб‑сайте, связанная с определенным «логином», и использование этого «логина» в приложении позволяет пользователю получить доступ к купленным книгам.

Приложениям, которые работают таким образом, не разрешается упоминать или направлять на функцию внешних покупок — разработчики должны сообщать своим пользователям о такой возможности другими способами (возможно, через электронный маркетинг или какой‑либо другой прямой канал).

Но, поскольку, для физических товаров вы не можете использовать IAP, в этом случае допускается использование альтернативного механизма оплаты (например, кредитную карту, PayPal) внутри приложения.

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

Вы не можете выбрать цену для своего продукта — лишь подобрать «ценовую категорию» с определенной стоимостью в каждой стране/валюте, которую поддерживает Apple. На других рынках у вас не может быть другой ценовой категории.

Проверка Ваших Соглашений

Прежде чем создать IAP и предложить их в своем приложении, вы должны сделать две вещи:

Если вы этого не сделали, обычно App Store Connect выдает следующее предупреждение:

Если вы видите что-то похожее, - выполните необходимые инструкции, чтобы принять соответствующие соглашения.

Также полезно перепроверить раздел «Agreements, Tax, and Banking» в App Store Connect:

Если вы видите раздел, озаглавленный как Запрос Контрактов, содержащий строку Платные Приложения, нажмите кнопку Запрос. Заполните всю необходимую информацию и отправьте ее. Одобрение вашего запроса может занять некоторое время.

В ином случае, если в списке Действующие Контракты вы видите Платные Приложения, похоже, что вы уже выполнили этот шаг! Отличная работа!

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

Создание покупок в App Store Connect

В этой части мы создадим IAP, которую будет предлагать ваше приложение. Перед этим давайте выясним, какие типы IAP доступны.

Существует четыре типа IAP, и внутри своего приложения вы можете предлагать несколько типов.

  • Расходуемые — тратятся после одного использования. Клиенты могут приобретать их многократно.

  • Нерасходуемые — оплачиваются один раз. Срок их действия не истекает.

  • Подписки с автопродлением на услуги или контент — это подписки, которые клиенты покупают один раз; продлеваются автоматически до тех пор, пока клиенты не решат отменить подписку.

  • Подписки без автопродления на услуги или контент предоставляют доступ в течение ограниченного периода времени, не продлеваются автоматически. Клиенты могут приобрести их снова.

Создайте продукт по подписке:

  1. В разделе Мои Приложения выберите свое приложение.

  2. На боковой панели в разделе Функции нажмите Подписки.

  3. Перед созданием продукта необходимо сначала создать Группу Подписки. Нажмите кнопку Создать в разделе Подписки с Автопродлением.

Интерфейс создания Группы Подписок
Интерфейс создания Группы Подписок
Установите имя для Группы Подписок
Установите имя для Группы Подписок

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

Подписки в Группе Подписок являются взаимоисключающими, это значит, что пользователи могут единовременно подписаться только на один вариант в группе. Если вы хотите, чтобы пользователи могли приобретать более одной подписки за раз, вы можете поместить эти встроенные покупки в разные группы подписок. Более того, все ознакомительные предложения, такие как пробные подписки, распространяются непосредственно на всю группу. Группы служат для разделения бизнес‑логики в приложении.

4. Чтобы создать свой первый продукт, перейдите к созданной вами Группе Подписок и в разделе Подписки нажмите кнопку Создать.

Интерфейс создания продукта подписки
Интерфейс создания продукта подписки

Добавьте ссылочное имя и ID продукта, затем нажмите Создать.

  • Ссылочное Имя: Это название продукта Подписки в App Store Connect, но предназначено оно только для внутреннего использования и не будет показано пользователям, так что сильно не беспокойтесь, какой параметр вы здесь присвоите. Но все же, дайте имя, которое ясно дает понять, к чему относится эта встроенная покупка.

  • ID Продукта: Это должна быть уникальная строка (буквенно‑цифровая, как говорит Apple), которая будет использоваться для составления отчетов; а вот рекомендация: в качестве префикса для параметра ID, который вы здесь укажете, используйте bundle identifier приложения. Таким образом, вы гарантируете, что он всегда будет уникальным. В нашем случае уникальный ID продукта — «com.testapp.year» (без кавычек).

Задайте имя и id продукта Подписки
Задайте имя и id продукта Подписки

Добавьте второй продукт, как описано выше.

Перейдите на вкладку Функции → Подписки → Ваша Группа Подписок должна выглядеть так:

Список ваших продуктов Подписки в App Store Connect
Список ваших продуктов Подписки в App Store Connect

Конфигурация Продукта

На данный момент мы добавили два продукта, но они все еще не готовы к использованию. Статус продуктов «Отсутствуют Метаданные», потому что мы не добавили информацию о стоимости и продолжительности подписки. Давайте это исправим.

Нажмите на продукт, чтобы настроить его.

Установка продолжительности и стоимости подписки
Установка продолжительности и стоимости подписки

Здесь нам нужно выбрать Продолжительность Подписки. В нашем случае выбираем 1 Год. Чтобы выбрать цену, нажмите Добавить Цену Подписки в разделе Стоимость Подписки.

Вы можете установить цену в зависимости от страны, но мы ограничимся автоматическими ценами в долларах США. App Store Connect автоматически конвертирует цены в другие валюты на основе обменных курсов. Вы можете вручную изменить цену для конкретной страны, подстраиваясь под свой целевой рынок.

Установка цен на товар
Установка цен на товар

Мы установили продолжительность подписки и стоимость, но статус продукта не изменился. Теперь нам нужно указать название товара, которое увидит пользователь, и указать информацию для обзора.

Добавьте Локализацию App Store для продукта по Подписке
Добавьте Локализацию App Store для продукта по Подписке
Укажите имя и описание
Укажите имя и описание
  • Отображаемое Имя: название продукта, которое будет отображаться в App Store.

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

  • Информация для Обзора. Согласно рекомендациям Apple, вы должны загрузить скриншот страницы продукта. Но я обычно загружаю иконку приложения в разрешении 1024×768. В моем случае это всегда срабатывало:)

Установите Информацию для Обзора
Установите Информацию для Обзора

Нажмите кнопку Сохранить, и статус продукта останется Отсутствуют Метаданные. Чтобы изменить его, нам нужно сделать последний шаг. Перейдите на вкладку Функции → Подписки → Ваша Группа Подписок. Нам нужно установить имя группы, которое будут видеть клиенты.

Установите Локализацию App Store для Группы Подписки
Установите Локализацию App Store для Группы Подписки
Установите имя для Группы Подписок
Установите имя для Группы Подписок

Нажмите на кнопку Создать, и если вы все сделали правильно, статус ваших товаров должен измениться на Готов к Отправке.

Бесплатный пробный период

В App Store Connect вы можете настроить входные предложения (introductory offers) для своих приложений, содержащих подписки с автопродлением. Вводное предложение — это ограниченная по времени цена со скидкой или бесплатная пробная версия в течение начального периода подписки.

Самый популярный способ увеличить количество подписок — бесплатный пробный период:

Клиент активирует его и использует приложение бесплатно. Если он/она не отменит подписку, по истечении пробного периода с клиента будет автоматически взиматься плата. Разработчики любят бесплатные пробные периоды, потому что у таких подписок хорошая конверсия. Давайте добавим его в одну из наших подписок.

Нажмите ( + ) в разделе «Цены на Подписку» и выберите «Создать Вводное Предложение«.

Выберите страны, в которых будет доступен пробный период. Я всегда выбираю Все.

Выбор стран для пробного периода.
Выбор стран для пробного периода.

На следующем шаге нам нужно выбрать даты, когда будет доступен пробный период. Мы выбираем Без Конечной Даты, таким образом пробный период доступен для клиентов без ограничений по дате.

Мы выбираем даты, когда пробный период будет доступен.
Мы выбираем даты, когда пробный период будет доступен.

На последнем шаге нам нужно выбрать Тип Предложения. Существует три типа начальных цен, которые вы можете предложить в подписке и территориально:

  • Оплата по мере использования (SKProductDiscount.PaymentMode.payAsYouGo): новые подписчики будут платить по сниженной цене каждый расчетный период в течение определенной продолжительности. Это может привлечь новых пользователей, которые заинтересованы в вашем приложении, но им нужен дополнительный толчок, чтобы начать платить обычную, более высокую цену за каждый период подписки. Например, в первые три месяца вы можете предложить сниженную цену в $1,99 в месяц, со стандартной ценой подписки в $3,99 в месяц, начиная с четвертого месяца.

  • Предоплата (SKProductDiscount.PaymentMode.payUpFront): новые подписчики будут платить единовременную начальную цену за определенный срок действия. Это полезно, когда вы считаете, что пользователю может понадобиться больше времени, чтобы увлечься контентом, который предлагает ваше приложение. Например, вы хотите предложить ежемесячную подписку, но считаете, что пользователям потребуется около шести месяцев, чтобы опыт пользования стал привычным и с большей вероятностью сохранить свою подписку, вы можете предложить полугодовую стартовую цену в размере $9,99 за весь пробный период, а затем стандартную цену $3,99 в месяц, начиная с седьмого месяца. Обратите внимание, что вам не обязательно использовать один и тот же период времени для стартовой цены и обычной подписки. Так, например, вы можете предложить стартовую цену на шестимесячный период, за которой последует годовая подписка.

  • Бесплатный пробный период (SKProductDiscount.PaymentMode.freeTrial): новые подписчики получат бесплатный доступ к контенту на определенный период времени. Подписка начинается немедленно, и первый счет выставляется по окончании бесплатного пробного периода. Это дает вашим пользователям возможность отменить подписку до того, как будет выставлен первый счет. Если вы уверены в контенте вашего приложения, но вам трудно убедить потенциальных подписчиков, что он стоит своих денег, этот вариант позволит им принять решение ничем не рискуя.

Независимо от того, какой тип вы выберете, по окончании ознакомительного периода подписка будет продлена по обычной цене.

В нашем случае мы выбираем Бесплатно и устанавливаем продолжительность в одну неделю.

Установите продолжительность и тип пробного периода
Установите продолжительность и тип пробного периода

Нажмите Подтвердить, чтобы закончить. Вот и все! Вы только что установили стартовую цену для вашей подписки с автопродлением.

Определение Права Пользователя

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

Как узнать, имеет ли пользователь право на скидку? Отличный вопрос!

Просмотрите прошлые транзакции пользователя, чтобы выяснить, не пользовался ли он скидкой из той же группы подписок в прошлом. Если да, - пользователь не имеет права на скидку.

В JSON-ответе сервера App Store вам будут нужны следующие поля: last_receipt_info, значением которого является массив, содержащий все транзакции встроенных покупок, и поля is_trial_period и is_in_intro_offer_period в поле квитанции для каждой соответствующей транзакции.

Чтобы определить право пользователя, проверьте значения Пробного Периода Подписки и Периода Стартовой Цены Подписки для всех транзакций IAP. Если значение любого из этих полей истинно для данной подписки, пользователь не имеет права на стартовую цену ни на один из продуктов в той же группе подписок.

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

Лучший порядок применения стартовой стоимости

Чтобы добавить Стартовую Стоимость в приложение, в котором уже есть подписки с автопродлением, вам не нужно вносить какие-либо изменения в код. Вы можете просто внести соответствующие изменения в App Store Connect и позволить Apple позаботиться об остальном. Однако, если вы действительно хотите выжать максимум из этого великолепного нового способа привлечения пользователей к подписке, вы можете внести некоторые изменения в UI/UX, чтобы потенциальные покупатели знали о стартовой цене, которую предлагает ваше приложение.

Рекомендации Apple Human Interface по IAP прямо на это указывают: «Предлагая стартовую стоимость, укажите стартовую цену, продолжительностьпредложения и стандартную цену, которую пользователь будет платить после окончания предложения».

При добавлении стартовых цен к приложениям, уже размещенным в App Store, учитывайте следующие моменты:

  • Убедитесь, что ваши пользователи осведомлены о предложении. Показывайте цену со скидкой в понятной и привлекательной форме, чтобы пользователи точно знали, что они покупают. Вы можете получить все необходимые сведения в новом свойстве, добавленном в SKProduct, которое называется introductoryPrice (с типом SKProductDiscount). Эти данные включают price, priceLocale, paymentMode, subscriptionPeriod и numberOfPeriods.

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

  • Стартовые цены на рекламируемые IAP также появляются в App Store. Принимая решение о том, как использовать эту функцию, помните, что потенциальные пользователи могут увидеть скидку до того, как установят ваше приложение. При правильном использовании начальные цены могут привлечь новых пользователей для установки вашего приложения и превратить существующих пользователей в новых подписчиков.

  • Теперь пользователи могут легко просматривать и управлять своими подписками по этой ссылке apps.apple.com/account/subscriptions. Там они могут видеть свои подписки и переключаться между различными вариантами в группе подписок. Важно проверить, как там выглядят ваши предложения IAP, и при необходимости направить туда своих пользователей.

  • Наконец, Apple добавила новую панель управления сохранением подписок в App Store Connect ▸ App Analytics. Как только ваше приложение будет запущено, следите за тенденциями на панели управления сохранением. Обратите внимание, как стартовые цены улучшают привлечение пользователей, и используйте эти данные для принятия решений о будущих предложениях и бизнес-модели вашего приложения.

Начните Внедрять Встроенные Покупки. Загрузите список SKProduct.

Теперь давайте сосредоточимся на реализации повторно используемого класса, который будет управлять IAP в нашем приложении. Хорошим правилом является создание класса‑синглтона для работы с StoreKit. Такой класс имеет только один экземпляр во всем приложении.

Наша первая задача — обновить IAPManager для получения списка IAPs с серверов Apple. Объявим новый класс с тем же именем, что и у файла: IAPManager. Оставьте пару пустых строк и добавьте это:

class IAPManager: NSObject {
  static let shared = IAPManager()
}

Далее нам нужно добавить несколько переменных. Константы наших ID продуктов и productsRequest, которые будут отвечать за загрузку продуктов.

let PREMIUM_MONTH_PRODUCT_ID = “com.testapp.month”
let PREMIUM_YEAR_PRODUCT_ID = “com.testapp.year”
fileprivate var productsRequest = SKProductsRequest()

Давайте добавим метод, в котором мы создадим SKProductsRequest для получения SKProduct.

func fetchAvailableProducts() {
    productsRequest.cancel()
    // Put here your IAP Products ID’s
    let productIdentifiers = NSSet(objects:       PREMIUM_MONTH_PRODUCT_ID, PREMIUM_YEAR_PRODUCT_ID)
    productsRequest = SKProductsRequest(productIdentifiers:         productIdentifiers as! Set<String>)
    productsRequest.delegate = self
    productsRequest.start()
}

Теперь нужно обязательно принять протокол SKProductsRequestDelegate и реализовать хотя бы один требуемый метод. Перейдите после закрывающей фигурной скобки класса IAPManager и добавьте расширение, в котором мы реализуем следующий метод, вызываемый, когда App Store отправляет ответ на исходный запрос:

extension IAPManager: SKProductsRequestDelegate {
    // MARK: — REQUEST IAP PRODUCTS
    func productsRequest (_ request:SKProductsRequest, didReceive
    response:SKProductsResponse) {
        if response.products.count > 0 {
           iapProducts = response.products
           for product in iapProducts {
              print("productIdentifier - ",
              product.productIdentifier)
           }
        }
    }
    func request(_ request: SKRequest, didFailWithError error:
    Error) {
        print(“Error load products”, error)
    }
}

ПримечаниеОбъект response предоставляет свойство с именем invalidProductIdentifiers. Это набор идентификаторов продуктов, которые нельзя купить. Хотя мы не используем его здесь, помните об этом на случай, если он вам когда-нибудь понадобится.

Если вы все сделали правильно, в логе отобразится список ID продуктов.

Ниже приведен весь исходный код класса IAPManager.

https://gist.github.com/sergey-zhuravel/ba38cc9d3725daadff280a845c5972c3#file-iapmanager-swift

Полный исходный код: GitHub

Комментарии (0)