In app Billing v3 returns Response Code (BILLING_RESPONSE_RESULT_USER_CANCELED:1) -1005 in more than one scenario.
Launching the purchase flow opens the Google Play-like UI. Whenever an error happens in this UI, say a network disconnection / Timeout / Item Unavailable / Item Already Purchased, a dialog pops up to indicate the error. When OK is clicked , Response code : User Cancelled(1) is invariably returned in the OnActivityResult Intent extras. According to the reference on Android developer's site this is supposed to happen only when the user cancels the activity/Dialog, which i clearly don't do.
I would like to separate out the different errors and handle them individually in my app. Having a single error code returned doesn't help. Any one faced it yet? Is there a solution?
For the record, this seems to be an issue with the Google Play client. Google has started rolling out updates to the GP client as versions 4.0+ and the bug appears to be fixed.
The TrivialDrive demo tests the onActivityResult() callback for the value Activity.RESULT_CANCELED,
and assumes that if that is the value returned then the user has canceled.
That is an incorrect assumption, because if the responseCode in that activity result is BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED (=7) then Activity.RESULT_CANCELED means that
the in-app billing service would not allow the purchase because the item is already owned.
This response code is working for me.
However, once that possibility is eliminated, I've found that it's safe to assume that the user has canceled. I haven't checked very recently however to see if Google has made the BILLING_RESPONSE_RESULT_USER_CANCELED response code directly testable and reliable.
Related
I am using in_app_purchases flutter package to handle my in app purchasing needs on both android and ios. I only use consumable IAP. But my purchase stream is not firing. Only the queryPastPurchases method returns the list of the consumable. So Im bit confused with the plugin. I have also started to listen to the purchasestream as soon as the app starts in the main method. However Im not receiving the purchase updates in the Purchase Stream.
Also this statement from the in_app_purchase seems a bit ambigous it says trying to complete a pending purchase can cause a error. However it is mentioned to retry the purchase completion on pending status
Completing a [PurchaseStatus.pending] purchase will cause an exception.
For convenience, [PurchaseDetails.pendingCompletePurchase] indicates if a
purchase is pending for completion.
The method returns a [BillingResultWrapper] to indicate a detailed status
of the complete process.
If the result contains [BillingResponse.error] or
[BillingResponse.serviceUnavailable], the developer should try
to complete the purchase via this method again, or retry the
[completePurchase] it at a later time.
If the result indicates other errors, there might be some issue with
the app's code. The developer is responsible to fix the issue.
Please take a look at my answer here:
How can I dd in-app-purchase functionality to my flutter app?
I've also added some links to a video tutorial, which will help you.
Please use the flutter_in_app_purchase package. It's a fork of the original in_app_purchase package
Am trying out in-app billing in my App for the first time. Am using the labHelper code (https://gist.github.com/yigit/4543005) from the TriviaDrive example in the samples folder in the Play Billing Services extras. When I tried with the test code that Google gives i.e. product code as 'android.test.purchased' (give here under 'Testing with static responses'), it worked fine. But now, I switched to using the test Google account (i.e. license testing, given under 'Setting up test accounts' here). I purchased the item successfully. But when I try to use a purchased item (it's a monthly subscription product), I get an error dialog saying 'You already own this item'. At the same time, in the logs, I see the message
05-02 17:10:36.599: D/Finsky(6396): 1 PurchaseFragment.handleError: Error: PurchaseError{type=3 subtype=3}
05-02 17:10:36.599: D/Finsky(6396): 1 PurchaseFragment.fail: Purchase failed: PurchaseError{type=3 subtype=3}
(response code 3 meaning 'billing unavailable')
But, if I dismiss the error dialog, I get response 7 (i.e. 'you already own this item').
Not sure why I keep getting 3 for an item that's already been purchased? Please help.
What I tried
I tried calling startSetup() and the listener OnIabSetupFinishedListener() in the Activity's onCreate(). Am getting response 0.
Then I tried labHelper class' 'queryInventoryAsync(mReceivedInventoryListener)' method and it also returns 3.
I tried consumption related methods from labHelper class
launchSubscriptionPurchaseFlow(this,
InAppBillingExportProductId,
10001, mPurchaseFinishedListener, "”);
mPurchaseFinishedListener returns the response 0 (i.e. success), but it immediately returns the error -1010 (IABHELPER_INVALID_CONSUMPTION)
Please help. Been struggling with this one issue for more than 3 days now!
IabHelper has a method called enableDebugLogging(...) that you can use (call it with true) to turn on pretty detailed logging for all IabHelper actions. If you can post a copy of the full log, it might be easier to figure out exactly what's going on.
But let me post a couple thoughts anyways based on what you wrote:
Just like normal managed products, subscription items can not be purchased again if they are already owned.
The way to check ownership is via queryInventoryAsync(...) (if inventory.getPurchase(sku) is not null, you own the item). Unfortunately this is not always 100% accurate and I haven't found a fix yet.
To "use" a managed product or subscription, simply have your application provide whatever service you sold if the above check tells you that the item is owned.
The big difference between managed products and subscriptions is the way that the user loses them again (i.e. can purchase the same sku for a second or third time):
Subscriptions expire automatically at the end of a pre-determined period if the user doesn't renew them,
while managed products need to actively be "consumed" by your app to make them available again.
So, if you try to purchase a managed product again before "consuming" it, you will get the "you already own this item"-error that you mentioned. Same goes for trying to purchase a subscription again that you already purchased and that hasn't expired yet.
The "IABHELPER_INVALID_CONSUMPTION" error is likely caused by the fact that subscriptions cannot be consumed, only managed products can. Subscriptions only expire (or you can refund them from the developer console).
I'm not sure where the "PurchaseError{type=3 subtype=3}"-error is coming from. That one might be easier to track down from the actual IabHelper debug output. If you can update your question with a full log, send me a comment and I can take a look at it and probably help you make sense of it if needed.
Let me know if you have any further questions. I hope this helps.
I've been setting up Android in app billing v3, using the IABHelper class, and following the example code provided by Google. I have it mostly working all the way through purchase (with signed apk and real credit card charge).
However, in the course of testing today I started to get a new error in my QueryInventoryFinishedListener from the queryInventoryAsync() method:
IABResult message: "Error refreshing inventory (querying prices of items)"
IABResult response: 5:Developer Error
Weird thing #1 is that this occurs after the onIabSetupFinished() callback returns (with the customary "Hooray" message). Weird thing #2 is that I can subsequently & successfully process an in app purchase (using the launchPurchaseFlow() method).
I found a patch here that addresses the same symptoms I'm experiencing, but it didn't work for me.
I've tried using different devices, using different gmail accounts, and building a new product from scratch. I even getting the error on earlier versions of my app that ran correctly (what?!).
My question is: Why can't I query the product inventory, even after IABHelper has confirmed the set up was successful? What could be causing this error, and how can I fix it?
Thank you for any insight.
UPDATE
I was able to get the inventory query transactions to work again by ditching the account I was testing with, and switching to a new account. No code change.
My tentative conclusion is that something got corrupted in the user account I was using (?). During testing, I had hit it pretty hard with a lot of purchases of different in-app products -- but I still need to find out what happened, and make sure this doesn't happen to any of my users.
Please let me know if you have any experience with this. Thanks!
We had the same problem in one of our apps under test mode. Later, we figured out that, we had to clear the Cache of the Google Play Store app.
So you can try this -
Go your device's Settings menu.
Go to Applications (may also be labeled Application Manager).
Tab over to All Applications.
Search for and open the Google Play Store app. Tap on it, application settings will show
Tap on Clear Data and Clear Cache.
Now go back to your app and try to load inventory. It solved our problem.
I found by trial and error that if you query more than 20 items at once, it will fail with this error.
I submitted a patch for IabHelper.java that splits the list of SKUs into packets of 20 items each and does the query.
You can grab it there: https://code.google.com/p/marketbilling/issues/detail?id=123
I have the same issue with this log :
"InAppBillingManager.getSkuDetails: Input Error: skusBundle array associated with key ITEM_ID_LIST cannot contain more than 20 items."
this note had mentioned in IInAppBillingService.aidl file, see the documentation of the method getSkuDetails(..) .
So you should make the same process for each 20 items every time
I face same error but my issue is Date Time change
Go to setting and check your date time is accurate
Our beta app uses android.test.purchased so customers can test for free. But recently something broke with consuming these test products. The purchase process still works fine but when we try to consume:
int response = ms.consumePurchase(3, mContext.getPackageName(), token);
This now always returns RESULT_DEVELOPER_ERROR == 5. The data passed appears valid, token is inapp:com.lootworks.swords:android.test.purchased which I think is correct for the static test products.
Simultaneously all our earlier app versions also stopped working and we did not change our code, so it sure seems like something changed with IAB itself.
I also tested purchase/consume of the real (for $) products and it succeeds with the same code. So the consume problem seems to affect only the static response test item.
With Sean's help and some additional testing this appears to be a google play IAB regression. Have opened a bug https://code.google.com/p/android/issues/detail?id=53077
My team and I are experiencing this same issue. Nothing has changed with the app consume code, so it is very strange. The app is not release-ready yet, so we have plenty else to work on, but this throws a monkey wrench into testing for sure.
This may not be an option for you, but you could change the namespace, delete the app entry in the dev console and go through the process of making a new one, and splitting the key up again, etc.
I only suggest this because this problem does not seem to be happening for all apps. Anyway, if the consume in our app does not start magically working again soon, this is what we will try.
I am trying to implement in-app. In android, in-app is working perfectly.But, when I remove the app from device and reinstall it, then after if I try to purchase, it displays this message (product is Managed and in-app API Version 2)
and in log, I have an error RESULT_DEVELOPER_ERROR , then I googled and I found the Version 3 has more number of response codes like BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED
So if product is already purchased, the response must be like BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED and this is not possible in Version 2.
Then what should I do ? Do I need to implement Version 3 ?
if you want force to buy product by every time then product should be Unmanaged.
Products can be of 3 types
1) Managed
2) Unmanaged
3) Subcription
Managed means google it self keep record. so by using same email id user not have to paid its charge e.g. remove ads
Unmanaged means user have to buy every time and will be a charged. e.g. Pocker chips
This 2 example i have read on developer site..
and refer http://developer.android.com/google/play/billing/billing_admin.html
Have you looked into RESTORE_TRANSACTIONS?
I had pretty much the same problem you describe above. My code is, for the most part, taken from the Market Billing Sample Application.
I added a RESTORE button to my purchase activity which calls the BillingService.restoreTransactions routine.
If you search for RESTORE_TRANSACTIONS within this page: https://developer.android.com/google/play/billing/v2/api.html, you'll find that calling that routine re-triggers the PURCHASE_STATE_CHANGED broadcast.
Which, in my code, triggered the onPurchaseStateChange routine and it worked the same way it would on the initial purchase with the PurchaseState was set to PURCHASED.
I ended up with calling BillingService.restoreTransactions() after catching RESULT_DEVELOPER_ERROR. Looks odd, but works fine.