// // EPLoginService.swift // YuMi // // Created by AI on 2025-01-27. // import Foundation /// 登录服务封装(Swift 现代化版本) /// 统一封装所有登录相关 API,完全替代 OC 版本的 LoginPresenter @objc class EPLoginService: NSObject { // MARK: - Constants private let clientSecret = EPLoginConfig.API.clientSecret private let clientId = EPLoginConfig.API.clientId private let version = EPLoginConfig.API.version // MARK: - Private Helper Methods /// 解析并保存 AccountModel /// - Parameters: /// - data: API 返回的数据 /// - code: 状态码 /// - completion: 成功回调 /// - failure: 失败回调 private func parseAndSaveAccount(data: BaseModel?, code: Int64, completion: @escaping (AccountModel) -> Void, failure: @escaping (Int, String) -> Void) { if code == 200 { if let accountDict = data?.data as? NSDictionary, let accountModel = AccountModel.mj_object(withKeyValues: accountDict) { // 保存账号信息 AccountInfoStorage.instance().saveAccountInfo(accountModel) completion(accountModel) } else { failure(Int(code), "账号信息解析失败") } } else { failure(Int(code), "操作失败") } } // MARK: - Request Ticket /// 请求 Ticket(登录成功后调用) /// - Parameters: /// - accessToken: 访问令牌 /// - completion: 成功回调 (ticket) /// - failure: 失败回调 (错误码, 错误信息) @objc func requestTicket(accessToken: String, completion: @escaping (String) -> Void, failure: @escaping (Int, String) -> Void) { Api.requestTicket({ (data, code, msg) in if code == 200, let dict = data?.data as? NSDictionary { if let tickets = dict["tickets"] as? NSArray, let firstTicket = tickets.firstObject as? NSDictionary, let ticket = firstTicket["ticket"] as? String { completion(ticket) } else { failure(Int(code), "Ticket 解析失败") } } else { failure(Int(code), msg ?? "请求 Ticket 失败") } }, access_token: accessToken, issue_type: "multi") } // MARK: - Send Verification Code /// 发送邮箱验证码 /// - Parameters: /// - email: 邮箱地址 /// - type: 类型 (1=登录, 2=找回密码) /// - completion: 成功回调 /// - failure: 失败回调 @objc func sendEmailCode(email: String, type: Int, completion: @escaping () -> Void, failure: @escaping (Int, String) -> Void) { // 🔐 DES 加密邮箱 let encryptedEmail = encryptDES(email) Api.emailGetCode({ (data, code, msg) in if code == 200 { completion() } else { failure(Int(code), msg ?? "发送邮箱验证码失败") } }, emailAddress: encryptedEmail, type: NSNumber(value: type)) } /// 发送手机验证码 /// - Parameters: /// - phone: 手机号 /// - areaCode: 区号 /// - type: 类型 (1=登录, 2=找回密码) /// - completion: 成功回调 /// - failure: 失败回调 @objc func sendPhoneCode(phone: String, areaCode: String, type: Int, completion: @escaping () -> Void, failure: @escaping (Int, String) -> Void) { // 🔐 DES 加密手机号 let encryptedPhone = encryptDES(phone) Api.phoneSmsCode({ (data, code, msg) in if code == 200 { completion() } else { failure(Int(code), msg ?? "发送手机验证码失败") } }, mobile: encryptedPhone, type: String(type), phoneAreaCode: areaCode) } // MARK: - Login Methods /// ID + 密码登录 /// - Parameters: /// - id: 用户 ID /// - password: 密码 /// - completion: 成功回调 (AccountModel) /// - failure: 失败回调 @objc func loginWithID(id: String, password: String, completion: @escaping (AccountModel) -> Void, failure: @escaping (Int, String) -> Void) { // 🔐 DES 加密 ID 和密码 let encryptedId = encryptDES(id) let encryptedPassword = encryptDES(password) Api.login(password: { [weak self] (data, code, msg) in self?.parseAndSaveAccount( data: data, code: Int64(code), completion: completion, failure: { errorCode, _ in failure(errorCode, msg ?? "登录失败") }) }, phone: encryptedId, password: encryptedPassword, client_secret: clientSecret, version: version, client_id: clientId, grant_type: "password") } /// 邮箱 + 验证码登录 /// - Parameters: /// - email: 邮箱地址 /// - code: 验证码 /// - completion: 成功回调 (AccountModel) /// - failure: 失败回调 @objc func loginWithEmail(email: String, code: String, completion: @escaping (AccountModel) -> Void, failure: @escaping (Int, String) -> Void) { // 🔐 DES 加密邮箱 let encryptedEmail = encryptDES(email) Api.login(code: { [weak self] (data, code, msg) in self?.parseAndSaveAccount( data: data, code: Int64(code), completion: completion, failure: { errorCode, _ in failure(errorCode, msg ?? "登录失败") }) }, email: encryptedEmail, code: code, client_secret: clientSecret, version: version, client_id: clientId, grant_type: "email") } /// 手机号 + 验证码登录 /// - Parameters: /// - phone: 手机号 /// - code: 验证码 /// - areaCode: 区号 /// - completion: 成功回调 (AccountModel) /// - failure: 失败回调 @objc func loginWithPhone(phone: String, code: String, areaCode: String, completion: @escaping (AccountModel) -> Void, failure: @escaping (Int, String) -> Void) { // 🔐 DES 加密手机号 let encryptedPhone = encryptDES(phone) Api.login(code: { [weak self] (data, code, msg) in self?.parseAndSaveAccount( data: data, code: Int64(code), completion: completion, failure: { errorCode, _ in failure(errorCode, msg ?? "登录失败") }) }, phone: encryptedPhone, code: code, client_secret: clientSecret, version: version, client_id: clientId, grant_type: "password", phoneAreaCode: areaCode) } // MARK: - Reset Password /// 邮箱重置密码 /// - Parameters: /// - email: 邮箱地址 /// - code: 验证码 /// - newPassword: 新密码 /// - completion: 成功回调 /// - failure: 失败回调 @objc func resetEmailPassword(email: String, code: String, newPassword: String, completion: @escaping () -> Void, failure: @escaping (Int, String) -> Void) { // 🔐 DES 加密邮箱和新密码 let encryptedEmail = encryptDES(email) let encryptedPassword = encryptDES(newPassword) Api.resetPassword(email: { (data, code, msg) in if code == 200 { completion() } else { failure(Int(code), msg ?? "重置密码失败") } }, email: encryptedEmail, newPwd: encryptedPassword, code: code) } /// 手机号重置密码 /// - Parameters: /// - phone: 手机号 /// - code: 验证码 /// - areaCode: 区号 /// - newPassword: 新密码 /// - completion: 成功回调 /// - failure: 失败回调 @objc func resetPhonePassword(phone: String, code: String, areaCode: String, newPassword: String, completion: @escaping () -> Void, failure: @escaping (Int, String) -> Void) { // 🔐 DES 加密手机号和新密码 let encryptedPhone = encryptDES(phone) let encryptedPassword = encryptDES(newPassword) Api.resetPassword(phone: { (data, code, msg) in if code == 200 { completion() } else { failure(Int(code), msg ?? "重置密码失败") } }, phone: encryptedPhone, newPwd: encryptedPassword, smsCode: code, phoneAreaCode: areaCode) } // MARK: - Phone Quick Login (保留接口) /// 手机快速登录(保留接口但 UI 暂不暴露) /// - Parameters: /// - accessToken: 访问令牌 /// - token: 令牌 /// - completion: 成功回调 (AccountModel) /// - failure: 失败回调 @objc func phoneQuickLogin(accessToken: String, token: String, completion: @escaping (AccountModel) -> Void, failure: @escaping (Int, String) -> Void) { Api.phoneQuickLogin({ [weak self] (data, code, msg) in self?.parseAndSaveAccount( data: data, code: Int64(code), completion: completion, failure: { errorCode, _ in failure(errorCode, msg ?? "快速登录失败") }) }, accessToken: accessToken, token: token) } }