You described a sequence of events in the sandbox such that the purchase of a consumable item is not completed with the finishTransaction call by the application. You then re-install the application, launch it, and it appears that the addTransactionObserver call results in the notification to the user that there is a pending successful transaction - the consumable purchase to be processed. The interesting part of the process is that on inspection of the application receipt at appStoreURL, that the item is not in the application receipt in the in_app array.
On this issue, it's important to verify that the app waited until the call to the updatedTransactions delegate method before checking the application receipt. The application receipt should be updated before the call to the delegate method. In this case, a consumable item should appear in the in_app array. The consumable item appears in the in_app array until the application completes the purchase process by calling finishTransaction.
In the case that the item is not in the in_app array, the app can present an alert to the effect that there appears to be a problem with the receipt and ask the user whether to refresh the receipt. When the user agrees, then make the SKReceiptRefreshRequest. If the in_app array remains empty, there's a problem, but don't call finishTransaction on a transaction you can't validate actually occurred (at least by it's presence in the in_app array).
You mentioned using the restoreCompletedTransactions method and finding that the method worked - it should have for 2 reasons, restoreCompletedTransactions isn't designed to restore consumable transactions types (as you noted) and it doesn't restore any transactions which are pending (you stated that the finishTransaction method had not been called).
However, a restoreCompletedTransaction call will cause the application receipt to be updated - maybe this is what you meant. In updating the receipt, this will cause the application receipt to be updated and a pending consumable item that is pending, will be present in the in_app array - again, maybe this is what you refer to - this is what the SKReceiptRefreshRequest does.
You also suggested buying another item - this again will trigger the receipt to be updated - which again is something that SKREceitRefreshRequest would do.
rich kubota - rkubota@apple.com
developer technical support CoreOS/Hardware/MFI