App won't respond when I try to restore a purchase.

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()

}

}

I don't do Swift so I can't read your code.


You need to:

1) add a transaction observer

2) call restoreCompletedTransactions


This will result in a call to

1) updatedTransactions if there is a transaction to restore - only non-consumable and autorenewable IAPs can be restored.

2) a call to paymentQueueRestoreCompletedTransactionsFinished

App won't respond when I try to restore a purchase.
 
 
Q