Is there a way to verify with the apple servers when a user first installed an app?
Let's say you have a payed app and want to make it free with ads but not send ads to those who previously bought.
Since it's not an IAP i assume Store Kit is out of the question.
Later edit: My problem being the ones that buy, delete and reinstall.
Nope, you can't do that! The best way is to remove your current app from the App Store and relaunch using a different Bundle ID. People who bought it previously can keep it how it is, although they won't get any updates.
A possible workaround
Here's a workaround I just thought of. When you send out your next update, set a flag in NSUserDefaults to mark everyone who has it now as paid user. That would be for your next update only; you would remove that code right after the update. Then, when you send out your version with ads, check that flag to determine if you should display them. The only problem is that if a paid user ever re-installed the app, they would see ads from then on.
Related
For an app that is yet to be first-released, it is easy to figure out how to detect first-launch: look for absence of a "wasLaunched" Bool, or a version number, in the UserDefaults. And then set its value. This is asked-and-answered in several places on StackOverflow.
But... I am updating an already-existing app that did not save any UserDefaults info (of any kind) in its first version. Is there any way to detect, on launch of the new version, that a previous version has existed and run? I can't think of one, but that doesn't prove much.
This is important because the new version charges money for some features that used to be free. I would prefer that earlier users not be suddenly faced with loss of fuctionality.
This was also previously asked (Detecting the first launch of an app with previous versions) but all the answers missed the point of the app already existing.
Note that writing to UserDefaults is not foolproof either. If a user deletes the app before re-installing or upgrading, the UserDefaults will vanish. However, that's an edge case I would be OK with ignoring.
Based on your answer to the first few questions in the comments, the question you posted really should be rewritten to something like:
I currently have a free app. In the next update I wish to make some of the currently free functionality into paid functionality using in-app purchases. However, I don't wish for any existing users of the app to have to pay for the functionality they have been using already. Only new users of the app starting with this update should have to pay for the in-app purchase. How can implement my updated app so that downloaders of the previous version of the app do not have to pay?
Given this, your question has nothing to do with any sort of "first launch" detections. Your need is to see if the user "purchased" (or downloaded) the previous version of your app.
This can be accomplished by performing receipt validation. Once you obtain and verify the receipt, you can inspect the receipt and obtain an original purchase date and original purchase version. If that version is a version prior to adding the paid in-app purchase, treat the user as if they have made the in-app purchase already and show them the paid functionality of your app. Otherwise, check the receipt to see if it includes data on the in-app purchase and give user access as appropriate.
I created an app which is a paid app. Now I want to make it free so more user can download the app and use in app purchase to limit some features. But some user already paid to buy my app. How can I implement in app purchase for new user at the same time keep full feature access to old user?
If you connect to your server for registering user info, you can always create an API which executes on app launch to verify that user is full access user or not.
But I am afraid your case is not the above one.
In that case you would require to sync your data (some encrypted key in this context) with iCloud and when application is launched you can verify the type of user.
Using data in iCloud is more safer as compared to keychain as it covers device format scenario. But definitely not foolproof.
Other solution can be using Apple Purchase Receipt to verify the version of previous purchase. But this is only supported since iOS7.
Checkout some opensource libs to understand the parsing of receipts:
https://github.com/rmaddy/VerifyStoreReceiptiOS
So combining multiple strategies is the only answer for your question.
You can do this by reading the App Store receipt. The receipt contains the version number and date of the original purchase.
There are two main caveats: first, this only works on iOS 7 and above. Secondly, Apple don't include code for parsing the receipt (so it's not too easy for users to hack I understand). There are, however, onen source libraries, though using a common one will be less secure.
There are no perfect solutions to this scenario.
Suggestion 1:
Roll out one last paid update. In this update, use keychain to store those IAP flags. Then in the free version, check for these flags in keychain. This will work even if app was deleted and reinstalled with the free version later. But it will not work if the device is being reset completely whether due to some iOS version updates or user's unless a backup and restore also is involved.
Suggestion 2:
Not quite a suggestion. But I have seen similar apps on AppStore have just rollout free version. Then app incurred bad reviews from those previous users!
This is a simple example, but if you're working with a database on a server (not on the phone itself), can't you use a boolean for each feature you plan on selling, and just set that boolean to true for all users currently in the database. This is assuming true means they've bought the feature, and false means they haven't bought it.
You could run this query once after releasing your updated app, and then every user after that would have a default value of false for these features you're selling.
How it works - The app is a subscription to a service that works cross platform. On the iphone the initial purchase will get you 30 days of full functionality then after 30 days you can't do ceirtain things until you buy a subscription with an in app purchase.
What I need - I need to know if it was the first run so that I can add the users info to the database. Or because it is cross platform they may have already paid for a subscription so I need to add 30 days to the user's already existing subscription.
What I am doing now - Currently I am storing the identifierForVendor in the remote database and in NSUserDefaults there is a bool checked to see 1. if it is the first run and 2. if it is the first run to allow the user to add themselves to the database for a 30 day full use, or to add 30 days to their existing subscription.
The Problem - The problem is that if the user deletes the app then reinstalls it the NSUserDefaults will be deleted too, and the identifierForVendor will change and that will allow the user to add another 30 days to their subscription for free just by deleting and reinstalling the app.
Ideal Solution I originally wanted to do a subscription for the app, but I didn't know how to check the receipt when the app is originally purchased and insert the user into the remote database. Also I don't really know how to setup a subscription that isn't an In App Purchase. I also thought about making the app free and then they can use the In App Purchase to buy the service but the app is useless without being able to connect to the remote server to build up data in the first place.
Bottom Line I would like to do one of the following
Make the subscription on the first purchase (I need to be able to detect if the purchase is valid so I can enter the user info into the remote database)
Make the app free then use In App Purchase to add subscription (Is it acceptable to have a free app that won't do anything until you subscribe?)
Leave it the way it is now (but find a more permanent solution to the identifierForVendor, and the identifierForAdvertising won't work either because it can be turned off)
This will help you so much. Basically it's a wrapper for Keychain that is patterned after NSUserDefaults. It heled me a lot. Storing things in the Keychain makes them stay past app reinstalls.
https://github.com/carlbrown/PDKeychainBindingsController
This project is intended to make using the Mac OSX and iOS Keychains
as easy as NSUserDefaults.
It is a KVO-compliant Cocoa wrapper around the Mac OSX and iOS
Keychains, and the model for this wrapper is NSUserDefaults, so the
intent is that for the common cases you would normally want to call:
[NSUserDefaultsController sharedUserDefaultsController] You should be
able to call
[PDKeychainBindingsController sharedKeychainBindingsController] And
for the common cases you normally would have called:
[NSUserDefaults standardUserDefaults] You should be able to call
[PDKeychainBindings sharedKeychainBindings]
I have an my app on appstore and currently it's free. I want to make future releases not free but remain this app free for those users who downloaded it before, is there way to make this? Can I check when user downloaded specific app at first and if date is before certain date it remains free otherwise user requested to pay for using this app.
If a user downloads an app and it's free, it will remain free for them in subsequent future updates. Going free-to-paid is fine, for this reason. Generally, going paid-to-free tends to upset the people that paid for your app.
To change the price of your app, you can manage this in iTunes Connect.
If it was free users that already downloaded it own it at all effect.
Setting a price won't affect previous downloads, they'll be able to download future versions as updates without having to pay anything.
Once a user has purchased an app, all updates for that app are free. You can change the price to whatever you'd like, and all existing users will continue to have updates available to them.
It appears that no work is required for you to get the effect you want.
I can't seem to find an answer to this question anywhere, so here goes...
I've developing an iOS app that will have non-consumable in-app purchases (expansion packs). Say I sell a pack that has 10 levels in it, for example, and in a month I want to update that in-app purchase to have 15 levels. The user will NOT have to re-purchase the pack; they would just need to update it.
Three questions:
Is this even possible?
How are users notified of this (or how SHOULD they be notified of this change?)
Does Apple need to review changes like this?
Thanks in advance,
Rick
Clearly yes. It is up to you, to write the code in a way, that your app remembers which updates a user has bought and how these updates are interpreted in your app. The only thing that will stop you from changing an in-app purchase content is when you take functionality or in your case levels, away again. Apple won't allow you to upload a new paid version with less functionality.
I would probably tell the user in the info text you have on the app-store, that they will receive 5 additional levels if they already have the 10 level upgrade.
Apple reviews every change you make to the app when you upload a new version to the app-store. This is true for any feature as it is for updates to in app purchase.
I did something similar to this in my app recently. I was saving a BOOL value in NSUserDefaults that specified if the user had purchased the expansion pack. In my update I simply had the change the code that was given to the user based on whether or not that BOOL value was YES or NO. As long as you designed it correctly you shouldn't have any troubles updating
Yes it's possible. Provided you keep a track of who has bought what pack (ie. keep a bool value as an NSUserDefault), then they will still have access to it (even if you add more stuff/levels to it).
It depends what you mean by notified; they will know if they read the update comments when they install the update. Also you could just choose to alert them when the load the app after the update - your call.
If you're submitting the code Apple will review it. Just think of it like any other update to an app.
Hope this helps!