Tulon
Tulon

Reputation: 4136

Restore purchase button always returns previously bought product for sandbox user Swift

Let me describe what have I done. I start & stop observing In-App purchase in my app delegate like this:

In didFinishLaunchingWithOptions:

IAPManager.shared.startObserving()

And in applicationWillTerminate:

IAPManager.shared.stopObserving()

These are the functions in my IAPManager class:

func startObserving() {
    SKPaymentQueue.default().add(self)
}

func stopObserving() {
    SKPaymentQueue.default().remove(self)
}

I know for sandbox user the purchase time frames are as below:

1 week = 3 minutes
1 month = 5 minutes
2 months = 10 minutes
3 months = 15 minutes
6 months = 30 minutes
1 year = 1 hour

But It doesn't match with the sandbox user testing. After crossing this time span If I tap on the "Restore Purchase" button, It still gives me all of my previously bought Product ids.

My Restore code:

PurchaseViewController:

func restorePurchases() {
    IAPManager.shared.restorePurchases { (result) in
        DispatchQueue.main.async {
            switch result {
            case .success(let success):
                if success {
                    self.restoredProductSuccessfully()
                    self.didFinishRestoringPurchasedProducts()
                } else {
                    self.didFinishRestoringPurchasesWithZeroProducts()
                }

            case .failure(let error):
                self.showIAPRelatedError(error)
            }
            self.activityIndicator.stopAnimating()
        }
    }
}

IAPManager class:

//Handler
var onBuyProductHandler: ((Result<Bool, Error>) -> Void)?

func restorePurchases(withHandler handler: @escaping ((_ result: Result<Bool, Error>) -> Void)) {
    onBuyProductHandler = handler
    totalRestoredPurchases = 0
    SKPaymentQueue.default().restoreCompletedTransactions()
}

SKPaymentTransactionObserver delegate methods:

extension IAPManager: SKPaymentTransactionObserver {
    //This delegate will trigger for every transactions, either for purchasing or restoring
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        transactions.forEach { (transaction) in
            switch transaction.transactionState {
            case .purchased:
                onBuyProductHandler?(.success(true))
                SKPaymentQueue.default().finishTransaction(transaction)
                
            case .restored:
                totalRestoredPurchases += 1
                let prodID = transaction.payment.productIdentifier
                print("restored productID \(prodID)")
                SKPaymentQueue.default().finishTransaction(transaction)

            case .failed:
                if let error = transaction.error as? SKError {
                    if error.code != .paymentCancelled {
                        onBuyProductHandler?(.failure(error))
                    } else {
                        onBuyProductHandler?(.failure(IAPManagerError.paymentWasCancelled))
                    }
                    onBuyProductHandler?(.failure(error))
                    //print("IAP Error:", error.localizedDescription)
                }
                SKPaymentQueue.default().finishTransaction(transaction)
                
            case .deferred, .purchasing: break
            @unknown default: break
            }
        }
    }
    
    func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
        if totalRestoredPurchases != 0 {
            onBuyProductHandler?(.success(true))
        } else {
            print("IAP: No purchases to restore!")
            onBuyProductHandler?(.success(false))
        }
    }
    
    func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
        if let error = error as? SKError {
            if error.code != .paymentCancelled {
                print("IAP Restore Error:", error.localizedDescription)
                onBuyProductHandler?(.failure(error))
            } else {
                onBuyProductHandler?(.failure(IAPManagerError.paymentWasCancelled))
            }
        }
    }
}

In this delegate method at line print("restored productID \(prodID)") I am always getting all of my previous product identifier although they suppose to be expired. What am I missing here?

Upvotes: 1

Views: 707

Answers (0)

Related Questions