2026-07-08 14:46:03 +08:00
|
|
|
|
# 版本检查接口契约(启动强制升级)
|
|
|
|
|
|
|
|
|
|
|
|
> 客户端在启动时请求版本接口,判断是否需要**强制升级**。本文是**服务端响应格式的权威契约**——字段以 `app/update_check.py` 的实际读取逻辑为准,服务端按此返回,避免格式漂移。
|
2026-07-13 11:58:05 +08:00
|
|
|
|
> T-544 已实现启动检查与浏览器下载引导;T-615 起增加自动安装所需的发布契约。T-615 只生成可验证发布包,客户端下载与替换由后续任务实现。
|
2026-07-08 14:46:03 +08:00
|
|
|
|
|
|
|
|
|
|
## 一、接口
|
|
|
|
|
|
|
|
|
|
|
|
- 客户端在 `main()` 启动流程里、进主界面之前请求(`app/gui/__init__.py` 的 `_run_startup_update_gate` → `app/update_check.py`)。
|
|
|
|
|
|
- URL 硬编码于 `app/version.py`:
|
|
|
|
|
|
```
|
|
|
|
|
|
APP_UPDATE_CHECK_URL = "https://cm.833729.com/api/v1/client/releases/latest?platform=windows"
|
|
|
|
|
|
```
|
|
|
|
|
|
- 方法:`GET`,请求头 `Accept: application/json`、`User-Agent: cmshopee/<版本>`。
|
|
|
|
|
|
- 客户端当前版本见 `app/version.py` 的 `APP_VERSION`。
|
|
|
|
|
|
|
|
|
|
|
|
## 二、客户端读取的字段(`update_check.parse_update_info`)
|
|
|
|
|
|
|
2026-07-13 12:02:47 +08:00
|
|
|
|
响应是一个 JSON 对象。T-544 兼容字段仍可位于顶层或 `release` 子对象;自动安装元数据由 `app/update_installer.py` 做第二层严格校验,生产服务应把同一版本的全部字段放进同一个 `release` 对象。
|
2026-07-08 14:46:03 +08:00
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 说明 |
|
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
|
| `version` / `latest_version` | string | 最新版本号。客户端取 `payload.latest_version` 或 `release.version`。**`latest_version` 与 `min_supported_version` 至少要有一个**,否则客户端判为"接口缺字段"、按失败放行 |
|
|
|
|
|
|
| `force_update` | bool | 是否强制升级。`true`/`1`/`yes`/`y`/`on`(大小写不敏感)都识别为真 |
|
|
|
|
|
|
| `min_supported_version` | string | 最低支持版本;本地低于它一律强制 |
|
2026-07-13 16:19:03 +08:00
|
|
|
|
| `download_url` | string(URL) | 安装包外链;优先 HTTPS,T-623 临时兼容任意公网 HTTP/HTTPS 地址 |
|
2026-07-13 11:58:05 +08:00
|
|
|
|
| `sha256` | string | zip 的 SHA-256;自动安装时必须是 64 位十六进制且不可为空 |
|
|
|
|
|
|
| `size_bytes` | integer | zip 的准确字节数;自动安装时必须大于 0 |
|
2026-07-08 14:46:03 +08:00
|
|
|
|
| `release_notes` / `message` | string | 升级说明,显示在强制升级弹窗里。客户端取 `message` 或 `release_notes` |
|
2026-07-13 17:17:25 +08:00
|
|
|
|
| `published_at` | string | 服务端发布时间;客户端当前不参与强制判定 |
|
|
|
|
|
|
|
|
|
|
|
|
`package_format`、`updater_protocol`、`min_updater_protocol` 不是 cmhub 版本接口字段。客户端使用内置 `cmshopee-portable-v1` 和当前更新器协议构造安装元数据,下载后再以包内 `package-manifest.json` 验证真实格式和协议;不兼容的包仍会在替换程序前拒绝。
|
2026-07-08 14:46:03 +08:00
|
|
|
|
|
|
|
|
|
|
版本号比较用**语义化数字段比较**(`compare_versions`,逐段比数字),不是字符串字典序:`0.1.10 > 0.1.9`。
|
|
|
|
|
|
|
|
|
|
|
|
## 三、强制规则(`is_forced_update`)
|
|
|
|
|
|
|
|
|
|
|
|
满足**任一**即判为强制:
|
|
|
|
|
|
|
|
|
|
|
|
1. `force_update = true` **且** 本地版本 `<` `latest_version`;
|
|
|
|
|
|
2. 本地版本 `<` `min_supported_version`。
|
|
|
|
|
|
|
|
|
|
|
|
两者都不满足 → **非强制**。
|
|
|
|
|
|
|
2026-07-13 12:12:58 +08:00
|
|
|
|
## 四、客户端行为(T-618)
|
2026-07-08 14:46:03 +08:00
|
|
|
|
|
2026-07-13 12:12:58 +08:00
|
|
|
|
- **强制且自动安装元数据完整**:弹模态进度窗口,显示中文阶段、下载百分比/字节数和发布说明;点击「立即升级」后在工作线程下载、校验和暂存,再启动独立更新器并退出旧程序。更新器完成事务替换后自动启动新版。
|
|
|
|
|
|
- **强制但元数据不完整,或下载/校验/更新器启动失败**:继续阻断主窗口,只允许「重试」或「退出程序」,不能降级放行旧版,也不再打开浏览器让用户手工覆盖。
|
2026-07-13 12:23:46 +08:00
|
|
|
|
- **同一版本和zip hash曾因新版早期崩溃回滚**:命中本地失败版本熔断,不重复自动安装;仍保持强制阻断,提示等待管理员发布不同hash的修复包/更高版本,或手动安装。
|
2026-07-08 14:46:03 +08:00
|
|
|
|
- **非强制**:**不弹任何提示**,直接进主界面(当前无"温和可跳过提示"分支;如需另立任务)。
|
|
|
|
|
|
- **失败放行**:接口断网、超时、返回非法 JSON、缺 `latest_version`/`min_supported_version` 时,客户端记诊断日志(`data/logs/cmshopee.log`,`step=startup_update_check`「已允许继续使用」)并**放行**,不因服务器故障导致全员打不开。
|
|
|
|
|
|
|
2026-07-13 16:19:03 +08:00
|
|
|
|
T-616 已实现安全暂存层,T-623 为兼容对象存储、CDN 和文件分发服务外链,临时允许任意公网 HTTP/HTTPS 下载地址及跨域、跨协议重定向。初始地址、每次跳转和最终响应都会拒绝本机、内网和非 HTTP(S) 目标;下载仍流式写入安装目录 `.cmshopee-update/`,并严格校验zip声明大小、SHA-256和包内manifest。任一步失败都不修改当前程序或 `data/`。
|
2026-07-13 12:02:47 +08:00
|
|
|
|
|
2026-07-13 12:12:58 +08:00
|
|
|
|
T-617 已提供独立无控制台更新器和事务回滚能力:更新器从系统临时目录运行,旧主程序退出后才切换程序根项目,并在新版进程无法创建时恢复旧版。T-618 已将其接入启动强制升级进度窗口。
|
2026-07-13 12:07:59 +08:00
|
|
|
|
|
2026-07-08 14:46:03 +08:00
|
|
|
|
## 五、发版约定(服务端据此控制)
|
|
|
|
|
|
|
2026-07-13 17:36:46 +08:00
|
|
|
|
自动安装使用的全部字段必须放在同一个 `release` 对象内,不得把版本取自一个对象、hash 取自另一个对象。构建脚本生成的 `release/release-metadata<APP_VERSION>.json` 提供版本、zip SHA-256 和准确大小;发布人员应选择与待发布 zip 版本一致的元数据文件,再录入公网 HTTP/HTTPS `download_url`、强制策略和中文发布说明,不得手工改写 hash 或大小。正式发布仍应优先使用 HTTPS;HTTP 只用于外链暂时无法提供 HTTPS 的兼容期。
|
2026-07-13 11:58:05 +08:00
|
|
|
|
|
2026-07-08 14:46:03 +08:00
|
|
|
|
| 想要的效果 | 服务端返回 |
|
|
|
|
|
|
| --- | --- |
|
|
|
|
|
|
| **强制升到最新**(方案 A) | `release.force_update: true` + `release.version` 高于要淘汰的客户端版本 |
|
|
|
|
|
|
| **强制淘汰旧版**(方案 B) | `min_supported_version` 设为要淘汰之上的版本(顶层或 `release` 里都可)|
|
|
|
|
|
|
| **不强制** | `force_update`/`min_supported_version` 都不给 → 客户端不弹(当前不提示)|
|
|
|
|
|
|
|
|
|
|
|
|
## 六、示例响应
|
|
|
|
|
|
|
|
|
|
|
|
### 强制升级(方案 A,推荐)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"platform": "windows",
|
|
|
|
|
|
"release": {
|
|
|
|
|
|
"version": "0.1.1",
|
|
|
|
|
|
"download_url": "https://cm.833729.com/media/downloads/%E8%9D%A6%E7%9A%AE%E5%9C%88%E5%84%AA%E5%8C%96%E5%8A%A9%E6%89%8B0.1.1.zip",
|
2026-07-13 11:58:05 +08:00
|
|
|
|
"sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
|
|
|
|
"size_bytes": 123456789,
|
2026-07-08 14:46:03 +08:00
|
|
|
|
"release_notes": "优化了ai模块的生图的功能",
|
|
|
|
|
|
"published_at": "2026-07-08T14:30:26.935549+08:00",
|
|
|
|
|
|
"force_update": true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
效果:本地 `0.1.0` < `0.1.1` 且 `force_update=true` → 强制弹窗、必须升级。
|
|
|
|
|
|
|
|
|
|
|
|
### 强制淘汰旧版(方案 B)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"platform": "windows",
|
|
|
|
|
|
"min_supported_version": "0.1.1",
|
|
|
|
|
|
"release": {
|
|
|
|
|
|
"version": "0.1.1",
|
|
|
|
|
|
"download_url": "https://cm.833729.com/media/downloads/...0.1.1.zip",
|
|
|
|
|
|
"release_notes": "优化了ai模块的生图的功能"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
效果:本地低于 `0.1.1` 的一律强制升级。
|
|
|
|
|
|
|
|
|
|
|
|
### 不强制(有新版但不逼升)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"platform": "windows",
|
|
|
|
|
|
"release": {
|
|
|
|
|
|
"version": "0.1.1",
|
|
|
|
|
|
"download_url": "https://cm.833729.com/media/downloads/...0.1.1.zip",
|
|
|
|
|
|
"release_notes": "优化了ai模块的生图的功能"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
效果:客户端解析成功但判为非强制 → **当前不弹提示**,直接进主界面。
|
|
|
|
|
|
|
|
|
|
|
|
## 七、注意
|
|
|
|
|
|
|
|
|
|
|
|
- 服务端返回 `force_update`/`min_supported_version` 属**本仓库外的服务端配置**;客户端代码(`app/update_check.py`/`app/version.py`/启动流程)已按本契约实现,**发强制版不需要改客户端**。
|
|
|
|
|
|
- `download_url` 里的中文可用 URL 编码(如 `%E8%9D%A6...`),系统浏览器能正确打开。
|
2026-07-13 16:19:03 +08:00
|
|
|
|
- 版本检查接口 `APP_UPDATE_CHECK_URL` 必须保持受信任 HTTPS;只有它返回的 `download_url` 可以在 T-623 兼容期使用公网 HTTP 外链。客户端不提供手工输入下载地址或关闭校验的入口。
|
2026-07-08 14:46:03 +08:00
|
|
|
|
- 若将来要"非强制也温和提示(可跳过、不阻断)",需在客户端加一个非强制分支,另立任务。
|
2026-07-13 17:17:25 +08:00
|
|
|
|
- 空 `sha256` 只兼容 T-544 的人工下载引导,绝不能进入自动安装。自动安装无论使用 HTTP 还是 HTTPS,都必须同时校验接口 `size_bytes`、整包 SHA-256,以及客户端内置格式/协议对应的包内manifest。
|
2026-07-13 11:58:05 +08:00
|
|
|
|
- `manifest_signature` 与 `signature_algorithm` 是预留字段;当前未启用数字签名,不能将 SHA-256 描述为发布者身份认证。
|
2026-07-13 12:23:46 +08:00
|
|
|
|
|
|
|
|
|
|
## 八、引导版本与灰度发布
|
|
|
|
|
|
|
2026-07-13 17:17:25 +08:00
|
|
|
|
仍只有T-544“浏览器下载”能力的旧客户端无法凭空获得独立更新器,必须先人工覆盖一个同时包含T-615至T-619代码和 `cmshopee-updater.exe` 的引导版本。后续自动发布先以非强制方式灰度确认接口字段、下载和manifest,再开启 `force_update` 或提高 `min_supported_version`。包内manifest的 `updater_protocol` / `min_updater_protocol` 必须与引导版本兼容,cmhub 版本接口无需重复返回。
|
2026-07-13 12:23:46 +08:00
|
|
|
|
|
|
|
|
|
|
更新器启动新版后等待健康标记:`process_started` 表示基础导入、Qt和版本核对完成;`main_window_ready` 表示数据目录、必要初始化和主窗口显示完成,此时才清理成功备份;`environment_blocked` 表示数据目录、配置或Chrome等本地环境需用户处理,保留新版且不误回滚。无已知标记、版本不符、早期退出或健康等待超时会恢复旧版并写失败版本熔断记录。
|