In App Purchase You already own this item error - android

I have two phones with same user account. and subscribed a product from one device. when i trying to subscribe the same in next device it shows error message as "You already own this item" . I need to subscribe the same two devices concurrently. How it can possible ? I am using V3 api for billing. Is there any restriction , that is only one subscription per one account or something like that ? Please help me to solve this issue.

All the purchases you make are synced across all the devices which are logged in with same google account i.e. if you make a purchase on 1 device that purchase will be available with you on all other devices which are configured to same google account and if you try to purchase the same item again IAP takes care of that and won't let you do that.
Still if you want to purchase the an item multiple time(like any healthpack in case of a game) then you need to inform playstore about the consumption of that item even if you haven't consumed it and in that case you need to keep track of that item yourself(use servers to keep track of the items)
check this video: http://www.youtube.com/watch?feature=player_embedded&v=DgcJPIRpfSk

Related

Are Refunds For Android In App Consumable Purchases Supported? - In App Billing API V3

I'm not specifically looking to have the option to refund a user for an in app purchase of a consumable, but just in the odd case that a user asks for a refund, either through google, or through the developer of an in app purchase of a consumable.
There does not seem any way of handling refunds through the In App Billing api V3. All documentation points to V2 of the api using broadcast receivers. This does not help me in least bit.
So how are refunds handled in the In App Billing v3 api? I'm assuming for a non consumable, the refund is processed, and then google handles the processing through their backend, and then when a getPurchaseState() is conducted, it would return a value of 2 (refunded). If so, this works great for a NON CONSUMABLE product.
When a getPurchaseState() call to a consumable purchase is made, it returns null. That's assuming if the purchase was previously successful, and that the item was consumed and provisioned. I figure I could store the purchase items locally within the app, but then there is still no way of receiving a refund notification for that product. I can check for purchase state, but again, it will return null, as long as it was consumed and provisioned already.
A slight workaround I can think of right now, is to not consume the purchase on provisioning. So that it remains "unconsumed" according to google, and remains in their database. Now, if a refund is requested, I am assuming a call to getPurchaseState() for that consumable will return refunded, thus the application logic can then subtract/deduct the provisioned consumable from user's inventory. If a user would want to repurchase that consumable again, then before the IAB api call is made for the purchase, get the purchaseState() and/or hasPurchase(), and if there is already a purchase there, consume that item without provisioning, this will let the user repurchase that consumable. Only issue with this workaround, is that if A user wants to re purchase the same consumable product, as soon as the select the option to repurchase, the item must be consumed regardless of whether they successfully repurchase the product or not. So if the user does not complete the purchase, the product is already consumed, and I end up back where I am now with inability to check for refund state on the consumable.
I can't think of any other way to do a refund for a consumable in app product, and that is what I ask here. Is the way I thought of sufficient, or is there a proper way to handle refunds using IAP v3 on consumables?
I was thinking I have 3 options:
Don't offer refunds for consumables, no/little exceptions, but the issue with this is if a user requests refund through google, and not through developer, leading to option 3 below)
Find a workaround (either properly through the api, or with my proposed workaround)
Offer refunds, but have no application logic to subtract/deduct the consumable. In this scenario, users could end up taking advantage of free purchases.
I know this is a super late response to this issue, but it took me quite some time to track down info on this issue, so hopefully it can help someone else out. There are a few ways of doing this... In the Google Play Developer console you can click on the left nav saying "Order Management" which will bring up a list of all recent orders though your app. If you need to refund one you can click on it, or multi select them and refund them in this view. Just a heads up... you will most likely need permissions from your account admin to see this view and refund users.
Your other option is though the API docs here. You will need to set up your API account though the Android console, which I will say is a massive pain and not clear. But once that's set up and your "Server Applications" is set up you will need to make sure it has proper permissions as well. Then you should be able to use a library such as this to do the heavy lifting for you, because from what I've read the JWT auth process though the google API is not super straightforward, and their docs are a mess. I hope this helps someone and comment if you have questions... I will do my best to answer.
This same API also can be used to find items that were purchased by users and then refunded, so you can remove these items from those users' apps. Also you can do server side purchase validation through this as well, which is highly recommended, because rooted phones can inject fake purchase requests making your app believe that it's hearing back from the google play store, but in reality it's not. You then send back to your server the purchase token and SKU of the item being purchased and then on your server you just run this. This will give you back a 400 error if it's invalid, and a 200 with a some JSON data if it's a successful purchase.

"You already own this item" Google play inapp error

I've implemented API version 3 of GooglePlay Inapp purchase.
I'm logged in with the same Google account on two devices.
On device #1, I've just purchased an item using this: https://developer.android.com/google/play/billing/billing_integrate.html#Purchase
When I immediately query the purchased items (on device #1) with: https://developer.android.com/google/play/billing/billing_integrate.html#QueryPurchases it returns the info of the in-app so everything is fine.
When I query the list of purchases on device #2, it won't return the item I've just purchased, it returns an empty list.
When I try to buy the item on device #2 it tells me I already own it.
Any ideas on why the purchase from device #1 is not reflected on device #2 ?
Please note that the inapps are Managed products, so Google should hande the syncing across different devices with the same google account, right ?
Invalidating a purchase to test it again
This applies to products that the user can buy only once. This means that you don’t consume the purchase. More on consumption later.
In this case, after you make a purchase, if you will try to purchase it again you will receive an error saying that you already own this item.
How do you get past that?
You refund the purchase from Google Play Console. But there’s a catch. When you refund it you will have to remove the entitlement for that product, or the user will still get the error that it already owns the item.
For that, you go into Order Management from Google Play Console main menu and select the Order you just made from your app. (If it’s a test order it will say Test: in front of the product name). Then in order details, you click refund and a screen with some options for a refund like the one below will appear.
In this screen, make sure to check the Remove entitlement box, so the user will no longer own the product in his Google Account. After you click refund you will be able to make a purchase again for the given product.
It seems that it takes a while for the changed to actually take place on GooglePlay. The device on which I buy the item, seems to cache that I did so, and instead of asking GooglePlay, it takes that from a local cache.
That's why another device did not know about the purchase.
It took about an hour for the second device to receive the purchase info from GooglePlay.

some google in-app billing API3 questions

I'm starting to make some in-app purchases on my future app, and i wish to ask some questions regarding the new API (3) of the in app billing library (shown here):
google says (here) that there are no more unmanaged items. this means that in order to have multiple consumable items, the play store cannot hold a counter, so you need to either consume the purchase right when you put it in the app, or only when you need it.
My question about it is how would you get the consumable items stay on multiple devices? for example, if the user purchased 2 health potions, and because of the new limitations, they both are stored only on the app itself of one device, how could the end user go to another device , run the app and see that he has 2 health potions?
is it possible to make some purchases for free on some cases, programmatically ?
it could be useful for testing or on some cases when i want to reward the user for something he has done . i might even want to do it completely transparent and without any dialogs.
i know that there is a sandbox mode but that's only available by adding specific accounts as test accounts .
the lecture speaks of a "developer payload" (here) that you can put on the purchases for better security. they said that the data should be an id of the user, but they don't say what id i should use (only gave an example of google plus , which many people don't have).
my question is: what should be used for the "developer payload" ? if i use the sample, what do they use, and is it safe to use it or should i change it ?
i also don't understand how could it be useful, since the play store should always hold data as to which user has which items, so how could the play store be fooled on this? or maybe they talk about protection from changing the apk of the app?
is it possible to make a transaction of multiple purchases ? if so, can i hide those that don't cost money ? and if all are for free, maybe not show anything at all ?
Answer 1)
The way I have found for the question 1 is given below.
if your application used server database(stored data on server using internet connection) then you can simply stored data for particular user,Like if user has purchased 2 health potions and when user trying to use that 2 health potion from the another device then simply checked it is purchased by that user previously or not. if it is already purchased by that user then simply restrict that user to purchase potions again.
Answer 2)
Google is provided trial period for the subscription product. so that user can purchase that item as $0.00 amount as a trial period and when time expired(time can be 7day or more) item can be changed it's type as subscription item with credit card information as like simple purchase flow.
but, you used word "pro grammatically and without any dialog" then according to my knowledge Google will not provide it for the single user or for the particular user. you can simply give trial period value in the Google console for the all application user.
check this link for more detail: "Free trials" http://developer.android.com/google/play/billing/billing_subscriptions.html#administering
Answer 3)
I would like to suggest you for the developer payload, first of all it is not mandatory you can pass either blank string or with developer payload. According to my knowledge it should be working like "security code" same as you given in the Google site while searching content "Some Random String".
how to use developer payload and what should be use for developer payload
check this link
Developer payload is useful for the application?
I think it is working like security code like Random String, and while you retrieve data you can verify that item that was purchased is same or not so that if in case some kind of hacker can be redirect to the other product then you can check it at response time, is it the same product as you are going to purchased or not and user can be protect from unnecessarily withdrawn money from his account.
and also check given link I have explained more for the developer payload.

Does Google Play In-App Billing Version 3 support refunds?

I've gotten IAB v3 working and I was able to make a purchase for a managed item. However, to continue developing and testing I wanted to refund the purchase so I could try making the same purchase again. I logged into my Google Checkout Merchant account and successfully refunded the purchase. However, the app still thinks that the user has the item purchased. It has already been several weeks since I made the refund so its not a delay issue.
Basically, in my QueryInventoryFinishedListener implementation, inventory.hasPurchase(SKU_REMOVE_ADS) always returns true, even after the refund (SKU_REMOVE_ADS is the SKU for item I'm selling). I was expecting it to return false after the refund had been processed.
If you look at the 'Handling Refunds' section of the IAB reference, it says that your app needs to be listening to the IN_APP_NOTIFY messages. However the documentation for IN_APP_NOTIFY is specific to v2 of in-app billing. It doesn't seem to be something that's available in v3 since its not mentioned anywhere in the v3 reference nor can I find any reference for it in the sample TrivialDrive app that they are using to demonstrate IAB v3.
So does v3 of IAB support refunds/cancelling purchases? Has any one tried it and got it working?
There really is no difference between a consumable item and a non-consumable item so far as Google Play is concerned; this distinction is entirely based on what you implement within your app. So even though the SKU you are testing is intended to be non-consumable (e.g., a permanent premium upgrade), for testing purposes, you can treat it as a consumable and consume it, so that it can be purchased again.
A convenient approach is to set up a temporary testing menu within your app (e.g., by adding a menu item during testing onto your app's main options menu), and then to have that item's handler invoke the consumeAsync() method of your IabHelper instance for the SKU that you want to test buying again. This will consume the item and thus make it immediately available for repurchase from your device.
You will, of course, still want to refund the purchase from Google Checkout, so that you won't be spending your own money just to test your app.
I would add that consumeAsync() also seems to work just fine for resetting the test SKU android.test.purchased, if you are testing using such static values.
Regarding the updating of purchase state to reflect a refund, I have personally experienced (and there are many similar reports posted by other developers) that manually initiating a refund via Checkout (e.g., for a test purchase from the TrivialDrive app) takes days to result in a change to the purchase state of the product (to INAPP_PURCHASE_STATE_REFUNDED).
(Knowing that misery loves company, some of those additional reports can be found on this discussion thread:
https://plus.google.com/+AndroidDevelopers/posts/R8DKwZDsz5m)
At least part of this is due to Google Play's caching of purchase data on the device.
In my experience, re-booting a device can sometimes cause Google Play to refresh its cache from the GP servers. So it may be that changes due to cancellation or refunding of an order via Checkout could also be detected after a reboot.
It might seem that such a long turnaround period would do you no good, since you can't know when users will reboot. But then again, you know that every device will, eventually, get rebooted, and so if your concern is that a user who receives a refund should eventually be blocked from using the refunded IAB product, a few days of delay may not matter much, so long as it eventually happens.
Of course, remember that this notion that cache will refresh on a reboot is undocumented and anecdotal (like quite a number of IAB3 and TrivialDrive behaviors, thus far). Folklore, they call it.
Another thing that triggers an update is when the user attempts to purchase the product. As soon as the purchase is launched, the system has to be sure that the product is not already owned, and so it updates the Google Play cache. In my personal experience, this has always occurred. But again, this is not a very practical way to check for a refund, because that would involve showing the purchase dialog unbidden, and also an error message that tells the user "you already own this, " (if they do own it).
Where this does come in handy is when the user pays for an IAB item on one of her devices, and then attempts to access that item on a different device that is owned by the same account as was used to buy it. The purchase information in that case has very often not yet been cached. But you can just put a little note in your purchase dialog that if the item has already been purchased, attempting a re-purchase should make it available on the present device at no additional charge. Sometimes it takes two (user-initiated) purchase attempts to finally get the IabHelper.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED response. Yes, a bit klugy, but I think in human terms it will work with appropriate highlighting of the message and apologetic wording of the confirmation dialog telling them that they own the item, etc. :-) ).
As a practical matter, you can see how Google might not want every instance of every IAB app in the world to access its servers every time the app's purchase data is being accessed, especially given that they are advising developers to do a check for what has been purchased each time the app is started. It's also a performance issue for your app - that's what caching is all about. So you need to be aware of the triggers for updating the cache, and I haven't found a single place where this is officially documented (except, we presume, in the code). So get ready to put your hands out in front of you and start feeling around in the dark.
For some additional information regarding Google Play buffering, see this page:
Under What Conditions are In-App Billing Version 3 Server Changes Made Available on Client Devices?
I would note that in your post's code snippet you are calling inventory.hasPurchase(SKU_REMOVE_ADS), but that will only tell you if the purchase is in the list of purchases returned in the inventory object; it will not tell you the state of the purchase for that SKU. I know that this is the approach used by the TrivialDrive app, but that app is not dealing with refunds and cancellations. To detect refunds and canceled orders, you'll need something like this:
Purchase removeAdsPurchase = inventory.getPurchase(SKU_REMOVE_ADS);
if(removeAdsPurchase != null) {
int purchaseStateForRemoveAds = removeAdsPurchase.getPurchaseState();
if(purchaseStateForRemoveAds == 1) {
//Do cancelled purchase stuff here
}
else if(purchaseStateForRemoveAds == 2) {
//Do refunded purchase stuff here
}
}
The good news about refunds and canceled orders is that both are, AFAIK, entirely at the option of the developer. So, if you find that users who get these are able to continue using your app for a long interval thereafter, and if you find that lots of users are taking advantage of this, then you can decide if you want to continue providing the refunds in all cases. My best guess is that it will not be a problem; even if some user who gets a refund gets to use your app for a while after that, that doesn't seen like a very big deal.
It is for testing that you need the ability to re-try a purchase very rapidly, and using consumeAsync() definitely works for that purpose.
I will suggest you to use static product ids while your app is in development phase.
Now make sure you are testing the app with same Gmail Id for which you have refund? To test the refund scenario I think you can use android.test.refundedas product id.
If this is not working then you can first check total purchased item(s) and Available item(s) in google play at first launch of your app and if you are getting same product id in both the calls(which should not be the case if this is the case please report this bug to google) then make api call to make same item as consumed.
Since posting this question, its been brought to my attention that I need to call getPurchase(...).getPurchaseState() and check for its value. Possible values are 0 (purchased), 1 (canceled), or 2 (refunded).
However, in my case its still retuning 0 (purhcased) even though the item is refunded. I'm posting this information here in case it helps someone else.

In App Billing managed and unmanaged state for product

I am very new to android.. I am working on In App billing.. My question is what is the main purpose of Managed and Unmanaged state while adding the In App product..
Can any one tell me what is the use of managed state and what is the use of unmanaged state..
The main difference between managed and un-managed is that a managed purchase can only be bought once and is tied to the Google account that purchases it.
Un-managed purchases can be bought multiple times and are intended for consumable items.
For more information, please see the Choosing a Purchase Type section of the Google in-app billing documentation.
As of Version 3 of Google's IAP Billing API this has changed. Both consumable (multiple purchase) and non-consumable items are "managed". Tf you want to use Version 3 of their API, all purchases must be created as "managed". You can then decide if the item should be consumed later.
Here's a link to their docs: http://developer.android.com/google/play/billing/api.html#consumetypes
UnManaged could be something like "Buy 50 points"
The 50 points would then be added to your account and you would store this on your accounts server, therefore the Android Market no longer needs to know that you purchased this product i.e. it will not remember your purchase and you can purchase it multiple times.
Managed could be "Buy this song"
In this scenario you do not have a server to record that they bought the song and so every time they reinstall you can query the market to see they bought the song and it will not let you download it more than once.
Managed is aimed at one time downloads then you 'own that object'.
UnManaged is for multiple downloads of the same thing to 'top something up'.
UnManaged could be something like "Buy 50 points"
The 50 points would then be added to your account and you would store this on your accounts server, therefore the Android Market no longer needs to know that you purchased this product i.e. it will not remember your purchase and you can purchase it multiple times.
Managed could be "Buy this song"
In this scenario you do not have a server to record that they bought the song and so every time they reinstall you can query the market to see they bought the song and it will not let you download it more than once.
Managed is aimed at one time downloads then you 'own that object'.
UnManaged is for multiple downloads of the same thing to 'top something up'.
Least thats my understanding.
Version 3 has the concept of 'consumables' and it works inline with the above. All products are managed but you can 'consume' a product.
i.e. "Buy 50 points" will give the user fifty managed points, the user will not be allowed to purchase that item again until you consume that product.
Therefore you can make unmanaged products by consuming instantly, or managed products by consuming when the user has "used" that product (i.e. never call consume for buying a song).

Categories

Resources