Skip to content
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

How do I check if an item is already purchased? #73

Closed
booboothefool opened this issue Mar 7, 2017 · 14 comments
Closed

How do I check if an item is already purchased? #73

booboothefool opened this issue Mar 7, 2017 · 14 comments

Comments

@booboothefool
Copy link

booboothefool commented Mar 7, 2017

I am implementing my first in-app purchase for iOS/Android. I realized https://github.com/idehub/react-native-billing (for Android), has a way to listOwnedProducts(). Is there an iOS equivalent using this library, or is the iOS process just different?

Specifically, this is a non-consumable purchase "No ads".

@chirag04
Copy link
Owner

chirag04 commented Mar 7, 2017

Usually you would save the purchased state on you backend for a given user.

If that's not an option, you can store what's purchases on device. There are many ways to do that outside the scope of this lib.

There also restorePurchase which you can use to find all purchased items.

On iOS there is no API to directly get purchased item other than restore purchases.

@booboothefool
Copy link
Author

booboothefool commented Mar 7, 2017

Ah, I see. I know how to do all of those then. Thanks.

Out of curiosity, why is saving the purchased state on the backend preferred over using restorePurchases? I guess I need to do that on Android too then, because it seems to save it to the Google Play account and not the user's account on my app.

In general, it is a better practice to store "already purchased" in my own user database instead of relying on App Store/Google Play?

@booboothefool
Copy link
Author

booboothefool commented Mar 7, 2017

Also, I am bit confused about the restorePurchases. https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Restoring.html

It says:

Include some mechanism in your app to let the user restore their purchases, such as a Restore Purchases button. Restoring purchases prompts for the user’s App Store credentials, which interrupts the flow of your app: because of this, don’t automatically restore purchases, especially not every time your app is launched.

But after trying out restorePurchases from this library, it seems to do exactly what I need: get a list of the already purchased items. I'm calling it every time the user launches the app, contrary to the article saying not to, and it doesn't seem to be prompting for credentials every time. I even tried uninstalling and reinstalling the app and it didn't even prompt me, properly restoring the purchase and applying no ads.

Is the article just outdated? I noticed it doesn't mention anything about non-consumables either - are they just treated differently? Because restorePurchases seems to work just fine for getting the list of already purchased items.

@booboothefool
Copy link
Author

booboothefool commented Mar 7, 2017

Nevermind. It seems like it wasn't prompting me because after you do it the first time, it saves the account in iTunes/App Store settings. If this was a brand new user however, and I restore the purchases on app start, it prompts them before they even buy anything or look at the store, which seems very bad. Going to look into storing it to the user account on the backend like you said.

@chirag04
Copy link
Owner

going to close as per my comment above.

@benadamstyles
Copy link
Contributor

Hi guys, sorry for resurrecting this issue, I just wondered if you could briefly help me with a bit of advice. I'm trying to decide where to persist the purchase receipts for non-consumable IAPs in my app, and after hours of googling I'm none the wiser. What confuses me is this: above, and in several other places on the web, the advice is to store the purchase on my own backend for a given app user. But unless I'm mistaken, IAPs are tied to an iTunes account, not to an app-specific user account.

For example, I might log out of my app, sign up as a different app user, then tap "restore purchases" and I would then get access to my non-consumable IAP feature without paying again.

And, conversely, if I log out of my iTunes account and sign in to my iPhone with a different iTunes account, and then log into my app with my original app account, I won't have access to my non-consumable IAP feature unless I pay again.

All of this to say – it makes no sense to me to store the receipt with the app-specific user account, given that the purchase is in no way related to that account.

Or am I (very likely!) wrong? Thanks for any help you can give!

@booboothefool
Copy link
Author

booboothefool commented May 3, 2017

@Leeds-eBooks I can give you some examples where I saw no other alternative than storing it on the user metadata.

  1. User is logging in
  2. I need to determine whether they are ad-free or not. But to do this, I shouldn't be prompting them/calling "Restore Purchases" every time. It should just be saved on their user metadata.
  3. Hide/show ads accordingly

(Also like I said in a previous post, you can have a brand new user -> they log in -> you have to call Restore Purchases just to check if they bought Ad-Free, which prompts them for their iTunes info before they've even looked at your in-app store for the first time!!! Bad.)

or simply, I want to show how many spendable "Gems" the user currently has remaining when they log on, which would've been a consumable IAP. Having to press "Restore Purchases" every time for this doesn't make sense.

I ended up going with storing it on the backend on user metadata as @chirag04 suggested + offering a Restore Purchases button (which iOS review makes you do anyway).

Imagine if Facebook had a shitload of ads and had an IAP to remove them all forever. Wouldn't people be pissed if they upgraded from their Samsung Galaxy S7 to an iPhone 7, and had to buy that again?

@benadamstyles
Copy link
Contributor

benadamstyles commented May 3, 2017

Thanks so much for your reply.

I need to determine whether they are ad-free or not. But to do this, I shouldn't be prompting them/calling "Restore Purchases" every time. It should just be saved on their user metadata.

If it's stored on the device, you can check without calling "Restore Purchases". If the app has been reinstalled, or we're on a new device, the user just taps "Restore Purchases" manually. I don't think this would be annoying.

(Also like I said in a previous post, you can have a brand new user -> they log in -> you have to call Restore Purchases just to check if they bought Ad-Free, which prompts them for their iTunes info before they've even looked at your in-app store for the first time!!! Bad.)

Again, if it's stored on the device, you don't need to do this. I would never call "Restore purchases" automatically – a new app user account, on the same old iTunes account, would just tap "Restore Purchases" manually.

Imagine if Facebook had a shitload of ads and had an IAP to remove them all forever. Wouldn't people be pissed if they upgraded from their Samsung Galaxy S7 to an iPhone 7, and had to buy that again?

This is a good point. Could you clarify something? If someone buys an IAP, then logs out of the app, then signs up with a new app account, they don't have the IAP purchase because they're a new user. But they're on the same iTunes account, so they can tap "Restore Purchases". At this point, in your app, do you store the restored purchase on this new user's account in your server?

Thanks again!

@booboothefool
Copy link
Author

booboothefool commented May 4, 2017

@Leeds-eBooks

Yeah, it really all depends on your use case. I don't know if you're familiar with Pokemon Go, but you could buy Pokeballs. Let's say you bought an IAP of 100 Pokeballs. No matter if you logged in from your iPhone 6, or iPhone 7, or iPad, or Android, you'd expect those Pokeballs to be there when you logged into your account, wouldn't you? In my case with the Ad-Free, my user already bought Ad-Free, an effect that should be available immediately upon initialization, so I didn't want to temporarily show them ads until they navigated to the Shop to press "Restore Purchases", which isn't even a thing on Android like it is on iOS. It seems like apps with online user profiles are a more fitting case for the backend storage. If you had an app where you didn't care if they lost their Pokeballs / progress, you could get away with something else. For example, a single-player game with unlockable maps, just using "Restore Purchases" would work fine I would imagine. As for your question, "If someone buys an IAP, then logs out of the app, then signs up with a new app account, they don't have the IAP purchase because they're a new user. But they're on the same iTunes account, so they can tap "Restore Purchases". At this point, in your app, do you store the restored purchase on this new user's account in your server?" In my case, yes. That's what I did. I don't expect them to re-buy "Ad-Free" on every account. This could be abused probably, but it's better than people getting pissed, 1 starring your app, asking for refunds, etc.

@benadamstyles
Copy link
Contributor

@booboothefool This is so helpful, thanks. You're totally right and as my use-case is extra premium features, you're right that a user with an account should only have to go through the purchase process once, and shouldn't be expected even to "restore purchases". And thanks for explicitly answering my last question, it really helps. Much appreciated!

@anonym24
Copy link

anonym24 commented Aug 29, 2018

Android Google Billing In-app gives all information about product (including if it's purchased or not)

What about iOS In-App Purchase (IAP)?

I don't want to save purchased items locally (UserDefaults for iOS) or to my own server after user bought it

Android uses Google Play Services, AIDL to get already purchased items even in offline mode

For safety in Android we can validate if user really bought item (and didn't use some hack app to get it for free) - https://developer.android.com/google/play/billing/billing_best_practices#validating-purchase-server

This additional validation for already purchased items we can do when user's device internet is enabled (though it should be enough to check it only during buying item), if internet is disabled we can temporary say that user bought it (but if he didn't buy it yet then internet is required anyway, we will validate it on our server anyway in this case)

So how does iOS work then? Does it have some, I don't know, iTunes Services to get IAP information for a specific app?

@anonym24
Copy link

anonym24 commented Aug 29, 2018

also implementing your own server just to check if user bought ad-free item is very excessive/expensive

our apps aren't pokemon go, your app may not even require any registration before user can use it

but yes only for pokemon go similar apps it looks good to have a server and facebook/google/other different variants to register/login in your app

@oguzhankarabulut
Copy link

@anonym24 hi, if user use our app without registiration how can we check this user already subscribe or not?

@superandrew213
Copy link
Contributor

@oguzhankarabulut InAppUtils.restorePurchases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants