Какой должна быть полезная нагрузка разработчика в API-интерфейсе Android In-App Billing v3?

Я внедряю в своем приложении биллинг, чтобы разблокировать премиум-функции. Биллинг в приложении настроен правильно. Кажется, все в порядке, кроме «полезной нагрузки разработчика».

В образце приложения говорится

 /*
     * TODO: verify that the developer payload of the purchase is correct. It will be
     * the same one that you sent when initiating the purchase.
     *
     * WARNING: Locally generating a random string when starting a purchase and
     * verifying it here might seem like a good approach, but this will fail in the
     * case where the user purchases an item on one device and then uses your app on
     * a different device, because on the other device you will not have access to the
     * random string you originally generated.
     *
     * So a good developer payload has these characteristics:
     *
     * 1. If two different users purchase an item, the payload is different between them,
     *    so that one user's purchase can't be replayed to another user.
     *
     * 2. The payload must be such that you can verify it even when the app wasn't the
     *    one who initiated the purchase flow (so that items purchased by the user on
     *    one device work on other devices owned by the user).
     *
     * Using your own server to store and verify developer payloads across app
     * installations is recommended.
     */

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


person Amit Jayant    schedule 04.09.2013    source источник
comment
проверьте эту ссылку: stackoverflow.com/questions / 17196562 /. Я надеюсь, что это решит все ваши вопросы.   -  person Maulik    schedule 05.09.2013
comment
Спасибо, Маулик. Ответ в ссылке мне очень помог :)   -  person Amit Jayant    schedule 05.09.2013
comment
Вы должны либо закрыть свой вопрос, либо исправить мой ответ ниже, чтобы вопрос был решен, чтобы другие могли отметить этот вопрос как полезный для своих нужд.   -  person Maulik    schedule 06.09.2013


Ответы (2)


Пожалуйста, проверьте ответ ниже, это может решить вашу проблему:

если вы используете расходный элемент (управляемый элемент), вы можете использовать случайную сгенерированную строку

Шаг 1: перед созданием метода объявите это:

         private static final char[] symbols = new char[36];

                static {
                    for (int idx = 0; idx < 10; ++idx)
                        symbols[idx] = (char) ('0' + idx);
                    for (int idx = 10; idx < 36; ++idx)
                        symbols[idx] = (char) ('a' + idx - 10);
                }

шаг 2: установите классы RandomString и SessionIdentifierGenerator в своей деятельности

          public class RandomString {

        /*
         * static { for (int idx = 0; idx < 10; ++idx) symbols[idx] = (char)
         * ('0' + idx); for (int idx = 10; idx < 36; ++idx) symbols[idx] =
         * (char) ('a' + idx - 10); }
         */

        private final Random random = new Random();

        private final char[] buf;

        public RandomString(int length) {
            if (length < 1)
                throw new IllegalArgumentException("length < 1: " + length);
            buf = new char[length];
        }

        public String nextString() {
            for (int idx = 0; idx < buf.length; ++idx)
                buf[idx] = symbols[random.nextInt(symbols.length)];
            return new String(buf);
        }

    }

    public final class SessionIdentifierGenerator {

        private SecureRandom random = new SecureRandom();

        public String nextSessionId() {
            return new BigInteger(130, random).toString(32);
        }

    }

Шаг 3: передайте полезные данные в ваш запрос на покупку:

RandomString randomString = new RandomString(36);
            System.out.println("RandomString>>>>" + randomString.nextString());
            /* String payload = ""; */
            // bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ
            String payload = randomString.nextString();
            Log.e("Random generated Payload", ">>>>>" + payload);

        Log.d(TAG, "Launching purchase flow for infinite gas subscription.");
            mHelper.launchPurchaseFlow(this, SKU_GAS,
                    IabHelper.ITEM_TYPE_INAPP, RC_REQUEST,
                    mPurchaseFinishedListener, payload);

для получения дополнительной информации проверьте эту ссылку: Токен, идентифицирующий пользователя

Надеюсь, это решит вашу проблему.

person Maulik    schedule 06.09.2013
comment
НЕ используйте случайную строку. Пользователь может купить товар на одном устройстве и захотеть иметь его на другом устройстве. Этот момент описан в квесте (2-й предмет). - person defhlt; 25.02.2015
comment
Это также проблема, когда вы отменяете покупку и пытаетесь купить снова. Google Play каждый раз возвращает первую полезную нагрузку. - person Kemal Taşkın; 12.01.2016
comment
@mlatu developer.android.com/training/ in-app-billing / Посетите веб-сайт Google. Мы должны хранить полезные данные разработчика на нашем собственном веб-сервере, чтобы конкретный пользователь мог избавиться от проблемы с устройством. - person Maulik; 05.08.2016
comment
@defhlt Я думал, что он уже прикреплен к вашей учетной записи Gmail, которую вы используете для завершения покупки. почему полезная нагрузка имеет значение? - person Emil; 25.04.2018

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

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

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

Чтобы ключ оставался секретным, я использовал различные функции манипулирования строками, чтобы замаскировать его, чтобы он не сохранялся видимым образом.

Пример изменения текста можно найти здесь: Android In App Billing: защита открытого ключа приложения

String Base64EncodedPublicKey key = DecrementEachletter("Bl4kgle") + GetMiddleBit() + ReverseString("D349824");

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

person Kc Gibson    schedule 11.01.2015
comment
Как вы при таком подходе идентифицируете пользователя? - person Renjith; 04.02.2015
comment
@ Ренджит, ты не знаешь. Этот метод позволяет определить, является ли покупка законной. - person Kc Gibson; 05.02.2015
comment
Пожалуйста, я не понимаю, как может быть уникальная полезная нагрузка для одних и тех же входов? Ключ все время один и тот же. И хеш из одних и тех же входов возвращает те же результаты. - person t0m; 09.05.2016
comment
@ t0m это зависит от используемого метода хеширования. Bcrypt позволяет использовать одну и ту же строку для получения разных результатов хеширования. - person Kc Gibson; 17.12.2017