Comments 23
Да, всегда юзал anjlab. Никак не мог понять сэмплы Google Billing'a на GitHub.
А либа в этой статье и Ваши примеры хороши! Еще не внедрял нигде, но на заметку взял.
Благодарю за статью!
+1 в пост и карму!
Было познавательно! ;-)
До 2017 года все пользовались библиотекой от anjlab

Не все. Я ей не пользовался, а вместо этого просто расковырял документацию, разобрался и сделал все так, как надо.
Притом что ничего сложного в нативной платежке нет. Зато позволяет понять получше весь биллинг и лучше понимать ошибки, которые могут возникать в процессе.
Единственная сложность, какая была — получение цены в валюте пользователя и приведение ее к нужному формату.
UFO landed and left these words here
Ну не знаю что там «нестабильного» — все работало. Я тоже о 2011-2013 — щас на библиотеках, правда на других (unity IAP).

Вот да, вот эта 1/1000 и подкашивала. Вроде были еще какие то трабблы чтобы получить локализированное название валюты, причем в каких то случаях оно до числа пишется, в каких то после. Но — это все очень глубокое копание, которое я и в этой статье не увидел.
UFO landed and left these words here
Аа, семпл был да, для истинных спартанцев ) Кто не выжил разобрался — огребали всякое, причем часто уже после выливки — пользователи то массой тестируют. А ведь кейсов там вагон и тележка, да. Веселые времена были )
То чувство, когда до сих пор пользуешься anjlab библиотекой, а про офф не слышал) Спасибо за информацию!
Добавьте ваш аккаунт в Play Console в качестве тестировщика и покупайте только с тестовой карточки.

Только нужно не забывать, что учётная запись гугла для тестирования должна отличаться от учётной записи разработка (той которая имеет доступ в google play developer console). В документации я не нашел такого описания, но если погуглить мы найдет не одно описание подобных решений вопросов и ответов (например, тут и https://medium.com/bleeding-edge/testing-in-app-purchases-on-android-a6de74f78878), да и по своему опыту я помню, что именно так оно и работало.

Так же это указано и в гугловом семпле тут


Make sure to add your test account (the one you will use to test purchases) to the "testers" section of your app. Your test account CANNOT BE THE SAME AS THE PUBLISHER ACCOUNT. If it is, your purchases won't go through.
Спасибо за статью! Но еще больше интересно увидеть какой-то пример практической реализации проверки достоверности сделанной покупки с помощью своего сервера (хотя бы PHP). А то при наличии LuckyPatcher и подобного — все эти покупки легко обходятся, насколько я понимаю.

Я так понимаю, что приложение должно что-то запросить у Гугл API, и запросить свой сервер, чтобы тот что-то запросил у Гугл API. А потом эти два ответа где-то надо сравнить, чтобы убедится в наличии платежа?
В «покупке» идёт вместе с данными о покупке и цифровая подпись, которую надо проверить:
public class Purchase {
private final String mOriginalJson;
private final String mSignature;

Ниже я дал ссылку на пример, там есть функции проверки подписи: github.com/googlesamples/android-play-billing/blob/master/TrivialDriveKotlin/app/src/main/java/com/kotlin/trivialdrive/billingrepo/Security.kt

Надеюсь, перевести его с Kotlin на PHP не составит труда, там обычная проверка подписи с открытым RSA — ключом.
Благодарю за инфо, но вот как раз практического полного примера PHP и не хватает.
Я не силён в PHP, но вот это оно? php.net/manual/ru/function.openssl-verify.php
Приложение передаёт на сервер originalJson и signature, которые используются в openssl_verify()

Тут есть ещё одна тонкость, что ответит сервер? Если он на проверку отвечает ok/error, то ничто не помешает в приложении подменить его ответ или убрать эту проверку. В идеале, если приложение после покупки получает доступ к какому-либо контенту, то этот контент должен загружаться с сервера с зашифрованном виде с ключом, который может быть сгенерирован только в этой инсталляции приложения. Если контент слишком большой для загрузки, то сервер может присылать что-то наподобие лицензионного ключа, позволяющего расшифровать контент в приложении.
UFO landed and left these words here
чтобы сервер подписывал ответ

Если потом стоит просто if(isSignatureValid) { letsPlay() }
То
код проверки и валидации, каким бы утончённым он ни был, можно просто заменить на заглушки.

Тут в соседней ветке дошли до того, что сервер после валидации покупки должен присылать зашифрованный контент и виртуальную машину для его расшифровывания. ;)

можно запрашивать факт покупки заново, и довольно часто).

Если у вас хотя бы сотня тысяч клиентов, то придётся поднимать хорошую серверную инфраструктуру для постоянной валидации покупок, а там довольно медленный RSA. Поэтому я и говорил о кэше покупок в приложении, чтобы валидацию делать как можно реже.
UFO landed and left these words here
Так пользователи будут искать приложение в том же Google Play. Конкретный пример: позавчера хабравчане выпустили приложение lamptest.ru. Сейчас в поиске Google Play по запросу lamptest отображается три приложения, а может появиться четвёртое, например, lamptest.pro — перепакованная версия lamptest.ru pro со своей рекламой, доходы от которой потекут в карман хакеру Васе. И пользователи даже не будут разбираться, кто там первый что выпустил. Ведь бесплатная про версия гораздо круче платной про версии ;)
UFO landed and left these words here
Не раскрыто две важных темы:
1. Кэш покупок, чтобы приложение могло работать в оффлайне.
2. Проверка валидности подписи покупки. Отсюда ещё возникает проблема скрытного хранения ключа проверки этой подписи внутри приложения (что не надёжно) или запуск собственного сервера по проверке этой покупки вне приложения (что рекомендуется Google).
В общих чертах это разобрано в свежем примере от Google: github.com/googlesamples/android-play-billing/tree/master/TrivialDriveKotlin

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

Billing-библиотека делает это сама, отдельно не надо ничего добавлять.
Приложение знает о покупках даже после того, как вы очистите данные. Это работает за счет кэша Google Servises, насколько я понимаю.
Да, покупки приходят потом из кэша Play Services, но если у вас валидация покупки происходит на сервере, то как приложение это сделает в оффлайне? Поэтому надо где-то хранить, что такой-то Order ID проверен. И не в открытом виде ;)
Only those users with full accounts are able to leave comments. Log in, please.