I want to add In-App purchase functionallity in my app.
My app contains many feature. In the free version, Some features of my app will be accessible and some features are disabled.
What i want to do is, i want to enable all the feature once the user pays for full version of my app.
How do I store flags in iOS keychain ?
How can I do this ?
Is there any examples or good links ?
There are many ways you could achieve this:
Using your own server and delivering the content once the app is purchased succesfully.
Using the iOS keychain to store some flags.
I will talk about the second point here. I will assume you can't get your own server.
The easiest way to do is to code in "disabled" features into your app, as you normally would. But store a flag a somewhere, say, a flag called "contentHasBeenPurchased". You could store this flag anywhere; in a plist, in NSUserDefaults, but these are insecure ways to store your flag because a jailbroken app could easily access your application's sandbox. These methods are secure with non-jailbroken users, for the most part... There is software that allows you to access the iOS filesystem and edit plists from there. So yeah, storing this specific flag in a plist or NSUserDefaults is certainly not a good idea.
So you are left in storing this flag "contentHasBeenPurchased" in the iOS keychain, because it is encrypted. If you don't know how to use the iOS keychain, it's a bit complex to learn, but it will certainly pay off in the near future. After you have your flag in the keychain, it's just matter of checking whether its value is true or false to enable the purchased content. When the user purchases the app, just set the flag to true, and you are ready to go.
Related
I'm thinking about building a series of iOS apps.
Each app will be purchased individually but I'd like in-app purchases within any of the apps to be universal. ie, pay for it in one app of the series, it's available in any other apps installed to use too.
Is this possible without forcing the user to create an account of any sort?
Many thanks
Answer is NO, Reason is all your IAP are identified by the bundle identifier and that is unique for each application, as all the IAP's are specific to the bundle identifier you can not share those.
There is another way of achieving what you asking for, I don't know all your requirements still I would NOT follow this solution, still I am writing to know some options.
You can sharing the keychain across the applications and keep track of purchases across apps.
Keychain data is not deleted on deletion of the app
If user resets/restore phone keychain data can get deleted and you will be at dead end, as user has to restore the content from your 1st application to use in 2nd application... (yeah confusing.. right ?)
There may be some other complications I am missing right now.. good luck
I'd like to use different targets for my free and full versions of my app.
I then want to setup in app purchases, so a full version upgrade can be purchased.
However, I'm unsure how I can modify the target to make it the full version. I assumed that the targets would be different binaries and therefore using targets for this purpose wouldn't work ?
The only example I've found is a simple NSUserdefaults flag, which seems very insecure and sounds very easy to crack ?
If you are doing an In App Purchase, then you provide all the code in your App, but you put some branching logic that excludes the execution of the paid for stuff unless they have paid for it. There is no downloading of a full app one if they do it in app.
What you are discussing is having a free app and an paid app and the user can then go to the app store and purchase the paid for app separately.
Using NSUserDefaults for the In App Purchases isn't necessarily insecure - just encrypt the data before saving it to disk.
I have some features which would be unlocked only after the purchase through in app purchase.
Is it fine if I store the flag value in NSUserDefaults to check whether app has been purchased or not?
Is it safe to store the flag in NSUserDefaults once purchase is done via In App Purchase?
No, this is not safe.
The contents NSUserDefaults are stored in plain text. They can be accessed and modified with tools like iExplorer. This also works on devices that are not jailbroken.
This means that if you save the purchase information in the NSUserDefaults, users can unlock your content without doing an actual purchase.
To save the flags in a way that is not as easy to "crack", you could do one of the following:
Save an additional salted hash of your stored information. Use the hash to validate that the user has not modified the information. You can find an implementation of this concept here.
Save the flags in the keychain. Read more in Apple's Keychain Services Programming Guide. You can find several implementations of this concept on GitHub, e.g. Lockbox.
Update: As of iOS 8.3, the access to the app sandbox is somewhat restricted. While this adds some security, I would still not recommend using NSUserDefaults, as access to the sandbox is still possible for jailbroken devices, apps that have iTunes file sharing enabled, and of course devices running older versions of iOS.
Yes, it's the best way. So you can tract through flag which are stored in NSUserDefault.
But,
When you delete the app from device then it's value become FALSE.
So it will ask for purchase again. But, it will not charge user for purchase same thing again.
Cheers.
Yes that is the best way. At lease I stored in NSUSerDefault in my Non-Consumable In-app purchase type.. So it is working as charm for me until now.
I currently have an app that is divided into multiple apps. I'd like to combine them all into a single application with the ability to use In App purchasing to download the parts currently held in multiple apps. Is there a way that I can allow people who currently own the individual apps to somehow make an In App purchase that unlocks the parts in the single app?
The most obvious solution is to use a web server holding user accounts and in-app purchases. If you require an offline solution, I will suggest you to use iCloud Keychain, you can mark your apps sharing the same keychain in XCode.
To enable keychain sharing:
-Select the target in XCode
-Go to capabilities
-Enable keychain sharing
-Add a group with same name for all apps.
After all your apps will be able to reach this shared data.
If you are not familiar with keychain this tutorial will be a good start. Keychain is not that complicated.
EDIT: woops didn't even notice I'm answering a 3 year old question.
I'm planning on implementing some in-app purchase items and I want to save purchase information/data such that iTunes will backup said information when my customers sync. The Apple provided documentation states that this is possible, but doesn't really tell you how.
Where/how do I save purchase history (let's say, a NSString for each item) such that iTunes will back it up on the next sync?
Lastly, how would you suggest that I test this before making all of this go live?
Thanks.
P.S. Right now I'm using NSUserDefaults to store this info.
NSUserDefaults is fine for storing that kind of thing, but you should also use StoreKit's “check for purchased items” capability—a lot of apps that use in-app purchases have a button somewhere that checks the “purchased” state of the available products and re-enables them in the app, in case a user uninstalls and then reinstalls the app or installs it on a different device.
Testing in-app purchases can be done using the sandbox environment—iTunes Connect will let you set up a test iTunes Store account which has free access to all of your app's in-app purchases.
Actually NSUserDefaults is under
<Application_Home>/Library/Preferences
And the Library directory will be backed up by the iTunes.
Another way to save your in app purchase data (because it's very little) is to save it to keychain. Because keychain is safe and will be reserved when the app is deleted. So when user install the app again user can get their purchase instantly. Check this link:Lockbox: Easily Secure Your App’s Sensitive Data
As already mentioned you can use UserDefaults for this purpose, but as Apple states it can also be achieved using iCloud and NSUbiquitousKeyValueStore
https://developer.apple.com/documentation/storekit/in-app_purchase/persisting_a_purchase
Testing can be easily done nowadays right within Xcode using .storekit configuration file.
https://developer.apple.com/documentation/storekit/in-app_purchase/testing_in-app_purchases_in_xcode
While NSUserDefaults can be used to store purchase history, it's possible for a hacker to modify that and get access to paid features for free.
Keychain is a little better in that it's more persistent (will still be there after an app is removed and re-installed) but it's still possible for a really dedicated hack to add data to the keychain that makes your application think a purchase has been made.
You could also write out purchase info into some encrypted file you store within the app, that would be backed up with the app as well and might be more flexible.
The best approach is to store purchase data wherever is most convenient for your app, but then also check the receipt of the application that is stored in Bundle.main.appStoreReceiptURL to make sure what you have stored, Apple also considers to have been purchased.
That receipt is supposed to be sent through your own server to Apple, which returns receipt JOSN from the data stored at that appStoreReceiptURL.
For testing, although you can also use a sandbox iTunes account for testing on device, a newer method introduced with Xcode 12 is to use a StoreKit configuration where you can define all of your products without having to enter them in appStoreConnect first. When you run it will process purchase transactions locally, including within the simulator (not possible with the iTunes sandbox).
For more information on testing using the Xcode App Store Config files read this article:
https://www.namiml.com/blog/inapp-purchases-ios14-simulator