Всем привет, я Ваня — фулстак разработчик в Adapty. Сегодня расскажу про добавление in-app покупок в приложения на React Native. Кросс-платформенные фреймворки для разработки приложений сильно облегчают жизнь разработчикам, позволяя писать сразу для нескольких платформ. Однако есть свои нюансы. Например, в React Native не существует базового инструмента для внедрения внутренних покупок. Поэтому неминуемо приходится пользоваться сторонними библиотеками. Самые популярные библиотеки для добавления покупок в приложения на React Native — это react-native-iap, expo-in-app-purchases. А расскажу я про react-native-adapty, потому что по сравнению с другими библиотеками, у неё есть преимущества: в отличие от других библиотек, есть серверная валидация покупок; библиотека поддерживает все текущие фичи магазинов от промо-офферов до оплаты наперёд, а поддержка новых функций появляется в ней быстро; код получается чище и понятнее; можно менять предлагаемые продукты, добавлять и убирать предложения без прохождения полного релиз-цикла: не надо выпускать беты и ждать одобрения. Кроме того, Adapty SDK даёт много других бонусов: встроенная аналитика по главным метрикам, когортный анализ, серверная валидация покупок, A/B тестирование пейволлов, промо-кампании по гибким сегментам, интеграции с системами аналитики. Но пока поговорим о настройке in-app purchases на React Native. Вот что нам сегодня предстоит: Почему Expo не подойдёт для внедрения in-app purchases в приложениях на React Native. Создание аккаунта разработчика — ссылки на инструкции. Настройка Adapty:конфигурация App Storeконфигурация Play Store Добавление подписок. Создание пейволла. Установка react-native-adapty. Пример приложения и результат. В статье мы попробуем написать приложение, которое будет показывать картинки котов подписанным юзерам, а остальным — предложение подписаться. > TL;DR — Expo managed не поддерживает нативные методы магазинов для работы с покупками (сторкитов). Нужен либо совсем чистый RN, либо Expo bare workflow. Тех, кто сразу подумал о том, чтобы использовать Expo, придётся разочаровать — он для этих целей не годится. Expo — это фреймворк для React Native, с которым разработка многократно упрощается. Однако для покупок/подписок их полноценный workflow не подходит. Expo не использует нативный код в своих методах и компонентах (только js), что требуется для сторкитов. Сделать покупки через js в мобильных магазинах не выйдет, так что надо эджектиться. Для начала нам предстоит настроить аккаунты в магазинах, создать и подготовить покупки/подписки и для iOS, и для Android. Этот процесс вряд ли займет больше 20 минут. Если вы еще не настроили аккаунты разработчика и продукты в App Store Connect и/или Google Play Console, то можете познакомиться с инструкциями по ссылкам: Для iOS — от начала статьи и вплоть до «Получение списка SKProduct» — там уже начинается нативная реализация Для Android — аналогично от начала статьи до «Получение списка продуктов в приложении». В случае react-native-adapty для начала надо настроить дашборд Adapty. Это занимает немного времени, зато по сравнению с хардкодом, в результате вы получите все описанные выше преимущества.  На третьем шаге после регистрации нам предлагают сконфигурироваться для App Store и Google Play: Для работы с iOS нам нужно: указать Bundle ID; установить App Store Server Notifications; App Store Connect shared secret.  Это обязательные поля для того, чтобы покупки работали. К каждому полю есть Read how — там очень понятные и актуальные пошаговые туториалы, лучше посмотрите туда.  Bundle ID — это уникальный ID вашего приложения. Здесь он должен совпадать с тем, что вы написали в Xcode в Targets > [App Name] > General: Для Android обязательны Package Name и Service Account Key File.Точно так же есть актуальные Read how. Package name — аналог Bundle ID с iOS. Нужно указать такой же, как и в коде. Найти его можно в файле /android/app/build.gradle в разделе android.defaultConfig.applicationId: На четвёртом шаге нам предлагают добавить Adapty SDK в наше приложение. Однако мы этот шаг пропустим и настроимся чуть позже. После того, как зарегистрировались, идем в настройки и запоминаем, что здесь лежит наш ключ (Public SDK key) — он нам понадобится чуть позднее:  Для разных подписок в Adapty  существуют продукты. У вас может быть подписка только на фото котов, но на месяц, полгода, год. Каждый этот вариант будет соответствовать одному продукту в Adapty.  Давайте укажем в дашборде, что у нас есть один продукт. Идем в раздел Products & A/B Tests → Products, кликаем Create product.  Здесь надо указать название продукта — то, как конкретная подписка будет выглядеть в интерфейсе Adapty.  Также надо указать App Store Product ID и Play Store Product ID. Период и название можно выставить для работы с аналитикой. Сохраняемся. Теперь надо создать пейволл — экран, который ограничивает доступ к платным функциям и предлагает купить подписку. В пейволл надо будет добавить созданный продукт. Для этого в этом же разделе Products & A/B Tests → Paywalls кликаем Create paywall.  В Paywall name вносим название пейволла. Важно делать его таким, чтобы потом и вы, и ваши коллеги могли легко по названию разобраться, что это за пейволл. В Paywall ID я напишу cats_paywall — по этому ID мы будем искать пейволл в приложении.  В выпадающем меню Product добавляем нашу подписку. Сохраняемся. Вот и вся настройка, дальше будем устанавливать зависимости и кодить. 1. Сначала подключаем зависимость: 2. Устанавливаем поды для iOS. Если у вас нет CLI pod, то рекомендую скачать. Она еще не раз вам пригодится в iOS-разработке. 3. Так как на iOS React Native проекты написаны на Obj-C, нам надо создать Swift Bridging Header, чтобы Obj-C мог читать Swift библиотеки. Для этого просто идем в Xcode проект, создаем новый любой Swift файл. Xcode нам предложит создать bridging header — то, что нам и нужно. Соглашаемся. 4. Для Android надо убедиться, что в проекте (/android/build.gradle по дефолту) стоит  kotlin-gradle-plugin версии 1.4.0 или выше: 5. Для Android надо включить multiDex, на этот раз в конфигурации приложения (/android/app/build.gradle по дефолту): Все настроено! Теперь можно отдыхать начинать кодить! 🎉 Под капотом react-native-adapty происходит много полезных штук, которые обязательно пригодятся, если не сейчас, то несколько позже. Поэтому библиотеку следует инициализировать в самом начале флоу. Идем как можно выше в приложении (можно прямо в App.tsx) и инициализируемся: Соответственно, вместо MY_PUBLIC_KEY пишем тот самый Public SDK ключ, который мы получили при настройке дашборда. На самом деле, метод activateAdapty() можно вызывать и больше одного раза, и больше, чем в одном месте — ничего страшного не будет, однако мы ограничимся такой версией. Теперь можем получать те продукты, которые мы добавили в дашборде Adapty:  Теперь к практике. Давайте попробуем написать небольшое приложение, где мы сможем смотреть продукты из наших пейволлов и делать покупки. Здесь я позволю себе писать достаточно плотно, чтобы не усложнять базовую логику. Также писать буду на typescript, чтобы показать, где какие типы фигурируют. Проверять весь код буду на своем стареньком iPhone 8 — важно понимать, что, начиная с iOS 14, App Store запрещает использовать сторкиты на симуляторах — только реальные девайсы. 1. Итак, сначала напишем корневой компонент App.tsx, в котором будет кнопка, которая показывает пейволл. Я уже настроил навигацию через react-native-navigation. Как по мне, он намного круче, чем рекомендуемый официальной документацией react-navigation.  Разберемся, что происходит. При маунте компонента вызывается наша функция fetchPaywalls(), которая активирует SDK и сохраняет пейволлы в стейт, чтобы при таче по кнопке нам не пришлось бы ждать фетча. На вью у нас только одна кнопка, которая должна переводить к пейволлу, который мы подготовили раньше в дашборде. На самом деле, мы могли не сохранять пейволлы в стейт, а фетчить их прямо тут — adapty.paywalls.getPaywalls() по умолчанию возьмет их из кэша (а закэшит при открытии приложения), то есть не надо будет ждать, пока метод сходит на сервер. Вот, что вышло: 2. Теперь напишем компонент пейволла в том же файле: Тут мы просто мапим продукты из пейволла и показываем к каждому продукту кнопку покупки.  3. Чтобы посмотреть, как это выглядит, давайте зарегистрируем этот экран в react-native-navigation. Если у вас другой навигатор, можете пропускать этот шаг. Мой корневой index.js выглядит так: 4. Теперь осталось только добавить действие на тап кнопки "Показать пейволл"; в моем случае, он будет открывать модальное окно через Navigation: Вот и все! Теперь мы можем показывать пейволлы юзерам. Если вы хотите протестировать покупки на iOS сэндбоксе, то вам нужно будет завести сэндбокс-тестер аккаунт. Тут стоит помнить, что сэндбокс-подписки инвалидируются быстрее, чтобы было удобнее тестировать. На андроиде дополнительные аккаунты не нужны, и даже можно тестить на симуляторе; подписки также ускорены. Теперь остается вопрос, где хранить информацию об активных подписках, чтобы давать конечному пользователю его премиум контент. Здесь Adapty нам тоже поможет — он сохраняет все покупки, связанные с пользователем. Давайте сделаем так: если у юзера нет подписки, то мы также показываем кнопку пейволла, но если подписка есть, то мы показываем кота. Информация об активной подписке берется из кэша или сервера, так что нужен будет лодер. Для простоты давайте добавим стейты isLoading и isPremium: Смотрим, что изменилось: добавились два флага в стейте. Все содержимое fetchPaywalls() мы завернули в try-catch, чтобы код гарантированно доходил до setIsLoading(false) в любом сценарии. Для проверки на подписку мы сначала получаем профиль юзера (там вся информация о его покупках), и далее смотрим на значение profile.accessLevels.premium.isActive. accessLevels — это уровни доступа, например, Gold, Premium и другие. Мы можем использовать столько, сколько нам нужно,  однако давайте оставим по дефолту. Адапти создает для нас premium, и большинству людей этого хватит. isActive будет true, пока есть активная подписка с таким access level. Дальше вроде все понятно: если у юзера премиум, то нам и не надо фетчить пейволлы, просто вырубаем лодер и показываем контент: Здесь мы добавили функцию, которая рендерит нужный контент, и добавили в onRequestBuy кусок логики — обновление стейта isPremium и закрытие модального окна. Смотрим, что вышло:  В итоге, у нас вышло замечательное и очень полезное приложение с подписками. Те, кто платят, будут видеть котов, а другим будет показываться пейволл. Этих знаний должно хватить, чтобы вы смогли построить все необходимое для покупок в вашем приложении. А для тех, кто хочет погрузиться в мир возможностей сторкитов чуть глубже, продолжение следует. Спасибо! Adapty не только упрощает техническую реализацию подписок: Встроенная аналитика позволяет быстро понять основные метрики приложения. Когортный анализ отвечает на вопрос, как быстро сходится экономика. А/Б тесты увеличивают выручку приложения. Интеграции с внешними системами позволяют отправлять транзакции в сервисы атрибуции и продуктовой аналитики. Промо кампании уменьшают отток аудитории. Open source SDK позволяет интегрировать подписки в приложение за несколько часов. Серверная валидация и API для работы с другими платформами. Познакомьтесь подробнее с этими возможностями, чтобы быстрее внедрить подписки в своё приложение и улучшить конверсии. Full-stack developer