Question

I'm trying to verify Android in-app purchases from my server using the Google Checkout API. As per this other query (App on Android market - HTTP notifications don't come), I get no callback so I'm using the polling API.

It's working fine, except that I'm getting a 5 or 6 minute delay before the polling receives the notifications about a purchase, even though all the information is already visible to the user logged in to the merchant account in a browser. Checking the API documentation, it implies it could take even longer, as it states "Using the Polling API, you can retrieve all notifications that are less than 180 days old and that are at least 30 minutes old".

Is this delay typical (I'm in the UK)? Is the polling API still the recommended way to verify an Android in-app purchase?

Was it helpful?

Solution

In my opinion, trying to validate GP LVL and/or IAB information via the Google Checkout Polling API on a server is not the best approach. There's a much better option available if you have a server anyway.

As mentioned in the article Securing Android LVL Applications, the best approach is to validate licence information on a trusted server. It goes like this:

  1. Don't use the Google demo code; it is not robust (does not check for all error conditions) and can be replaced even by scripts such as to fake a response (although, if you implement the server-side check as below, that's irrelevant anyway). Use com.android.vending.licensing directly. Don't include your Google Developer Console app key with your app, you don't need it there.
  2. Your App asks your server for a nonce for the ILicensingService.checkLicense() call. Your server supplies a secure random nonce to your app. Your app calls ILicensingService.checkLicense() with that nonce.
  3. The Android GP LVL Servce calls back your app via ILicenseResultListener.verifyLicense(), prodiving signed data and a signature. (Hint: The signed data contains the nonce, so not even a re-play attack is possible here.)
  4. Your app passes the signed data along with the signature to your server.
  5. Your server is the only instance which knows your Google Developer Console app key. It validates the signature against the signed data.
  6. The validation result will contribute to your authentication decision regarding access to server data.
  7. Make sure you do not check the licence too often. Google wants you to obey the validity time stamp provided with the licence response (and they claim it even reflects the 15 minute refund period). Obviously, this would only be safe if you store the validity on the server side and the server allows the app to skip the test in step 2.

With one difference, the same applies to IAB. Unfortunately, IAB V3 does not work with a nonce for getPurchases(). The reason is probably that the IAB Service itself (and not just the Google app-side reference code) uses caching extensively. Still, for purchases, you can pass a developerPayload to com.android.vending.billing.IInAppBillingService.getBuyIntent(), which will be included in the signed data which getPurchases() returns. So as long as you have either no expiration criteria or some kind of implicit (time-based) or server-managed explicit expiration criteria for in-app purchases, the API is still safe enough; the server would then ask the app to consume expired items and it's not even a problem if that fails because the server still knows it and can ask the app to consume the items again and again.

I hope I could shed a bit of light on this topic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top