Android in App Purchase: Signature Verification Failed

Android In-App Billing : Security.java says Signature Verification Failed

That signature verification error can be caused by:

1.- A wrong public key. Maybe you've forgotten to copy some character. It happens :)

2.- The .apk must be signed. You can't use the debug.keystore, if you do your signature string will be empty.

And remember, for testing In-app billing:

  • Add Android Market public key to Security.java (String base64EncodedPublicKey = "your public key here")

  • Build in release mode and sign it (If you are using Eclipse, you can use the Export Wizard).

  • Upload the release version to Android Market, do not publish it, and create the product list.

  • Install the application onto your device ( adb -d install myapp.apk ) and make a test account primary on your device.

android in app billing purchase verification failed

Replace your verifyPurchase() method with below one. Use old code that given below, google developer are trying to solve this error in the near future but before they updated their code you should prefer below code.

 public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
if (signedData == null) {
Log.e(TAG, "data is null");
return false;
}

boolean verified = false;
if (!TextUtils.isEmpty(signature)) {
PublicKey key = Security.generatePublicKey(base64PublicKey);
verified = Security.verify(key, signedData, signature);
if (!verified) {
Log.w(TAG, "signature does not match data.");
return false;
}
}
return true;
}

check this link for more information:

In App billing not working after update - Google Store

Use try to replace OLD CODE method verifyPurchase() method in your project. But It should be only happens when you are trying to purchase test products. Let me know for the real products purchase also after using this code.

Edit:

Why it happens because we will not get any signature while we are using dummy product like "android.test.purchased". So in the old code it is working good because we were return true even if signature is not given and for the New code we are returning false.

more information about the signature data null or blank from link1 and link2

So I suggest you just replace old code method verifyPurchase() instead of New Code method.

I think may be New Code will work fine for the real product but not in the dummy product. But yet I have not tested for the real product.

or

use GvS's answer for the test purchases it also the good solution for the new code.

Hope it will solve your problem.

In apps billing signature verification

According to android documentation here it is stated that

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). Typically, this is used to pass in a string token that
uniquely identifies this purchase request. 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.

Security Recommendation: It’s good practice to pass in a string 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.

So , For the product ID SKU_2006 if you initiated the purchase flow with String payload = email+item1; then Google Play will return the same payload in the response and hence you would get it here as

boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
..
}

Now , let me define the whole scenario in terms of code :

First , you would initiate a purchase request like below

String payload = getUserEmailFromAndroidAccounts() + itemUniqueId;

mHelper.launchPurchaseFlow(new PurchaseFinishListener(itemUniqueId), SKU_GAS, 10001,
mPurchaseFinishedListener, payload);

If the purchase order is successful, the response data from Google Play is stored in an Purchase object that is passed back to the listener.

    private class PurchaseFinishListener implements IabHelper.OnIabPurchaseFinishedListener {
private final String mItemUniqeId;
public PurchaseFinishListener(String itemUniqeId) {

mItemUniqeId = itemUniqeId;
}

public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (result.isFailure()) {
Log.d(TAG, "Error purchasing: " + result);
return;
}
if (!verifyDeveloperPayLoad(mItemUniqeId , purchase)) {
Log.d(TAG, "Authenticity verification failed");
return;
}

// set your product as purchased in your DB or server

}
}

Now your verifyDeveloperPayLoad(purchase) method should look as below :

 private boolean verifyDeveloperPayLoad(String itemUniqueId , Purchase purchase) {
String responsePayload = purchase.getDeveloperPayload();
String computedPayload = getUserEmailFromAndroidAccounts() + itemUniqueId;

return responsePayload != null && responsePayload.equals(computedPayload);
}

If you have closely observed code , you would surely understand how is the work flow .

Further information about Subscription based purchase and one time purchase can be obtained from Android site.



Related Topics



Leave a reply



Submit