Android in app purchase: Signature verification failed

后端 未结 14 691
说谎
说谎 2020-11-28 02:27

I have tried for several days to solve this problem, using the Dungeons demo code that comes with the SDK. I\'ve tried to Google for an answer but can\'t find one.

相关标签:
14条回答
  • 2020-11-28 03:01

    Yes, the problem still occurs. After I bought android.test.purchased I start getting the error on quering the inventory. It is possible to fix your phone by just clearing data of Google Play Store application and running Google Play one time. When you clear data of Google Play it forgets that you bought android.test.purchased

    0 讨论(0)
  • 2020-11-28 03:03

    Signature verification fails only for the default test product. A quick fix :

    • Goto IabHelper class.
    • Invert the if conditions of Security.verifyPurchase.

    Thats it!

    Remember to revert the changes when test product is replaced by actual product

    0 讨论(0)
  • 2020-11-28 03:08

    What worked for me, while using In-app Billing v3 and the included utility classes, was consuming the test purchase within the returned onActivityResult call.

    No changes to IabHelper, Security, or any of the In-app Billing util classes are needed to avoid this for future test purchases.

    If you have already tried purchasing the test product and are now stuck on the purchase signature verification failed error, which you likely are since you are looking up answers for this error, then you should:

    1. make the changes that GMTDev recommended
    2. run the app to ensure that it consumes the product
    3. remove/undo GMTDev's changes
    4. implement the code below within onActivityResult.

    Not only does this allow for the purchase testing process to be fluid but this should also avoid any conflicting issues with iab returning the " Item Already Owned " error when attempting to repurchase the test product.

    If this is being called from within a fragment and your fragment's onActivityResult isn't being called then be sure to call YourFragmentName.onActivityResult(requestCode, resultCode, data) from your parent ActivityFragment if necessary. This is explained in more detail in Calling startIntentSenderForResult from Fragment (Android Billing v3).

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_PURCHASE) {
    
            //this ensures that the mHelper.flagEndAsync() gets called 
            //prior to starting a new async request.
            mHelper.handleActivityResult(requestCode, resultCode, data);
    
            //get needed data from Intent extra to recreate product object
            int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
            String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
            String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
    
            // Strip out getActivity() if not being used within a fragment
            if (resultCode == getActivity().RESULT_OK) {
                try {
                    JSONObject jo = new JSONObject(purchaseData);
                    String sku = jo.getString("productId");
    
                    //only auto consume the android.test.purchased product
                    if (sku.equals("android.test.purchased")) {
                        //build the purchase object from the response data
                        Purchase purchase = new Purchase("inapp", purchaseData, dataSignature);
                        //consume android.test.purchased
                        mHelper.consumeAsync(purchase,null);
                    }
                } catch (JSONException je) {
                    //failed to parse the purchase data
                    je.printStackTrace();
                } catch (IllegalStateException ise) {
                    //most likely either disposed, not setup, or 
                    //another billing async process is already running
                    ise.printStackTrace();
                } catch (Exception e) {
                    //unexpected error
                    e.printStackTrace();
                }
            }
        }
    }
    

    It will only remove the purchase if it's sku is "android.test.purchased" so it should be safe to use.

    0 讨论(0)
  • 2020-11-28 03:09

    Ran into the same issue (signature verification, and getting rid of the test purchase) today (Oct 30, 2018).

    The signature issue is probably being caused by the fact that these test sku's are not really part of your app, and are thus do not have your app's signature. I did open a ticket with Google, but not sure if they can fix this. The workaround, as others pointed out, is to replace the code

    if (verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
    

    with

    if (verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature()) ||
                            (purchase.getSku().startsWith("android.test.")) ) { 
    

    Regarding "how to get rid of the purchase of android.test.purchased SKU", I found that a simple reboot of the device, followed by waiting for a minute or so and/or re-starting your app a couple of times fixed it for me (i.e. I didn't have to 'consume' the purchase by code). I am guessing that the wait is needed so that the Play store completes syncing with Google's servers. (Not sure if this will continue to work this way in the future, but if it works for you now, this might help you move forward.)

    0 讨论(0)
  • 2020-11-28 03:09

    This is what worked for me:

    1. Call BillingClient.querySkuDetailsAsync to query if item if available
    2. Wait for SkuDetailsResponseListener.onSkuDetailsResponse
    3. Wait another 500ms
    4. Start purchase using BillingClient.launchBillingFlow...

    The step 3 shouldn't be necessary because when I received onSkuDetailsResponse it should be OK but it isn't, had to wait a little bit. After that purchase works, no more "Item not available error". This is how I tested it:

    1. clear my app data
    2. clear Google Play data
    3. run app
    4. purchase android.test.purchased
    5. try to purchase my items (it fails with item not available)
    6. use my solution above, it works
    0 讨论(0)
  • 2020-11-28 03:12

    I have the same problem and follow @Deadolus said based on https://www.gaffga.de/implementing-in-app-billing-for-android/

    The key point is we need to make the SKU is consumable even the inventory query result is failed. Below is the sample how i did that.

    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
            public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
                Log.d(TAG, "Query inventory finished.");
    
                // Have we been disposed of in the meantime? If so, quit.
                if (mHelper == null) return;
    
                // Is it a failure?
                if (result.isFailure()) {
                    try {
                        Purchase purchase = new Purchase("inapp", "{\"packageName\":\"PACKAGE_NAME\","+
                                "\"orderId\":\"transactionId.android.test.purchased\","+
                                "\"productId\":\"android.test.purchased\",\"developerPayload\":\"\",\"purchaseTime\":0,"+
                                "\"purchaseState\":0,\"purchaseToken\":\"inapp:PACKAGE_NAME :android.test.purchased\"}",
                                "");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    mHelper.consumeAsync(purchase, null);
                    complain("Failed to query inventory: " + result);
                    return;
                }
    
                Log.d(TAG, "Query inventory was successful.");
    
                /*
                 * Check for items we own. Notice that for each purchase, we check
                 * the developer payload to see if it's correct! See
                 * verifyDeveloperPayload().
                 */                   
            }
        };
    

    Replace PACKAGE_NAME in the code above with the package name of your app.

    0 讨论(0)
提交回复
热议问题