I have code in my app to purchase and unlock additional levels. I am currently testing my app's ability to restore previous purchases, but the app doesn't recognize the purchase as being restored. If I click "Buy", StoreKit will say it is restoring the item, but then nothing happens. If I click "Restore", I don't see the app responding appropriately. Sometimes, on the first tap, when I tap "Restore" I get an error, but often my app just does nothing. As in, it doesn't even call paymentQueue:updatedTransactions:. What can I do to fix this? (Obviously, I can't finish the transaction yet. Not until I can get this figured out.)
import StoreKit
@objc protocol IAPObserver {
@objc func levelPurchaseCompleted()
@objc func levelPurchaseProcessing()
@objc func levelPurchasingError()
}
@objc class IAPHelper:NSObject,SKProductsRequestDelegate,SKPaymentTransactionObserver {
@objc var delegate : IAPObserver?
@objc override init() {
super.init()
delegate = nil
SKPaymentQueue.default().add(self)
}
@objc init(_delegate : IAPObserver) {
delegate = _delegate
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
let transaction = transactions.first
if (transaction?.transactionState == SKPaymentTransactionState.purchasing || transaction?.transactionState == SKPaymentTransactionState.deferred)
{
// Purchase is processing.
print("Purchase is processing.")
delegate!.levelPurchaseProcessing()
}
else if (transaction?.transactionState == SKPaymentTransactionState.failed)
{
// Purchase failed.
print("The purchase failed.")
let error = (transaction?.error as NSError?)
if (error?.code != SKError.paymentCancelled.rawValue)
{
delegate?.levelPurchasingError()
}
}
else
{
// The purchase is valid.
print("The purchase is valid")
UserDefaults.standard.set(true, forKey: "levelsWerePurchased")
// UserDefaults.standard.synchronize()
delegate?.levelPurchaseCompleted()
}
}
var errorOccurred : Bool! // Used if an error occurs.
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
// Check if product was purchased.
let invalidIdentifiers = response.invalidProductIdentifiers
print("Response received.")
if (invalidIdentifiers.count > 0)
{
print("Invalid App Store identifiers:")
for identifier in invalidIdentifiers {
print(identifier)
}
}
let products = response.products
if (products.count == 0)
{
print("No products!")
delegate?.levelPurchasingError()
return
}
let product = products.first
// Purchase the product.
purchase(product: product!)
}
@objc func purchase(product : SKProduct)
{
let payment = SKMutablePayment(product: product)
payment.quantity = 1
SKPaymentQueue.default().add(payment)
}
var request: SKProductsRequest!
let productIdentifier : String = "IntegratedDesignSolutionsInc.ReadingExpy.RestofLevels2"
/** Verify that levels 3 and up have been purchased.*/
@objc func verifyPurchased() -> Bool
{
// Check for purchased product within NSUserDefaults.
let levelsWerePurchased = UserDefaults.standard.value(forKey: "levelsWerePurchased") as? String
if (levelsWerePurchased != nil)
{
return true
}
else
{
return false
}
}
/** Check app store for product. If it's available, purchase it. **/
@objc func initializeRequest()
{
let productIdentifiers : Set<String> = Set([productIdentifier])
request = SKProductsRequest(productIdentifiers: productIdentifiers)
request.delegate = self
request.start()
}
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
print("Restored.")
delegate?.levelPurchaseCompleted()
}
func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
print("Error.")
print(error)
}
@objc func restore()
{
print("Trying to restore previous purchase.")
SKPaymentQueue.default().restoreCompletedTransactions()
}
}