28

The Android docs say that its meant for "supplemental information about an order" but at the same time it also says not to use this to send "actual data or content".

So what is the purpose of this "developer payload"? Why does this feature exist? Can you describe a real-world practical example of how I can use it in my own In-app Billing implementation?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Regex Rookie
  • 10,432
  • 15
  • 54
  • 88

4 Answers4

30

As aromero mentioned the developer payload field is limited in size. This is why the docs recommend not to use this key to send data or content.

What you do instead is save the content to a database somewhere (e.g. on the user's device or your own server), and then put the record's index in the developer payload field. When you receive it back via the PURCHASE_STATE_CHANGED broadcast intent, you can associate it with the data in your database.

Note that the developer payload is not sent by the Market when using any of the test android item ids. You have to be using real in app purchase items.

Also, according to this (I have not verified this yet), you will not be receiving the developerPayload in DEBUG MODE. You need to sign your application to RELEASE MODE to receive developerPayload.

Lastly, as you commented below, the returned JSONObject (in response to GetPurchaseInformation) already includes orderId, productId, purchaseTime and more. So "developer payload" should actually be used for anything but to identify the purchase... i.e. the answer is the opposite of what has been suggested below. What you can use "developer payload" is to add some information not in the JSONObject, like purchaser's additional details (e.g. GPS location if enabled, device brand & model, etc.).

Community
  • 1
  • 1
Bill The Ape
  • 3,261
  • 25
  • 44
  • 1
    The only answer so far that actually adds something that's not already in the docs. Accepting. – Regex Rookie Jan 27 '12 at 17:14
  • 3
    The last paragraph in the answer is just plain WRONG. Quoting docs from Google here: You should pass in a string token that helps your application to identify the user who made the purchase, so that you can later verify that this is a legitimate purchase by that user. When you get back the response from Google Play, make sure to verify that the developer payload string matches the token that you sent previously with the purchase request. As a further security precaution, you should perform the verification on your own secure server. – inteist Oct 05 '14 at 03:07
  • This answer is not correct IMHO. This field is meant to be used to perform receipt validation. Typically used to pass in a string token that uniquely identifies the purchase request, as explained here: http://developer.android.com/google/play/billing/billing_best_practices.html#payload – Lio Jul 29 '15 at 17:59
8

The accepted answer is misleading and the last paragraph is plain wrong. Here's what the official documentation has to say about it.

You should pass in a string token that helps your application to identify the user who made the purchase, so that you can later verify that this is a legitimate purchase by that user. For consumable items, you can use a randomly generated string, but for non-consumable items you should use a string that uniquely identifies the user.

When you get back the response from Google Play, make sure to verify that the developer payload string matches the token that you sent previously with the purchase request. As a further security precaution, you should perform the verification on your own secure server.

The payload may help you prevent to identify users who circumvented Google Play Service API or your app somehow by sending the payload to your server where you can check whether this user ever purchased the item. Presumably circumventing the GPS will get your app fooled with the purchase certificate. But if you have all the user IDs of people who actually did honestly purchase the item saved on your server - it would be easy to validate the purchase based on the user ID. The problem here - google made it impossible to rely on it unless you have all your users "logged in" in some way.

Community
  • 1
  • 1
inteist
  • 493
  • 8
  • 15
3

The docs provide a real example:

A developer-specified string that can be specified when you make a REQUEST_PURCHASE request. This field is returned in the JSON string that contains transaction information for an order. You can use this key to send supplemental information with an order. For example, you can use this key to send index keys with an order, which is useful if you are using a database to store purchase information. We recommend that you do not use this key to send data or content.

You can use this field to identify the item the user is purchasing. When you issue a REQUEST_PURCHASE request you can put additional information using DEVELOPER_PAYLOAD. When you get the response from PURCHASE_STATE_CHANGED you'll get this info back in the developerPayload field, so you can identify the order.

This field is limited to 256 chars and it's unencrypted (you can verify the signature though), it's not meant to store actual content.

aromero
  • 25,681
  • 6
  • 57
  • 79
  • 1
    Thanks but that example doesn't explain much. What are "index keys"? "index keys" to what? What does it mean by "using a database to store purchase information"? On the phone? on a remote server? This "real example" is so laconic, whoever wrote it must be assuming that anyone programming for the Android is a genius... But I am not a genius, I am merely trying to understand what this field is for, since it seems to be playing a major role in the Dungeons sample. Why do I need to identify the item purchased using this key, when there already is `sku/productId/item_id` in the request? – Regex Rookie Jan 23 '12 at 21:40
  • You seem to be upset either with my answer or with the docs. Index keys means some key (a string in this case, can be anything you want up to 256 chars) that will index **the actual order**. "using a database to store purchase information" means a db to store orders on the phone (the Dungeons example uses an approach like this, take a look at PurchaseDatabase.java). In the Dungeons example this field has no major role, it's there to only to show how it can be used. The item_id must match a valid id that's defined in you in-app settings, however the developer payload can be whatever you want – aromero Jan 23 '12 at 22:02
  • ...(continued) and identifies an actual purchase/order, not the item. Note that this is OPTIONAL, you can use it if you need it, otherwise you can just ignore it and everything will work. Google doesn't use this field, it's for you as a developer. – aromero Jan 23 '12 at 22:03
  • Not upset but confused by the existence of a one-and-only example. If using the payload as an index to a datastore is the only use, why not simply define (and document it) as such? Thanks +1 for the explanations. – Regex Rookie Jan 24 '12 at 00:59
  • I'm not saying that's the only use. The essence of that field is to identify the purchase, since the flow is asynchronous you **might** need some "key" to identify the purchase. The datastore example can be the most common use case, but it isn't limited to that. – aromero Jan 24 '12 at 01:21
  • That's exactly what I asked in my OP: Any use example **other** than the index one? – Regex Rookie Jan 24 '12 at 01:26
  • Also, why another field "to identify the purchase", when there is already transaction ID??? – Regex Rookie Jan 24 '12 at 18:05
  • For the benefit of later readers like me the docs referenced by @aromero are at http://www.androiddocs.com/google/play/billing/v2/billing_reference.html#billing-interface. Note this is from v2 of the in-app billing API, since deprecated in favour of v3. – snark Aug 10 '16 at 18:02
0

I hope this will help:

Security Recommendation: When you send a purchase request, create a String token that uniquely identifies this purchase request and include this token in the developerPayload.You can use a randomly generated string as the token. When you receive the purchase response from Google Play, make sure to check the returned data signature, the orderId, and the developerPayload String. For added security, you should perform the checking on your own secure server. Make sure to verify that the orderId is a unique value that you have not previously processed, and the developerPayload String matches the token that you sent previously with the purchase request.

More information here.

Michal
  • 2,071
  • 19
  • 30