In-app billing developer payload argument?

1.2k Views Asked by At

I've Googled this concept six ways from Sunday and I feel like I can't find a straight answer on it. The official Google docs say it isn't meant for security, but then a bunch of answers I find seem to imply otherwise, etc.

From the docs:

The fifth argument contains a 'developer payload' string that you can use to send supplemental information about an order (it can be an empty string). If you specify a string value, Google Play returns this string along with the purchase response. Subsequently, when you make queries about this purchase, Google Play returns this string together with the purchase details.

Caution: Don't use the developerPayload field for security validation purposes. This field isn't always available when completing tasks related to In-app Billing. For more information about security best practices, see the In-app Billing Security and Design guide.

From the official Google test project:

/** Verifies the developer payload of a purchase. */
boolean verifyDeveloperPayload(Purchase p) {
    String payload = p.getDeveloperPayload();

    /*
     * 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.
     */

    return true;
}

I have absolutely no idea what this means. If I don't have my own server, should I just be using a blank string? How am I supposed to differentiate users and purchases and devices?

None of this is clear to me and this code / the official docs offer no real clarification, and most of the online answers are similarly sparse.

Can anyone just lay it out: What should I be sending as my developer payload argument?

2

There are 2 best solutions below

0
On

The last point in the remarks of Google's code seems helpful

Using your own server to store and verify developer payloads across app installations is recommended.

If you have a server you could have a getRandomString endpoint, which the server creates and adds to the list of available random strings associated with the user account.

When the string is returned to the client, this can be used as the developer payload.

Then when it comes to verifying the purchase token on the server you can get the payload and check it against the list of available random strings on the server.

However, I'm not sure if this adds any security as such. And I don't see how this helps "across app installations." Because for managed products, regardless of the app installation, you can't buy multiple managed products. They have to be consumed before they can be purchased again...

Did you solve your problem in the end. I would be interested to know what you did in the end as I'm facing the same problem, only I have a server back end.

0
On

At least you have security reason to generate random string: two the same purchases with different developerPayload always will have different purchase data and signatures.

String developerPayload = UUID.randomUUID().toString();

If you don't process answers on your server, you don't have any reasons to remember and check this string (see warning at google test).