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


78

Я використовую версію 3 API оплати через додаток. У мене є один керований, невитратний товар. Я ще не випустив цю функцію у своєму додатку, тому хочу вирішити питання щодо вмісту корисного набору до покупки.

З "Найкращих практик безпеки" :

Встановіть рядок корисного навантаження розробника під час надсилання запитів на придбання

За допомогою API виставлення рахунків у програмі версії 3 ви можете включити маркер рядка "корисне навантаження розробника" під час надсилання запиту на покупку в Google Play. Як правило, це використовується для передачі рядкового маркера, який однозначно ідентифікує цей запит на придбання. Якщо ви вказали значення рядка, Google Play повертає цей рядок разом із відповіддю на покупку. Згодом, коли ви робите запити щодо цієї покупки, Google Play повертає цей рядок разом із деталями покупки.

Ви повинні передати ланцюговий маркер, який допомагає вашій програмі ідентифікувати користувача, який зробив покупку, щоб згодом ви могли переконатися, що це законна покупка цим користувачем. Для витратних елементів ви можете використовувати випадково сформований рядок, але для невитратних елементів слід використовувати рядок, який однозначно ідентифікує користувача.

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

Справедливо чи неправильно, я вирішив не вживати «подальших заходів безпеки» щодо налаштування сервера для перевірки покупки. І я не зберігаю власний запис про покупку - я завжди викликаю API виставлення рахунків. Тож чи справді є якась причина для мене, щоб я перевірив це корисне навантаження? Сам API перевірки, безумовно, перевіряє особу користувача, перш ніж повідомляти про товар як придбаний, і якщо зловмисник зламав пристрій (або програму, або API Google play), я не бачу користі від проведення додаткової перевірки ідентифікацію користувача на пристрої, де його можна легко обійти. Або є причина для цього, про яку я не думаю?

Відповіді:


70

Якщо ви не ведете записи, немає можливості підтвердити, що те, що ви отримуєте, є тим, що ви надіслали. Отже, якщо ви додаєте щось до корисного навантаження розробника, ви можете або довіряти, що це є законним (що є обґрунтованим припущенням, якщо підпис перевіряється), або не довіряти йому повністю і використовувати лише посилання, але не для перевірки статусу ліцензії тощо. Наприклад, якщо ви зберігаєте електронну пошту користувача, ви можете використовувати значення, а не просити їх ввести його знову, що трохи зручніше для користувача, але ваша програма не зламається, якщо її там немає.

Особисто я вважаю, що вся ця частина "найкращих практик" бентежить і намагається змусити вас виконати роботу, якою API повинен справді займатися. Оскільки покупка пов’язана з обліковим записом Google, і Play Store, очевидно, зберігає цю інформацію, вони повинні просто вказати вам це в деталях покупки. Отримання належного ідентифікатора користувача вимагає додаткових дозволів, які вам не потрібно додавати лише для покриття недоліків IAB API.

Отже, якщо коротко, якщо у вас немає власного сервера та спеціальної логіки надбудови, просто не використовуйте корисне навантаження розробника. З вами повинно бути добре, поки працює IAB v3 API (що, на жаль, на даний момент є великим "якщо").


4
Через півтора роки після первинної відповіді ви все ще почуваєтесь так само? Я не впевнений, чи були в API якісь кулісні зміни, внесені з ..., і я не можу сказати, що зараз довіряю документації Google.
Alex Lockwood,

6
Я все ще вважаю, що IAP повинен забезпечувати безпеку прозоро, і використання корисного навантаження розробника не вимагається. Можливо, це і зараз, але я вже давно не дивився (і навіть не використовував). У моїх програмах все ще використовується оригінальний IAP, здебільшого тому, що він надає сповіщення про покупки, які я можу відстежувати на своєму власному сервері, а "новий" IAP цього не робить.
Микола Єленков

2
Я думаю, що потрібно перевірити на сервері, звичайно, що V3 робить досить складно, якщо у вас немає користувача, який «увійшов» з якимсь ідентифікатором облікового запису (власним або 3-dparty). Збирався, можливо, спробувати API V2, АЛЕ ... Ми плануємо вимкнути службу виставлення рахунків через додаток версії 2 27 січня 2015 року, після чого користувачі більше не зможуть купувати товари та підписки через додаток через API версії 2. Ми настійно рекомендуємо вам перенести ваші програми на використання версії 3 API до листопада 2014 року, щоб забезпечити користувачам достатньо часу для оновлення своїх програм до нової версії.
inteist

@ Микола Миколайович Єленков, яка ваша нарада наразі? Я погоджуюсь з вами, що вся ця найкраща практика має бути на стороні Google.
застряг у переливі

30

Ви повинні передати рядок, що допомагає вашій програмі ідентифікувати користувача, який зробив покупку ...

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

напр

Припустимо, наш додаток має логін для користувачаA та userB. А обліковий запис Google на телефоні Android - X.

  1. userA, входить в наш додаток і купує довічне членство. Інформація про покупку зберігається в обліковому записі Google X.
  2. userA виходить із системи, а userB входить в наш додаток. Тепер userB також отримує переваги довічного членства, оскільки обліковий запис Google Android все ще є X.

Щоб уникнути такого зловживання, ми пов’яжемо покупку з рахунком. У наведеному вище прикладі ми встановимо корисне навантаження розробника як "userA", коли userA робить покупку. Отже, коли userB входить в систему, корисне навантаження не збігатиметься з зареєстрованим користувачем (userB), і ми будемо ігнорувати покупку. Таким чином userB не може отримати переваги від покупки, здійсненої userA.


Хороша відповідь. Але що, якщо ми не використовуємо жодного механізму входу? Тоді ми просто не використовуємо корисне навантаження?
tasomaniac

7
Деякий час чухаючи голову про цю проблему ідентифікатора користувача, я думаю, що на що ви вказуєте, може бути фактичним наміром рядка корисного навантаження. Це просто дуже погано пояснено в документації Google.
Pooks

Отже, користувач gmail зробить трюк і може бути використаний якdeveloperPaylod
Sami Eltamawy

3
@keybee Саме в цьому суть. У випадку, про який ви згадали, якщо ми не використовуємо корисне навантаження розробника, нам доведеться надати преміум-функції userB, коли виставлення рахунків у програмі повертає "Ви вже маєте цей елемент" (оскільки ми не маємо можливості дізнатись, чи зробив це userB покупка в першу чергу). Якщо userB повинен купувати на тому самому пристрої, де купував userA, userB повинен перейти на власний обліковий запис Google і здійснити покупку.
therealsachin

3
@therealsachin Я отримую це, але якщо я перевірю на своєму сервері та заблокую userB, він не матиме можливості придбати членство в іншому обліковому записі, оскільки Google Play перевіряє спочатку основний рахунок, тому 2 користувачі на одному пристрої не зможуть робота. Однак це може бути проблемою лише тоді, коли користувачеві А з якоїсь причини потрібен ще один обліковий запис. Він ніколи не зможе зробити ще одну покупку з тим самим обліковим записом Google, навіть не з різним корисним навантаженням. - Ідеальним для мене було б, щоб у разі нового корисного навантаження я мав змогу знову придбати передплату.
keybee

21

Існує також інший підхід до обробки корисного навантаження розробника. Як сказав Микола Єленков, занадто багато накладних витрат, щоб вимагати ідентифікатор користувача та встановлювати додаткові дозволи для профілю користувача для вашої програми, тому це невдалий підхід. Тож давайте подивимося, що Google говорить у останній версії зразка програми TrivialDrive у зразках In-App Billing v3:

  • ПОПЕРЕДЖЕННЯ. Генерування випадкового рядка під час початку покупки та перевірки його тут може здатися хорошим підходом, але це не вдасться у випадку, коли користувач купує товар на одному пристрої, а потім використовує ваш додаток на іншому пристрої, оскільки на на іншому пристрої ви не матимете доступу до випадкового рядка, який ви спочатку створили.

Тож випадковий рядок - це не гарна ідея, якщо ви збираєтеся перевірити придбаний товар на іншому пристрої, але все-таки вони не кажуть, що це не є гарною ідеєю для перевірки відповіді на покупку. Я б сказав - використовуйте корисний набір розробника лише для підтвердження покупки, надіславши випадковий унікальний рядок, збережіть його у налаштуваннях / базі даних та на відповіді на покупку перевіряйте цей корисний набір розробника. Що стосується запитів інвентаризації (покупок у програмі) на початку активності - не турбуйтеся перевіряти корисне навантаження розробника, оскільки це може статися на іншому пристрої, де у вас немає такої випадкової унікальної рядки. Ось як я це бачу.


4
Дякую, я застосовую цей підхід (і я підтримав :), тому що це звучить як хороший компроміс, але я думаю, що є проблема з логікою, як описано. Якщо перевірка корисного навантаження не вдається здійснити покупку, тоді Google Play все ще вважає, що ви є власником товару, тому вам просто потрібно перезапустити програму, вона прочитає інвентар і без перевірки корисного навантаження видасть вам товар. Одним з виправлень є споживання товару, якщо перевірка корисного навантаження не вдається здійснити покупку, але тоді ви взяли гроші користувача, що може призвести до неприємних листів, якщо це колись трапиться невинно ...
Джорджі

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

Прочитайте коментар @Georgie. Інакше ви витратите багато часу на те, щоб зрозуміти, що це погана ідея.
Halvor Holsten Strand

16

Це залежить від способу підтвердження developerPayload. Є два сценарії: віддалена перевірка (за допомогою сервера) та локальна (на пристрої).

Сервер

Якщо ви використовуєте сервер для developerPayloadперевірки, це може бути довільний рядок, який можна легко обчислити як на пристрої, так і на сервері. Ви повинні мати можливість ідентифікувати користувача, який виконав запит. Припускаючи, що кожен користувач має відповіднийaccountId , його developerPayloadможна обчислити як комбінацію з purchaseId(ім'я SKU) таким чином:

MD5(purchaseId + accountId)


Пристрій

developerPayload не повинна бути електронною адресою користувача . Хорошим прикладом того, чому не слід використовувати електронну пошту як корисне навантаження, є сервіс Google for Work. Користувачі можуть змінювати свою електронну адресу, пов’язану з обліковим записом. Єдина постійна річ accountId. У більшості випадків електронна пошта буде в порядку (наприклад, адреси Gmail на даний момент незмінні), але не забудьте розробити на майбутнє.

Кілька користувачів можуть використовувати один і той самий пристрій, тому ви повинні мати змогу розрізнити, хто є власником товару. Для перевірки пристрою developerPayloadє рядок, який однозначно ідентифікує користувача, наприклад:

MD5(purchaseId + accountId)


Висновок

Як правило, developerPayloadв обох випадках може бути лише accountId. Для мене це виглядає як безпека через неясність . MD5 (або інший алгоритм хешування) purchaseId- це лише спосіб зробити корисне навантаження більш випадковим, не чітко показуючи, що ми використовуємо ідентифікатор облікового запису. Зловмисникові довелося б декомпілювати програму, щоб перевірити, як вона обчислюється. Якщо програма затумована ще краще для вас.

Корисне навантаження не забезпечує жодної безпеки . Це може бути легко підроблено підходом "пристрій" і без будь-яких зусиль, використаних під час перевірки "сервера". Не забудьте застосувати перевірку підписів, використовуючи ваш відкритий ключ, доступний на консолі облікового запису Google Publisher.

* A повинен прочитати повідомлення в блозі про використання облікового запису ідентифікатора замість електронної пошти.


1
що таке accountId? & Як отримати ідентифікатор рахунку? чи можна зберегти один і той самий ідентифікатор для кількох облікових записів google play (при переключенні облікового запису) для отримання детальної інформації github.com/googlesamples/android-play-billing/issues/2
Сарат Кумар

5

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

На мій погляд, цей захист здається ідеальним для додатків з підключенням до Інтернету, таких як зіткнення кланів (корисне навантаження з’являється природно, оскільки в будь-якому випадку потрібно ідентифікувати користувачів), особливо там, де злом компрометує багатокористувацький геймплей із далекосяжними ефектами, крім простого локалізованого випадку піратства . На відміну від цього, якщо хакерські атаки apk вже можуть розблокувати преміум-вміст, тоді цей захист не надто корисний.

(Якщо зловмисник намагається підробити корисне навантаження, перевірка підпису не зможе).


Чи можу я використовувати Firebase із входом в Google і базу даних у реальному часі з полями account_id, developer_payload, зберігаючи їх у реальному часі, перевіряючи їх, поки користувач відкриває програму (з додатковими спільними налаштуваннями для роботи в автономному режимі)?
Dhaval Jotaniya

5

Оновлення наприкінці 2018 року: офіційна бібліотека платежів Google Play навмисно не викриває developerPayload. Від сюди :

Поле developerPayload є застарілим полем, яке зберігається для підтримки сумісності зі старими реалізаціями, але, як згадувалося на сторінці Придбання платіжних продуктів, що продаються через додаток ( https://developer.android.com/training/in-app-billing/purchase-iab -products.html ), це поле не завжди доступне під час виконання завдань, пов’язаних із оплатою через додаток. Оскільки бібліотека була розроблена для представлення найновішої моделі розробки, ми вирішили не підтримувати developerPayload у нашій реалізації, і ми не плануємо включати це поле до бібліотеки.

Якщо ви покладаєтеся на будь-яку важливу реалізацію вашої логіки виставлення рахунків у додатку на developerPayload, ми рекомендуємо вам змінити цей підхід, оскільки це поле в якийсь момент (або найближчим часом) буде застарілим. Рекомендований підхід - використовувати власний сервер для перевірки та відстеження важливих деталей про ваші замовлення. Щоб отримати докладнішу інформацію, перегляньте сторінку безпеки та дизайну ( https://developer.android.com/google/play/billing/billing_best_practices.html ).


Це вирішує питання для мене ... Це застаріло, тому його не слід використовувати
smitty1

3

Я боровся з цим. Оскільки обліковий запис Google Play може мати лише один із будь-яких "керованих" елементів, але може мати кілька пристроїв (у мене три), наведений вище коментар від когось, що ви продаєте "за пристрій", не буде працювати ... вони зможете поставити його на свій перший пристрій, і жоден інший ніколи ... Якщо ви купуєте преміум оновлення, воно має працювати на всіх ваших телефонах / планшетах.

Я зневажаю уявлення про отримання електронної адреси користувача, але насправді не знайшов іншого надійного методу. Тож я беру перший обліковий запис, який відповідає "google.com" у списку облікових записів (так, дозвіл на додавання до вашого маніфесту), а потім негайно хеш, щоб він більше не використовувався як адреса електронної пошти, але надав "досить унікальний "маркер. Це те, що я надсилаю як розробницьке навантаження. Оскільки більшість людей активують свій пристрій за допомогою свого ідентифікатора Google Play, є хороший знімок, тому що всі три пристрої отримають однаковий маркер (використовуючи однаковий хеш-алгоритм на кожному пристрої).

Він навіть працює на KitKat з кількома "користувачами". (Мій ідентифікатор розробника - у одного користувача, мій ідентифікатор тесту - у іншого, а кожен користувач - у своїй пісочниці).

Я протестував його на шести пристроях із загалом 3 користувачами, і кожен користувач пристрою повернув один і той же хеш, і всі користувачі мають різні хеші, що відповідає вимогам.

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

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


6
Це все чудово, але вимагає дозволів на РАХУНКИ, що тут зайве. Чому, по суті, Google не міг зробити хеш облікового запису, за допомогою якого робиться доступною покупка ... Це було б найчистішим рішенням для цього. Тепер це просто "зламано".
inteist

Я зробив щось подібне до цього, але тепер, з Android 6, додаток повинен попросити користувача надати дозвіл Контакти, що для користувача стає жахливим досвідом, коли він запускає програму вперше. Можливо, я замість цього застосую варіант Відновити покупки. Крім того, якщо ви захопите перший обліковий запис google.com, ви можете зіткнутися з проблемами, якщо користувач має більше одного облікового запису на своєму телефоні та переставить облікові записи (наприклад, видаліть обліковий запис А, а потім додайте його знову пізніше, але тепер це не перший обліковий запис) . Це трапляється, хоча, правда, рідко. Тоді вам теж потрібно скористатися засобом вибору облікового запису! Юч!
snark

1

Це часто відповідає визначенню продукту (Ваша заявка). Наприклад для випадку підписки. Чи зможе той самий користувач використовувати підписку на всіх своїх пристроях? Якщо відповідь позитивна. Ми не перевіряли корисне навантаження.

Для витратних матеріалів. Припустимо, покупка у вашому додатку дає вам 10 віртуальних монет. Чи зможе користувач використовувати ці монети на різних пристроях? 4 на одному пристрої та 6 на іншому? Якщо ми хочемо працювати лише на пристрої, який здійснив покупку, ми повинні перевірити корисне навантаження, наприклад, за допомогою самогенерованого рядка та локально збереженого.

На основі цих питань ми повинні вирішити, як здійснити перевірку корисного навантаження.

З повагою

Сантьяго

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