Привет, разработчики, у меня возникли некоторые проблемы или неуместные задачи
, поэтому мне пришлось разработать каркас с некоторыми функциями
Это моя основная ФУНКЦИЯ, с которой началась проблема
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)
}