diff --git a/Sources/XuqmCoreSDK/SDKConfig.swift b/Sources/XuqmCoreSDK/SDKConfig.swift index 2d509a5..1db7d03 100644 --- a/Sources/XuqmCoreSDK/SDKConfig.swift +++ b/Sources/XuqmCoreSDK/SDKConfig.swift @@ -30,10 +30,32 @@ public extension SDKConfig { } } -extension SDKConfig { -} - public enum SDKEndpoints { - public static let apiBaseURL = URL(string: "https://dev.xuqinmin.com")! - public static let imWebSocketURL = URL(string: "wss://dev.xuqinmin.com/ws/im")! + private static var _apiBaseURL: URL? + private static var _imWebSocketURL: URL? + + public static var apiBaseURL: URL { + _apiBaseURL ?? URL(string: "https://dev.xuqinmin.com")! + } + + public static var imWebSocketURL: URL { + _imWebSocketURL ?? URL(string: "wss://dev.xuqinmin.com/ws/im")! + } + + public static func configure( + apiBaseURL: String? = nil, + imWebSocketURL: String? = nil + ) { + if let api = apiBaseURL, let url = URL(string: api) { + _apiBaseURL = url + } + if let ws = imWebSocketURL, let url = URL(string: ws) { + _imWebSocketURL = url + } + } + + public static func reset() { + _apiBaseURL = nil + _imWebSocketURL = nil + } } diff --git a/Sources/XuqmCoreSDK/TokenStore.swift b/Sources/XuqmCoreSDK/TokenStore.swift index 0195ac8..ba63f6c 100644 --- a/Sources/XuqmCoreSDK/TokenStore.swift +++ b/Sources/XuqmCoreSDK/TokenStore.swift @@ -1,20 +1,56 @@ import Foundation +import Security public final class TokenStore: @unchecked Sendable { - private let key = "com.xuqm.sdk.token" + private let service = "com.xuqm.sdk.token" + private let account = "auth_token" public init() {} public func save(_ token: String) { - UserDefaults.standard.set(token, forKey: key) + delete() + + guard let data = token.data(using: .utf8) else { return } + + let query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: service, + kSecAttrAccount as String: account, + kSecValueData as String: data, + kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock, + ] + + SecItemAdd(query as CFDictionary, nil) } public func get() -> String? { - UserDefaults.standard.string(forKey: key) + let query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: service, + kSecAttrAccount as String: account, + kSecReturnData as String: true, + kSecMatchLimit as String: kSecMatchLimitOne, + ] + + var item: CFTypeRef? + let status = SecItemCopyMatching(query as CFDictionary, &item) + guard status == errSecSuccess, let data = item as? Data else { + return nil + } + return String(data: data, encoding: .utf8) } public func clear() { - UserDefaults.standard.removeObject(forKey: key) + delete() + } + + private func delete() { + let query: [String: Any] = [ + kSecClass as String: kSecClassGenericPassword, + kSecAttrService as String: service, + kSecAttrAccount as String: account, + ] + SecItemDelete(query as CFDictionary) } } diff --git a/Sources/XuqmCoreSDK/XuqmSDK.swift b/Sources/XuqmCoreSDK/XuqmSDK.swift index ca41739..46db37c 100644 --- a/Sources/XuqmCoreSDK/XuqmSDK.swift +++ b/Sources/XuqmCoreSDK/XuqmSDK.swift @@ -75,6 +75,12 @@ public final class XuqmSDK: NSObject { if let configBundle = file.iosBundleId, !configBundle.isEmpty, configBundle != bundleId { throw XuqmSDKError.packageMismatch(license: configBundle, local: bundleId) } + if let baseUrl = file.baseUrl { + SDKEndpoints.configure(apiBaseURL: baseUrl) + } + if let serverUrl = file.serverUrl { + SDKEndpoints.configure(imWebSocketURL: serverUrl + "/ws/im") + } let cfg = SDKConfig(appKey: file.appKey, debug: debug) initialize(config: cfg) }