In app purchase android developer

Встраиваем In-App purchase в своё приложение

Во второй части статьи про свою новогоднюю игрушку я расскажу про внутри игровые покупки. Я совсем не люблю рекламу в приложениях, по этому вопрос встраивания рекламы в своё приложение, для меня отпал сразу. Мой опыт выкладывания в Gooogle Play платных игр говорит о том, что резко падает количество желающих эту игру скачать, по этому вариант продажи игры, тоже отпал. И так как я не стремлюсь заработать на игре состояние, а делаю это больше в своё удовольствие, то решил что пусть пользователи сами решают, платить что-нибудь или нет.

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

Для работы со встраиваемыми покупками я остановился на очень простой, на мой взгляд, но вполне функциональной библиотеке Anjlab (ссылка на GitHub).

В Google play существуют два типа товаров:

  • Продукт — приобретается разово, до реализации, не имеет срока действия
  • Подписка — может приобретаться регулярно, имеет срок действия

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

Для подключения библиотеки в наше приложение необходимо в файле build.gradle (Module: app)

Добавить строку compile ‘com.anjlab.android.iab.v3:library:1.0.44’ в раздел dependencies (Не забываем после внесения изменений, нажать Sync Now в верхнем правом углу окна.)

Добавляем в файл с Activity две библиотеки:

Снабжаем нашу Activity функционалом BillingProcessor.IBillingHandler:

Для работы с покупками создаём объект класса BillingProcessor и добавляем требуемые методы:

В методе onCreate инициализируем переменную:

Заполняем кодом переопределённые методы:

Со стороны приложения всё сделали, теперь надо выполнить ряд действий в консоли Google Play.
Сначала необходимо получить «ЛИЦЕНЗИОННЫЙ КЛЮЧ ИЗ Google Play». Этот ключ уникальный для каждого приложения, по этому, чтобы его получить, приложение необходимо опубликовать, например, как бета-версию.

После того как приложение будет опубликовано, заходим в раздел управления приложением (просто щёлкнув на него в списке приложений), затем в левом меню раскрываем раздел «Инструменты разработки» и переходим в подраздел «Службы и API», там в панели «Лицензирование и продажа контента» и есть необходимый ключ, который имеет вид «MIIBIjANBgkqhkiG9w0BAQEFAAOCA. »

Этот ключ используется при вызове метода:

Теперь нам необходимо создать контент, который будем продавать. Для этого в левом меню переходим в раздел «Настройки страницы приложения» и подраздел «Контент для продажи».
Далее нам необходимо определить какой тип контента нам нужен — продукт или подписка, определившись с типом, переходим на соответствующую вкладку и создаём необходимый контент, заполняя требуемые поля. В приложении может быть как продукты, так и подписки одновременно.

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

Например, создаём продукт с идентификатором one_dollar_donate, и для покупки в приложении будем использовать следующий вызов функции:

С Наступающим Новым Годом! и пусть он будет интереснее предыдущих!

Источник

Покупки в Android приложении — Play Billing Library

И как это до сих пор на Хабре нет статьи об этом? Не дело, надо исправлять.

Есть 2 способа добавить In-App покупки в Android-приложение — старый и новый. До 2017 года все пользовались библиотекой от anjlab, но с июня 2017 года ситуация изменилась, Google выпустила собственную библиотеку для внутренних покупок и подписок — Play Billing Library. Сейчас последний считается стандартом.

Play Billing Library это очень просто.

Добавьте разрешение в манифесте.

Создайте инстанс BillingClient и начните соединение.

Читайте также:  Mortal kombat ultimate для android

В метод onPurchasesUpdated() мы попадаем когда покупка осуществлена, в методе onBillingSetupFinished() можно запросить информацию о товарах и покупках.

Запросить информацию о товарах. Поместите querySkuDetails() в onBillingSetupFinished().

В коде вы могли заметить понятие SKU, что это? SKU — от английского Stock Keeping Unit (идентификатор товарной позиции).

Теперь в mSkuDetailsMap у нас лежит вся информация о товарах (имя, описание, цена), зарегистрированных в Play Console данного приложения (об этом позже). Обратите внимание на эту строку skuList.add(mSkuId);, здесь мы добавили id товара из Play Console, перечислите здесь все товары, с которыми вы хотите взаимодействовать. У нас товар один —sku_id_1.

Все готово к тому, чтобы выполнить запрос на покупку. Передаем id товара. Запустите этот метод, например, по клику на кнопку.

Теперь, запустив этот метод, вы увидите вот такое диалоговое окно (прим. картинки из Интернета).

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

Все хорошо, но если пользователь перезапустит приложение, наша программа ничего не знает о покупках. Надо запросить информацию о них. Сделайте это в onBillingSetupFinished().

В purchasesList попадает список всех покупок, сделанных пользователем.

Делаем проверку: если товар куплен — выполнить payComplete().

Готово. Осталось это приложение опубликовать в Play Console и добавить товары. Как добавить товар: Описание страницы приложения > Контент для продажи > Создать ограниченный контент.

Примечание 1: Вы не сможете добавить товар пока не загрузите билд приложения в Play Console.

Примечание 2: Чтобы увидеть диалоговое окно о покупке, вам надо загрузить билд в Play Console, добавить товар и подождать какое-то время (

30 минут — 1 час — 3 часа), пока товар обновится, только после этого появится диалоговое окно и можно будет осуществить покупку.

Примечание 3: Ошибка Please fix the input params. SKU can’t be null — товар в Play Console еще не успел обновиться, подождите.

Примечание 4: Вы можете столкнуться с ошибкой Error «Your transaction cannot be completed», в логах как response code 6 пока будете тестировать. По каким причинам это происходит мне точно неизвестно, но по моим наблюдениям это происходит после частых манипуляций с покупкой и возвратом товара. Чтобы это починить перейдите в меню банковских карт и передобавьте вашу карту. Как этого избежать? Добавьте ваш аккаунт в Play Console в качестве тестировщика и покупайте только с тестовой карточки.

(Кстати, на Хабре работает система донейтов по кнопке под статьёй — прим. модератора).

Источник

In-app purchases: продвинутые механики работы с покупками на Android и iOS

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

iOS in-app purchases:

Android in-app purchases:

Написано совместно с:

Андреем Кяшкиным,

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

Работа с продуктами на сервере

Для получения данных о продуктах на iOS/Android с помощью StoreKit/Billing Library нам нужно передавать id продуктов, информацию о которых мы хотим запросить — то есть, нет способа получить все доступные продукты, не зная о них вообще ничего. Бэкенд дает нам замечательное преимущество — не зашивать id продуктов на клиенте и тем самым иметь возможность манипулировать списком актуальных продуктов без обновления приложения.

Таким образом, мы можем отдавать на клиент общую модель продукта:

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

Читайте также:  Андроид с автозаписью звонков

introductory_offer_eligibility , promotional_offer_eligibility и promotional_offer_id — это поля, которые несут в себе информацию о скидочных предложениях, доступных конкретному пользователю. В отличие от предыдущего пункта, эти штуки мы как раз вынесли на бэк, потому что — внезапно — ни AppStore, ни Play Market напрямую не дают информацию, доступно ли intro или promo для конкретного пользователя. Соответственно, у самого продукта может быть intro, но данному пользователю оно недоступно, потому что он его уже использовал. И чтобы отобразить это в UI, вычислять это нужно самостоятельно, лучше на бэке.

И теперь флоу получения продуктов на клиенте будет выглядеть так:

Получаем историю транзакций от стора на девайсе.

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

Запрашиваем у бэка продукты.

По id продуктов запрашиваем у стора всю остальную информацию.

Отображаем в UI.

Предоставление кросс-доступа пользователю

Как только вы вынесли продукты на сервер и сделали само понятие «продукт» универсальным, стоит задуматься о том, как сделать то же самое для понятия «статус покупки». Идея в том, что если у вас больше одной платформы, то покупка на одном устройстве должна разблокировать доступ к контенту на любом устройстве вне зависимости от ОС, но в пределах аккаунта, с которого она была совершена. Если у вас больше одного продукта, то сделать это не так просто, т.к. вам на устройстве необходимо понимать, что именно купил пользователь, и давать ему доступ к той или иной части вашего приложения.

Для универсализации статуса покупки удобно ввести понятие «уровень доступа», который выставляется пользователю при совершении покупок из определенного набора. Например, мы добавляем четыре продукта — по два на каждую платформу, недельная премиум и недельная премиум плюс. Пример из жизни — Silver и Gold подписка в Тиндере. Gold стоит дороже и открывает больше возможностей. За обычными недельными мы закрепляем уровень доступа «обычная», а за премиум подписками, соответственно, «премиум». Если пользователь на какой-либо платформе или девайсе покупает подписку, за которой, например, закреплен уровень доступа «обычная» то сервер должен после покупки прислать на устройство этот идентификатор (внутри профиля или каким-то другим способом) и, выполнив обычное сравнение строк, вы сможете понять, что именно купил пользователь и отреагировать на это.

Так выглядит проверка на наличие уровня доступа:

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

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

Синхронизация истории покупок и восстановление покупок

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

Читайте также:  Android usb driver issue

просто запросив рецепт (receipt) — актуально, если в пределах установки уже были совершены какие-то покупки;

запустив процесс восстановления покупок (restore purchases).

А вот на iOS 15+ появилась возможность получать все entitlements пользователя в любой момент.

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

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

В iOS 15+ появился listener, который в две строки можно запустить на старте приложения. Этот listener получает все текущие покупки, которые есть у пользователя, в виде массива и на старте обновляет их данные – статус и проч. В целом, при первом запуске приложения рестор покупок больше не нужен, т.к. в реал-тайме можно получить обновления по всем покупкам пользователя между разными девайсами.

Обработка покупок, когда сервер не отвечает

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

При этом с ошибками от сторов на iOS или Android, как правило, сложно что-то сделать, кроме как показать ошибку в UI, а вот в случае недоступности нашего бэка мы можем чуть лучше сгладить углы.

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

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

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

Заключение

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

Как видите, процесс подключения покупок довольно трудоёмкий и требует учёта очень разных сценариев. Упростить задачу можно с помощью сторонних сервисов. Например, в Adapty все продвинутые кейсы и, тем более, базовое подключение покупок с серверной валидацией уже готовы. Для работы нужно создать аккаунт и подключить Adapty SDK. Так вы сэкономите пару месяцев разработки и начнёте быстрее монетизироваться. Для роста продаж в Adapty есть продвинутая аналитика, когортный анализ, а/б тесты пейволлов и интеграции с сервисами аналитики и атрибуции.

Источник

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