23

i' having trouble implementing in app billing in my android app. i'm getting a purchase signature verification failed. In a first time i tough it was the base64 key but i checked it many times and i'm still getting the error, then after i took a look at the Security.java file and i found this method which i edited for get some informations about what was wrong:

    public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
    if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) ||
            TextUtils.isEmpty(signature)) {
        if(TextUtils.isEmpty(signedData)) Log.d(TAG, "SIGNED DATA EMPTY");
        if(TextUtils.isEmpty(base64PublicKey)) Log.d(TAG, "KEY IS EMPTY");
        if(TextUtils.isEmpty(signature)) Log.d(TAG, "SIGNATURE IS EMPTY");
        Log.e(TAG, "Purchase verification failed: missing data.");
        return false;
    }

    PublicKey key = Security.generatePublicKey(base64PublicKey);
    return Security.verify(key, signedData, signature);
}

And i'm getting "signature is empty". Even after i follow the steps below: -Sign the apk with my release key -upload it as a draft -install it on a device with "adb -d install app.apk"

I'm testing with real purchases. Thanks.

Edit The purchase flow is fine, i get the error when i call queryInventoryAsync

GvS
  • 52,015
  • 16
  • 101
  • 139
MineConsulting SRL
  • 2,340
  • 2
  • 17
  • 32

4 Answers4

41

You can use the test SKU's to do testing, as explained here. These are:

  • android.test.purchased
  • android.test.canceled
  • android.test.refunded
  • android.test.item_unavailable

These purchases will be successful (at least the android.test.purchased) even in test and debug scenario's, without the need to cancel the purchase.

In the verifyPurchase I changed return false to:

    Log.e(TAG, "Purchase verification failed: missing data.");
    if (BuildConfig.DEBUG) {
            return true;
    }
    return false;           

but you should be aware to use this only in test scenario's.

This will return true, if you have a debug build, and the signature data is missing. Since the BuildConfig.DEBUG will be false in a production build this should be OK. But better is to remove this code after everything is debugged.

GvS
  • 52,015
  • 16
  • 101
  • 139
  • 2
    i get the same result, i'm able to purchase the item but then the queryInventoryAsinc(listener) gives me the error – MineConsulting SRL Nov 02 '13 at 07:50
  • For me, this works when debugging. You can also place a breakpoint in the verifyPurchase or IabHelper.handleActivityResult to see where it goes wrong. – GvS Nov 02 '13 at 08:33
  • @GvS, old code for the verifyPurchase() is working fine for all, but when google developers has been updated code to make more secure transaction in the verifyPurchase() method, they put some extra code to verify signature as well, but now they are trying to improve the bug. According to what I have heard uptil now. – Maulik Nov 06 '13 at 06:55
  • 1
    @Maulik: I like that the new verifyPurchase is more secure. But I don't like it blocking my debug. Java optimalisations will remove the `if (BuildConfig.Debug)` from Apps in production. So I can debug and profit from added security. – GvS Nov 06 '13 at 09:22
  • +1 for the answer. Yes, it is also temporarily good solution for test purchase. – Maulik Nov 07 '13 at 05:53
  • +1 It works perfectly.How to test after uploading signed apk to console? I've uploaded under beta testing. can we test or we need to publish before we can do necessary testing? It works perfectly with test id(android.test.purchased) – moDev Dec 21 '13 at 13:41
  • BEWARE `android.test.purchased`, it is broken. After purchasing that item with an account, that account is now broken for signed, non-debug versions of the application. Other accounts that haven't ever purchased `android.test.purchased` work fine. – CorayThan May 14 '14 at 08:18
  • Regarding CorayThan's comment, it's true that android.test.purchased is broken for the account. However, you can fix things by temporarily returning true in verifyPurchase(), then consuming android.test.purchase, which will delete it on the server, then rectifying verifyPurchase() to return false again. – rustyWhitefeather Jul 12 '14 at 11:52
  • even if I force return true, "inventory' is coming as null in onQueryInventoryFinished(IabResult result, Inventory inventory). So I cannot update my inventory. The trivial drive sample code contains call : Purchase premiumPurchase = inventory.getPurchase(SKU_PRO); which will fail.. – Sanmoy Sep 07 '14 at 16:54
  • Can you help me on in app purchases? http://stackoverflow.com/questions/36298320/in-app-purchases-working-but-method-not-executing – Ruchir Baronia Apr 01 '16 at 01:28
  • Also, I get Purchase signature verification FAILED for sku android.test.purchased – Ruchir Baronia Apr 01 '16 at 01:32
40

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.

Community
  • 1
  • 1
Maulik
  • 3,316
  • 20
  • 31
  • @Maulik Thanks it serve my purpose for test item, But i have a question that is it application in the scenario like purchasing books using inAppBilling Application? please suggest me – Irshad Khan Jan 08 '14 at 11:12
  • I can't seem to find that method `Security.generatePublicKey(base64PublicKey);` Is Security class part of java.security? Thanks. – roxrook Sep 09 '14 at 23:27
  • @Chan - It's not part of Java security, but rather part of the sample app that Google advises to use for in-app billing implementation, that method is inside the Security.java file. – Levon Feb 12 '15 at 12:08
1

Make sure that you are logged in with the right user on your phone or e.g. add your phone's google account as a test user in the developer console.

http://developer.android.com/google/play/billing/billing_testing.html#billing-testing-static:

In some cases, the reserved items may return signed static responses, which lets you test signature verification in your application. The reserved items only return signed responses if the user running the application has a developer or test account.

Till - Appviewer.io
  • 4,529
  • 1
  • 31
  • 35
0

set return value to true In

public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
    return true;
}

after tesing undo the change

Dayanand Waghmare
  • 2,979
  • 1
  • 22
  • 27