как правильно обрабатывать URLSession.shared.dataTask - PullRequest
0 голосов
/ 28 января 2020

Привет, разработчики, у меня возникли некоторые проблемы или неуместные задачи

, поэтому мне пришлось разработать каркас с некоторыми функциями

Это моя основная ФУНКЦИЯ, с которой началась проблема

func saveDataDevice(idPos: String, macAddress: String) {
        // this first function obtains the MAIN token for further tasks == 'tokenForTransaction'
        let value = FirstInitDevice.tokentransaccional(username: idPos)

//now i'd 2 seconds timer after tokentransaccional is launched 
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0, execute: {

            //after obtain tokenForTransaction i can do any WS, deviceInitWsCall gets call now it returns 'PosId' 
//after finish the task so i'd save it for further fuctions 
           let value2 = FirstInitDevice.deviceInitWsCall(serialNumber: idPos)
            let posidd = value2.PosId
            let convert = String(posidd)
            UserDefaults.standard.set(convert, forKey: "PosId")
            
            //now i can do the third function using PosId parameter and obtain  'rsa'
            //this is where the trouble shows for the first time, because the application hasn't finish the past task
//FirstInitDevice.deviceInitWsCall is not done yet that's why my if == "" just in case ill show the error immediately
        let value3 = FirstInitDevice.getKeyWS(posId: value2.PosId)
            LoginSingleton.shared.pos_id = value2.PosId
            
            if value3.rsa == "" {
                let alert = UIAlertController(title: "alert", message: "Cannot init KEYS", preferredStyle: UIAlertController.Style.alert)
                       let action = UIAlertAction(title: "OK", style: UIAlertAction.Style.destructive, handler: nil)
                       alert.addAction(action)
                self.present(alert, animated: true, completion: nil)
            }else {
// if not continue
//decrypt rsa data 
            let rsaData = RSA().getRSAData(publicKeyHex: value3.rsa)
                   
                 
                   keysSingleton.shared.tk = rsaData.tk
        
                //func 4 runs after decrypt is done BUT is not, because third function is not over yet 
            let value4 = FirstInitDevice.callInitDukptKeys(pos_id: value2.PosId, rsa: rsaData.rsa, check_value: rsaData.checkValue, crc32: rsaData.crc32)


            //same IF just in case == ""
            if value4.ksnString == ""{
                 let alert = UIAlertController(title: "Alert", message: "Cannot init KEYS", preferredStyle: UIAlertController.Style.alert)
                       let action = UIAlertAction(title: "OK", style: UIAlertAction.Style.destructive, handler: nil)
                       alert.addAction(action)
                self.present(alert, animated: true, completion: nil)
            } else{
                keysSingleton.shared.ksn = value4.ksnString
                keysSingleton.shared.new_key = value4.newKey
                keysSingleton.shared.tk = value4.ksnString
                self.doTransaction()
            }
            }
        })
        

        
    }

как вы можете видеть, одна функция ведет к другой, и так далее, она не работает без получения предыдущего параметра, по какой-то причине приложения сохраняют полученный LAST параметр INSTED текущий, это применяется к любой другой функции в библиотеке я попытался

1.- увеличить таймер для DispatchQueue.main.asyncAfter (дедлайн: .now () + 8.0, выполнить: {

2.- установить для каждого крайнего срока функции 8s

3.- установите DispatchGroup () .enter .leave для каждой функции

, но это не сработало, поэтому возникает вопрос: как я могу обработать URLSession.shared.dataTask после их завершения sh правильно, чтобы значение ответа не получало прошедшего значения

* ПРИМЕЧАНИЕ. Я не могу выполнить urlsessiondelegate с conection finish. К счастью, мне пришлось работать с библиотекой. ответ *

это функции моей библиотеки

ПЕРВАЯ ФУНКЦИЯ tokentransaccional

public static func tokentransaccional(username: String){
    let baseUrl = "http://bla bla"

     let headers = [
         "Authorization": "Basic bla bla"
     ]
        let url = URL(string: "bla bla")!
        var request = URLRequest(url: url)
        request.allHTTPHeaderFields = headers
        request.httpMethod = "POST"
        request.timeoutInterval = 60
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        let password = username+"bla bla"
        let postString = "bla bla"
        request.httpBody = postString.data(using: .utf8)
        
     let task = URLSession.shared.dataTask(with: request) { data, response, error in
         guard let data = data, error == nil else {
            // check for fundamental networking error
             print("error=\(error)")
             return
         }

         if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
            // check for http errors
             print("statusCode should be 200, but is \(httpStatus.statusCode)")
             print("response = \(response)")
         }

             do {
                 if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {

                     let responseError = convertedJsonIntoDict["error"] as? String
                     let errorDescription = convertedJsonIntoDict["error_description"] as? String
                     
                     
                     if responseError?.count == nil {

                         let tokenAcceso = convertedJsonIntoDict["access_token"] as? String
                         LoginSingleton.shared.tokenForTransaction = tokenAcceso ?? ""
                         UserDefaults.standard.set(tokenAcceso, forKey: "AccessTokenLogin")
                     } else {
                         print("error")
                     }
                 }
             }
         catch let error as NSError {
             print("catch let error")
             print(error.localizedDescription)
         }

     }
     task.resume()

     }

вторая функция deviceInitWsCall

public static func deviceInitWsCall(serialNumber: String) -> (PosId: Int, transaction_profile: String) {
        let token = UserDefaults.standard.string(forKey: "AccessTokenLogin") ?? ""
            let headers = [
                "Authorization": "bla bla"
            ]
            let baseUrl = "bla bla"
            let portBPC = "bla bla"
            let deviceInitWsPoint = "bla bla"
        
            let Url = String(format: "bla bla")
             let serviceUrl = URL(string: Url)
            let parameterDictionary = ["bla bla": serialNumber]
            var request = URLRequest(url: serviceUrl!)
            request.httpMethod = "POST"
            request.allHTTPHeaderFields = headers
            request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
            request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
            request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
        
            let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: [])
            request.httpBody = httpBody
            let task = URLSession.shared.dataTask(with: request) { data, response, error in
                
                guard let data = data, error == nil else {
                    print("error=\(error)")
                    return
                }
                
                if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                    print("statusCode should be 200, but is \(httpStatus.statusCode)")
                    print("response = \(response)")
                }
                
                do {
                    if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
                        print(convertedJsonIntoDict)
                        let response = convertedJsonIntoDict
                        let status = response["status"] as? Bool
                        if status == true {
                        UserDefaults.standard.set(response, forKey: "deviceInitDictionary")
                       
                         let mainResponse = response["dataResponse"] as! NSDictionary
                         let getPosId = mainResponse["posId"] as! Int
                            UserDefaults.standard.set(getPosId, forKey: "getPosId")
                         let getQps = mainResponse["qps"] as! Bool
                         let getTransactionProfile = mainResponse["transactionProfile"] as! String
                            UserDefaults.standard.set(getTransactionProfile, forKey: "getTransactionProfile")
                         
                         let dataContact = mainResponse["contact"] as! NSDictionary
                         let indicatorPartialCancellation = mainResponse["partialCancellation"] as? Bool
                         LoginSingleton.shared.qps = getQps
                            UserDefaults.standard.set(getQps, forKey: "getQps")

                         LoginSingleton.getInstance().pos_id = getPosId
                         dataPresentReatailPresent.shared.posId = getPosId
                         LoginSingleton.getInstance().qps = getQps
                         LoginSingleton.getInstance().transaction_profile = getTransactionProfile
                         LoginSingleton.getInstance().partialCancellation = indicatorPartialCancellation ?? false


                        }
                        else{
                            print("error")
                        }


                    }
                } catch let error as NSError {
                    print("catch let error")
                    print(error.localizedDescription)
                }
                }.resume()
        let PosId = UserDefaults.standard.integer(forKey: "getPosId")
        let transaction_profile = UserDefaults.standard.string(forKey: "getTransactionProfile") ?? ""
        return (PosId, transaction_profile)
        }

третья функция getKeyWS

public static func getKeyWS(posId: Int) -> (rsa: String, rsa_id: Int) {

            let token = UserDefaults.standard.string(forKey: "AccessTokenLogin") ?? ""
            let headers = [
                "Authorization": "bla bla"
            ]
        
            let baseUrl = "bla bla"
            let portBPC = ":bla bla"
            let deviceGetKeyUrl = "bla bla"
        
            let Url = String(format: "bla bla")
            let serviceUrl = URL(string: Url)
            let parameterDictionary = ["bla bla": posId]
            var request = URLRequest(url: serviceUrl!)
            request.httpMethod = "POST"
            request.allHTTPHeaderFields = headers
            request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
            request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")

            let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: [])
            request.httpBody = httpBody
        
            let task = URLSession.shared.dataTask(with: request) { data, response, error in
                
                guard let data = data, error == nil else {
                    print("error=\(error)")
                    return
                }
                
                if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                    print("statusCode should be 200, but is \(httpStatus.statusCode)")
                    print("response = \(response)")
                }
                
                do {
                    if let convertedJsonIntoDict = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
                        // Print out dictionary
                        print(convertedJsonIntoDict)
                        let response = convertedJsonIntoDict
                              guard let MainDataResponse = response["dataResponse"] as? NSDictionary else { return }
                              let rsa_id = MainDataResponse["rsaId"] as? Int ?? 0
                              let rsa = MainDataResponse["rsa"] as? String ?? ""

                         
                        UserDefaults.standard.set(rsa_id, forKey: "rsa_id")
                        UserDefaults.standard.set(rsa, forKey: "rsa")
                              

                    



                    }
                } catch let error as NSError {
                    print("catch let error")
                    print(error.localizedDescription)
                }
                }.resume()
        let rsa = UserDefaults.standard.string(forKey: "rsa") ?? ""
        let rsa_id = UserDefaults.standard.integer(forKey: "rsa_id")
        return (rsa, rsa_id)
        }

четвертая функция callInitDukptKeys

public static func callInitDukptKeys(pos_id: Int, rsa: String, check_value: String , crc32: String) -> (newKey: String, ksnString: String, crc32: String, checkValue: String) {

       let token = UserDefaults.standard.string(forKey: "AccessTokenLogin") ?? ""
       let headers = [
           "Authorization": "bla bla"
       ]

       let baseUrl = "bla bla"
       let portBPC = ":bla bla"
       let deviceInitDukptKeysUrll = "bla bla"
    
       let UUrl = String(format: "bla bla")
       let serviceUrlll = URL(string: UUrl)
       let parameterDictionary = ["bla bla": String(pos_id),
       "bla bla": rsa,
       "bla bla": check_value,
       "bla bla": crc32]
       var requests = URLRequest(url: serviceUrlll!)
       requests.httpMethod = "POST"
       requests.allHTTPHeaderFields = headers
       requests.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
       requests.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")
    

       let httpBody = try? JSONSerialization.data(withJSONObject: parameterDictionary, options: [])
       requests.httpBody = httpBody

    _ = URLSession.shared.dataTask(with: requests) { data, response, error in
           
           guard let data = data, error == nil else {
            print("error=\(String(describing: error))")
               return
           }
           
           if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
               print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(String(describing: response))")
           }
           
           do {
               if let DictConvert = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
                   // Print out dictionary

                   let response = DictConvert
                   let status = response["status"] as? Bool
                   if status == true {
                   let mainResponse = response["dataResponse"] as? NSDictionary
                   let getKey = mainResponse!["key"] as? String
                   let keyCheckValue = mainResponse!["keyCheckValue"] as? String
                   let keyCrc32 = mainResponse!["keyCrc32"] as? String
                   let ksn = mainResponse!["ksn"] as? String
                   
                    print("valor getKey: \(getKey)")
                    print("valor ksn: \(ksn)")
                    print("valor keyCrc32: \(keyCrc32)")
                    print("valor keyCheckValue: \(keyCheckValue)")
                    UserDefaults.standard.set(getKey, forKey: "getKey")
                    UserDefaults.standard.set(ksn, forKey: "ksn")
                    UserDefaults.standard.set(keyCrc32, forKey: "keyCrc32")
                    UserDefaults.standard.set(keyCheckValue, forKey: "keyCheckValue")
                   } else {
                       print("error")
                   }


               }
           } catch let error as NSError {
               print("catch let error")
               print(error.localizedDescription)
           }
           }.resume()
    let newKey = UserDefaults.standard.string(forKey: "getKey") ?? ""
   let ksnString = UserDefaults.standard.string(forKey: "ksn") ?? ""
   let crc32 = UserDefaults.standard.string(forKey: "keyCrc32") ?? ""
   let checkValue = UserDefaults.standard.string(forKey: "keyCheckValue") ?? ""
    
   return (newKey, ksnString, crc32, checkValue)
   }

...