# iOS 授权管理（License SDK）

**模块**：`LicenseSDK`（包含在 `XuqmSDK` 中）· **最低 iOS 版本**：iOS 16

License SDK 用于设备授权注册与验证，Android / iOS / RN / Flutter 共用同一个 AppKey，设备数量统一计算。

---

## 快速接入

### 1. 添加依赖

License 模块已内置于 `XuqmSDK`，无需额外安装包：

```swift
// Package.swift 或 Xcode → File → Add Package Dependencies
// URL: https://xuqinmin.com/xuqinmin12/XuqmGroup-iOSSDK
import XuqmSDK
```

### 2. 放置 License 文件

从租户平台下载 `.xuqmlicense` 加密文件，放入 App Bundle：

```
MyApp/Resources/xuqm/license.xuqm
```

在 Xcode 中将该文件添加到 Target → Build Phases → Copy Bundle Resources，确保它出现在 App Bundle 中。SDK 会自动读取 `Bundle.main` 中的 `xuqm/license.xuqm`。

### 3. 检查授权

SDK **无需手动初始化**，首次调用 `checkLicense()` 时自动读取并解密 License 文件：

```swift
import XuqmSDK

Task {
    let result = await LicenseSDK.shared.checkLicense()
    switch result {
    case .success(let reason):
        print("授权通过：\(reason)")
    case .error(let message):
        print("授权失败：\(message)")
    }
}
```

---

## API 说明

### checkLicense

```swift
func checkLicense(userInfo: LicenseUserInfo? = nil) async -> LicenseResult
```

**内部逻辑**：
1. 检查本地缓存（默认 10 分钟有效期）
2. 缓存有效 → 直接返回 `.success`
3. 缓存过期或无缓存：
   - 有 Token → 调用验证接口
   - 无 Token 或验证失败 → 调用注册接口
4. 网络异常且缓存曾成功 → 返回 `.success("Offline - cached ok")`
5. 网络异常且无缓存 → 返回 `.error`

### getStatus

```swift
func getStatus() -> LicenseStatus  // .ok / .denied / .unknown
```

同步查询当前状态（不发起网络请求）。

### getDeviceId

```swift
func getDeviceId() -> String?
```

### clear

```swift
func clear()
```

清除所有本地授权数据（token、deviceId、状态）。

---

## 携带用户信息

注册时可携带业务用户信息，方便在租户平台进行设备管理：

```swift
let userInfo = LicenseUserInfo(
    userId: "user_001",
    name: "张三",
    email: "zhangsan@company.com"
)

let result = await LicenseSDK.shared.checkLicense(userInfo: userInfo)
```

---

## 设备唯一码

| 优先级 | 来源 | 说明 |
|--------|------|------|
| 1 | `UIDevice.identifierForVendor` | 同一 App 卸载重装不变（同 Vendor）|
| 2 | 首次生成 UUID 存入 Keychain | identifierForVendor 不可用时 |

---

## 数据存储

| 数据 | 存储方式 | 说明 |
|------|----------|------|
| deviceId | Keychain（Security framework）| 加密持久化 |
| token | Keychain | 加密持久化 |
| 授权状态 | UserDefaults（Suite: `xuqm_license`）| 非敏感 |
| statusTime | UserDefaults | 缓存有效期判断 |

---

## 离线模式

- 首次激活需要网络连接
- 激活成功后，10 分钟缓存内可离线使用
- 网络异常时，若历史缓存成功，继续返回授权通过

---

## 手动初始化（高级用法）

```swift
// 不使用 License 文件，手动指定 AppKey
LicenseSDK.shared.initialize(
    appKey: "your_app_key",
    baseUrl: "https://auth.dev.xuqinmin.com",
    deviceName: "我的 iPhone"
)
```

---

## 完整示例

```swift
import XuqmSDK

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .task { await checkLicense() }
        }
    }

    func checkLicense() async {
        let result = await LicenseSDK.shared.checkLicense(
            userInfo: LicenseUserInfo(userId: "user_001")
        )
        switch result {
        case .success:
            break // 授权通过，正常使用
        case .error(let msg):
            // 提示用户，限制功能入口
            print("License 验证失败: \(msg)")
        }
    }
}
```

---

## 常见问题

**Q: checkLicense 返回 error 怎么办？**
检查：
- License 文件是否已添加到 Build Phases → Copy Bundle Resources
- 文件路径是否为 `xuqm/license.xuqm`（大小写敏感）
- 设备是否有网络连接（首次激活需要网络）
- License 是否已过期或被管理员禁用

**Q: 不同平台可以用同一个 License 吗？**
可以，所有平台共用同一个 AppKey，设备数量统一计算。
