15

I have implemented a test app with Android's In-App Billing. I have filled in my Public Key in the Security.java file. Everything works, but when I submit the payment, the app crashes. I receive an error in LogCat that says "Signature Verification Failed", which corresponds to this bit of code:

if (!sig.verify(Base64.decode(signature))) {
                Log.e(TAG, "Signature verification failed.");
                return false;
}

If I change that bit to return true instead of return false, then everything works properly - I can submit payment and safely return to the app - but I am assuming that something else is wrong, since I probably should change that to return true.

Any ideas about what could be causing this?

Chris
  • 5,485
  • 15
  • 68
  • 130

5 Answers5

27

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.

gergonzalez
  • 2,488
  • 1
  • 22
  • 21
  • 2
    The APK you push to your test device must also have the EXACT same version values as the APK you uploaded to Developer Console. It can take up to 6 hours for Developer Console to refresh your APK version. – Cory Trese Nov 05 '13 at 21:11
  • 6
    As of today, base64PublicKey is the parameter passed to IabHelper, it is not in defined in Security.java – 18446744073709551615 Nov 20 '13 at 08:10
  • 8
    Isn't there an easier way to develop billing integration flow without signing, uploading, waiting, etc.? I agree that testing should be done as near production as possible but the development cycle is sooo long. If I mistakenly did a bad if or NPE, I need to do the whole publishing phase all over again! – AlikElzin-kilaka Dec 16 '13 at 08:07
  • 9
    I'm amazed that Google have still not improved this. Tons of code, really complicated and lot of things can go wrong. This should be very simple to integrate. Also they do not fix the open issues submitted to the source project. – powder366 May 30 '14 at 05:48
21

In my case there was a well hidden problem.

When I first set up in-app billing I tried static responses and bought android.test.purchased item. When I switched to production items and tried to query the inventory, that fake product caused all my troubles.

So, in this case, the solution was to remove the fake product from my owned item.

Just add in the IABHelper.java file this snippet:

                Purchase p = new Purchase(itemType, purchaseData, signature);
                try {
                    consume(p);
                } catch (IabException e) {
                    e.printStackTrace();
                }

in the else statement of the method having this signature:

int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException

Once cleaned up your own items, revert back to the original the helper java file. Of course, this is only for development phase.

  • 1
    Works like a miracle. Yet another bug in In-App Billing. – X. Wo Satuk Jul 03 '14 at 18:03
  • 2
    This problem is still going on in the current Google billing version. Basically the android.test.purchased is broken; After you buy android.test.purchased the verifyPurchase function in Security.java will always fail and the QueryInventoryFinishedListener will stop at the line if (result.isFailure()); this is because the android.test.purchased item always fails the TextUtils.isEmpty(signature) check in Security.java as it is not a real item and has no signature returned by the server. – MPaulo Sep 11 '14 at 16:21
  • ... and also mark your in app products "ACTIVE" when you are querying for them – appsthatmatter Feb 03 '16 at 15:00
  • You sir, are a miracle worker. What a flagrantly cryptic issue that is long overdue for a patch!! – dooleyo Jan 05 '17 at 22:22
  • that was nice. thanks – Mohamad Rostami Sep 22 '21 at 12:38
2

In my case, I pasted a wrong public key which has a same prefix and suffix. Just make 100% sure that it's correct.

rensq
  • 101
  • 4
  • Thanks, you saved me! The same problem - the keys are very similar but different for different applications – Dmitry Sep 09 '18 at 08:06
0

My Answer may be helpful to someone in future

Make sure that you have a correct base64EncodedPublicKey in your application.

shyam
  • 1,084
  • 12
  • 20
-1

As said before, I was using the wrong base64EncodedPublicKey.

You can find it in the Google Play Console, under your app tab, go to the Monetization Setup Tab and the you can copy it.

jas-chu
  • 525
  • 5
  • 4