Sometimes Receipt Validation for In-App Purchase is taking to much time to give response Swift

652 Views Asked by At

This is my verification validation code:

func receiptValidation(completion: @escaping(_ isPurchaseSchemeActive: Bool, _ error: Error?) -> ()) {
    let receiptFileURL = Bundle.main.appStoreReceiptURL
    guard let receiptData = try? Data(contentsOf: receiptFileURL!) else {
        //This is the First launch app VC pointer call
        completion(false, nil)
        return
    }
    let recieptString = receiptData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    let jsonDict: [String: AnyObject] = ["receipt-data" : recieptString as AnyObject, "password" : AppSpecificSharedSecret as AnyObject]
    
    do {
        let requestData = try JSONSerialization.data(withJSONObject: jsonDict, options: JSONSerialization.WritingOptions.prettyPrinted)
        let storeURL = URL(string: self.verifyReceiptURL)!
        var storeRequest = URLRequest(url: storeURL)
        storeRequest.httpMethod = "POST"
        storeRequest.httpBody = requestData
        let session = URLSession(configuration: URLSessionConfiguration.default)
        let task = session.dataTask(with: storeRequest, completionHandler: { [weak self] (data, response, error) in
            do {
                if let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
                    if let latestInfoReceiptObjects = self?.getLatestInfoReceiptObjects(jsonResponse: jsonResponse) {
                        self?.getCurrentTimeFromServer(completionHandler: { currentDateFromServer in
                            let purchaseStatus = self?.isPurchaseActive(currentDateFromServer: currentDateFromServer, latestReceiptInfoArray: latestInfoReceiptObjects)
                            completion(purchaseStatus!, nil)
                        })
                    }
                }
            } catch let parseError {
                completion(false, parseError)
            }
        })
        task.resume()
    } catch let parseError {
        completion(false, parseError)
    }
}

I start calling the observer inside of didFinishLaunchingWithOptions:

IAPManager.shared.startObserving()

And then call the receiptValidation to check the subscription status of product:

IAPManager.shared.receiptValidation { isPurchaseSchemeActive, error in
    //Handle authentication based on isPurchaseSchemeActive status
}

I end calling the observer inside of applicationWillTerminate:

IAPManager.shared.stopObserving()

I am also calling the receiptValidation inside of the applicationWillEnterForeground to check the validity whenever user come from background to foreground:

IAPManager.shared.receiptValidation { isPurchaseSchemeActive, error in
    //Handle authentication based on isPurchaseSchemeActive status
}

My IAPManager in short:

class IAPManager: NSObject {
    static let shared = IAPManager()     
    private override init() { super.init() }

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

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

And obviously calling receiptValidation after each successful purchase transaction and restoring product transactions before SKPaymentQueue.default().finishTransaction(transaction).

It works perfectly. But sometimes the receiptValidation stuck at JSON response for more than 10 or higher minutes. In this case, I am trying to cancel the receiptValidation call with a 1 minute timer. A pop up alert will appear saying try again and It will request the call again if user tap on "Try again" button.

My question is If I want to cancel an ongoing receiptValidation call, should I turn off IAPManager.shared.stopObserving() observer and turn on IAPManager.shared.startObserving() observer again before calling it? Or simply recall the receiptValidation request?

0

There are 0 best solutions below