Привет! Я Андрей, тимлид мобильной разработки в Adapty, я делаю SDK под iOS.  В нашей серии статей мы с командой рассказываем о внедрении покупок на iOS, и это шестая статья из серии. Познакомиться с остальными можно по ссылкам: iOS in-app purchases, часть 1: Конфигурация и добавление в проект. iOS in-app purchases, часть 2: Инициализация и обработка покупок. iOS in-app purchases, часть 3: Серверная верификация покупок. iOS in-app purchases, часть 4: Тестирование покупок. iOS in-app purchases, часть 5: Обработка ошибок. iOS in-app purchases, часть 6: Скидки для iOS in-apps purchases. — Вы тут. Скидки помогают приложениям привлечь новых подписчиков и удержать тех, кто потерял интерес к продукту. В Apple довольно большой инструментарий для их реализации, и сегодня я расскажу, какие возможности можно использовать, чтобы предоставить пользователям скидку: introductory offers, promo offers, offer codes,  и проч. В статье я опишу, как работают все эти скидки, как их реализовать для кого их можно применять. Offer (в статье иногда буду называть его cкидочным предложением) — это снижение цены на подписки для пользователей. Есть несколько вариантов: стартовое предложение — introductory offer; промо предложение — promo offer — скидка уже подписанному пользователю, например, при переходе на более дорогую подписку возможность активировать промокод — offer code, который гарантирует определенную фиксированную цену при покупке. Каждое скидочное предложение имеет один из доступных способов оплаты. В этом варианте подписчик может активировать подписку бесплатно на какое-то время. Деньги не будут списаны до конца периода, и пользователь может отменить подписку в любой момент. Пример: первый месяц бесплатного использования. Подписчик платит сниженную цену каждый период подписки на протяжении какого-то времени. По истечении пробного периода списание происходит по обычной цене. Пример: три месяца со скидкой в 50%. Пользователь единовременно оплачивает подписку на какой-то период. После окончания этого периода списание происходит по обычной цене. Пример: оплата сразу за год вперед со скидкой в 70%. Стартовое предложение позволяет пользователю ознакомиться с вашим приложением в течение какого-то фиксированного периода бесплатно или со скидкой, как упоминали выше: free trial, pay as you go, pay upfront. Каждая подписка может иметь только одно стартовое предложение, которое в целом нельзя регулировать — Apple сам определяет, может ли пользователь применить эту скидку или нет. Чтобы на это влиять, есть более сложные сценарии, например, создать набор продуктов со скидкой и без и показывать разные продукты пользователю в зависимости от каких-то внутренних признаков, но это уже тема для другой статьи. Для использования таких скидок нужно сначала настроить их в личном кабинете. Далее адаптировать интерфейс для отображения подобных скидок: Шаг 1. Используя SKProductsRequest, нужно получить список продуктов из магазина: Шаг 2. Далее найти нужный продукт, внутри которого будет лежать поле introductoryPrice, которое содержит всю информацию о вводном предложении, и сформировать цену скидки, ее длительность и проч. После отобразить это на экране оплаты: Покупка совершается в обычном режиме, разработчику ничего дополнительно указывать не требуется. Про покупки мы уже писали в нашей второй статье из серии про iOS. Чтобы проверить доступность вводного предложения для пользователя, нужно изучать его рецепт с покупками. Для этого необходимо провалидировать его на стороне сервера, а далее смотреть на признаки is_trial_period и is_in_intro_offer_period для всех покупок. Если хотя бы где-то эти флаги равны true, то у пользователя нет права использовать вводное предложение в пределах этой подписки, а также для всех подписок из этой же группы. Для определения всех подписок группы можно использовать поле subscription_group_identifier внутри responseBody.Pending_renewal_info. Определять доступность вводного предложения лучше всего на стороне сервера и как можно раньше, чтобы на этапе экрана оплаты уже принять решение, показывать пользователю скидку или нет. Introductory offer доступен не для всех пользователей: Для новых пользователей всегда доступно вводное предложение. Для отписавшихся и не использовавших подобную скидку раньше также все доступно, но только при возобновлении подписки или активации любой другой подписки в пределах группы подписок. Текущие подписчики не имеют права использовать вводное предложение для любого продукта в пределах существующей группы подписок, независимо от того, использовали ли они его в прошлом, или нет. Промо-предложение — это скидка или бесплатный доступ на определенный период. Такую скидку можно делать и тем, кто пользуется приложением сейчас, и тем, кто уже отписался. Обычно они используются для удержания существующей аудитории, чтобы продать более дорогой план или же вернуть отписавшихся пользователей.  Для каждой подписки можно завести не более десяти промо-предложений. Пользователи, активировавшие introductory offer, также могут использовать и  promotional offer. Решение, как и когда показывать промо предложение пользователю, ложится исключительно на плечи владельца приложения. Сценариев применения множество и они ничем не ограничиваются, например:  предложить скидку, как только пользователь не обновил подписку или отменил ее; если пользователь уже несколько раз обновил месячную подписку, то можно предложить ему годовую подписку со скидкой. Добавление промо-предложений состоит из нескольких шагов, в частности: проверка доступности промо-предложения; показ промо на экране оплаты; генерация подписи для совершения покупки с использованием промо; покупка с использованием идентификатора промо. Общая схема выглядит примерно так, как показано ниже. Пусть она вас не пугает, далее мы пройдемся по каждому ее аспекту и покажем на примерах как это выглядит на деле. Для начала нужно сгенерировать приватный ключ, которым сервер будет подписывать все активируемые промо-предложения. Для этого нужно пойти в App Store connect → Users and Access → Keys → In-App Purchase → Generate In-App Purchase Key → Ввести желаемое имя (оно используется лишь для отображения в списке) → Generate. После генерации приватного ключа требуется скачать его. Для скачивания он будет доступен только один раз, так что лучше его не терять. Далее нужно настроить сервер, чтобы он умел валидировать рецепты и слушать серверные уведомления App Store. Дополнительно нужно добавить функционал генерации подписи для промо предложений с использованием ключа из предыдущего пункта. Следующим шагом нужно добавить желаемые предложения в дашборде App Store Connect. Для каждого из них требуется указать: название (reference name), используется только для отображения в списке; идентификатор предложения (promotional offer id), активно используется в приложении при определении того, какую скидку требуется применить; метод предоставления скидки (offer type): free trial, pay as you go, pay upfront; продолжительность; цены, можно указывать разные цены для разных валют. Теперь можно приступить к реализации на стороне приложения. Как и в случае с вводным предложением (introductory offer), нужно получить список продуктов из магазина, используя SKProductsRequest. У каждого продукта внутри поля discounts лежат все сгенерированные промо предложения для каждой конкретной подписки. Владелец приложения сам регулирует то, какое промо предложение применить в той или иной ситуации. Делается это посредством идентификатора скидки — он используется для поиска нужного элемента из общего списка. Адаптация платежного экрана, чтобы вывести на нем информацию о промо-предложении, точно такая же, как и в случае с вводным предложением. Т.к. модель сущности SKProductDiscount используется та же самая, можно с легкостью переиспользовать код, который был написан для обработки introductory offer. Требуется лишь дополнительно передавать идентификатор предложения, который нужно применить: При покупке требуется явно указывать идентификатор предложения, который нужно применить, а также нужно получить сгенерированную подпись и еще ряд параметров для промо предложения с сервера. Далее передать это все в объект SKPaymentDiscount и уже этот объект скидки положить в поле paymentDiscount в покупку. При желании можно узнать, какое промо предложение было применено к конкретной покупке. Для этого надо посмотреть успешную транзакцию SKPaymentTransaction. Внутри нее есть поле paymentDiscount, где лежит идентификатор примененного промо. Проверка доступности промо-предложения для пользователя базируется на двух идеях. App Store считает, что у всех, у кого есть действующая или истекшая подписка, по умолчанию есть доступ к промо-предложению. Для понимания того, что у пользователя есть или была подписка, достаточно провалидировать и изучить его рецепт. Далее нужно уже самостоятельно определять любые дополнительные критерии доступности конкретного предложения. Право на применение может зависеть от широкого спектра логики в зависимости от потребностей бизнеса. Один из распространенных способов применения промо-предложений — через серверное уведомление DID_CHANGE_RENEWAL_STATUS, которое отправляется, когда пользователь меняет тип автопродления подписки. Например, когда пользователь отключает автопродление, можно показать ему промо-предложение, чтобы мотивировать возобновить подписку. Также стоит учитывать, что промо-предложения доступны только на iOS 12.2 и выше, macOS 10.14.4 и выше, tvOS 12.2 и выше, поэтому нужно проверять доступность устройства и предлагать пользователю обновить OS, если он хочет применить промо предложение на неподдерживаемой версии операционной системы. Промокоды — это строка из букв и цифр, которая даёт скидку на подписку или бесплатный триал. Промокоды стали доступны с iOS 14 и iPadOS 14, когда их анонсировали Apple. Распространять их можно как онлайн, так и оффлайн, например: при отправке рассылки с новыми функциями приложения можно приложить промокод на бесплатный период, чтобы заинтересовать пользователя; раздача листовок на улице с промокодом на скидку на первую покупку внутри приложения; партнерские программы с другими компаниями или блогерами, которые предоставляют эксклюзивный промокод на индивидуальную скидку. Для начала нужно сгенерировать эти промокоды в пределах какой-то подписки. Делается это через App Store Connect.  Пользователь может активировать код любым из трех способов: Через App Store. Для этого нужно открыть App Store и в разделе с приложениями найти соответствующую форму ввода кода. По специальной ссылке из дашборда App Store Connect. Этот сценарий не отличается от первого, разве что ссылку проще напрямую отправить аудитории и не придется искать заветного окна ввода в приложении App Store, достаточно будет кликнуть на ссылку и ввести код. Напрямую в приложении. В случае активации через приложение надо вызвать соответствующий метод, который покажет окно ввода кода: SKPaymentQueue.default().presentCodeRedemptionSheet() Когда пользователь активирует промокод, в приложение приходит уведомление с транзакцией в SKPaymentQueue, а также на сервер попадает уведомление в случае, если были настроены соответствующие серверные уведомления. В итоге после покупки надо получить уведомление с транзакцией в SKPaymentQueue, взять актуальный рецепт и отправить этот рецепт на валидацию на сервер. Уже сервер должен понять, что был применен промокод.  Для определения активированного промокода требуется проверять рецепт на наличие транзакции с полем offer_code_ref_name.  Это поле содержит название скидочного предложения, которое было создано в App Store Connect. Искать его следует в responseBody.Latest_receipt_info и responseBody.Pending_renewal_info внутри рецепта, но для серверных уведомлений аналогичные поля называются уже по-другому – unified_receipt.Latest_receipt_info и unified_receipt.Pending_renewal_info. Надо также учесть, что промокод мог быть активирован еще в магазине, перед установкой приложения. В этом случае, во время запуска надо валидировать рецепт, чтобы сразу выдать пользователю доступ к контенту на старте. Можно сгенерировать только 10 скидочных предложений, для которых есть лимит в 150 000 промокодов за квартал на приложение, так что используйте их с умом. Срок жизни промокодов — шесть месяцев. Тестировать промокоды можно только на живой сборке из App Store, Sandbox для подобных вещей пока не предусмотрен. Когда Apple ввели запрет на общий доступ к IDFA, некоторые пытались использовать промо-коды, чтобы атрибуцировать пользователей, но ограничение в 150 тысяч кодов свели все эти старания на нет. В целом добавление скидочных предложений в приложение не является очень сложной механикой, но потенциально может привлечь дополнительную прибыль. Adapty SDK упрощает подключение покупок в приложениях, поддерживает все актуальные фичи магазинов, как те, которые мы описали в этой статье, и делает серверную валидацию платежей. Но это не все преимущества: Встроенная аналитика позволяет легко понимать главные метрики приложения. Когортный анализ показывает, сходится ли экономика. А/Б тесты пейволлов делаются налету и помогают увеличивать конверсию в платных пользователей. Интеграции с внешними системами позволяют отправлять транзакции в сервисы атрибуции и продуктовой аналитики. Промо кампании уменьшают отток аудитории. Open source SDK позволяет интегрировать подписки в приложение за несколько часов. Серверная валидация и API для работы с другими платформами упрощает работу с покупками. Познакомьтесь подробнее с этими возможностями, чтобы быстрее внедрить подписки в своё приложение и улучшить конверсии. iOS разработчик