// // KMRequestServerManager.swift // PDF Reader Pro // // Created by lizhe on 2023/2/22. // import Cocoa enum KMRequestServerErrorCodeType: Int, CaseIterable { case unknown = 0 //未知 case correct = 200 //正确 case EXCEPTION_MSG_IMAGE_CODE_ERROR = 301 case EXCEPTION_MSG_USER_NOT_FOUND = 302 case EXCEPTION_MSG_TOKEN_IS_INVALID = 304 case EXCEPTION_MSG_DEVICE_NUM_MAX = 305 case EXCEPTION_MSG_USER_NOT_LOGIN = 306 case EXCEPTION_MSG_GET_CODE_FAIL = 307 case EXCEPTION_MSG_GET_TOKEN_FAIL = 308 case EMAIL_VERIFY_CODE_KEY_ERROR = 309 case EMAIL_REGISTER_ERROR = 310 case EXCEPTION_MSG_PASSWORD_ERROR = 311 case EXCEPTION_MSG_CODE_ACTION_ERROR = 312 case EXCEPTION_MSG_CODE_SEND_ERROR = 313 case EXCEPTION_MAIL_CODE_SEND_ERROR = 314 case VERIFY_CODE_SEND_TOO_QUICKLY = 315 case EXCEPTION_MSG_EMAIL_EXIST = 316 case EXCEPTION_MSG_EMAIL_NOT_REGISTER = 317 case EXCEPTION_MSG_EMAIL_LOGOUT_ING = 318 case EXCEPTION_MSG_EMAIL_INVALID = 319 case EXCEPTION_MSG_PASSWORD_NOT_INCONSISTENT = 320 case EXCEPTION_MSG_PASSWORD_SIZE_MIN = 321 case EXCEPTION_MSG_PASSWORD_SIZE_MAX = 322 case EXCEPTION_MSG_PLEASE_ADD_AUTH_CONFIG = 323 case EXCEPTION_MSG_USER_SUBSCRIPTION_IN_PROGRESS = 324 case EXCEPTION_MSG_USER_TRAIL_IN_PROGRESS = 325 case EXCEPTION_TIME_TRANSFER_ERROR = 326 case EXCEPTION_MSG_PASSWORD_CONTAIN_EMRTY = 327 case EXCEPTION_MSG_CREATE_ORDER_PARAMETER = 328//,"支付方式异常"), case EXCEPTION_MSG_EVENT_IS_CURRENTLY_NOT_SUPPORTED = 329 //, "当前事件暂不支持"), case EXCEPTION_MSG_THE_ACCOUNT_IS_ALREADY_LOGGED_IN_ON_OTHER_DEVICES = 330//, "账号已在其他设备登录"), case EXCEPTION_MSG_ABNORMAL_USER_STATUS = 331 //,"当前邮箱已被停用或者处于注销中状态"), case EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_FAILED = 332 //"AppStore票据验证失败"), case EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_NEED_TO_RETRY = 333// "AppStore票据验证需要重试"), case EXCEPTION_MSG_REPEAT_SUBSCRIPTION = 334 //"用户已订阅该产品" case EXCEPTION_MSG_RESTORING_PURCHASES_IS_NOT_CURRENTLY_SUPPORTED = 335 //"恢复购买暂不支持"), case EXCEPTION_MSG_USER_TRANSACTION_CANCELED_OR_FAILED = 336 //"用户交易取消或失败") case EXCEPTION_MSG_CURRENT_ORDER_NOT_RECORDED = 337 //"当前订单未记录,请稍后重试"), case EXCEPTION_MSG_THE_SAME_USER = 338//"同一用户,无需处理"), case EXCEPTION_MSG_THIRD_PAY_ID_ILLEGAL = 339//"thirdPayId非法"), case EXCEPTION_MSG_ORDER_DOES_NOT_EXIST = 340// "订单不存在"), case EXCEPTION_MSG_THE_ORDER_STATUS_IS_ABNORMAL = 341// "订单状态异常"), case EXCEPTION_MSG_TRANSACTION_ID_REPEAT = 342 //"transactionId重复"), case EMAIL_VERIFY_CODE_KEY_ERROR2 = 700 static func typeOfMessage(type: KMRequestServerErrorCodeType?) -> String { var result: String = "" switch type { case .EXCEPTION_MSG_IMAGE_CODE_ERROR: result = "Graphic verification code error" case .EXCEPTION_MSG_USER_NOT_FOUND: result = "Email address is not registered" case .EXCEPTION_MSG_TOKEN_IS_INVALID: result = "Invalid token or token has expired" case .EXCEPTION_MSG_DEVICE_NUM_MAX: result = "You have reached the maximum number of devices, please log out of other devices and log in again." case .EXCEPTION_MSG_USER_NOT_LOGIN: result = "User is not logged in. Please log in and try again." case .EXCEPTION_MSG_GET_CODE_FAIL: result = "Failed to obtain authorization code" case .EXCEPTION_MSG_GET_TOKEN_FAIL: result = "Failed to obtain token" case .EMAIL_VERIFY_CODE_KEY_ERROR: result = "Email code error" case .EMAIL_REGISTER_ERROR: result = "Register error" case .EXCEPTION_MSG_PASSWORD_ERROR: result = "Wrong password. You can check whether the letter is uppercase or lowercase." case .EXCEPTION_MSG_CODE_ACTION_ERROR: result = "Incorrect code" case .EXCEPTION_MSG_CODE_SEND_ERROR: result = "Code send error" case .EXCEPTION_MAIL_CODE_SEND_ERROR: result = "Mail send error" case .VERIFY_CODE_SEND_TOO_QUICKLY: result = "Enter an existing verification code" //result = "Too many codes sent, please try again later." case .EXCEPTION_MSG_EMAIL_EXIST: result = "This email is already registered, please log in." case .EXCEPTION_MSG_EMAIL_NOT_REGISTER: result = "This account is not registered, click Sign Up to create a new account." case .EXCEPTION_MSG_EMAIL_LOGOUT_ING: result = "Your account is currently being canceled and cannot be logged in. If you have any questions, please contact customer service." case .EXCEPTION_MSG_EMAIL_INVALID: result = "Please enter the correct email format" case .EXCEPTION_MSG_PASSWORD_NOT_INCONSISTENT: result = "Wrong password. You can check whether the letter is uppercase or lowercase." //result = "Passwords are different. Please re-enter them." case .EXCEPTION_MSG_PASSWORD_SIZE_MIN: result = "Password must be 6-24 characters" //result = "At least 6 characters" case .EXCEPTION_MSG_PASSWORD_SIZE_MAX: result = "Password must be 6-24 characters" //result = "Up to 24 characters" case .EXCEPTION_MSG_PLEASE_ADD_AUTH_CONFIG: result = "Please add auth config" case .EXCEPTION_MSG_USER_SUBSCRIPTION_IN_PROGRESS: result = "You are still in the subscription and cannot cancel account. Please click Cancel Account after the subscription period ends." case .EXCEPTION_MSG_USER_TRAIL_IN_PROGRESS: result = "You are still in the subscription and cannot cancel account. Please click Cancel Account after the trial expired." case .EXCEPTION_TIME_TRANSFER_ERROR: result = "Time conversion failure" case .EMAIL_VERIFY_CODE_KEY_ERROR2: result = "Email code error" case .EXCEPTION_MSG_PASSWORD_CONTAIN_EMRTY: result = "Spaces are not allowed in password" //result = "The password cannot contain Spaces" case .EXCEPTION_MSG_CREATE_ORDER_PARAMETER: result = "Abnormal payment method" case .EXCEPTION_MSG_EVENT_IS_CURRENTLY_NOT_SUPPORTED: result = "The current event is not supported" case .EXCEPTION_MSG_THE_ACCOUNT_IS_ALREADY_LOGGED_IN_ON_OTHER_DEVICES: result = "Your account has been logged into another device." case .EXCEPTION_MSG_ABNORMAL_USER_STATUS: result = "This email account is no longer available or canceled." case .EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_FAILED: result = "AppStore receipt verification failed." case .EXCEPTION_MSG_APP_STORE_TICKET_VALIDATION_NEED_TO_RETRY: result = "Please re-verify the receipt." case .EXCEPTION_MSG_REPEAT_SUBSCRIPTION: result = "Users have already subscribed to PDF Reader Pro." case .EXCEPTION_MSG_RESTORING_PURCHASES_IS_NOT_CURRENTLY_SUPPORTED: result = "Restoring purchases may not work due to the temporary problem with the App Store system." case .EXCEPTION_MSG_USER_TRANSACTION_CANCELED_OR_FAILED: result = "Payment Cancelled or Failed." case .EXCEPTION_MSG_CURRENT_ORDER_NOT_RECORDED: result = "The current order is not recorded, please try again later." case .EXCEPTION_MSG_THE_SAME_USER: result = "Same user, no processing required." case .EXCEPTION_MSG_THIRD_PAY_ID_ILLEGAL: result = "ThirdPayID illegal" case .EXCEPTION_MSG_ORDER_DOES_NOT_EXIST: result = "This order does not exist." case .EXCEPTION_MSG_THE_ORDER_STATUS_IS_ABNORMAL: result = "This order status is abnormal." case .EXCEPTION_MSG_TRANSACTION_ID_REPEAT: result = "Duplicate TransactionID" case .unknown: result = "" case .correct: result = "" default: result = "Network error" } return result } } enum KMVerifyCodeType: String, CaseIterable { case unknown = "" // case register = "user_register" // 注册 case logOff = "user_log_off" //注销 case resetPassword = "user_reset_password" //重置密码 } enum KMVerifyEmailType: String, CaseIterable { case login = "1" // 登录 case register = "2" //注册 } struct Result { var result: NSDictionary = [:] var message: String = "" var code : Int = 200 var error: NSError? } typealias KMRequestServerComplete = (_ success: Bool, _ result: Result?) -> Void typealias KMRequestServerDateComplete = (_ success: Bool, _ result: NSDictionary?) -> Void class KMRequestServerManager: NSObject { static let manager = KMRequestServerManager() var loginAlert: NSAlert? = nil } //MARK: - 会员 extension KMRequestServerManager { /** @abstract 获取验证码 @param verifyCodeType 验证入口类型 @param email 邮箱 */ func getVerifyCode(verifyCodeType: KMVerifyCodeType, email: String, complete: @escaping KMRequestServerComplete) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/getVerifyCode" let params: [String: Any] = ["action": verifyCodeType.rawValue, "appId": "16", "receiver": email, "type": "0"] KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } /** @abstract 注册 @param userName 用户账号(邮箱) @param verifyCode 验证码 */ func register(userName: String, password: String, verifyCode: String, complete: @escaping (_ success: Bool, _ requestData: KMLightMemberToken?, _ result: Result) -> Void) { let uuid: String = GetHardwareUUID() ?? "" let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/emailRegister" let params: [String: Any] = ["appId": "16", "deviceSign": uuid, "password": password, "platformType": "0", "username": userName, "verifyCode": verifyCode, "model": "Mac"] KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] task, responseObject, error in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { //解析数据 KMLightMemberToken.parseData(data: result.result) { data in //登录成功 KMLightMemberManager.manager.logIn() complete(true, data, result) } } else { complete(false, nil, result) } } } /** @abstract 注销 @param verifyCode 验证码 */ func logOff(verifyCode: String, complete: @escaping KMRequestServerComplete) { let token: String = KMLightMemberManager.manager.token.access_token if token == "" { return } var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/logOffForUser" // let params = ["code":verifyCode] urlString = urlString + (NSString(format: "?code=%@&appId=%@", verifyCode, "16") as String) KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { //登出 KMLightMemberCache.cache.clean() KMLightMemberManager.manager.logOut() complete(true, result) } else { complete(false, result) } } } /** @abstract 登录 @param email 邮箱 @param password 密码 */ func login(email: String, password: String, complete: @escaping (_ success: Bool, _ requestData: KMLightMemberToken?, _ result: Result?) -> Void) { var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/emailLogin" let uuid: String = GetHardwareUUID() ?? "" // let params: [String: String] = ["appId": "16", // "deviceSign": uuid, // "email": email, // "password": password, // "platformType": "0"] urlString = urlString + (NSString(format: "?appId=16&deviceSign=%@&email=%@&password=%@&platformType=0&model=%@", uuid, email, password, "Mac") as String) KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { //解析数据 KMLightMemberToken.parseData(data: result.result) { data in //登录成功 KMLightMemberManager.manager.logIn() complete(true, data, nil) } } else { complete(false, nil, result) } } } /** @abstract 登出 */ func logout(complete: @escaping KMRequestServerComplete) { let token: String = KMLightMemberManager.manager.token.access_token if token == "" { return } let uuid: String = GetHardwareUUID() ?? "" var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/logout" // let params: [String: Any] = ["deviceSign": uuid, // "appId": "16"] urlString = urlString + (NSString(format: "?appId=16&deviceSign=%@", uuid) as String) KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in //登出成功 let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { //登出 KMLightMemberManager.manager.logOut() complete(true, result) } else { complete(false, result) } } } /** @abstract 修改密码 @param url 源文件url @param data 数据 @retrun document */ func resetPassword(account: String, firstPassword: String, secondPassword: String, verifyCode: String, complete: @escaping KMRequestServerComplete) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/resetPassword" let params: [String: Any] = ["account": account, "appId": "16", "firstPassword": firstPassword, "platformType": "0", "secondPassword": secondPassword, "verifyCode": verifyCode] KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } /** @abstract 获取用户信息 */ func getUserInfo(complete: @escaping (_ success: Bool, _ data: KMLightMemberUserInfo?, _ result: Result?, _ isLocal: Bool) -> Void) { let token: String = KMLightMemberManager.manager.token.access_token if token == "" { complete(false , nil, Result(message: "token 不存在", code: 304), false) return } //先拿缓存数据 再请求新数据 let cacheData = KMLightMemberCache.cache.readData() if cacheData.count != 0 { KMLightMemberUserInfo.parseData(data: cacheData, needSave: false) { data in complete(true ,data, nil, true) } } let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/me" KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: nil) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { //解析数据 KMLightMemberUserInfo.parseData(data: responseObject as! NSDictionary) { data in KMLightMemberManager.manager.reloadUserInfo() complete(true, data, nil, false) } } else { complete(false, nil, result, false) } } } func getUserInfo2() async throws -> (Bool, Result) { let token: String = KMLightMemberManager.manager.token.access_token if token == "" { return (false, Result()) } if #available(macOS 10.15, *) { return try await withCheckedThrowingContinuation { continuation in let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/user/me" KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: nil) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) DispatchQueue.main.async { if result.code == 200 { //解析数据 KMLightMemberUserInfo.parseData(data: responseObject as! NSDictionary) { data in KMLightMemberManager.manager.reloadUserInfo() continuation.resume(returning: (true, result)) } } else { continuation.resume(returning: (false, result)) } } } } } else { // Fallback on earlier versions return (true, Result()) } } /** @abstract 验证码验证是否正确 @param account 用户账号(邮箱) @param verifyCode 验证码 @retrun verifyCodeType 验证码入口类型 */ func verificationCode(account: String, verifyCode: String, verifyCodeType: KMVerifyCodeType, complete: @escaping KMRequestServerComplete) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/isEmailCodeValid" let params: [String: Any] = ["account": account, "code": verifyCode, "type": verifyCodeType.rawValue, "appId": "16"] KMRequestServer.requestServer.request(urlString: urlString, method: .get, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } /** @abstract 邮箱验证 @param account 用户账号(邮箱) @param verifyCodeType 验证码 @retrun verifyCodeType 验证码入口类型 */ func verificationEmail(userName: String, verifyEmailType: KMVerifyEmailType, complete: @escaping KMRequestServerComplete) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/validUser" let params: [String: Any] = ["appId": "16", "username": userName, "platformType": "0", "validType": verifyEmailType.rawValue] KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } func getDeviceRetensionCoupon(complete: @escaping KMRequestServerDateComplete) { let urlString = AIInfoConfig().aiActionURL + "api/devices/getRetensionCoupon" let params: [String:Any] = ["unique_sn": self.uuid(), "platform": "DMG"] KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 && result.error != nil && result.message != "unknown error" { complete(true, responseObject as? NSDictionary) } else { complete(false, responseObject as? NSDictionary) } } } //MARK: Private Method private func uuid() -> String { return GetHardwareUUID()! } } //MARK: - 订阅 extension KMRequestServerManager { //创建订单 func createOrder(productId: String, userId: String, complete: @escaping (_ success: Bool, _ orderId: String?, _ result: Result?) -> Void) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreCreateOrder" let params: [String: Any] = ["productId": productId, "paymentMethod": "APPLE_PAY", "userId": userId, "appId": "16"] let token: String = KMLightMemberManager.manager.token.access_token if token == "" { complete(false, "", Result()) return } KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result.result["id"] as! String, result) } else { complete(false, "", result) } } } // func restore(productId: String, userId: String, complete: @escaping (_ success: Bool, _ orderId: String?, _ result: Result?) -> Void) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreCreateOrder" let params: [String: Any] = ["productId": productId, "paymentMethod": "APPLE_PAY", "userId": userId, "appId": "16"] let token: String = KMLightMemberManager.manager.token.access_token if token == "" { complete(false, "", Result()) return } KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result.result["id"] as! String, result) } else { complete(false, "", result) } } } func parseVerification(applePayProductId: String, orderId: String, receipt: String, restore: Int = 0, complete: @escaping KMRequestServerComplete) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreOrderSucceed" let params: [String: Any] = ["applePayProductId": applePayProductId, "orderId": orderId, "receipt": receipt, "restore": restore] KMPrint("二次验证上传数据:\(params)") let token: String = KMLightMemberManager.manager.token.access_token if token == "" { complete(false, Result()) return } KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } func checkDeviceStatus(complete: @escaping KMRequestServerComplete) { var urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-sso/auth/checkDeviceStatus" let uuid: String = GetHardwareUUID() ?? "" // let params: [String: Any] = ["appId": "16", // "deviceSign": uuid] urlString = urlString + (NSString(format: "?appId=16&deviceSign=%@", uuid) as String) KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: nil) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } func appStoreEquityVerification(applePayProductId: String, receipt: String, complete: @escaping KMRequestServerComplete) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreEquityVerification" let params: [String: Any] = ["applePayProductId": applePayProductId, "paymentMethod": "APPLE_PAY", "receipt": receipt ] KMPrint("票据信息上传数据:\(params)") var token: String = KMLightMemberManager.manager.token.access_token if token == "" { complete(false, Result()) return } KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } func appStoreBuyComplete(applePayProductId: String, receipt: String, isPurchase: Bool = false, complete: @escaping KMRequestServerComplete) { let urlString = KMLightMemberManager.manager.config.kServerURL + "/pdf-office-website/pay/appStoreBuyComplete" let userId = KMLightMemberManager.manager.info.id let params: [String: Any] = ["applePayProductId": applePayProductId, "paymentMethod": "APPLE_PAY", "receipt": receipt, "appId": "16", "productId": "21", "userId": userId ] KMPrint("票据信息上传数据:\(params)") KMRequestServer.requestServer.request(urlString: urlString, method: .post, params: params) { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { [unowned self] (task, responseObject, error) in let result = self.dealData(responseObject: responseObject as? NSDictionary, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } } } //MARK: - AI extension KMRequestServerManager { /** @abstract 翻译上传 @param file 文件路径 @param version 版本号 */ func aiTranslationFileUpload(file: String, version: String, complete: @escaping KMRequestServerComplete) { let infoDictionary = Bundle .main.infoDictionary! let userInfo = KMLightMemberCache.cache.readData(type: .info) let majorVersion = infoDictionary["CFBundleShortVersionString"] let urlString = KMAIServerConfig().aiTranslationURL + "/v1/translate/fileUpload" let fileData = FileManager.default.contents(atPath: file) let params: [String: Any] = ["file": fileData, "projectId": "2", "version": version, "userId": userInfo["id"] as Any] KMRequestServer.requestServer.aiTranslation(urlString: urlString, params: params) { formData in let fileURL = URL(fileURLWithPath: file) try? formData.appendPart(withFileURL: fileURL, name: "file", fileName: fileURL.lastPathComponent, mimeType: "application/octet-stream") } requestSerializer: { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { task, responseObject, error in if responseObject != nil { let data: NSDictionary = responseObject!["data"] as? NSDictionary ?? [:] let code: String = responseObject!["code"] as? String ?? "06005" let message: String = responseObject!["msg"] as? String ?? "unknown error" let error = NSError(domain: message, code: Int(code)!) let result = Result(result: data,message: message,code: Int(code)!, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } else { let error = NSError(domain: "unknown error", code: 404) let result = Result(result: [:],message: "unknown error",code: 404, error: error) complete(false, result) } } } /** @abstract 文件翻译 @param fileKey 文件Key @param from 初始语言 @param to 结束语言 @param version 应用版本 */ func aiTranslationFileTranslateHandle(fileKey: String, from: String, to: String, version: String, complete: @escaping KMRequestServerComplete) { let infoDictionary = Bundle .main.infoDictionary! let userInfo = KMLightMemberCache.cache.readData(type: .info) let majorVersion = infoDictionary["CFBundleShortVersionString"] let urlString = KMAIServerConfig().aiTranslationURL + "/v1/translate/fileTranslateHandle" if userInfo.count > 0 { var semaphore = DispatchSemaphore (value: 0) let parameters = String(format: "{\r\n \"fileKey\": \"%@\",\r\n \"from\": \"%@\",\r\n \"to\": \"%@\",\r\n \"version\": \"%@\",\r\n \"projectId\": \"2\",\r\n \"userId\": \"%@\"\r\n}", fileKey, from, to, version, userInfo["id"] as! String) let postData = parameters.data(using: .utf8) var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity) request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpMethod = "POST" request.httpBody = postData let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data else { KMPrint(String(describing: error)) semaphore.signal() return } let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary ?? [:] if jsonObject != nil { let data1: NSDictionary = jsonObject!["data"] as? NSDictionary ?? [:] let code: String = jsonObject!["code"] as? String ?? "06005" let message: String = jsonObject!["msg"] as? String ?? "unknown error" let error = NSError(domain: message, code: Int(code)!) let result = Result(result: data1,message: message,code: Int(code)!, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } else { let error = NSError(domain: "unknown error", code: 404) let result = Result(result: [:],message: "unknown error",code: 404, error: error) complete(false, result) } semaphore.signal() } task.resume() semaphore.wait() } } /** @abstract 内容翻译 @param q 选中 @param from 初始语言 @param to 结束语言 @param version 应用版本 */ func aiTranslationTextTrans(q: String, from: String, to: String, version: String, complete: @escaping KMRequestServerComplete) { let infoDictionary = Bundle .main.infoDictionary! let userInfo = KMLightMemberCache.cache.readData(type: .info) let majorVersion = infoDictionary["CFBundleShortVersionString"] let urlString = KMAIServerConfig().aiTranslationURL + "/v1/translate/textTrans" if userInfo.count > 0 { var semaphore = DispatchSemaphore (value: 0) var escapedString = q if q.contains("\n") || q.contains("\r") { escapedString = q.replacingOccurrences(of: "\n", with: "\\n") escapedString = escapedString.replacingOccurrences(of: "\r", with: "\\r") } else if q.contains("\u{2028}") { } escapedString = String(data: escapedString.data(using: .utf8)!, encoding: .utf8)! // let escapedString = String(data: q.data(using: .utf8)!, encoding: .utf8)! let parameters = String(format: "{\r\n \"q\": \"%@\",\r\n \"from\": \"%@\",\r\n \"to\": \"%@\",\r\n \"version\": \"%@\",\r\n \"projectId\": \"2\",\r\n \"userId\": \"%@\"\r\n}", escapedString, from, to, version, userInfo["id"] as! String) let postData = parameters.data(using: .utf8) var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity) request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpMethod = "POST" request.httpBody = postData let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data else { KMPrint(String(describing: error)) semaphore.signal() return } let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary ?? [:] if jsonObject != nil { let data1: NSDictionary = jsonObject!["data"] as? NSDictionary ?? [:] let code: String = jsonObject!["code"] as? String ?? "06005" let message: String = jsonObject!["msg"] as? String ?? "unknown error" let error = NSError(domain: message, code: Int(code)!) let result = Result(result: data1,message: message,code: Int(code)!, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } else { let error = NSError(domain: "unknown error", code: 404) let result = Result(result: [:],message: "unknown error",code: 404, error: error) complete(false, result) } semaphore.signal() } task.resume() semaphore.wait() } } /** @abstract重写 & 纠错 @param content 内容 @param version 版本号 */ func aiRewriting(content: String, version: String, state: KMAIRewritingState, complete: @escaping KMRequestServerComplete) { let userInfo = KMLightMemberCache.cache.readData(type: .info) var urlString = KMAIServerConfig().aiRewritingURL + "/api/rewrite" // if state == .AIErrorCorrection { // urlString = KMAIServerConfig().aiRewritingURL + "/api/correct-typos" // } let params: [String: Any] = ["project_id": 2, "content": content, "version": version, "user_id": userInfo["id"] as Any] KMRequestServer.requestServer.aiRewriting(urlString: urlString, params: params) { formData in } requestSerializer: { requestSerializer in requestSerializer.setValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") } completion: { task, responseObject, error in if responseObject != nil { let data: NSDictionary = responseObject!["data"] as? NSDictionary ?? [:] let code: String = responseObject!["code"] as? String ?? "06005" let message: String = responseObject!["message"] as? String ?? "unknown error" let error = NSError(domain: message, code: Int(code)!) let result = Result(result: data,message: message,code: Int(code)!, error: error) if result.code == 200 { complete(true, result) } else { complete(false, result) } } else { let error = NSError(domain: "unknown error", code: 404) let result = Result(result: [:],message: "unknown error",code: 404, error: error) complete(false, result) } } } } //MARK: - 数据处理 extension KMRequestServerManager { func dealData(responseObject: NSDictionary?, error: NSError?) -> Result { var dic: NSDictionary = [:] if (error == nil && responseObject != nil) { dic = responseObject! } else { var info = responseObject if (error != nil) { let data = error!.userInfo["com.alamofire.serialization.response.error.data"] if (data != nil) { info = try?JSONSerialization.jsonObject(with: data as? Data ?? Data(), options: JSONSerialization.ReadingOptions.mutableLeaves) as? NSDictionary } dic = info ?? [:] } } let result: NSDictionary = dic["result"] as? NSDictionary ?? [:] var code: Int = dic["code"] as? Int ?? 0 let message: String = dic["msg"] as? String ?? "unknown error" let error = NSError(domain: message, code: code) if result.count == 0 && responseObject != nil && code == 0 { code = 200 } if code == 318 { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1, execute: { let alert = NSAlert() alert.messageText = NSLocalizedString("Unable to Log in", comment: "") alert.informativeText = NSLocalizedString("Your account is currently being canceled and cannot be logged in. If you have any questions, please contact us at support@pdfreaderpro.com", comment: "") alert.addButton(withTitle: NSLocalizedString("Contact Us", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) var window = NSWindow.currentWindow() if window != nil { alert.beginSheetModal(for: window) { result in if (result == .alertFirstButtonReturn) { // KMMailHelper.newEmail(withContacts: "support@pdfreaderpro.com", andSubjects: "") // NSWorkspace.shared.launchApplication("Mailto:support@pdfreaderpro.com") // NSWorkspace.shared.open(URL(string: "mailto:support@pdfreaderpro.com")!) NSWorkspace.shared.open(URL(string: "https://www.pdfreaderpro.com/contact")!) // let service = NSSharingService(named: NSSharingService.Name.composeEmail) // service?.recipients = ["support@pdfreaderpro.com"] // service?.subject = "Test Mail" // service?.perform(withItems: ["Test Mail body"]) } else if result == .alertSecondButtonReturn { return } } } }) } if code == 304 { self.checkDeviceStatus { success, result in } } if code == 330 { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { [unowned self] in if loginAlert == nil { loginAlert = NSAlert() loginAlert?.messageText = NSLocalizedString("Please Log in again", comment: "") loginAlert?.informativeText = NSLocalizedString("Your account has been logged into another device. If it was not done by you, please change your password as soon as possible.", comment: "") loginAlert?.addButton(withTitle: NSLocalizedString("Change Password", comment: "")) loginAlert?.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) var window = NSWindow.currentWindow() if window != nil { loginAlert?.beginSheetModal(for: window) { result in if (result == .alertFirstButtonReturn) { if KMLoginWindowController.fetchSampleController() == nil { KMLoginWindowController.show(window: window) } } else if result == .alertSecondButtonReturn { self.loginAlert = nil return } self.loginAlert = nil } } else { self.loginAlert = nil } } }) } if code == 343 { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2, execute: { [unowned self] in var window = NSWindow.currentWindow() let _ = KMAccountExceptionWindowController.show(window: window) KMLightMemberManager.manager.logOut() }) } // if code == 500 { // let alert = NSAlert() // alert.messageText = NSLocalizedString(message, comment: "") // alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) // if NSApp.mainWindow != nil { // alert.beginSheetModal(for: NSApp.mainWindow!) // } else { // alert.runModal() // } // } KMPrint(dic) return Result(result: result,message: message,code: code, error: error) } } extension NSWindow { static func currentWindow() -> NSWindow { var window = NSApp.mainWindow if NSApp.mainWindow?.sheets.first != nil { window = NSApp.mainWindow?.sheets.first } if window == nil { window = NSApplication.shared.windows.first } return window ?? NSWindow() } }