Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Play Billing - signature verification failed for sku android.test.purchased

EDIT: since some people are still checking out this thread, I want to mention that this is highly obsolete, because it is about v2 in app purchase, which is now deprecated. Please check out the latest (currently v3) documentation, it is pretty straightforward

There are loads of threads about this issue, and I think I understand the problem, however, at the moment I cannot test with real purchases, since I don't currently have a valid credit card, what Google accepts, only a Maestro, which is not accepted. This is why I ask for help (not purchase verification, but verifying that my thought process is good).

First, the problem comes from the new verifyPurchase method. The new method checks for signatures, which should be fine. However, Google does not provide any signature for test ids, such as android.test.purchased. This causes the method below to always fail, and it will always return false on the verification, even if the fake purchase has been completed, and I had a confirmation dialog, that the purchase is indeed succesful. The method:

public static boolean verifyPurchase(String base64PublicKey, String signedData, String signature) {
    //if(BuildConfig.DEBUG) return true;

    if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) ||
            TextUtils.isEmpty(signature)) {
        Log.e(TAG, "Purchase verification failed: missing data.");
        return false;
    }

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

The problem comes from the TextUtils.isEmpty() checks, since the signature will be empty, the code will return false. My temporary, testing workaround is in the code, commented out. If I add the if(BuildConfig.DEBUG) return true; at the beginning of the method for testing, everything is working fine, the user gets the premium features up and running, so the problem is indeed about signatures.

Another problem is, if I purchase android.test.purchased, I cannot query the inventory of the user, so I cannot be sure, that my checker method, which checks if the user has purchased the premium feature, works.

My two questions:

If I remove the if(BuildConfig.DEBUG) return true; line from verifyPurchase, and replace the android.test.purchased id with the real id of the real SKU I am offering, can I be sure everything will work correctly in my case? I repeat, with the added debug functionality everything is working fine. If you need to see any more code, let me know!

The method below checks if the user has purchased the premium feature, if he/she has, then it sets the corresponding preferences, otherwise, if anything goes south, it leaves everything as it is. Is this method correct? I am doing this in the Application class, on every app start up, to prevent tinkering.

private void checkPremium()
{
    //get the helper up and running
    final IabHelper helper=new IabHelper(INSTANCE, getBase64Key());
    helper.startSetup(new IabHelper.OnIabSetupFinishedListener()
    {
        @Override
        public void onIabSetupFinished(IabResult result)
        {
            //if the helper is in a correct state, check the inventory
            if(result.isSuccess())
            {
                helper.queryInventoryAsync(new IabHelper.QueryInventoryFinishedListener()
                {
                    @Override
                    public void onQueryInventoryFinished(IabResult result, Inventory inv)
                    {
                        //if the inventory is reachable, check if we got the premium
                        if(result.isSuccess())
                        {
                            setPremium(inv.hasPurchase(ActWidgetSearch.SKU));
                        }
                    }
                });
            }
        }
    });
}

Thanks in advance!

like image 910
hundeva Avatar asked Mar 26 '14 10:03

hundeva


2 Answers

I was facing the same question as you a few days ago. For those who download your live application from Google Play, if the test id ("android.test.purchased") works as you said, they will be able to buy your in-app purchases. Google play treats it the same as a 'real purchase' and it goes through the same channel as your personal SKU's. See Below:

Test Purchases (In-app Billing Sandbox)

Once authorized with testing access, those users can side-load your app and test the full merchandising, purchase, and fulfillment flow for your products. Test purchases are real orders and Google Play processes them in the same way as other orders. When purchases are complete, Google Play prevents the orders from going to financial processing, ensuring that there are no actual charges to user accounts, and automatically canceling the completed orders after 14 days.

http://developer.android.com/google/play/billing/billing_testing.html#test-purchases

I just tested my own personal SKU's now and I can say for a fact they're working! (I saw the order in my Google Merchant account). So go out and there, and make some money :)

On a side note, developer to developer... could you show me any examples or links to tutorials on how to run my purchase verification in the Application class? I think that is an idea I definitely want to steal from you. Cheers!

like image 58
Abimbola Esuruoso Avatar answered Oct 19 '22 02:10

Abimbola Esuruoso


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.

like image 24
Till Avatar answered Oct 19 '22 01:10

Till