Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signature verification failed - Android in-app purchase

I have implemented in app billing on an Android application and although it works ok with the testing constants, it breaks on real products.

I have uploaded the application as a draft on Google Play, created and published products, installed the exact same application on the device (included the right base64EncodedPublicKey) and used the right test account (the primary account on the device & the one i did set on my developer account)

The flow is that I get on the Google Play Activity where I can see the product and its details, I press buy, introduce the test account password, it gets out of the activity, receive the congratulation message and

Signature verification failed for product(response:-1003:Purchase signature verification failed)

The item is actually purchased (it appears on Google Checkout and on a 2nd buying atempt it says "Item already owned"). Also I have used only the TriviaDrive example code from Google.

Any suggestions are very helpful. Thank you!

like image 788
gabi906 Avatar asked Mar 14 '13 12:03

gabi906


3 Answers

In the In App Billing documentation there is a section called Initiate your connection to Google Play.

It tells you that you would need a base64 encoded Public Key to instantiate your IabHelper. You can get this code from the Google Play Developer Console. Login into the console, click apps and then go to the "Services and API" tab.

IabHelper mHelper;

@Override
public void onCreate(Bundle savedInstanceState) {
   // ...
   String base64EncodedPublicKey;

   // compute your public key and store it in base64EncodedPublicKey
   mHelper = new IabHelper(this, base64EncodedPublicKey);
}

Please consider the security recommendations suggested in the documentation:

Security Recommendation: It is highly recommended that you do not hard-code the exact public license key string value as provided by Google Play. Instead, you can construct the whole public license key string at runtime from substrings, or retrieve it from an encrypted store, before passing it to the constructor. This approach makes it more difficult for malicious third-parties to modify the public license key string in your APK file.

like image 86
Sergio del Amo Avatar answered Oct 15 '22 09:10

Sergio del Amo


Another reason this error can appear in v3 of IAB is if you purchase a product (say, a subscription) on one device, and the purchase info doesn't make it fully into the cache of the Play store app on another device.

I had a scary period where after purchasing a subscription on a Kitkat phone, another phone (gingerbread) was getting this -1003 error. I traced it down to the fact that the getpurchases() method was returning ONLY the INAPP_PURCHASE_ITEM_LIST with a (correct) list purchases. The INAPP_PURCHASE_DATA_LIST and INAPP_DATA_SIGNATURE_LIST were returned as null. (This was even though I could see the subscription in the Play app.)

The signature was null, so of course it got a signature verification error. After a lot of head-scratching/panicking about why it wasn't working, suddenly it worked without me doing anything. I presume Google Services/Play app finally flushed the cache and updated itself.

Given this, I think the solution may be to just silence that error until the full purchase info propagates to Play Services.... w/iabhelper it was something like:

if (result.getResponse() != IabHelper.IABHELPER_VERIFICATION_FAILED)
                    complain("Failed to query inventory: " + result);
Log.d(TAG, "Query inventory was NOT successful.");

This seems like a pretty big bug-- the Play store should wait until it knows everything about the purchase before passing it on to an app, I think. I don't know whether or not this issue manifests itself in other areas of the purchase flow, but there ya go.

like image 2
fattire Avatar answered Oct 15 '22 10:10

fattire


I had this problem with my subscriptions because I haven't set the "itemType"

 mHelper.launchPurchaseFlow(this,
            SKU_INFINITE_GAS, IabHelper.ITEM_TYPE_SUBS,
            RC_REQUEST, mPurchaseFinishedListener, payload);
like image 1
stefan Avatar answered Oct 15 '22 11:10

stefan