Inn app purchase android

Android in-app purchases, часть 2: инициализация и обработка покупок

Это вторая статья из нашего цикла о реализации покупок на Android. В первой статье мы рассказывали о том, как создавать продукты в Google Play Console, сконфигурировать подписки и получить список продуктов в приложении. Cоветую познакомиться и с остальными:

Android in-app purchases, часть 2: инициализация и обработка покупок. — Вы тут

В прошлой части мы создали класс-обертку для работы с Billing Library:

Класс-обертка для работы с Billing Library

Перейдем дальше к реализации покупки и дополним наш класс.

Создание экрана с подписками

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

На данном этапе для примера мы сделали упрощённый вариант пейволла:

Итак, на нашем пейволле располагаются следующие элементы:

Набор кнопок для инициализации процесса покупки. На них указаны основные свойства продуктов: название и цена в местной валюте.

Кнопка восстановления прошлых покупок. Этот элемент необходим для всех приложений, в которых используются подписки либо non-consumable покупки.

Доработка кода для отображения информации о продуктах

В нашем примере четыре продукта:

две автовозобновляемые подписки («premium_sub_month» и «premium_sub_year»);

продукт, который нельзя купить повторно, — non-consumable (“unlock_feature”);

продукт, который можно покупать много раз, — consumable (“coin_pack_large”).

Для упрощения примера будем использовать Activity, в которую заинжектим BillingClientWrapper из предыдущей статьи, и layout с жестко заданным количеством кнопок для покупки.

Для удобства добавим словарь, где ключом является sku продукта, а значением — соответствующая кнопка на экране.

Объявим метод для отображения продуктов в UI, опираясь на логику из предыдущей статьи:

product.price — это уже отформатированная строка с указанием местной валюты для данного аккаунта, здесь никакое дополнительное форматирование не нужно; остальные поля в объекте класса SkuDetails также приходят уже с учетом локализации.

Запуск процесса покупки

Для проведения покупки необходимо вызвать метод launchBillingFlow() из главного потока приложения.

Добавим для этого метод purchase() в BillingClientWrapper :

У метода launchBillingFlow() нет колбэка, ответ вернется в метод onPurchasesUpdated() . Помните, мы в прошлой статье его объявили, но оставили на потом? Вот сейчас он нам понадобится.

Метод onPurchasesUpdated() вызывается при каком-либо результате после взаимодействия пользователя с диалогом покупки. Это может быть успешная покупка, отмена покупки (пользователь закрыл диалог, в этом случае приходит код BillingResponseCode.USER_CANCELED) или же какая-то другая ошибка.

По аналогии с интерфейсом OnQueryProductsListener из предыдущей статьи, объявим в классе BillingClientWrapper интерфейс OnPurchaseListener , с помощью которого будем получать либо покупку (объект класса Purchase — о кейсе, когда он может быть null даже в случае успеха, расскажем в следующей статье), либо ошибку, которую мы также объявляли в предыдущей статье:

И реализуем его в PaywallActivity:

Добавим логику в onPurchaseUpdated():

Если purchaseList не пустой, для начала для каждой покупки делаем проверку, что ее purchasedState равен PurchaseState.PURCHASED, потому что покупки также могут быть отложенными, и в этом случае флоу на данном этапе прекращается. Далее, согласно документации, нужно сделать серверную верификацию покупки, о ней мы расскажем в следующих статьях. После этого надо предоставить пользователю доступ к контенту и сообщить об этом в Google. Если не сообщить, то через три дня покупка автоматически отменится. Интересно, что это характерно только для Google Play, в то время как на iOS такого нет. Сообщить о предоставлении доступа к контенту можно двумя способами:

В случае с consumable-продуктом вместо него нужно вызвать метод consumeAsync() , который под капотом делает acknowledge, а заодно дает возможность покупать этот продукт повторно. Это можно сделать только с помощью Billing Library: Google Play Developer API почему-то не предоставляет возможность делать это на бэкенде. Любопытно, что, в отличие от Google Play, в App Store и в AppGallery свойство consumable за продуктом жестко определено на уровне App Store Connect и AppGallery Connect соответственно. Справедливости ради, замечу, что консьюмить такие продукты из AppGallery нужно всё-таки явно.

Читайте также:  Какие смартфоны honor обновятся до андроид 11

Напишем методы для acknowledge и consume, а также две версии метода processPurchase() — в случае, когда у нас есть свой бэкенд и когда его нет.

Без серверной верификации:

С серверной верификацией:

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

Во втором примере acknowledge, конечно, тоже можно было сделать на клиенте, но так как здесь у нас есть бэкенд, всё, что можно сделать на бэке, лучше отдать бэку. Что касается ошибок на acknowledge и consume, их нельзя игнорировать, потому что если ни одно из этих действий не произойдет в течение трёх дней после того, как покупка получила статус PurchaseState.PURCHASED, она отменится, а пользователю вернут средства. Поэтому, если мы не можем это сделать на бэкенде, и даже после нескольких повторных попыток всё еще получаем ошибку, самый надежный способ — получать текущие покупки пользователя в каком-нибудь методе жизненного цикла, например в onStart() или onResume(), и пытаться повторить в надежде, что пользователь в течение трёх дней зайдет в наше приложение при работающем интернете :).

Таким образом, текущая версия класса BillingClientWrapper будет выглядеть так:

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

Про Adapty

Он не только упрощает работу по добавлению покупок:

Встроенная аналитика позволяет быстро понять основные метрики приложения.

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

А/Б тесты увеличивают выручку приложения.

Интеграции с внешними системами позволяют отправлять транзакции в сервисы атрибуции и продуктовой аналитики.

Промо-кампании уменьшают отток аудитории.

Open source SDK позволяет интегрировать подписки в приложение за несколько часов.

Серверная валидация и API для работы с другими платформами.

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

Источник

Android in-app purchases, часть 1: конфигурация и добавление в проект

Всем привет, меня зовут Влад и я разработчик Android SDK для обработки платежей в мобильных приложениях в Adapty.

Внутренние покупки и в частности подписки являются наиболее популярным способом монетизировать приложение. С одной стороны, подписка дает разработчику возможность постоянно развивать контент и продукт, с другой стороны, благодаря им пользователь получает более высокое качество приложения в целом. Внутренние покупки облагаются 30% комиссией, но если пользователь подписан больше года или приложение зарабатывает меньше $1М в год, то комиссия составляет 15%.

Это первая статья из серии, посвящённой работе с внутренними покупками на Android. В этой серии мы охватываем темы от создания in-app purchases до серверной верификации платежей:

Android in-app purchases часть 1: конфигурация и добавление в проект. — Вы тут

В этой статье мы разберём, как:

создавать продукты в Google Play Console;

конфигурировать подписки: указывать длительность, стоимость, пробные периоды;

получать список продуктов в приложении.

Создание подписки/покупки

Перед тем, как мы начнем, убедитесь, что

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

Перейдем к делу, а именно создадим наш первый продукт.

Переходим в наш аккаунт разработчика и выбираем нужное приложение.

Дальше в левом меню ищем секцию Продукты, выбираем Подписки и жмем на Создать Подписку.

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

Создаем ID, который потом используем в приложении. Хорошо, когда в ID мы кодируем период подписки и какую-то еще полезную информацию. Это позволяет создавать продукты в одном стиле, чтобы в будущем было проще анализировать статистику по покупкам.

Читайте также:  Календарь с номерами недель для андроид

Название подписки, как пользователь ее увидит в магазине.

Описание подписки, пользователь тоже это увидит.

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

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

Обратите внимание, что Google сразу указывает налог в каждой стране, это очень круто, а в App Store Connect такого нет.

Скроллим ниже и опционально выбираем:

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

Начальная цена. Промо-предложение на первые периоды оплаты.

«Льготный период». То есть, если у пользователя проблема с оплатой, сколько дней вы продолжаете давать ему премиум доступ.

Возможность подписаться заново из Play Market, а не из приложения, после отмены подписки.

Сравнение процесса покупки с App Store Connect

Несмотря на то, что подписки значительно лучше монетизируются на iOS, админка Play Console выглядит намного удобнее. Она работает быстрее, лучше и проще структурирована, качественно локализована.

Сам процесс создания продукта предельно упрощен. Здесь мы описали, как создавать продукты на iOS.

Получение списка продуктов в приложении

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

Подключаем платежную библиотеку.

Разрабатываем структуру класса для взаимодействия с продуктами из Google Play.

Реализуем все методы обработки покупки.

Подключаем серверную верификацию покупки.

В этой части разберем первые два пункта.

Подключим Billing Library к проекту:

На момент написания статьи актуальной версией является 4.0.0. Вы можете в любой момент заменить ее на другую версию.

Создадим класс-обертку, который будет инкапсулировать логику взаимодействия с Google Play, и проинициализируем в нем BillingClient из библиотеки Billing Library. Назовем такой класс BillingClientWrapper.

Наш класс будет реализовывать интерфейс PurchasesUpdatedListener. Мы сразу переопределим его метод onPurchasesUpdated(billingResult: BillingResult, purchaseList: MutableList

?) , который вызывается после совершения покупки, но саму реализацию опишем уже в следующей статье.

Google рекомендует, чтобы одновременно было не больше одного активного соединения BillingClient’а с Google Play, чтобы колбэк о совершенной покупке не вызывался несколько раз. Для этого целесообразно иметь единственный экземпляр BillingClient в классе-синглтоне. Класс в примере выше сам по себе синглтоном не является, но мы можем провайдить его с помощью dependency injection (например, используя Dagger или Koin) таким образом, чтобы в один момент времени существовало не больше одного экземпляра.

Для совершения любого запроса с помощью Billing Library нужно, чтобы у BillingClient’а в момент запроса было активное соединение с Google Play, но в какой-то момент оно может быть утеряно. Для удобства напишем обертку, чтобы любой запрос выполнялся только при активном соединении.

Чтобы получить продукты, нам нужно знать их идентификаторы, которые мы задавали в маркете. Но для запроса этого недостаточно, нужно указать еще и тип продуктов (подписки или разовые покупки), поэтому общий список продуктов мы можем получить только путем «склеивания» результатов двух запросов.

Так как запрос на продукты асинхронный, нам нужен колбэк, в котором мы получим либо список продуктов, либо ошибку. Billing Library при ошибке возвращает один из определенных в ней BillingResponseCode, а также debugMessage. Создадим интерфейс колбэка и модель для ошибки:

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

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

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

Про Adapty

Как видите, в процессе добавления покупок в приложения на Android много нюансов. Если использовать готовые библиотеки, всё будет проще. Советую познакомиться с Adapty — SDK для in-app покупок. Он не только упрощает работу по добавлению покупок:

Встроенная аналитика позволяет быстро понять основные метрики приложения.

Читайте также:  Виджет часов для android 4pda

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

А/Б тесты увеличивают выручку приложения.

Интеграции с внешними системами позволяют отправлять транзакции в сервисы атрибуции и продуктовой аналитики.

Промо-кампании уменьшают отток аудитории.

Open source SDK позволяет интегрировать подписки в приложение за несколько часов.

Серверная валидация и API для работы с другими платформами.

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

Источник

In-App Purchase в Android приложениях

1. Что это такое и зачем это нужно?

In-App Purchase, грубо говоря, представляет собой сервис покупки виртуальных товаров внутри приложения (например игровой валюты, новых уровней, игровых предметов и т.д.). Применяется он в основном в играх, в тех случаях, когда встает вопрос о необходимости заработка на своем творении, а распространять его платно не особо хочется (или нет смысла).

2. In-App Purchase в андроид-приложениях

Когда я столкнулся с необходимостью использования in-app purchase в разрабатываемой игре, было очень трудно найти подробную русскоязычную информацию о том, как прикрутить данный сервис к своей игре. Наиболее хорошо сервис был описан в одной из статей Хабра, но мне бы хотелось показать свое видение по данному вопросу. Поэтому решил сам написать небольшой мануал по подключению сервиса к приложению.

Для начала неплохо было бы разобраться с тем, как это все работает.

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

Предполагается, что у вас уже есть аккаунт разработчика на Android Market.

Для того, чтобы работать с системой покупок внутри приложения нам понадобится файл с названием IMarketBillingService.aidl. Найти его можно в примере приложения по работе с in-app purchase, который в свою очередь является скачиваемым компонентом Android SDK. Запустите Android SDK and AVD Manager и выберете Available Packages. Далее необходимо будет выбрать Third party add-ons -> Google Inc. add-ons -> Google Market Billing package.

Теперь необходимо из скаченного примера скопировать в свой проект файл IMarketBillingService.aidl. Важно, чтобы он лежал в com.android.vending.billing. После этого в манифесте добавляем расширение: .

В примере приложения кроме вышеописанного файла есть также несколько реализованных классов для работы с системой платежей. Копируем их в свой проект. Что собой представляет каждый из них:

BillingReceiver – получает все асинхронные ответы с маркета и отправляет их далее в BillingService;
BillingService – отправляет запросы на маркет;
Consts – содержит все константы примера приложения;
Dungeons – обеспечивает UI и отображает историю совершенных покупок;
PurchaseDatabase – локальная база данных;
PurchaseObserver – наблюдение за изменениями, связанными с покупками;
ResponseHandler – обновление базы данных и UI;
Security – обеспечение безопасности;
Base64 и Base64DecoderException – кодирование из двоичной системы в base64. Необходимы для функционирования класса Security.

В классе Security ищем строку:
String base64EncodedPublicKey = “…”
и вписываем сюда свой PublicKey, полученный при регистрации аккаунта на Android Market.

В классе Dungeons ищем список товаров, которые предполагается продавать, и меняем их на свои. При этом, товары должны быть залиты в Android Market и опубликованы (само приложение при этом публиковать не обязательно – в случае его тестирования, однако надо не забыть добавить себя (или кого-то другого) в разработчики (делается в настройках профиля)). Далее дописываем интерфейс и в принципе приложение готово.

Однако стоит позаботиться о безопасности. Лучший способ обеспечения безопасности покупок – использование соответствующего сервиса на сервере. После того, как пользователь совершил покупку товара, маркет пришлет JSON строку с информацией о купленном товаре:
< "nonce" : 1836535032137741465,
«orders» :
< "notificationId" : "android.test.purchased",
«orderId» : «transactionId.android.test.purchased»,
«packageName» : «com.example.dungeons»,
«productId» : «android.test.purchased»,
«developerPayload» : «bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ»,
«purchaseTime» : 1290114783411,
«purchaseState» : 0 >
>
и подпись для проверки подлинности запроса.

На серверной части приложения нужно выполнить проверку вернувшейся строки с помощью подписи и вашего ключа (шифрование RSA) и вернуть результат проверки клиенту. Для этого есть небольшая открытая библиотека, написанная на php, я использовал ее.

Более подробно о безопасности при работе с in-app purchase написано тут.

Источник

Оцените статью