Probably you solved your issue already, but i met the same issue and have some additional solution points:
Sorry, i use Swift, but I think it's understandable here.
First of all, there are two important moments in your code, which you must cover:
class InAppPurchaseViewController: UIViewController , SKProductsRequestDelegate
, SKPaymentTransactionObserver //NOTE THIS!
{
override func viewDidLoad() {
super.viewDidLoad()
//
...
...
SKPaymentQueue.defaultQueue().addTransactionObserver(self)
// here you create the observer
}
//before you leave this ViewController you should delete this Observer.
//I had a bug which worked like this: when user leaved the IAPViewController without
//buying something and then came back, viewDidLoad added one more Observer
// so App crashed on the attempt to buy
// for example:
@IBAction func exitTapped(sender: AnyObject) {
dismissViewControllerAnimated(true) { () -> Void in
SKPaymentQueue.defaultQueue().removeTransactionObserver(self)
}
}
after you added the observer, don't forget to finish the transaction:
func paymentQueue(queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .Restored:
print("Restored")
break
case .Failed:
print("Failed")
//FINISH TRANSACTION
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
break
case .Purchasing:
print("Purchasing")
break
case .Purchased:
// DO your stuff here
// ...
// and FINISH TRANSACTION
SKPaymentQueue.defaultQueue().finishTransaction(transaction)
}
break
case .Deferred:
print("Deferred")
break
}
}
}
One more issue, that I solved here, is: I forgot to add the finish transaction line of code, so i had open transaction with consumable IAP.
When i tried to buy one more time with this Sandbox User, i received the message "This In-App Purchase has already been bought. It will be restored for free. [Environment: Sandbox]" This happened again and again even after I added FinishTransaction. I changed the sandbox user. App became to prompt FirstSandBoxUser iTunes Password every time i ran the App. Catastrophe... Very annoying...
Every time I tried to make this purchase with FirstSandBoxUser, the transaction.transactionState was .Purchasing, and you can't finish the transaction in this state!
I made an assumption, that if transaction is not finished, StoreKit takes it like a non-consumable, so I should start a restoration process, and then catch a moment to finish the transaction. This is the code:
func paymentQueue // see above
//....
case .Purchasing:
print("Purchasing")
SKPaymentQueue.defaultQueue().restoreCompletedTransactions()
break
//...
}
func paymentQueueRestoreCompletedTransactionsFinished(queue: SKPaymentQueue) {
for transaction in queue.transactions {
queue.finishTransaction(transaction)
}
}
It's enough to run this code once, I think, it will catch all "Purchasing" transaction, Restore them and after that Finish.
Of course, after fixing the issue remove this additional code.
Good luck!