# Flutter 授权管理（License SDK）

**模块**：`xuqm_flutter_license` · **依赖**：`cryptography`、`device_info_plus`、`shared_preferences`

---

## 1. 安装

在 `pubspec.yaml` 中添加：

```yaml
dependencies:
  xuqm_flutter_license:
    git:
      url: https://xuqinmin.com/xuqmGroup/XuqmGroup-FlutterSDK.git
      ref: v0.2.2
      path: packages/license
```

---

## 2. 放置 License 文件

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

```yaml
# pubspec.yaml
flutter:
  assets:
    - assets/xuqm/license.xuqm
```

---

## 3. 检查授权

```dart
import 'package:flutter/services.dart' show rootBundle;
import 'package:xuqm_flutter_license/xuqm_flutter_license.dart';

Future<void> verifyLicense() async {
  // 从 assets 读取加密文件
  final content = await rootBundle.loadString('assets/xuqm/license.xuqm');

  // 自动解密并初始化
  await initializeFromFile(content);

  // 检查授权（有缓存时直接返回，否则网络验证）
  final result = await checkLicense();
  switch (result) {
    case LicenseSuccess(reason: final r):
      print('授权通过: $r');
    case LicenseError(message: final m):
      print('授权失败: $m');
  }
}
```

---

## 4. 携带用户信息

```dart
final result = await checkLicense(
  userInfo: LicenseUserInfo(
    userId: 'user_001',
    name: '张三',
    email: 'zhangsan@company.com',
  ),
);
```

---

## 5. API 说明

### initializeFromFile

```dart
Future<void> initializeFromFile(String encryptedContent)
```

从加密 License 文件内容自动解析 appKey 和 baseUrl 并初始化。

### checkLicense

```dart
Future<LicenseResult> checkLicense({LicenseUserInfo? userInfo})
```

返回 `LicenseSuccess(reason)` 或 `LicenseError(message)`（密封类，使用 `switch` 匹配）。

**缓存策略**：10 分钟有效期，有效期内不发起网络请求。

### getStatus

```dart
Future<LicenseStatus> getStatus()  // LicenseStatus.ok / .denied / .unknown
```

### getDeviceId

```dart
Future<String?> getDeviceId()
```

### clear

```dart
Future<void> clear()
```

---

## 6. 设备唯一码

| 平台 | 来源 | 说明 |
|------|------|------|
| Android | `androidInfo.id` | `Settings.Secure.ANDROID_ID` |
| iOS | `iosInfo.identifierForVendor` | 同 Vendor 下卸载重装不变 |
| 其他 | 生成 UUID 存入 SharedPreferences | fallback |

---

## 7. 数据存储

| 数据 | 存储方式 | 说明 |
|------|----------|------|
| deviceId | SharedPreferences | 持久化 |
| token | SharedPreferences | 持久化 |
| 授权状态 | SharedPreferences | 非敏感，持久化 |
| statusTime | SharedPreferences | 缓存有效期判断 |

---

## 8. 离线模式

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

---

## 9. 完整示例

```dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:xuqm_flutter_sdk/xuqm_flutter_sdk.dart';
import 'package:xuqm_flutter_license/xuqm_license.dart' as license;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await XuqmSDK.initialize(XuqmInitOptions(appKey: 'your_app_key'));

  // 初始化 License
  final content = await rootBundle.loadString('assets/xuqm/license.xuqm');
  await license.initializeFromFile(content);

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FutureBuilder(
        future: license.checkLicense(
          userInfo: license.LicenseUserInfo(userId: 'user_001'),
        ),
        builder: (context, snapshot) {
          if (!snapshot.hasData) return const CircularProgressIndicator();
          final result = snapshot.data!;
          if (result is license.LicenseError) {
            return Scaffold(
              body: Center(child: Text('授权失败: ${result.message}')),
            );
          }
          return const HomePage();
        },
      ),
    );
  }
}
```

---

## 10. 常见问题

**Q: 提示 `Invalid license file format`？**
检查 License 文件是否完整，以及是否已在 `pubspec.yaml` 的 `flutter.assets` 中声明。

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