XuqmGroup-iOSSDK/Sources/XuqmLicenseSDK/LicenseStore.swift

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)
}
}