I've made an iOS app that starts the user with a certain number of an item. The user can buy more of these items via a consumable in-app purchase. The app is not a game so the state of the app does not matter (for example, the level they are on).
What can I do to prevent the user from simply uninstalling the application and receiving the starting number of items (rather than buying more)? I'm storing the items via NSUserDefaults.
You can save your saved info to iOS KeyChain, they will probably be there for you.
See an example code at:
KeychainItemWrapper
Related
I'm aware of the restore functionality and have implemented it in my apps before, but still has holes in it.
I'm trying to display customized screens based on what apps the user have. Without user interaction, I want to be able to ask apple to retrieve me the in-app purchases that belong to that user for this app?
Other posts mention that I should always keep track of that via calling methods like:
NSUserDefaults.StandardUserDefaults.BoolForKey
But at the same time considers it insecure.
I am currently storing the info in DB. That's easy, but consider the following scenario:
User downloads the app. My DB records that user has 0 in-app purchases. The user later purchases 1 in-app purchase. My DB records that too.
User deletes the app for whatever reason
After a while, he re-downloads the app. My DB at this point starts a fresh and records that the user 0 purchases.
the user sees the in-app purchase (he already bought) and clicks on purchase again.
Here, my execution flow stops and apple picks up... Apple alerts the user that he has already bought the in-app and offers to get it for free.
That message is for the benefit for the user only, and my app is unaware of that. I haven't been able to find a call to apple asking what purchases a user had made for my app? I too, wouldn't want the user to pay again, but be able to always know what purchases he has made in the past at any given point. Why is that information so sealed at apple side? They alrady know the user has may app and I am only asking about in-app purchases in that app.
I am using Xamarin.
You need to refresh the receipt file and then scan through it. It will list all purchases the user has made inside that app, whatever device it was on. This code will let you parse the file and see the purchases made: https://github.com/rmaddy/VerifyStoreReceiptiOS
You could simply make your database store account information the user creates when they want to purchase something from your in-app extras. So in order to make that purchase they have to create a username and password for your app, thus giving you a way to keep track of who owns what in app content without having to ask apple.
I intend my app to gain access to my server after the in-app purchase is complete. This access requires real work, and data & traffic ($$).
A typical client might own anywhere up to a couple of hundred devices (and I assume on one account, for their simplicity).
Thus I only get the one payment across many, many devices interacting with the server.
I'm not trying to be stingy - but can I prevent multiple devices sharing the same purchase (in my case server access)?
Or do I implement another method for selling access?
You'll have to implement another method. Apple's guide explicitly states that:
Users can restore products that they previously purchased—for example, to bring content they’ve already paid for onto their new phone.
If the same iTunes account is associated with more than one device then Apple requires any purchases to be available on all those devices.
#Tommy is correct - regarding non-consumable IAPs. However, you could implement a non-recurring subscription in-app purchase instead and give each device a unique identifier. When the user attempts to access the server, you could see if that identifier is in your database (if the user has purchased the IAP), and determine whether or not they need to purchase a subscription. Even though you may not want a subscription-based service, you could probably make a membership for a very long period of time like 10 years (it's not required to be selected in iTunes Connect) and handle it that way. Only issue is that you need to figure out a way to give each device a unique ID that won't change.
Further to the #Tommy answer, in the February 3, 2014 version of Apple's Getting Started with In-App Purchase on iOS and OS X it says:
There are a handful of important guidelines to keep in mind as you design your application:
- You must make your In-App Purchase items available to all of the devices registered to a user
and
Users view the items they purchase as theirs to keep and permanent. Therefore be sure
purchased items are available in all instances of your app running on all the devices the user
owns, even after your app is deleted from a device, reinstalled, or downloaded to a new device.
and
For Non-Renewing Subscriptions, [blah, blah, blah]..
Additionally, your application must include a mechanism to deliver the purchased Non-
Renewing Subscription In App Purchase to all iOS devices owned by a single user.
Looks like there is no way to restrict items to a single device :(
My iOS app has in-app purchases (consumable) and shows ads periodically. The idea is to remove ads after user has purchased anything. But in-app items are consumable, so after user re-installs the app, I would be unable to determine if he has purchased anything using [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];, right? And I would bomb him with ads again...
What would you suggest to find out that the user has purchased anything already?
Well when a user re-installs your app (i.e. delete it and install it again) there is no immediate way of knowing what purchases did he made. That's why Apple requires your app to provide a way to restore previous purchases so that when the user performs this operation he restores these purchases for free.
For consumable items you might need to use a server for managing the purchases such that when the app loads it checks with the server which purchases the user has made and immediately enable the relevant content.
I do not know if mandatory but "Remove Ads" IAP should be non-consumable so the user will only need to purchase it once (Otherwise I believe users will complain or just won't buy it).
Some creative ways can be found here : iPhone - in-App purchase consumable correct approach
As an improvement on the situation, you could store the fact that a purchase was made in NSUserDefaults. That won't survive if the user uninstalls and reinstalls the app, but at least it survives if the user buys a new phone and restores a backup to transfer everything to the new phone.
You could have a look at Cloud Kit as well, which would store information per AppleId. It's a bit overkill for the problem, but it means you can use Apple's servers instead of your own for free. There would be a difference that if a user installs your app on six devices, makes a consumable purchase on one device, ads will stop on all of them.
Our app is moving from paid to free, and in the process, moving a key functionality from being included to activating via In-App purchase. Obviously, we don't want current users who paid for the app functionality to be charged again in the In-App purchase for functionality they already had. So on the update by the user, we want to 1) identify current users and 2) make it so they don't see the In-App purchase in the first place, sort of 'faking' the In-App purchase so that the app will appear to them exactly as it did before.
The app does not have a backend, so we have to determine current users from new by examining the saved user data fields for certain values. I do understand that if a previous user has deleted the app from their device that nothing can be done, and I don't mind charging them for the In-App purchase, since they never used the app anyway.
But for those current users who update and assuming we can examine the saved user data and determine that they are current users, what would be a good way to bypass the In-App purchase and make the app look like they already got it, when in fact they never paid for it? Thanks!
Here's what I would do - keep in mind this will take some time:
Set up a server (I prefer EC2) with mySQL on it. Plenty of tutorials about this.
Submit an update to your app that sends the user's UUID to your server.
Wait. This is the hardest part. You'll need to wait until satisfactory majority has updated to your app. That majority percentage is up to you to figure out. It could take months for this to happen.
Make your new, free, app send the UUID to the server.
Check to see if the UUID is in the DB.
If it is, set whatever you would have set when an in-app purchase was made to true.
You have several options:
Free in-app purchase for a limited time:
You would create a free tier in-app purchase content and release an update that somehow makes the user sign up for it. This way, when your user switches devices they can restore the purchase and regain the functionality.
Wait for a period so most people use the in-app purchase content
Change the tiers and release your app as free
Dual versions
Make a demo version of your app. Note this can be rejected by Apple.
Create a file in the filesystem
Make a file in the filesystem and save into iCloud. The app will check for the file and thats how you would determine if the user has paid for the app (or should buy the in-app purchase).
iCloud will synchronise the file between user's devices and it will make sure that whatever device the user uses the app will see the user as 'paid'.
I hope this helps, currently having this problem myself.
I have an old app with in app purchase items. We are moving to a totally new app that will sell the same items while the old one will not be in use.
Can we move the items to the new app in iTunes connect?
No, you cannot. The IAP process is governed completely by Apple. You can probably set up a server generating promo codes for the users of the old app. And using the promo code unlocks the features in the new app?
Or some document type that could be sent via email and when your app opens it, unlocks the content.
You will need some mechanism to ensure these (either the promo code or the files) are used just once.