- In-App Purchase в Android приложениях
- Покупки в Android приложении — Play Billing Library
- Implement In-app Update In Android
- Make sure every user of your app is on the new version.
- What is In-App Update:
- Flexible Update:
- Benefits:
- Android in-app purchases, часть 3: получение активных покупок и смена подписки
- Получение списка покупок
- Смена подписок
- Про Adapty
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 написано тут.
Источник
Покупки в Android приложении — Play Billing Library
И как это до сих пор на Хабре нет статьи об этом? Не дело, надо исправлять.
Есть 2 способа добавить In-App покупки в Android-приложение — старый и новый. До 2017 года все пользовались библиотекой от anjlab, но с июня 2017 года ситуация изменилась, Google выпустила собственную библиотеку для внутренних покупок и подписок — Play Billing Library. Сейчас последний считается стандартом.
Play Billing Library это очень просто.
Добавьте разрешение в манифесте.
Создайте инстанс BillingClient и начните соединение.
В метод 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 в качестве тестировщика и покупайте только с тестовой карточки.
(Кстати, на Хабре работает система донейтов по кнопке под статьёй — прим. модератора).
Источник
Implement In-app Update In Android
Make sure every user of your app is on the new version.
Apr 6, 2020 · 8 min read
In this article, we will learn about the In-app update feature in Android what is all about In-app update, what are the benefits of using the In-app update in your android application. Recently I’ve been working on a product in which I need to Implement an In-app update Why we need to Implement this?.
As a Developer we always want our users to have the updated version of their application but there are a lot of people who actually turned off their auto update from google play store and he/she doesn’t know about any update available or not.
To overcome the problem Google Introduced this feature called In-app update from this feature you can easily prompt the user to update the application and with the user permission you can update the application also while updating the app user can be able to interact with the application. Now the user doesn’t need to go to google play store to check there is any update available or not.
What is In-App Update:
An In-app update was Introduced as a part of the Play Core Library, which actually allows you to prompts the user to update the application when there is any update available on the Google Play Store.
There are two modes of an In-app update.
- Flexible Update
- Immediate Update
Flexible Update:
In Flexible update, the dialog will appear and after the update, the user can interact with the application.
This mode is recommended to use when there is no major change In your application like some features that don’t affect the core functionality of your application.
The update of the application is downloading in the background in the flexible update and after the completion of the downloading, the user will see the dialog in which the user needs to restart the application. The dialog will not automatically show, we need to check and show to the user and we will learn how later.
Benefits:
The major benefit of the flexible update is the user can interact with the application.
Источник
Android in-app purchases, часть 3: получение активных покупок и смена подписки
Привет, я Влад, core разработчик Adapty SDK для встроенных покупок на Android. Это наша третья статья из цикла статей про внедрение покупок на Android. В этой серии мы полностью закрываем вопросы добавления покупок в приложениях в Google Play:
Android in-app purchases, часть 3: получение активных покупок и смена подписки. — Вы тут.
Cегодня мы рассмотрим еще две важные темы по реализации in-app purchases с Google Play Billing Library. Начнем с получения активных покупок пользователя, то есть действующих подписок и ранее купленных non-consumable продуктов. Купленные consumable-продукты сюда не входят, потому что вы их обменяли на голду законсьюмили, чтобы иметь возможность купить повторно.
Это нам может пригодиться, если мы, допустим, хотим сделать кнопку покупки такого продукта неактивной. Или, например, написать на ней, что это текущая подписка, если это подписка. Или просто дать пользователю доступ к оплаченным фичам.
Получение списка покупок
В Billing Library для получения активных покупок есть метод queryPurchasesAsync(String skuType, PurchasesResponseListener listener) (раньше использовался синхронный метод queryPurchases(String skuType), но с версии Billing Library 4.0.0 его задепрекейтили). Да, все подобные методы почему-то требуют указания типа продуктов, поэтому получение полного списка снова придется комбинировать из двух запросов.
Дополним наш BillingClientWrapper по аналогии с тем, как мы делали в предыдущих статьях:
В колбэке нам возвращается список объектов класса Purchase. Раньше, чтобы понять, к какому продукту относится покупка, нужно было вызвать ее метод getSku() и получить id продукта. Но в 2021 году на Google I/O были анонсированы покупки нескольких продуктов в рамках одной транзакции, поэтому в версии 4.0.0 getSku() сменился на getSkus() и возвращает список id продуктов, а еще добавился метод getQuantity(), который возвращает их количество. Правда, способ инициировать такую покупку я в документации не нашел: кажется, он пока не в релизе. Если что-то про это знаете, пишите в комментариях, ставьте лайки, жмите на колокольчик.
У метода queryActivePurchases() есть одна небольшая проблема — он берет покупки из локального кэша Play Services, и результат не всегда бывает актуален, особенно если покупка была совершена на другом устройстве. Лечится это несложным хаком, заодно добавим в BillingClientWrapper api для получения истории покупок:
Здесь колбэк возвращает список с самой последней покупкой каждого продукта, который пользователь когда-либо приобретал, а заодно синхронизирует локальный кэш активных покупок с актуальным состоянием. Также обратите внимание, что покупка здесь представлена не классом Purchase, а классом PurchaseHistoryRecord.
Теперь мы можем объявить метод получения только что синхронизированных активных покупок:
Мы не просто так начали с получения покупок – следующая тема тесно связана с ними. Поговорим о замене подписок.
Смена подписок
В базовом случае, если купить обе подписки тем способом, который мы описали в предыдущей статье, они обе будут активны. Это не всегда ожидаемое поведение, поэтому, например, в App Store, как и в случае с consumable/non-consumable, это решается на уровне App Store Connect с помощью групп подписок. А с продуктами из Play Market, как и в случае с consumable/non-consumable, эту логику нужно делать на клиенте.
В нашем примере из предыдущей статьи подписки отличаются только периодом оплаты, поэтому, по логике, должны быть взаимоисключающими. Добавим в BillingClientWrapper метод для замены старой подписки на новую:
От обычной покупки он отличается только параметром SubscriptionUpdateParams. В классе SubscriptionUpdateParams.Builder нас интересуют 2 метода:
setOldSkuPurchaseToken(String purchaseToken) — метод, в который мы передаем purchaseToken той активной покупки, где purchase.skus.first() равен id подписки, которую мы хотим заменить (мы получали список активных покупок в том числе и для этого).
Каждая из констант говорит о том, когда подписка должна будет фактически смениться, а также какие финансовые транзакции должны будут произойти и в какой день. Рассмотрим на примерах.
В нашем случае есть 2 подписки: помесячная за $9.99 и годовая за $49.99. Для удобства расчетов округлим их до $10 и $50 соответственно. Представим, что 1 сентября пользователь купил помесячную подписку, а 15-го решил сменить ее на годовую. Какие есть варианты:
Подписка меняется немедленно. Так как прошло всего полмесяца, остались неиспользованные $5 от помесячной подписки, то есть 1/10 стоимости годовой – их хватает на 36 дней. Таким образом, $50 за годовую подписку пользователь заплатит 22 октября, следующее продление будет 22.10.2022 и т.д.
Этот режим не подходит для нашего соотношения цен, потому что для него стоимость новой подписки за единицу времени должна превышать стоимость старой подписки за ту же единицу времени (у нас получается $50/г.
$4.17/мес. onPurchasesUpdated(billingResult: BillingResult, purchaseList: MutableList
?) был клиффхэнгер, что даже при успехе purchaseList может быть null – это тот самый кейс.
Помесячная подписка сменится на годовую только 1 октября, тогда же с пользователя снимут $50. Но колбэк onPurchaseUpdated(billingResult: BillingResult, purchaseList: MutableList
?) вызовется уже сейчас, только в параметре purchaseList придет null.
В этом кейсе Google настоятельно рекомендует делать acknowledge новой подписки на бэке при получении нотификации SUBSCRIPTION_RENEWED , которая придет только 1 октября, потому что, как мы помним, если этого не сделать, подписка отменится через 3 дня, и если пользователь в начале октября не будет заходить в приложение, выполнить acknowledge на клиенте нет шансов.
Впрочем, всё, что связано с бэком, расскажем уже в пятой статье.
Про Adapty
А пока предлагаю вам подписаться на наш блог на Habr, чтобы не пропустить следующие материалы. Мы пишем про покупки в мобильных приложениях: от технической реализации до метрик подписок и монетизации приложений; а также записываем подкаст, где общаемся с интересными гостями на тему приложений.
И ещё советую познакомиться с Adapty SDK, с которым работа с подписками становится проще не только технически:
Встроенная аналитика позволяет легко понимать главные метрики приложения.
А/Б тесты пейволлов делаются налету и помогают увеличивать конверсию в платных пользователей.
Интеграции с внешними системами позволяют отправлять транзакции в сервисы атрибуции и продуктовой аналитики.
Промо-кампании уменьшают отток аудитории.
Open source SDK позволяет интегрировать подписки в приложение за несколько часов.
Серверная валидация и API для работы с другими платформами упрощает работу с покупками.
Познакомьтесь подробнее с этими возможностями, чтобы быстрее внедрить подписки в своё приложение и улучшить конверсии.
Источник