XuqmGroup-iOSSDK/Sources/XuqmLicenseSDK/LicenseStore.swift
XuqmGroup e016adbb71 chore(ci): 更新 Jenkins 配置以支持多模块版本管理
- 为 Android、Flutter、iOS 和 RN SDK 的 Jenkinsfile 添加模块化版本控制
- 引入版本升级策略选择(major/minor/patch)和自定义版本号功能
- 实现多模块独立版本管理和选择性构建发布
- 更新 iOS SDK Package.swift 以支持独立模块化库
- 修改 iOS SDK podspec 文件以适应新的标签命名约定
- 优化 Jenkins 构建流程以支持按需选择特定模块进行构建和发布
- 修复 iOS 测试中的可选类型转换问题以提高代码健壮性
2026-05-23 01:20:57 +08:00

87 行
2.6 KiB
Swift

import Foundation
import XuqmCoreSDK
import Security
final class LicenseStore {
private let keychainService = "com.xuqm.license"
private let defaults: UserDefaults
init() {
defaults = UserDefaults(suiteName: "xuqm_license") ?? .standard
}
var token: String? {
get { keychainGet("token") }
set { keychainSet("token", value: newValue) }
}
var deviceId: String? {
get { keychainGet("deviceId") }
set { keychainSet("deviceId", value: newValue) }
}
var status: String? {
get { defaults.string(forKey: "status") }
set { defaults.set(newValue, forKey: "status") }
}
// Stored as Double (milliseconds since epoch) to match Android's currentTimeMillis
var statusTime: Double {
get { defaults.double(forKey: "statusTime") }
set { defaults.set(newValue, forKey: "statusTime") }
}
var appKey: String? {
get { defaults.string(forKey: "appKey") }
set { defaults.set(newValue, forKey: "appKey") }
}
func clear() {
token = nil
deviceId = nil
status = nil
statusTime = 0
appKey = nil
}
private func keychainGet(_ key: String) -> String? {
let query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrService: keychainService,
kSecAttrAccount: key,
kSecReturnData: true,
kSecMatchLimit: kSecMatchLimitOne,
]
var result: AnyObject?
guard SecItemCopyMatching(query as CFDictionary, &result) == errSecSuccess,
let data = result as? Data else { return nil }
return String(data: data, encoding: .utf8)
}
private func keychainSet(_ key: String, value: String?) {
guard let value else { keychainDelete(key); return }
let data = Data(value.utf8)
let query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrService: keychainService,
kSecAttrAccount: key,
]
if SecItemCopyMatching(query as CFDictionary, nil) == errSecSuccess {
SecItemUpdate(query as CFDictionary, [kSecValueData: data] as CFDictionary)
} else {
var item = query
item[kSecValueData] = data
SecItemAdd(item as CFDictionary, nil)
}
}
private func keychainDelete(_ key: String) {
let query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrService: keychainService,
kSecAttrAccount: key,
]
SecItemDelete(query as CFDictionary)
}
}