I am about to create my first iOS app with in-app purchase. I read documentation and everything, but I can't find anywhere how to append some metadata to in-app purchase object. I would like to add some additional information to each item, like category, sub-title e.t.c.
iBooks uses this for category, author and other stuff, so it should be possible. I presume they are using in-app purchase in iBooks, is that correct?
Only solution I came up with so far is to have all metadata on my server and retrieve them when items from store load. Is there any other way?
I need to add new items (and possibly new metadata) after app is online, so I can't put them inside app
Nope. That's what you're supposed to do. Metadata and the like is entirely up to you, and Apple provides no inbuilt mechanism in StoreKit or iTunes Connect for supplying it.
Related
If I offer an in-app Non-consumable purchase (say a book, or a song) within my app and then 2-3 months after it has been released I realize that there is something wrong with my digital content, Can I do an update of the digital content? So if I had a digital article as an in-app purchases for $1.99 and sold 1,000 copies, then I realized that I have a spelling error on page 3. Would I be able to upload an updated article that would go out to all the people who bought the article and prevent people from downloading the old copy? If not, how is this situation handled in the real world? I have looked in apples doc, but cannot find an answer.
Edit: Assume I am using the new io6 feature of hosting the content through apple.
Yes, as a matter of fact, provided that you do a few steps, you can keep track and systematically, efficiently keep track of what is downloaded.
1.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).
2.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.
3.If you're submitting the code Apple will review it. Just think of it like any other update to an app.
This is taken directly from here: Update in-app purchase content for iOS app?
After you have updated your content for the app store, you can allow your users to Restore Purchases and obtain the updated content!
Overall, have a mechanism to keep track of the version of the in-App purchases' version and then update when needed!
There is always, apple's own documentation:
Here you go! :)
I hope this is clear and helpful!
EDIT:
After checking the user's content version number and finding that it's outdated, you would call the method (by the way, you would probably implement this checking mechanism in your app delegate.
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
This would restore the transactions, but make sure you also need to include the rest of the implementation code!
I assume you know the code to restore in app purchases, but if not, here are a couple good links!
Restore already bought in-app-purchases on iPhone?
http://www.iosdeveloperguide.com/in-app-purchase-heads-up-to-avoid-app-rejection/
http://appotography.com/2011/07/06/restoring-purchases-on-iphone-and-ipad/
About AppStore Hosted Content
I have not tried, but browsing inside Apple doc, I've found this which confirms that you can upload multiple versions of a digital content hosted by Apple.
"You can have multiple versions of hosted content, but each one needs to be approved by Apple before it can be purchased by users."
Also, you can check this and this tutorials, that shows that you have to specify the Content Version and IAP ProductIdentifier in the ContentInfo.plist when you create an App Store Hosted Content with Xcode.
How to notify the users that content has changed
This depends of how you implement your purchase system, the content delivery, and how you keep track of the "state of your purchased products". Usually we keep track of the version of the purchased products, thats means, we save the product_id with the content version when the purchased content is downloaded. We can save this data in files or inside a DB locally. Also, you don't have to worry about non downloaded (and non purchased) products, those do not need an update. When you update your in-app store with the last information of your available products (via update button, or app launch, or whatever you implemented) you should compare the last content versions with those you have downloaded, then you can notify the user that an update of his purchased product is available. Finally, you have to enable the download for that product.
This all depends on how you make the content available to the user. When the user makes their original purchase of the in-app content, where does the content come from?
If it is part of the app bundle, then the only way to get updated content to these users is to submit an update to your app that includes the updated content. When the user installs the updated app, they will see the updated content.
If, upon purchase, the app downloads the content from your server then you can build in a mechanism in your app that checks your server for updated versions of the content. If it detects there is an update, and the user has the IAP, then the app can download the updated content.
Edit: This doesn't cover the new iOS 6 feature of Apple hosted downloadable content.
For the above problem:
please have a look at the following urls for separate things:
Following link is the link to the SKDownload API:
http://developer.apple.com/library/ios/#documentation/StoreKit/Reference/SKDownload_Ref/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011851
Following link is the link to a great post which explains the working of SKDownload API:
How to download In-App hosted content?
Now in your position we can follow the following steps:
Push another package on the Apple Account which is to be hosted (with corrections).
Push an update the app on the App store with the following changes: (This handles any new download from the new users.)
a. Update your code of the InAppPurchase with the new identifier of the file
Now we have to handle the old users, we can consider the following two approaches:
a. We can show the user a restore button, by tapping which the user would be downloading the article again.
b. In iOS for things to go automatically to all existing users we do have a mechanism of push notifications, on the receiving of this the user would be triggering the event to again download the data from the Apple Hosting.
My apps are currently in the App Store.
Later I will remove this app from the AppStore and submit a new app.
So, the old app in-app purcharse user information must be moved to the new app.
What is the best way? Is there a safe way?
How to write the best code? Is there sample code?
There is no official, supported way of doing this. That is, your new app will never be able to "restore purchases" as you can with the old one.
I suppose you could have a button (or URL scheme) in your old app that sent data to the new one (using a URL scheme). Of course that could be faked unless you're careful.
You also want to be careful about what data you transfer. Apple may reject if you're circumventing an IAP in the new app, for example.
I want to create an ebook store app which has in app purchase.
All the ebooks will contain images, sounds, text and XML file and will be stored on a web server.
XML file will contain mapping on what sound to play and what text to display on particular page.
1) Being a newbie for in-App Purchase, I would like to know whether I should download all images, sounds, text and XML together or one after another. Or what would be a better mechanism to download all these items?
2) I have read that Apple requires that if a user purchases an item through in-App purchase, all his devices should be able to access that purchased item. How do we ensure that?
Also, if you have experience related to similar project, can you please share the challenges that I might face and possible solution to it.
I really appreciate your advice.
Thank You.
I would compress all the files into one archive and then decompress them on the device. This will speed up the download and will also make your code a little simpler as you'd only need to download one file per ebook.
The StoreKit framework has methods for determining if a user has already purchased an item. If an ebook has already been purchased, then just have the app download it to the device. This is all documented in the StoreKit documentation.
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
Apple doesn't offer promotional codes for in-app purchases. What's the best way to let users try the features or content unlocked by in-app purchases for free, while complying with Apple's Developer Guidelines?
The idea is to allow a special set of users (reviewers, key fans, etc.) to access the content or features offered as in-app purchases without paying.
Examples of apps that worked around this limitation would be much appreciated.
You could submit a version of your application that has all features unlocked by default.
Submitted apps have a publish date that you can set when you submit (and I believe you can change this on the fly as well) you could simply prevent the app from being published in the App store but still be able to give promotional codes for it.
Promo codes apply to a specific app version, so when users redeem promo codes for a version of an app that hasn’t been released yet, they download the prerelease version.
Source
Something like shareware? An app, that has a subset of features enabled until in-app purchase? Apple allows it now.
As example. We've a puzzle game, that has 12 difficulty levels. 4 or 5 of them are available for free and others are unlocked after in-app purchase.
I'm working on this now.
What I'm doing is I generate a random code/guid and store that on my webService's DB. Then give that code to who ever you want. They enter that code and it calls the web service passing the code, and device UDID. The webService returns another code indicating if that promocode was valid. If valid then the app will add that purchase to NSUserDefaults or Core Data (however you keep track of purchases).
If you don't have a server up and running (say the content is already in the app bundle) and you don't want a server would require you making an algorithm to generate keys that your app validates. However this is far less robust. Using a web service allows you to prevent 1 working key from being distributed between all users, as you can tie 1 promo code to 1 device.