| | |
| | | // |
| | | // NetworkRequest.swift |
| | | // HandyJSON |
| | | // |
| | | // Created by Sweet on 2018/12/25. |
| | | // Copyright © 2018 Sweet. All rights reserved. |
| | | // |
| | | // |
| | | // NetworkRequest.swift |
| | | // HandyJSON |
| | | // |
| | | // Created by Sweet on 2018/12/25. |
| | | // Copyright © 2018 Sweet. All rights reserved. |
| | | // |
| | | |
| | | import Foundation |
| | | import SwifterSwift |
| | |
| | | import RxSwift |
| | | import SVProgressHUD |
| | | |
| | | // 假设这是服务端返回的统一定义的response格式 |
| | | // 假设这是服务端返回的统一定义的response格式 |
| | | struct BaseResponse<T :HandyJSON>: HandyJSON { |
| | | var sysTime: Int = 0 |
| | | var code: Int = -1 // 服务端返回码 |
| | | var data: T? = nil // 具体的data的格式和业务相关,故用泛型定义 |
| | | var msg: String = "" |
| | | var sysTime: Int = 0 |
| | | var code: Int = -1 // 服务端返回码 |
| | | var data: T? = nil // 具体的data的格式和业务相关,故用泛型定义 |
| | | var msg: String = "" |
| | | } |
| | | |
| | | struct BaseResponseList<T :HandyJSON>: HandyJSON { |
| | |
| | | } |
| | | |
| | | struct BaseData<T: HandyJSON>: HandyJSON { |
| | | var records = [T]() |
| | | var records = [T]() |
| | | } |
| | | |
| | | struct SimpleModel: HandyJSON { |
| | | |
| | | |
| | | } |
| | | struct HtmlModel: HandyJSON { |
| | | var content = "" |
| | | var content1 = "" |
| | | var id = 0 |
| | | var type = 0 |
| | | var content = "" |
| | | var content1 = "" |
| | | var id = 0 |
| | | var type = 0 |
| | | } |
| | | |
| | | extension String: HandyJSON{ |
| | | |
| | | |
| | | } |
| | | extension Array: HandyJSON{ |
| | | |
| | | |
| | | } |
| | | extension Bool: HandyJSON{ |
| | | |
| | | |
| | | } |
| | | |
| | | extension Int: HandyJSON{ |
| | |
| | | } |
| | | |
| | | class ParamsAppender: NSObject { |
| | | var url: URL |
| | | var params:Dictionary = [String: Any]() |
| | | |
| | | private init(url: String){ |
| | | self.url = URL(string: url)! |
| | | } |
| | | var url: URL |
| | | var params:Dictionary = [String: Any]() |
| | | |
| | | @discardableResult |
| | | func interface(url: String) -> ParamsAppender { |
| | | self.url.appendPathComponent(url) |
| | | return self |
| | | } |
| | | |
| | | // @discardableResult |
| | | // func append(key: String,value: String) -> ParamsAppender { |
| | | // if value.isEmpty{return self} |
| | | // params += ["\(key)":"\(value)"] |
| | | // return self |
| | | // } |
| | | |
| | | @discardableResult |
| | | func append(key: String,value: Bool) -> ParamsAppender { |
| | | params += ["\(key)":"\(value)"] |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,value: String?) -> ParamsAppender { |
| | | if value != nil && value?.isEmpty == false { |
| | | params += ["\(key)":"\(value!)"] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,value: Array<String>) -> ParamsAppender { |
| | | if value.isEmpty == false { |
| | | params += ["\(key)":value] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | |
| | | @discardableResult |
| | | func append(key: String, value: Int?) -> ParamsAppender { |
| | | if value != nil{ |
| | | params += ["\(key)":value!] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String, value: Int64) -> ParamsAppender { |
| | | params += ["\(key)":value] |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String, value: Double?) -> ParamsAppender { |
| | | if value != nil{ |
| | | params += ["\(key)":value!] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,data: Data?) -> ParamsAppender { |
| | | if data != nil{ |
| | | params += ["\(key)": data!] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,url: URL) -> ParamsAppender { |
| | | params += ["\(key)":"\(url)"] |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(dic: [String : Any]) -> ParamsAppender { |
| | | params += dic |
| | | return self |
| | | } |
| | | |
| | | /// 参数加密 |
| | | @discardableResult |
| | | func done() -> Parameters { |
| | | var paramsArray: [String] = [] |
| | | // 排序 |
| | | let sortedArray: [String] = Array(params.keys).sorted() |
| | | |
| | | //防止自签名而错误 |
| | | if !sortedArray.contains("sign"){ |
| | | for item in sortedArray{ |
| | | // 拼接字符串 |
| | | if params.has(key: item){ |
| | | paramsArray.append("\(item)=\(params[item]!)") |
| | | private init(url: String){ |
| | | self.url = URL(string: url)! |
| | | } |
| | | } |
| | | let content = paramsArray.joined(separator: "&") |
| | | params += ["sign": "\(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))"] |
| | | |
| | | @discardableResult |
| | | func interface(url: String) -> ParamsAppender { |
| | | self.url.appendPathComponent(url) |
| | | return self |
| | | } |
| | | |
| | | // @discardableResult |
| | | // func append(key: String,value: String) -> ParamsAppender { |
| | | // if value.isEmpty{return self} |
| | | // params += ["\(key)":"\(value)"] |
| | | // return self |
| | | // } |
| | | |
| | | @discardableResult |
| | | func append(key: String,value: Bool) -> ParamsAppender { |
| | | params += ["\(key)":"\(value)"] |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,value: String?) -> ParamsAppender { |
| | | if value != nil && value?.isEmpty == false { |
| | | params += ["\(key)":"\(value!)"] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,value: Array<String>) -> ParamsAppender { |
| | | if value.isEmpty == false { |
| | | params += ["\(key)":value] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | |
| | | @discardableResult |
| | | func append(key: String, value: Int?) -> ParamsAppender { |
| | | if value != nil{ |
| | | params += ["\(key)":value!] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String, value: Int64) -> ParamsAppender { |
| | | params += ["\(key)":value] |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String, value: Double?) -> ParamsAppender { |
| | | if value != nil{ |
| | | params += ["\(key)":value!] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,data: Data?) -> ParamsAppender { |
| | | if data != nil{ |
| | | params += ["\(key)": data!] |
| | | } |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(key: String,url: URL) -> ParamsAppender { |
| | | params += ["\(key)":"\(url)"] |
| | | return self |
| | | } |
| | | |
| | | @discardableResult |
| | | func append(dic: [String : Any]) -> ParamsAppender { |
| | | params += dic |
| | | return self |
| | | } |
| | | |
| | | /// 参数加密 |
| | | @discardableResult |
| | | func done() -> Parameters { |
| | | var paramsArray: [String] = [] |
| | | // 排序 |
| | | let sortedArray: [String] = Array(params.keys).sorted() |
| | | |
| | | //防止自签名而错误 |
| | | if !sortedArray.contains("sign"){ |
| | | for item in sortedArray{ |
| | | // 拼接字符串 |
| | | if params.has(key: item){ |
| | | paramsArray.append("\(item)=\(params[item]!)") |
| | | } |
| | | } |
| | | let content = paramsArray.joined(separator: "&") |
| | | params += ["sign": "\(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))"] |
| | | |
| | | #if DEBUG |
| | | LogInfo("签名:\(content) ----- \(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))") |
| | | LogInfo("签名:\(content) ----- \(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))") |
| | | #endif |
| | | } |
| | | return self.params |
| | | } |
| | | |
| | | class func build(url: String) -> ParamsAppender { |
| | | return ParamsAppender(url: url) |
| | | } |
| | | |
| | | } |
| | | return self.params |
| | | } |
| | | |
| | | class func build(url: String) -> ParamsAppender { |
| | | return ParamsAppender(url: url) |
| | | } |
| | | |
| | | } |
| | | class NetworkRequest { |
| | | |
| | | static let sharedSessionManager: Alamofire.Session = { |
| | | let configuration = URLSessionConfiguration.default |
| | | configuration.timeoutIntervalForRequest = 10 |
| | | return Alamofire.Session(configuration: configuration) |
| | | }() |
| | | enum NetRequestError: Error { |
| | | case Other(Int,String) |
| | | case URLNotFound |
| | | case DownloadFailed |
| | | case InvaildSession |
| | | case ModelError(String) |
| | | case DataAnalysis(String) |
| | | } |
| | | |
| | | class func request<T: HandyJSON>(params: ParamsAppender, method: HTTPMethod, encoding: ParameterEncoding? = nil, progress: Bool = true,ignoreAlert:Bool = false) -> Observable<BaseResponse<T>>{ |
| | | |
| | | return Observable<BaseResponse<T>>.create{ ob in |
| | | guard NetworkReachabilityManager.init(host: All_Url)!.isReachable else { |
| | | alertError(msg: "当前网络不可用") |
| | | ob.onError(AFError.invalidURL(url: params.url)) |
| | | return Disposables.create{} |
| | | } |
| | | static let sharedSessionManager: Alamofire.Session = { |
| | | let configuration = URLSessionConfiguration.default |
| | | configuration.timeoutIntervalForRequest = 10 |
| | | return Alamofire.Session(configuration: configuration) |
| | | }() |
| | | enum NetRequestError: Error { |
| | | case Other(Int,String) |
| | | case URLNotFound |
| | | case DownloadFailed |
| | | case InvaildSession |
| | | case ModelError(String) |
| | | case DataAnalysis(String) |
| | | } |
| | | |
| | | if progress {showHUD()} |
| | | class func request<T: HandyJSON>(params: ParamsAppender, method: HTTPMethod, encoding: ParameterEncoding? = nil, progress: Bool = true,ignoreAlert:Bool = false) -> Observable<BaseResponse<T>>{ |
| | | |
| | | var headers = HTTPHeaders() |
| | | if let token = UserViewModel.getToken(){ |
| | | headers.add(name: "Authorization", value: "Bearer" + " " + token) |
| | | LogInfo("USER_token:Bearer \(token)") |
| | | } |
| | | return Observable<BaseResponse<T>>.create{ ob in |
| | | guard NetworkReachabilityManager.init(host: All_Url)!.isReachable else { |
| | | // alertError(msg: "当前网络不可用") |
| | | ob.onError(AFError.invalidURL(url: params.url)) |
| | | return Disposables.create{} |
| | | } |
| | | |
| | | if encoding is JSONEncoding { |
| | | headers.add(name: "Content-Type", value: "application/json;charset=UTF-8") |
| | | } |
| | | if progress {showHUD()} |
| | | |
| | | var newEncoding: ParameterEncoding |
| | | if encoding != nil { |
| | | newEncoding = encoding! |
| | | } else { |
| | | newEncoding = method == .post ? URLEncoding.httpBody : URLEncoding.queryString |
| | | } |
| | | |
| | | sharedSessionManager.request(params.url.absoluteString, method: method, parameters:params.done(), encoding: newEncoding, headers:headers).validate().responseData{response in |
| | | LogInfo("请求地址:\(params.url)") |
| | | LogInfo("请求参数:\(params.params)") |
| | | hiddenHUD(0.5) |
| | | var headers = HTTPHeaders() |
| | | if let token = UserViewModel.getToken(){ |
| | | headers.add(name: "Authorization", value: "Bearer" + " " + token) |
| | | LogInfo("USER_token:Bearer \(token)") |
| | | } |
| | | |
| | | guard response.error == nil else { |
| | | LogError("\(response.error!)") |
| | | if encoding is JSONEncoding { |
| | | headers.add(name: "Content-Type", value: "application/json;charset=UTF-8") |
| | | } |
| | | |
| | | var errorString = "" |
| | | errorString.append("服务器故障:\(response.error!.localizedDescription)") |
| | | if let code = response.error?.responseCode{ |
| | | errorString.append("\n【错误码:\(code)】") |
| | | } |
| | | if !ignoreAlert{ |
| | | alert(msg: errorString) |
| | | } |
| | | ob.onError(response.error!) |
| | | return |
| | | } |
| | | if let data = response.data,let jsonString = String(data: data, encoding: String.Encoding.utf8){ |
| | | LogResponse(try! JSONSerialization.jsonObject(with: data)) |
| | | if let next = BaseResponse<T>.deserialize(from: jsonString){ |
| | | switch next.code{ |
| | | case 200:ob.onNext(next) |
| | | case 501: |
| | | CommonAlertView.show(title: "提示", content: next.msg,isSingle: true) { _ in |
| | | var newEncoding: ParameterEncoding |
| | | if encoding != nil { |
| | | newEncoding = encoding! |
| | | } else { |
| | | newEncoding = method == .post ? URLEncoding.httpBody : URLEncoding.queryString |
| | | } |
| | | |
| | | sharedSessionManager.request(params.url.absoluteString, method: method, parameters:params.done(), encoding: newEncoding, headers:headers).validate().responseData{response in |
| | | LogInfo("请求地址:\(params.url)") |
| | | LogInfo("请求参数:\(params.params)") |
| | | hiddenHUD(0.5) |
| | | |
| | | guard response.error == nil else { |
| | | LogError("\(response.error!)") |
| | | |
| | | var errorString = "" |
| | | errorString.append("服务器故障:\(response.error!.localizedDescription)") |
| | | if let code = response.error?.responseCode{ |
| | | errorString.append("\n【错误码:\(code)】") |
| | | } |
| | | if !ignoreAlert{ |
| | | alert(msg: errorString) |
| | | } |
| | | ob.onError(response.error!) |
| | | return |
| | | } |
| | | if let data = response.data,let jsonString = String(data: data, encoding: String.Encoding.utf8){ |
| | | LogResponse(try! JSONSerialization.jsonObject(with: data)) |
| | | if let next = BaseResponse<T>.deserialize(from: jsonString){ |
| | | switch next.code{ |
| | | case 200:ob.onNext(next) |
| | | case 501: |
| | | CommonAlertView.show(title: "提示", content: next.msg,isSingle: true) { _ in |
| | | |
| | | } |
| | | ob.onError(NetRequestError.InvaildSession) |
| | | case 600: |
| | | if !ignoreAlert{ |
| | | alertError(msg: "登录失效,请重新登录");ob.onError(NetRequestError.InvaildSession) |
| | | } |
| | | app.needLogin() |
| | | default: |
| | | if !ignoreAlert{ |
| | | alertError(msg: "\(next.msg)") |
| | | } |
| | | ob.onError(NetRequestError.Other(next.code,next.msg)) |
| | | } |
| | | } |
| | | } |
| | | ob.onCompleted() |
| | | } |
| | | return Disposables.create{} |
| | | } |
| | | ob.onError(NetRequestError.InvaildSession) |
| | | case 600: |
| | | if !ignoreAlert{ |
| | | alertError(msg: "登录失效,请重新登录");ob.onError(NetRequestError.InvaildSession) |
| | | } |
| | | app.needLogin() |
| | | default: |
| | | if !ignoreAlert{ |
| | | alertError(msg: "\(next.msg)") |
| | | } |
| | | ob.onError(NetRequestError.Other(next.code,next.msg)) |
| | | } |
| | | } |
| | | } |
| | | ob.onCompleted() |
| | | } |
| | | return Disposables.create{} |
| | | } |
| | | } |
| | | |
| | | // class func requestData(params: ParamsAppender, method: HTTPMethod, encoding: ParameterEncoding? = nil, progress: Bool = true) -> Observable<Data>{ |
| | | // return Observable<Data>.create{ ob in |
| | | // if progress { |
| | | // SVProgressHUD.show() |
| | | // } |
| | | // |
| | | // var headers = HTTPHeaders() |
| | | // // if let token = UserViewModel.getUserInfo()?.token { |
| | | // // headers.add(name: "Authorization", value: "Bearer" + " " + token) |
| | | // // LogInfo("USER_token:\(token)") |
| | | // // } |
| | | // if encoding is JSONEncoding { |
| | | // headers.add(name: "Content-Type", value: "application/json;charset=UTF-8") |
| | | // } |
| | | // |
| | | // var newEncoding: ParameterEncoding |
| | | // if encoding != nil { |
| | | // newEncoding = encoding! |
| | | // } else { |
| | | // newEncoding = method == .post ? URLEncoding.httpBody : URLEncoding.queryString |
| | | // } |
| | | // |
| | | // sharedSessionManager.request(params.url.absoluteString, method: method, parameters: params.done(), encoding: newEncoding, headers: headers).validate().responseData{response in |
| | | // LogInfo("请求地址:\(params.url)") |
| | | // LogInfo("请求参数:\(params.params)") |
| | | // SVProgressHUD.dismiss() |
| | | // if response.error != nil { |
| | | // LogError("\(response.error!)") |
| | | // ob.onError(response.error!) |
| | | // }else if let data = response.data{ |
| | | // LogInfo("返回数据:\(data)") |
| | | // ob.onNext(data) |
| | | // } |
| | | // ob.onCompleted() |
| | | // } |
| | | // return Disposables.create{} |
| | | // } |
| | | // } |
| | | // |
| | | // /// 带code请求的 |
| | | // /// - Parameters: |
| | | // /// - params: <#params description#> |
| | | // /// - method: <#method description#> |
| | | // /// - progress: <#progress description#> |
| | | // /// - Returns: <#description#> |
| | | // class func requestCode<T: HandyJSON>(params: ParamsAppender,method: HTTPMethod,progress: Bool = true) -> Observable<BaseResponse<T>>{ |
| | | // return Observable<BaseResponse<T>>.create{ ob in |
| | | // if progress { |
| | | // SVProgressHUD.show() |
| | | // } |
| | | // sharedSessionManager.request(params.url.absoluteString, method: method, parameters: |
| | | // params.done(),encoding: URLEncoding.default).validate().responseData{response in |
| | | // LogInfo("请求地址:\(params.url)") |
| | | // LogInfo("请求参数:\(params.params)") |
| | | // if response.error != nil { |
| | | // SVProgressHUD.dismiss() |
| | | // LogInfo("\(response.error!)") |
| | | // ob.onError(response.error!) |
| | | // }else if let data = response.data,let jsonString = String(data: data, encoding: String.Encoding.utf8){ |
| | | // |
| | | // SVProgressHUD.dismiss() |
| | | // LogInfo("返回数据:\(jsonString)") |
| | | // if let next = BaseResponse<T>.deserialize(from: jsonString){ |
| | | // ob.onNext(next) |
| | | // }else{ |
| | | // SVProgressHUD.dismiss() |
| | | // // alert(msg: "请求失败") |
| | | // LogInfo("error") |
| | | // } |
| | | // }else{ |
| | | // SVProgressHUD.dismiss() |
| | | // // alert(msg: "请求失败") |
| | | // LogInfo("Netrequest-Tag:No data") |
| | | // } |
| | | // ob.onCompleted() |
| | | // } |
| | | // return Disposables.create{} |
| | | // } |
| | | // } |
| | | // /// 上传 |
| | | // /// - Parameter params: <#params description#> |
| | | // class func upload<T: HandyJSON>(params: ParamsAppender) -> Observable<BaseResponse<T>> { |
| | | // return Observable<BaseResponse<T>>.create{ob in |
| | | // // let hud = MBProgressHUD.showAdded(to: screnDelegate!.window!, animated: true) |
| | | // // hud.bezelView.style = .solidColor |
| | | // // hud.contentColor = .white |
| | | // // hud.bezelView.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.8) |
| | | // // hud.bezelView.color = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.8) |
| | | // // hud.removeFromSuperViewOnHide = true |
| | | // |
| | | // var headers = HTTPHeaders() |
| | | // // if let token = UserViewModel.getUserInfo()?.token { |
| | | // // headers.add(name: "Authorization", value: "Bearer" + " " + token) |
| | | // // LogInfo("USER_token:\(token)") |
| | | // // } |
| | | // |
| | | // |
| | | // AF.upload(multipartFormData: { data in |
| | | // let p = params |
| | | // LogInfo("Netrequest-Upload-Starting.") |
| | | // for key in p.params{ |
| | | // if let d = key.value as? Data { |
| | | // LogInfo("Netrequest-Upload-Appending-Data: Length = \(d.count) bytes") |
| | | // |
| | | // data.append(d, withName: key.key, fileName: "\(Date().timeIntervalSince1970).png", mimeType: "image/png") |
| | | // } else if let url = key.value as? URL { |
| | | // LogInfo("Netrequest-Upload-Appending-Data: Url = \(url)") |
| | | // data.append(url, withName: key.key) |
| | | // } |
| | | // } |
| | | // }, to: params.url, method: .post, headers: headers) .uploadProgress(queue: .main, closure: { progress in |
| | | // // progressClosure(progress.fractionCompleted) |
| | | // }).responseJSON(completionHandler: { data in |
| | | // print("upload finished: \(data)") |
| | | // |
| | | // }).response { (response) in |
| | | // |
| | | // // hud.hide(animated: true) |
| | | // switch response.result { |
| | | // case .success(let dataObj): |
| | | // // alert(msg: "上传成功") |
| | | // let jsonString = String(data: dataObj ?? Data(), encoding: String.Encoding.utf8) |
| | | // if let next = BaseResponse<T>.deserialize(from: jsonString){ |
| | | // ob.onNext(next) |
| | | // } |
| | | // case .failure(let err): |
| | | // alert(msg: "上传失败") |
| | | // print("upload err: \(err)") |
| | | // } |
| | | // |
| | | // } |
| | | // return Disposables.create{ |
| | | // |
| | | // } |
| | | // |
| | | // } |
| | | // } |
| | | } |
| | | } |
| | | extension Dictionary { |
| | | mutating func append(dict: Dictionary) { |
| | | dict.forEach { (key, value) in |
| | | self.updateValue(value, forKey: key) |
| | | } |
| | | } |
| | | mutating func append(dict: Dictionary) { |
| | | dict.forEach { (key, value) in |
| | | self.updateValue(value, forKey: key) |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | func createError(text:String,code:Int)->AFError{ |
| | | return AFError.createURLRequestFailed(error: NSError(domain: text, code: code)) |
| | | return AFError.createURLRequestFailed(error: NSError(domain: text, code: code)) |
| | | } |