Files
e-party-iOS/yana/APIs/LoginModels.swift
edwinQQQ fb7ae9e0ad feat: 更新.gitignore,删除需求文档,优化API调试信息
- 在.gitignore中添加忽略项以排除不必要的文件。
- 删除架构分析需求文档以简化项目文档。
- 在APIEndpoints.swift和LoginModels.swift中移除调试信息的异步调用,提升代码简洁性。
- 在EMailLoginFeature.swift和HomeFeature.swift中新增登录流程状态管理,优化用户体验。
- 在多个视图中调整状态管理和导航逻辑,确保一致性和可维护性。
- 更新Xcode项目配置以增强调试信息的输出格式。
2025-07-18 15:57:54 +08:00

416 lines
14 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
// MARK: - Account Model
///
/// oauth/token oauth/ticket
/// OC AccountModel
struct AccountModel: Codable, Equatable {
let uid: String? //
let jti: String? // JWT ID
let tokenType: String? // Token (bearer)
let refreshToken: String? //
let netEaseToken: String? //
let accessToken: String? // OAuth 访
let expiresIn: Int? //
let scope: String? //
var ticket: String? // oauth/ticket
enum CodingKeys: String, CodingKey {
case uid
case jti
case tokenType = "token_type"
case refreshToken = "refresh_token"
case netEaseToken
case accessToken = "access_token"
case expiresIn = "expires_in"
case scope
case ticket
}
///
var hasValidAuthentication: Bool {
return accessToken != nil && !accessToken!.isEmpty
}
///
var hasValidSession: Bool {
return hasValidAuthentication && ticket != nil && !ticket!.isEmpty
}
/// IDLoginData AccountModel
/// - Parameter loginData:
/// - Returns: AccountModel nil
static func from(loginData: IDLoginData) -> AccountModel? {
// accessToken uid
guard let accessToken = loginData.accessToken,
let uid = loginData.uid else {
return nil
}
return AccountModel(
uid: String(uid),
jti: loginData.jti,
tokenType: loginData.tokenType,
refreshToken: loginData.refreshToken,
netEaseToken: loginData.netEaseToken,
accessToken: accessToken,
expiresIn: loginData.expiresIn,
scope: loginData.scope,
ticket: nil // oauth/ticket
)
}
/// ticket
/// - Parameter ticket: oauth/ticket
/// - Returns: AccountModel
func withTicket(_ ticket: String) -> AccountModel {
var updatedModel = self
updatedModel.ticket = ticket
return updatedModel
}
}
// MARK: - ID Login Request Model
struct IDLoginAPIRequest: APIRequestProtocol {
typealias Response = IDLoginResponse
let endpoint = APIEndpoint.login.path // 使
let method: HTTPMethod = .POST
let includeBaseParameters = true
let queryParameters: [String: String]?
var bodyParameters: [String: Any]? { nil }
let timeout: TimeInterval = 30.0
/// ID
/// - Parameters:
/// - phone: DESID/
/// - password: DES
/// - clientSecret: "uyzjdhds"
/// - version: "1"
/// - clientId: ID"erban-client"
/// - grantType: "password"
init(phone: String, password: String, clientSecret: String = "uyzjdhds", version: String = "1", clientId: String = "erban-client", grantType: String = "password") {
self.queryParameters = [
"phone": phone,
"password": password,
"client_secret": clientSecret,
"version": version,
"client_id": clientId,
"grant_type": grantType
];
}
}
// MARK: - ID Login Response Model
struct IDLoginResponse: Codable, Equatable {
let status: String?
let message: String?
let code: Int?
let data: IDLoginData?
///
var isSuccess: Bool {
return code == 200 || status?.lowercased() == "success"
}
///
var errorMessage: String {
return message ?? "登录失败,请重试"
}
}
// MARK: - ID Login Data Model
struct IDLoginData: Codable, Equatable {
let accessToken: String?
let refreshToken: String?
let tokenType: String?
let expiresIn: Int?
let scope: String?
let userInfo: UserInfo?
let uid: Int? // String?Int?API
let netEaseToken: String? // token
let jti: String? // JWT token identifier
enum CodingKeys: String, CodingKey {
case accessToken = "access_token"
case refreshToken = "refresh_token"
case tokenType = "token_type"
case expiresIn = "expires_in"
case scope
case userInfo = "user_info"
case uid
case netEaseToken
case jti
}
}
// MARK: - User Info Model
struct UserInfo: Codable, Equatable {
let userId: String?
let username: String?
let nickname: String?
let avatar: String?
let email: String?
let phone: String?
let status: String?
let createTime: String?
let updateTime: String?
enum CodingKeys: String, CodingKey {
case userId = "user_id"
case username
case nickname
case avatar
case email
case phone
case status
case createTime = "create_time"
case updateTime = "update_time"
}
}
// MARK: - Login Helper
struct LoginHelper {
/// ID
/// DES
/// - Parameters:
/// - userID: ID
/// - password:
/// - Returns: APInil
static func createIDLoginRequest(userID: String, password: String) async -> IDLoginAPIRequest? {
// 使DESID
let encryptionKey = "1ea53d260ecf11e7b56e00163e046a26"
guard let encryptedID = DESEncrypt.encryptUseDES(userID, key: encryptionKey),
let encryptedPassword = DESEncrypt.encryptUseDES(password, key: encryptionKey) else {
debugErrorSync("❌ DES加密失败")
return nil
}
debugInfoSync("🔐 DES加密成功")
debugInfoSync(" 原始ID: \(userID)")
debugInfoSync(" 加密后ID: \(encryptedID)")
debugInfoSync(" 原始密码: \(password)")
debugInfoSync(" 加密后密码: \(encryptedPassword)")
return IDLoginAPIRequest(
phone: userID,
password: encryptedPassword
)
}
}
// MARK: - Ticket API Models
/// Ticket
struct TicketAPIRequest: APIRequestProtocol {
typealias Response = TicketResponse
let endpoint = "/oauth/ticket"
let method: HTTPMethod = .POST
let includeBaseParameters = true
let queryParameters: [String: String]?
var bodyParameters: [String: Any]? { nil }
let timeout: TimeInterval = 30.0
let customHeaders: [String: String]?
/// Ticket
/// - Parameters:
/// - accessToken: OAuth 访
/// - issueType: "multi"
/// - uid:
init(accessToken: String, issueType: String = "multi", uid: Int? = nil) {
self.queryParameters = [
"access_token": accessToken,
"issue_type": issueType
]
//
var headers: [String: String] = [:]
if let uid = uid {
headers["pub_uid"] = "\(uid)" //
}
self.customHeaders = headers.isEmpty ? nil : headers
}
}
/// Ticket
struct TicketResponse: Codable, Equatable {
let code: Int?
let message: String?
let data: TicketData?
///
var isSuccess: Bool {
return code == 200
}
///
var errorMessage: String {
return message ?? "Ticket 获取失败,请重试"
}
/// Ticket
var ticket: String? {
return data?.tickets?.first?.ticket
}
}
/// Ticket
struct TicketData: Codable, Equatable {
let tickets: [TicketInfo]?
}
/// Ticket
struct TicketInfo: Codable, Equatable {
let ticket: String?
}
// MARK: - Ticket Helper
struct TicketHelper {
/// Ticket
/// - Parameters:
/// - accessToken: OAuth 访
/// - uid:
/// - Returns: Ticket API
static func createTicketRequest(accessToken: String, uid: Int?) -> TicketAPIRequest {
return TicketAPIRequest(accessToken: accessToken, uid: uid)
}
/// Ticket
/// - Parameters:
/// - accessToken: OAuth 访
/// - uid:
static func debugTicketRequest(accessToken: String, uid: Int?) {
debugInfoSync("🎫 Ticket 请求调试信息")
debugInfoSync(" AccessToken: \(accessToken)")
debugInfoSync(" UID: \(uid?.description ?? "nil")")
debugInfoSync(" Endpoint: /oauth/ticket")
debugInfoSync(" Method: POST")
debugInfoSync(" Headers: pub_uid = \(uid?.description ?? "nil")")
debugInfoSync(" Parameters: access_token=\(accessToken), issue_type=multi")
}
}
// MARK: - LoginResponse
typealias LoginResponse = IDLoginResponse
// MARK: - Email Verification Code Models
///
struct EmailGetCodeRequest: APIRequestProtocol {
typealias Response = EmailGetCodeResponse
let endpoint = APIEndpoint.emailGetCode.path
let method: HTTPMethod = .POST
let includeBaseParameters = true
let queryParameters: [String: String]?
var bodyParameters: [String: Any]? { nil }
let timeout: TimeInterval = 30.0
///
/// - Parameters:
/// - emailAddress: DES
/// - type: 1=/
init(emailAddress: String, type: Int = 1) {
self.queryParameters = [
"emailAddress": emailAddress,
"type": String(type)
]
}
}
///
struct EmailGetCodeResponse: Codable, Equatable {
let status: String?
let message: String?
let code: Int?
let data: String? //
///
var isSuccess: Bool {
return code == 200 || status?.lowercased() == "success"
}
///
var errorMessage: String {
return message ?? "验证码发送失败,请重试"
}
}
///
struct EmailLoginRequest: APIRequestProtocol {
typealias Response = IDLoginResponse // ID
let endpoint = APIEndpoint.login.path
let method: HTTPMethod = .POST
let includeBaseParameters = true
let queryParameters: [String: String]?
var bodyParameters: [String: Any]? { nil }
let timeout: TimeInterval = 30.0
///
/// - Parameters:
/// - email: DES
/// - code:
/// - clientSecret: "uyzjdhds"
/// - version: "1"
/// - clientId: ID"erban-client"
/// - grantType: "email"
init(email: String, code: String, clientSecret: String = "uyzjdhds", version: String = "1", clientId: String = "erban-client", grantType: String = "email") {
self.queryParameters = [
"email": email,
"code": code,
"client_secret": clientSecret,
"version": version,
"client_id": clientId,
"grant_type": grantType
]
}
}
// MARK: - Email Login Helper
extension LoginHelper {
///
/// - Parameter email:
/// - Returns: APInil
static func createEmailGetCodeRequest(email: String) -> EmailGetCodeRequest? {
let encryptionKey = "1ea53d260ecf11e7b56e00163e046a26"
guard let encryptedEmail = DESEncrypt.encryptUseDES(email, key: encryptionKey) else {
debugErrorSync("❌ 邮箱DES加密失败")
return nil
}
debugInfoSync("🔐 邮箱DES加密成功")
debugInfoSync(" 原始邮箱: \(email)")
debugInfoSync(" 加密邮箱: \(encryptedEmail)")
return EmailGetCodeRequest(emailAddress: email, type: 1)
}
///
/// - Parameters:
/// - email:
/// - code:
/// - Returns: APInil
static func createEmailLoginRequest(email: String, code: String) async -> EmailLoginRequest? {
let encryptionKey = "1ea53d260ecf11e7b56e00163e046a26"
guard let encryptedEmail = DESEncrypt.encryptUseDES(email, key: encryptionKey) else {
await debugErrorSync("❌ 邮箱DES加密失败")
return nil
}
debugInfoSync("🔐 邮箱验证码登录DES加密成功")
debugInfoSync(" 原始邮箱: \(email)")
debugInfoSync(" 加密邮箱: \(encryptedEmail)")
debugInfoSync(" 验证码: \(code)")
return EmailLoginRequest(email: encryptedEmail, code: code)
}
}