Як перевірити придбання програми для Android на стороні сервера (Google Play у програмі виставлення рахунків v3)


96

У мене є простий додаток (потрібен вхід користувача з обліковим записом). Я пропоную деякі преміум-функції для платних користувачів, наприклад більше новин.

Мені потрібно записати, чи користувач купив цей товар у моїй базі даних сервера. Коли я надаю вміст даних на пристрій користувача, я можу перевірити статус користувача та надати інший вміст для платного користувача.

Я перевірив офіційний зразок Trivialdrive, наданий Google, він не містить жодного зразка коду для перевірки на стороні сервера, ось мої запитання.

  1. Я виявив, що зразок використовує відкритий ключ мого додатка всередині для перевірки покупки, це виглядає недобре, я думаю, що я можу просто перенести процес перевірки на мій сервер у поєднанні з обліковими даними для входу користувачів, щоб побачити, чи завершена покупка користувача, а потім оновити базу даних.
  2. Також є API придбання, який я можу використовувати для запиту. Мені потрібно передати користувачеві purchaseToken на сервер.

Я не впевнений, який метод мені слід скористатися для підтвердження покупки користувача та позначення статусу користувача у моїй базі даних, можливо, обох?

І я боюся, що склалася ситуація, якщо користувач придбав цей предмет у Google Play, але з якихось причин саме в той час, коли мій додаток запустив перевірку на мій сервер, мережеве з’єднання перервано або мій власний сервер не працює , користувач щойно заплатив гроші в Google Play, але я не записав покупку на своєму сервері? Що мені робити, як я можу впоратися з цією ситуацією.


Ймовірно, вам слід видалити прапор ios з цього питання.
Густаво Гевара

Відповіді:


160

Здається, те, що ви шукаєте, - це спосіб перевірити, чи користувач увімкнув преміум-функції у своєму обліковому записі, тож тут я б почав;

Переконайтеся, що у вашій базі даних є якийсь прапор, який вказує, чи має користувач преміум-функції, та включіть його до корисного навантаження відповіді API при запиті інформації про обліковий запис. Цей прапор буде вашим основним повноваженням щодо "преміум-функцій".

Коли користувач робить покупку в додатку, кешуйте деталі (маркер, ідентифікатор замовлення та ідентифікатор продукту) локально на клієнті (тобто програмі), а потім надішліть їх у ваш API.

Потім ваш API повинен надіслати його purchaseTokenдо API розробника Google Play для перевірки.

Звідси може статися кілька речей:

  1. Квитанція дійсна, ваш API відповідає клієнту кодом стану 200 Ok
  2. Квитанція недійсна, ваш API відповідає клієнту кодом статусу 400 поганих запитів
  3. API Google Play не працює, ваш API відповідає кодом стану 502 Bad Gateway

У випадку 1. або 2. (коди стану 2xx або 4xx) ваш клієнт очищає кеш деталей покупки, оскільки він йому більше не потрібен, оскільки API вказав, що його отримано.

Після успішної перевірки (випадок 1.) вам слід встановити для користувача premiumпрапорець істинним.

У випадку 3. (код стану 5xx) або мережевий тайм-аут клієнт повинен продовжувати намагатися, поки не отримає код стану 2xx або 4xx від вашого API.

Залежно від ваших вимог, ви можете змусити зачекати кілька секунд, перш ніж надсилати знову, або просто надіслати деталі в ваш API, коли колись програма буде запущена знову або з’явиться у фоновому режимі, якщо деталі покупки є в кеші програми.

Цей підхід повинен подбати про таймаути мережі, недоступність серверів тощо.

Зараз потрібно розглянути кілька питань:

Що має статися відразу після покупки? Чи слід додатку чекати, поки перевірка буде успішною, перш ніж надавати преміум-вміст, чи вона повинна попередньо надати доступ і забрати його, якщо перевірка не вдається?

Надання попереднього доступу до преміум-функцій згладжує процес для більшості ваших користувачів, але ви також надаватимете доступ кільком шахрайським користувачам, поки ваш API перевіряє purchaseToken.

Іншими словами: Покупка дійсна до тих пір, поки не буде доведено шахрайство або; шахрайський, поки не буде доведено, що він дійсний?

Для того, щоб визначити, чи є у користувача ще дійсна підписка, коли термін її підписки настає для поновлення, вам потрібно буде запланувати повторну перевірку purchaseTokenдля запуску в тому, expiryTimeMillisякий було повернуто в результаті .

Якщо expiryTimeMillisце минуле, ви можете встановити premiumпрапор на false. Якщо це буде в майбутньому, переплануйте його знову на новий expiryTimeMillis.

Нарешті, щоб забезпечити користувачеві преміум-доступ (чи ні), ваш додаток повинен запитувати ваш API щодо даних користувачів про запуск програми або коли вона виходить із фонового режиму.


Як я отримую квитанцію від Google за платним додатком?
Мербін Джо

2
Привіт! Немає способу отримати доступ до історії підписок у google? Як запобігти втраті факту, який використовував вже придбану кубскрипцію у випадку, якщо додаток аварійно завершує роботу під час зберігання purchaseToken?
scythargon

2
У мене схожа проблема .. замість того, щоб дозволяти програмі надсилати маркер на API не було б надійніше вказувати серверу розробника Google робити це за допомогою push-сповіщення прямо на мій api?
Джанлука Геттіні,

За скасовані підписки API розробника Google Play поверне 200 після скасування, якщо для перевірки використовується той самий старий маркер покупки.
Цезар Кобуз,

Отже, для передплати ви пропонуєте, щоб після першого дзвінка на сервер ми зберігали маркер покупки та ідентифікатор товару та планували інший виклик перевірки (повторно запускати той самий запит), коли відбувається expiryTimeMillis? Чи так ми повинні перевірити дійсність передплати? Чи існують вказівки від Android щодо того, як це зробити? Apple отримала про це відео WWDC, яке досить чітко пояснює хорошу практику, але не може знайти багато про Play Store.
счанкам

26

Документація щодо цього заплутана і дивно багатослівна з речами, які є майже несуттєвими, в той час як фактично важлива документація залишається майже без зв’язку та надзвичайно важкою для пошуку. Це має чудово працювати на найпопулярнішій серверній платформі, яка може запускати клієнтські бібліотеки google api, зокрема Java, Python, .Net та NodeJS. Примітка: Я протестував лише клієнт API Python, як показано нижче.

Необхідні кроки:

  1. Створіть проект API за посиланням API Access на консолі Google Play

  2. Створіть новий обліковий запис служби, збережіть приватний ключ JSON, який генерується. Вам потрібно буде перенести цей файл на свій сервер.

  3. Натисніть Готово в розділі облікового запису служби консолі Play, щоб оновити, а потім надати доступ до облікового запису служби

  4. Перейдіть за адресою https://developers.google.com/api-client-library бібліотеку клієнта goi api для вашої серверної платформи

  5. Використовуйте клієнтську бібліотеку вашої платформи для створення інтерфейсу служби та безпосереднього зчитування результату підтвердження вашої покупки.

Вам не потрібно морочитися з обсягами авторизації, робити дзвінки за власними запитами, оновлювати маркери доступу тощо. Про все дбає бібліотека клієнта api. Ось приклад використання бібліотеки python для перевірки підписки:

Спочатку встановіть google api-клієнт у свій pipenv так:

$ pipenv install google-api-python-client

Потім ви можете встановити облікові дані клієнта api, використовуючи файл json приватного ключа для автентифікації облікового запису служби.

credentials = service_account.Credentials.from_service_account_file("service_account.json")

Тепер ви можете перевірити придбання передплати або придбання продуктів безпосередньо за допомогою бібліотеки.

#Build the "service" interface to the API you want
service = googleapiclient.discovery.build("androidpublisher", "v3", credentials=credentials)

#Use the token your API got from the app to verify the purchase
result = service.purchases().subscriptions().get(packageName="your.app.package.id", subscriptionId="sku.name", token="token-from-app").execute()
#result is a python object that looks like this ->
# {'kind': 'androidpublisher#subscriptionPurchase', 'startTimeMillis': '1534326259450', 'expiryTimeMillis': '1534328356187', 'autoRenewing': False, 'priceCurrencyCode': 'INR', 'priceAmountMicros': '70000000', 'countryCode': 'IN', 'developerPayload': '', 'cancelReason': 1, 'orderId': 'GPA.1234-4567-1234-1234..5', 'purchaseType': 0}

Документація до інтерфейсу служби платформи для API розробника відтворення пов'язана не так просто, як для деяких, її просто важко знайти . Ось посилання на популярні платформи, які я знайшов:

Пітон | Java | .NET | PHP | NodeJS (Github TS) | Перейти (Github JSON)


5
Погодьтеся, документація жахлива ... Будь-які ідеї, як це зробити за допомогою функцій Firebase (Firestore) та Cloud як бекенда?
Jeff Padgett

Якщо ваші хмарні функції знаходяться в NodeJS, то ви можете скористатися посиланням NodeJS вище, щоб налагодити роботу бібліотеки клієнта API?
Дхірадж Гупта,

17

Повний приклад використання клієнтської бібліотеки Google API для PHP :

  1. Налаштуйте свій проект Google і отримайте доступ до Google Play для свого облікового запису служби, як описано у відповіді Марка тут https://stackoverflow.com/a/35138885/1046909 .

  2. Встановіть бібліотеку: https://developers.google.com/api-client-library/php/start/installation .

  3. Тепер ви можете підтвердити свою квитанцію таким чином:

    $client = new \Google_Client();
    $client->setAuthConfig('/path/to/service/account/credentials.json');
    $client->addScope('https://www.googleapis.com/auth/androidpublisher');
    $service = new \Google_Service_AndroidPublisher($client);
    $purchase = $service->purchases_subscriptions->get($packageName, $productId, $token);

    Після цього покупка $ є екземпляром Google_Service_AndroidPublisher_SubscriptionPurchase

    $purchase->getAutoRenewing();
    $purchase->getCancelReason();
    ...

Це не працює, я продовжую отримувати (401) Необхідний вхід і setAuthConfig не приймає облікові дані службового рахунку json
Раулнд,

Цей працював у мене putenv ('GOOGLE_APPLICATION_CREDENTIALS = credentials.json'); $ client = новий Google_Client (); $ client-> useApplicationDefaultCredentials (); $ client-> addScope (' googleapis.com/auth/androidpublisher' ); $ service = новий Google_Service_AndroidPublisher ($ клієнт); $ покупка = $ послуга-> покупки_продукти-> отримати ($ packageName, $ productId, $ маркер); var_dump ($ покупка);
Роулнд,

Це стосується випадків виставлення рахунків за додатками. Що робити, якщо я хочу отримати orderId до своєї бази даних кожного разу, коли користувач купує мою програму з play store замість inapp?
Ankesh kumar Jaisansaria

stackoverflow.com/questions/48662787/… Будь ласка, перегляньте це питання. Шукаю відповіді на це питання. Це також має активну нагороду
Ankesh kumar Jaisansaria

@MingalevME Що робити, якщо формат маркера недійсний, і PHP отримує фатальну помилку, як мені виявити цю помилку?
alexx0186 02

12

Ви можете спробувати скористатися Purchases.subscriptions: отримати сторону сервера. Він приймає packageName, subscriptionId та маркер як параметри і вимагає авторизації .

Перевіряє, чи є підписка користувача дійсною, і повертає термін її дії.

У разі успіху цей метод повертає ресурс Purchases.subscriptions у тілі відповіді.


9
У мене серйозні проблеми з тим, щоб авторизація працювала.

8
Серйозно. Наскільки важливі покупки для деяких програм, підтримка та документація відсутні. Це те, що вам потрібно зробити на сервері: github.com/google/… . Більше інформації тут: stackoverflow.com/questions/35127086/…
користувач

0

Я відповідаю на це занепокоєння

мережеве з’єднання не працює або не працює мій власний сервер, користувач просто заплатив гроші в google play, але я не записав покупку на своєму сервері? Що мені робити, як я можу впоратися з цією ситуацією.

Ситуація така:

Користувач купує елемент "abc" за допомогою сервісу google play -> повернути ОК -> не вдається підтвердити з сервером з деяких причин, таких як відсутність підключення до Інтернету.

Рішення:

На стороні клієнта, перед тим, як показувати кнопку "Google Wallet", ви перевіряєте, чи вже є елемент "abc".

  • якщо так, перевірте сервер ще раз
  • якщо ні, покажіть кнопку "Google Wallet".

Покупка придбання = mInventory.getPurchase ('abc');

if (purchase != null) // Verify with server 

else // show Google Wallet button

https://developer.android.com/google/play/billing/billing_reference.html#getSkuDetails


4
Я не розумію, чому перевірка на сервері є більш безпечною, ніж перевірка на додатку. Врешті-решт це програма розблоковує функції, тому все ще можна видалити або інвертувати код у програмі, яка перевіряє, чи відповідь сервера "ОК"
Джанлука Геттіні

2
@GianlucaGhettini, тому що іноді сервер надає придбану послугу, а не додаток, крім того, додаток може бути реконструйовано, а потім із певною проблемою може бути зламаний процес перевірки.
Мох'яддін Алаоддін,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.