-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
billingClient.queryPurchases returns the list with already cancelled subsription #122
Comments
i confirm this issue, i have the same problem, and there is another issue related to this method, if we already made a purchase with another device and we want to make another purchase with other device lets say before the other purchase i want to check the purchase list of the same google account, so its empty which is not correct because i have a purchase active in other device .. i don't know if its clear or not but at the end i wanted to ask why we don't have method as before to |
Has anyone found any workaround for this? Or does anyone know how long it takes for the cache to invalidate itself? |
Is this actually just a problem in testing or in production too? I guess the latter one. In my case, the only problem with the cache is, that IabHelper wants to up- or downgrade a purchase which does not exist anymore. The solution can only be to query the information from another source (e.g. your backend) and if there are no purchases, don't pass the wrongly cached purchase as oldSkus to |
Not all apps have a backend. So while this may work, it's not a universal solution. |
And how would the backend be informed about a purchase being canceled or refunded? While all the payments go through Play Billing (new or old version), there's no trigger / callback / function that we can call that would inform the app or backend that one specific purchase was canceled. Since the Play Store cache related to purchases gets invalidated correctly every time a purchase is made, it should also be invalidated when a cancellation / refund occurs. |
@ashughes That's true. I don't see any other solution for now. If anyone knows a better way, please tell us. @phrozenra When someone makes a purchase, I always transfer the purchase data to my backend. There you can query all necessary information about the purchase, for example if it's auto renewing, or if it was cancelled: https://developers.google.com/android-publisher/api-ref/purchases/subscriptions/get.
(see my solution here https://stackoverflow.com/questions/48176187/server-side-authorization-with-google-play-developer-api how this API can be accessed.) For my solution here: The only thing I hopefully have to do now is to fetch the information, if the user has a 'purchased' purchase record. If yes, then the purchase it allowed to update. If there is no purchase, then I must not pass the oldSkus. |
@Bevor thanks for the info, will allow the cache a few days. In my cast, I'm not having subscriptions, but rather one-time purchases, so i'll wait a few days to see if the cache updates by itself. I'm fine with it updating in the 24-72 hours ballpark. Rolling a backend just to check purchase status kinda defeats the purpose of having Google "manage" your products / purchases. |
I can confirm, that my workaround I described above works. I can purchase, upgrade, downgrade, cancel, re-purchase consecutively and the currently shown subscription is always the correct one. (In my case, the purchase concept is very time critical. If a user cancels a subscription but think about re-purchasing again, he will not loose all his data saved as premium customer in my backend if he is doing that within one week. If I would rely on this error-prone Google caching concept, it's not save that a user can re-purchase on time.) |
I am facing this issue as well, and it certainly looks like a bug:
I think the solution to integrate with the Developer APIs is a pretty unsatisfactory work around:
Please fix this, or let us know what is the right way to handle non-active subscriptions in a serverless setup. |
In order to fix this, just clear the system cache on your phone. I have the galaxy S8 and follow this process. |
any update on this issue? |
queryPurchases() returns the list of purchases regardless of their status. In order to understand the status of a given purchase, you need to Google Play Developer API. In order to do that, you'll need a client ID, client secret, and a refresh token. You can get the refresh token by calling the Oauth API once using curl on your local device (https://stackoverflow.com/questions/48176187/server-side-authorization-with-google-play-developer-api). Here's the code I'm using to verify purchases, it's deployed on AWS Lambda using Claudia js: It currently validates properly both one time purchases and subscriptions. |
@phrozenra in my specific case the subscription returned has the flag autoRenew set to true, but in the manage subscriptions screen it is missing, also our server validation says it's expired, it should either have been autorenewed or the flag should have been false |
@nicusorflorin when you say "subscription returned" are you talking about the info returned by queryPurchases() or the info returned by the developer API? The only issue I've had so far with validating subscriptions was that the subscription was cancelled, payment was refunded, but the access to the subscription was not "revoked" upon refund. So it was still valid for the period of the subscription (until next payment). Here's a sample of what the developer API returns: So basically if autoRenewing is true or expiryTimeMillis is in the future, you should grant them access to the product. |
@phrozenra i mean from queryPurchases(), yes i should in that case, but in my case autoRenewing == true and expiryTimeMillis is in the past |
queryPurchases() returns a list from the cache of Google Play Services. It shouldn't be trusted for business decisions (apart from it being a list of purchases). Every purchase on that list needs to be validated individually using the google play developer API.
That's fine, it might be a grace period where Google is waiting for the user to pay. Just trust the autoRenewing = true and trust that Google will flip that switch after the grace period. |
@phrozenra grace period shouldn't be a thing for test subscriptions, and even so it fails the server validation, and it's missing from the playstore subscription management menu, so autoRenewing should definitely be false. but for some reason it didn't update |
I have no clue what’s different for “test“ subscriptions. I’ve simply created a different Google account and did an actual purchase, that I’ve then refunded for testing. Since it’s a test purchase I’m guessing it makes sense not to show up in the real purchases list on PlayStore. |
The workaround for the test only and the test only. Is to go to settings > applications > [whatever you have here] > Google Play Shop. Then Clear Storage. It will not work for your customers but at list you can carry on with your tests. |
I met the same issue, what I do is clear the google play cache, it works for me : |
Though the bug was marked as fixed it seems that the issue still exists. |
You can't tell all the users that have this issues to do adb cache clear. What the hell is happening with this? We pay for all the services, do everything following all the docs, why the hell you can't do the only service that helps developers to make better apps just work as expected? Why the hell queryPurchases return only cached purchases and couldn't update 2 days? In that case why the hell onUpdate called with the purchase done immediately????!!!!!? This issue not fixed already for a long time!!! I have made a lot of refunding because of users complains!!! |
I can confirm this issue still exists. |
I can also confirm this issue still exists. |
another issue related to caches. |
Same issue here, this is a huge problem! I know this was working before in the past, needs to be fixed! |
but google says that it is not a problem and you need to control purchases in your backend , lets move to here to make issue more important, |
My issue is with one off purchases, not subscriptions. If I'm understanding correctly, I can call the cached method of How can I get back the most up to date data on purchases whether they've been refunded or not, and not have to rely on cached data? |
Could you please outline how you do this? |
created seprate variable for the purchase request. and then use that variable while i am processing in app purchase. on the console side i am creating new in app item to test the in app purchase is having any issue or not because when i first tried it just got refunded but in the app it was saying that it has been purchased so it was very difficult for me to understand how that work. then i saw this issue and realize that it is problem that library caches everything in the playstore. but i could not wait to test for another purchase . so i created another item to purchase and replace the id that is it ! . It seems very unprofessional at first but for testing it is the only work around. |
Guys don't ask Google fix this bug, it's impossible :) answer - simple JSON: Where expiryTimeMillis - end subscription time. |
Please can you provide the code sample. How exactly do we do it. |
Guys, I suggest create demo app with backend on spring to show how can to control subscription. What do you think about it? Please, give me feedback. like my post, and if count > 5 I create app + spring server |
That will be great. I'm waiting for your help. |
Here simple example: https://github.com/xupeng7/GoogleApi |
Google at it's best. Before I was using outdated Google Play's billing system with AIDL. That worked amazing, code is messy but it works. No caching issues, just works. Now I am forced to "upgrade" to billing library, and caching issues all over the place. |
Still happening to few users every now and then Yesterday it happened to an user that he could not restore purchases but he was able to buy them again. I am talking about non-consumable products. He gave me his email so I could check his purchases and he had the same purchase twice. This is almost unbelievable. |
Can confirm the issue still exists. |
Can confirm issue will exists forever |
Still exists. It's fucking annoying. Mass tech company and absolutely terrible at making something this important work properly. I am on the verge of migrating to iOS. |
Just migrate to a purchase handling service like RevenueCat and call it a day. 🤷 RevenueCat is free up to a certain amount of money you are making via in-app purchases. No need to build your own server. |
Working on it now. Thanks so much for introducing me to this. Life saver <3 |
Does it also cover simple one-time purchases, or only subscriptions? Any other alternatives if I don't have subscriptions? |
@GrosserStuhl it works for one time purchases too |
Folks, I feel your pain, as I experience the same issues, but posting here is meaningless, it's a samples repo, no one accepts library bug reports here. |
Do you have a link to the issue tracker. I am no longer working on the project where I had to kinda shim this issue but I’d happily +1 an issue filed in the correct location.
…On Mar 6, 2021, 4:28 AM -0800, Dmitry Saviuk ***@***.***>, wrote:
Folks, I feel your pain, as I experience the same issues, but posting here is meaningless, it's a samples repo, no one accepts library bug reports here.
There's a dedicated issues tracker for these purposes
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
The problem seems to be with the samples, not with the library. Subscriptions work fine in my own app (in internal testing at the moment), but I have had to make a lot of changes in the Classy Taxi code after I downloaded it last July. I put the parts of the sample code which I needed into my own app as soon as I got Classy Taxi partially working, and worked on them there, because I didn't want to spend time troubleshooting features which I wasn't going to use. Because of that, I can't copy and paste a solution, but I would say the problem belongs here and not in the issue tracker. |
Hi guys, You must check the "revoke" option when refunding on Google Play Console, and the returned list will be correctly updated (queryPurchasesAsync). Without clear cache... By default the option is not checked, so the user keep his rights (stay in the list returned). It makes sense for consumable products but not for non-consumable with unlocked features (ie with API not free...). Works properly for me in test and production. |
It's September 2021, we are still stuck with this issue. The only thing that sometimes solves this is manually clearing the storage of Google Play store and Google Play Services. |
billingClient.queryPurchase is returning empty list for me after a successfull payment. While purchasing, it shows the purchase list values as expected. But after purchase it not showing the purchase list for the app. Can anyone kindly let me know. |
Still facing this issue. |
1 similar comment
Still facing this issue. |
I'm getting an empty list when I call |
It is 2024, and even after 4 years Google STILL HAS NOT FIXED THIS ˆˆ. This is unbelievable incompetence...I have no words. I have tried recommended "hack" from here & stackoverflow, calling Call EDIT: For now I came up with this solution:
So far my testing shows it works fine, just not sure how fool-proof is this solution... |
@mil84 is |
Steps to reproduce (test account):
Expected: Subscription is no longer in the list which billingClient.queryPurchases(SUB_SKU_TYPE) returns
Actual: Subscription is still in the list which billingClient.queryPurchases(SUB_SKU_TYPE) returns (even after ~1 hour)
As it is stated in the documentation queryPurchases works with cache without doing any network calls, this could be a reason for this issue. queryPurchaseHistoryAsync could be a good alternative but Purchase class doesn't have state of the actual purchase (i.e. SUBSCRIBED, CANCELLED, etc.).
The text was updated successfully, but these errors were encountered: