For those interested in the StoreKit flow -
The “store kit flow”, is a process taken at the time of an attempt to purchase an "in app purchase" item such that the store kit determines that there is a problem with the user’s storekit account - for example, when the credit card information has expired. When this issue is detected, the user is given the option to be taken to the App Store app to update their account information.
It used to be that the StoreKit would alert the user and ask them to fix the issue in the App Store app, when the issue was detected. Beginning with iOS 7, this check won’t bother the user until an actual charge is attempted - either when an app is requested for download or when a user attempts an in app purchase.
When such a purchase is attempted (application makes the addPayment call and the user credentials are checked), and the store detects the account problem the StoreKit flow process occurs. The process begins with an initial purchase transaction result as a failure. It’s not clear that the user credit info or whatever issued caused the problem, will be fixed.
The transaction failure notification is delayed since the application is moved to the background as the App Store app is moved to the foreground. iOS stores the transaction failure to be passed to the app when it moves back to the foregound.
With the App Store application in the foreground, and the user updates their information then is presented with the option to continue with the purchase attempt - which many agree to. In this case, a successful purchase transaction is now sent to the app.
When the app moves to the foreground, the queued transaction results are passed to the updatedTransactions delegate method. For many apps, this means seeing first the queued SKPaymentTransactionStateFailed result, followed by a second SKPaymentTransactionStatePurchased result.
The proper way to handle this sequence of events is to make sure to call finishTransaction for the SKPaymentTransactionStateFailed state, then process the SKPaymentTransactionStatePurchased state as you normally would in the app. This might mean validating the receipt or downloading hosted content. Make sure that there are no other actions to be taken before the application responds to the successful transaction with the finishTransaction result.
Some observations to consider - don't assume that one call to addPayment will result in either a successful or failed transaction result. An app should never call removeTransactionObserver following a transaction result. Of course it's a best practice to make the addTransactionObserver call only once in the didFinishLaunchingWithOptions delegate method.
In some cases, the user may not relaunch the app until much later, when the app starts up as a new launch. In this case, it becomes especially important that the app make the addTransactionObserver call early on, so as to process the queued transaction result.
rich kubota - rkubota@apple.com
developer technical support CoreOS/Hardware/MFI