# Python SDK 弹窗复用指南（给 AI）

目标：在新的 Python 桌面项目中复用卡密登录弹窗。  
当前文件只说明 Python 端；Web 端接入方式不同，不要混用。

---

## 1. 拷贝文件

从卡密系统项目拷贝整个目录到新项目根目录：

```text
TK_SDK_Python/
```

必须保留核心文件：

```text
TK_SDK_Python/license_sdk_python.py
TK_SDK_Python/VERSION
```

可选保留工具目录：

```text
TK_SDK_Python/一键预览弹窗样式/
TK_SDK_Python/一键检测SDK双端不一致/
```

---

## 2. 安装依赖

新项目需要：

```bash
pip install requests PySide6
```

---

## 3. 配置文件格式

在新项目中准备一个 JSON 配置文件，例如 `config.json`：

```json
{
  "app_settings": {
    "server_url": "http://127.0.0.1:5000",
    "software_id": 2,
    "license_key": ""
  }
}
```

字段要求：

- `server_url`：卡密服务端地址。
- `software_id`：卡密后台“软件管理”里的软件 ID，必须正确。
- `license_key`：可为空；勾选“记住卡密”后 SDK 会写入。

---

## 4. 最小接入代码

在主程序启动前先弹授权弹窗；授权通过后再启动主窗口。

```python
import sys
from pathlib import Path

from PySide6.QtWidgets import QApplication, QDialog

from TK_SDK_Python.license_sdk_python import LicenseAuthClient, LicenseLoginDialog


CONFIG_FILE = Path(__file__).parent / "config.json"


def get_machine_code():
    # 必须返回稳定设备码。不要每次启动随机生成。
    return "YOUR-STABLE-MACHINE-CODE"


def main():
    app = QApplication(sys.argv)

    auth = LicenseAuthClient(str(CONFIG_FILE), get_machine_code)
    base_conf, err = auth.load_config(require_license_key=False)
    if err:
        print(err)
        return

    dlg = LicenseLoginDialog(auth, base_conf)
    if dlg.exec() != QDialog.Accepted or not dlg.license_runtime:
        return

    runtime = dlg.license_runtime

    # 授权通过。这里启动新项目自己的主窗口。
    # window = MainWindow()
    # window.show()
    # sys.exit(app.exec())


if __name__ == "__main__":
    main()
```

---

## 5. runtime 返回字段

授权通过后从这里取运行信息：

```python
runtime = dlg.license_runtime
```

常用字段：

```text
runtime["server_url"]
runtime["software_id"]
runtime["license_key"]
runtime["device_id"]
runtime["update_mode"]
runtime["latest_version"]
runtime["update_url"]
runtime["license_mode"]
runtime["end_date"]
runtime["remaining_days"]
runtime["points_amount"]
runtime["points_redeemed"]
runtime["redeemed_at"]
```

试用成功时还会有：

```text
runtime["from_trial"] = True
runtime["trial_result"]
```

---

## 6. 服务端接口约定

不要改 SDK 的接口字段。SDK 会调用：

```text
GET  /api/software-notice?software_id=...
POST /api/verify
POST /api/trial
```

`/api/verify` 请求体：

```json
{
  "software_id": 2,
  "license_key": "XXXX-XXXX-XXXX-XXXX",
  "machine_code": "设备码"
}
```

`/api/trial` 请求体：

```json
{
  "software_id": 2,
  "machine_code": "设备码"
}
```

---

## 7. 关键业务规则

- Python 弹窗会根据后台 `trial_enabled` 自动显示或隐藏“免费试用”。
- 正式卡密有效期从首次激活/首次绑定设备当天开始计算。
- 试用卡密从创建当天开始计算。
- 新用户专享卡密按设备限制，只允许同设备使用一次。
- `get_machine_code()` 必须稳定，否则会触发设备不匹配。

---

## 8. AI 接入任务摘要

给另一个 AI 接入时，可直接执行：

```text
1. 将 TK_SDK_Python 整个目录复制到新 Python 项目根目录。
2. 安装 requests 和 PySide6。
3. 新建 config.json，填写 app_settings.server_url、software_id，license_key 默认留空。
4. 实现稳定的 get_machine_code()。
5. 程序启动时先创建 LicenseAuthClient。
6. 调用 auth.load_config(require_license_key=False)。
7. 弹出 LicenseLoginDialog。
8. 只有 dlg.exec() == QDialog.Accepted 且 dlg.license_runtime 存在时，才启动主窗口。
9. 不要改服务端 API 字段。
10. 不要随机生成 machine_code。
```
