123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- //
- // NetworkManager.swift
- // iOSFirst
- //
- // Created by 孙宇峰 on 2023/2/22.
- //
-
- import Foundation
- import Moya
- import Alamofire
- import HandyJSON
- import RxSwift
- import SwiftyJSON
-
- /// 超时时长
- private var requestTimeOut:Double = 30
- ///endpointClosure
- public let myEndpointClosure = { (target: TargetType) -> Endpoint in
- ///这里的endpointClosure和网上其他实现有些不太一样。
- ///主要是为了解决URL带有?无法请求正确的链接地址的bug
- let url = target.baseURL.absoluteString + target.path
- var endpoint = Endpoint(
- url: url,
- sampleResponseClosure: { .networkResponse(200, target.sampleData) },
- method: target.method,
- task: target.task,
- httpHeaderFields: target.headers
- )
- switch target {
- default:
- requestTimeOut = 30//设置默认的超时时长
- return endpoint
- }
- }
-
- public let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
- do {
- var request = try endpoint.urlRequest()
- //设置请求时长
- request.timeoutInterval = requestTimeOut
- // 打印请求参数
- if let requestData = request.httpBody {
- log.info("\(request.url!)"+"\n"+"\(request.httpMethod ?? "")"+"发送参数"+"\(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "")")
- }else{
- log.info("\(request.url!)"+"\(String(describing: request.httpMethod))")
- }
- if let header = request.allHTTPHeaderFields {
- log.info("请求头内容\(header)")
- }
- done(.success(request))
- } catch {
- done(.failure(MoyaError.underlying(error, nil)))
- }
- }
-
-
- /// NetworkActivityPlugin插件用来监听网络请求
- public let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
-
- log.info("networkPlugin \(changeType)")
- //targetType 是当前请求的基本信息
- switch(changeType){
- case .began:
- log.info("开始请求网络")
-
- case .ended:
- log.info("结束")
- }
- }
-
-
- // https://github.com/Moya/Moya/blob/master/docs/Providers.md 参数使用说明
- //stubClosure 用来延时发送网络请求
-
- final class TdwMoyaPlugin: PluginType {
-
- public func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
- var request = request
- request.addValue("token值", forHTTPHeaderField: "token名字")
- return request
- }
- }
-
- /*
- Moya默认有4个插件分别为:
- AccessTokenPlugin 管理AccessToken的插件
- CredentialsPlugin 管理认证的插件
- NetworkActivityPlugin 管理网络状态的插件
- NetworkLoggerPlugin 管理网络log的插件
- */
- // 插件,实现pluginType可以实现在网络请求前转菊花,请求完成结束转菊花,或者写日志等功能
- struct NetworkPlugin: PluginType {
- let userDefault=UserDefaults.standard
-
- /// Called to modify a request before sending.(可进行数据加密等)
- func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
- var mRequest = request
- let key = "XINGHUOLIAOYUAN7"
- // let jsonString = AESEncryptor.aes_encrypt(request.httpBody!.toHexString(),aes_key: key)
- //TODO AES加密相关
- let jsonString = aesEncryptData(request.httpBody,key.data(using: .utf8))
-
- // let jsonString = AESEncryptor.aes_encrypt(request.httpBody!.toHexString(),aes_key: key)
- //TODO AES加密相关
- // let jsonString = aesEncryptString(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "",key)
- mRequest.httpBody = jsonString?.toHexString().data(using: .utf8)
- print("""
- #############↓网络请求参数↓#################
- \(target.baseURL)\(target.path)
- \(jsonString?.toHexString() ?? "无参数")
- #############↑网络请求参数↑#################
- """)
- let userinfo = NSKeyedUnarchiver.unarchiveObject(with: userDefault.object(forKey: "userinfo") as! Data ) as! LoginUserInfo
- if(userDefault.bool(forKey: "isLogin")){
- let bool = userDefault.bool(forKey: "isLogin")
- log.info("prepare\(bool)")
- let cc = userinfo.cloudcode == nil ? "" : userinfo.cloudcode ?? ""
- let id = userinfo.userid == nil ? "" : String(userinfo.userid ?? -1)
- let tv = (userinfo.token_value == nil ? "" : userinfo.token_value) ?? ""
- let key = "\(cc)_\(id)_p_phone_t"
- mRequest.addValue(key, forHTTPHeaderField: "Token_Key")
- mRequest.addValue(tv, forHTTPHeaderField: "Token_Value")
- }
- if let header = mRequest.allHTTPHeaderFields {
- log.info("请求头内容\(header)")
- }
- return mRequest
- }
-
- /// Called immediately before a request is sent over the network (or stubbed).(可进行网络等待,loading等)
- func willSend(_ request: RequestType, target: TargetType) {
- // guard let target = target as? AccountService else { return }
- // let jsonData = try? JSONSerialization.data(withJSONObject: target.parameters, options: .prettyPrinted)
- // let jsonString = String(data: jsonData ?? Data(), encoding: .utf8)
- // print("""
- // #############↓网络请求参数↓#################
- // \(target.baseURL)\(target.path)
- // \(jsonString ?? "无参数")
- // #############↑网络请求参数↑#################
- // """)
-
- }
-
- /// Called after a response has been received, but before the MoyaProvider has invoked its completion handler.(loading结束等)
- func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
-
- }
-
- /// Called to modify a result before completion.(可进行数据解密等)
- func process(_ result: Result<Response, MoyaError>, target: TargetType) -> Result<Response, MoyaError> {
- return result
- }
-
- }
-
-
-
- let accountProvider = MoyaProvider<AccountService>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
-
- public class NetworkManaer{
-
- /// 使用Moya的请求封装
- ///
- /// - Parameters:
- /// - target: 请求API,TargetType里的枚举值
- /// - success: 成功的回调
- /// - error: 连接服务器成功但是数据获取失败
- /// - failure: 连接服务器失败
- ///
- public class func request<T: TargetType,U: HandyJSON>(_ target: T, success: @escaping((U) -> Void), failure: ((Int?, String) ->Void)?) {
- let provider = MoyaProvider<T>(
- endpointClosure: myEndpointClosure,
- requestClosure: requestClosure,
- plugins: [networkPlugin,NetworkPlugin.init()],
- trackInflights: false
- // networkLoggerPlugin
- )
-
- provider.request(target) { result in
- switch result {
- case let .success(response):
- // let json = try? response.mapString()
- // let responseObject = try? response.mapJSON()
- // JhLog( responseObject ?? "" );
- do {
- // *********** 这里可以统一处理错误码,弹出提示信息 ***********
- let resObject = try? response.mapJSON()
- log.info("网络请求到的数据是:\(resObject)")
- let responseObject = JSON(resObject ?? "")
- let code = responseObject["code"].intValue
- let msg = String(describing: responseObject["msg"])
- switch (code) {
- case 0 :
- let dictionary=responseObject["obj"].dictionaryObject
- let responseData=U.deserialize(from: dictionary)
- log.info(responseData?.toJSONString())
- // 数据返回正确
- success(responseData!)
- case 2:
- let userDefault=UserDefaults.standard
- userDefault.setValue(false, forKey: "isLogin")
- // 请重新登录
- failure!(code,msg)
- alertLogin(msg)
- default:
- // 其他错误
- failureHandle(failure: failure, stateCode: code, message: msg)
- }
- }
- case let .failure(error):
- let statusCode = error.response?.statusCode ?? 1000
- let message = "请求出错,错误码:" + String(statusCode)
- log.error(message)
- failureHandle(failure: failure, stateCode: statusCode, message: error.errorDescription ?? message)
- }
- }
-
- // 错误处理 - 弹出错误信息
- func failureHandle(failure: ((Int?, String) ->Void)? , stateCode: Int?, message: String) {
- // Alert.show(type: .error, text: message)
- //弹出错误信息
- failure?(stateCode ,message)
- }
-
- // 登录弹窗 - 弹出是否需要登录的窗口
- func alertLogin(_ title: String?) {
- // TODO: 跳转到登录页的操作:
- }
-
- }
-
- // MARK: - 打印日志
- // static let networkLoggerPlugin = NetworkLoggerPlugin(verbose: true, cURL: true, requestDataFormatter: { data -> String in
- // return String(data: data, encoding: .utf8) ?? ""
- // }) { data -> (Data) in
- // do {
- // let dataAsJSON = try JSONSerialization.jsonObject(with: data)
- // let prettyData = try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
- // return prettyData
- // } catch {
- // return data
- // }
- // }
- }
-
|