100 gold coins • Can be purchased multiple times • Can (obviously) not be restored • Non-consumable • e.g. Red shorts for your David Hasselhoff character in Baywatch: The Game • Can be purchased only once • Can be restored (e.g. onto another device) • Subscription • Auto-renewable or not
through iTunes Connect • Each product has: • Unique identifier (you choose this) • Price tier (just like with apps) • Title and description (localized!)
• Or download from your server • Get SKProduct objects using product IDs • SKProductsRequest • SKProduct objects contain all the info you configured in iTunes Connect
the logged-in user’s App Store region — not based on the device language like everything else! • If your Apple ID is using the Finnish App Store, your IAP dialogs will be in Finnish even if your device language is English
• Persists even if app is deleted and re-installed! • Transactions in the queue can be in different states: • Purchasing (Apple is processing it) • Purchased (Apple is done with it — now you finish it) • Failed • Your app must have a single payment transaction observer registered at all times • SKPaymentTransactionObserver protocol • Only one global observer (the transaction queue is conceptually global so the observer should be, too) • Transaction state transitions can occur at any time
Apple has processed it and now you are responsible for “finishing” it (and marking it as such) • Finishing a transaction means your app giving the user what they paid for • Purchased transactions remain in the queue forever until you mark them as finished • -[SKPaymentQueue finishTransaction:] • Once you’ve marked them as “finished”, purchase transactions will disappear forever from the queue
transaction had its own receipt •SKPaymentTransaction.transactionReceipt • In iOS 7, an app has one receipt • “Grand Unified Receipt” • Info about the purchase of the app itself + IAPs •NSBundle.mainBundle.appStoreReceiptURL • Do not use -respondsToSelector: to check for this API (exists as a private method on iOS 6)! • Receipt may not exist on disk yet → must use SKReceiptRefreshRequest • e.g. if app has just been installed
server • Q: Where do you store the thing the user purchased? • If you assign purchased content to a user account on your server, it makes sense to validate receipts there • If you assign purchased content to a user only on the device itself, it makes sense to validate receipts there
Apple’s validation server HTTP API — get back JSON • Never talk to Apple’s validation server from your client — this is insecure. Client talks to your server, which in turn talks to Apple’s validation server.
servers: production and “sandbox” (testing) • Always send receipts to the production server first • If the production server says “this is a sandbox receipt”, then re-send it to the sandbox server • Also do this on your production server — Apple’s reviewers use test environment (“sandbox”) receipts to test your IAPs
• Dev-signed (or ad-hoc signed) apps use “sandbox” environment for IAPs — must use test Apple IDs; no actual credit card required • Only apps signed by Apple (i.e. released in the App Store) can perform actual IAP payments
• “Apps utilizing a system other than the In-App Purchase API (IAP) to purchase content, functionality, or services in an App will be rejected” • Heavily enforced! • The only way around this is to simply avoid any mention of the external payment mechanism, and ensure that the app contains zero links to any web pages from where you could access the external payment system • Cases in point: Spotify, Kindle…
“Apps using IAP to purchase physical goods or goods and services used outside of the application will be rejected” • Sharing purchased content between platforms: Inconclusive but might be a problem • “Apps that use IAP to purchase credits or other currencies must consume those credits within the App”
game character on my iPhone; now I want it on my iPad as well” • Subscriptions • Product downloads hosted by Apple • Newsstand (should probably avoid anyway)