7.3 KiB
版本检查接口契约(启动强制升级)
客户端在启动时请求版本接口,判断是否需要强制升级。本文是服务端响应格式的权威契约——字段以
app/update_check.py的实际读取逻辑为准,服务端按此返回,避免格式漂移。 T-544 已实现启动检查与浏览器下载引导;T-615 起增加自动安装所需的发布契约。T-615 只生成可验证发布包,客户端下载与替换由后续任务实现。
一、接口
- 客户端在
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)
响应是一个 JSON 对象。T-544 兼容字段仍可位于顶层或 release 子对象;自动安装元数据由 app/update_installer.py 做第二层严格校验,生产服务应把同一版本的全部字段放进同一个 release 对象。
| 字段 | 类型 | 说明 |
|---|---|---|
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 | 最低支持版本;本地低于它一律强制 |
download_url |
string(URL) | 下载地址;自动安装时必须是 HTTPS |
sha256 |
string | zip 的 SHA-256;自动安装时必须是 64 位十六进制且不可为空 |
size_bytes |
integer | zip 的准确字节数;自动安装时必须大于 0 |
package_format |
string | 自动安装固定为 cmshopee-portable-v1 |
updater_protocol |
integer | 发布包要求的更新器协议版本,当前为 1 |
min_updater_protocol |
integer | 可安装此包的最低更新器协议,当前为 1 |
release_notes / message |
string | 升级说明,显示在强制升级弹窗里。客户端取 message 或 release_notes |
版本号比较用语义化数字段比较(compare_versions,逐段比数字),不是字符串字典序:0.1.10 > 0.1.9。
三、强制规则(is_forced_update)
满足任一即判为强制:
force_update = true且 本地版本<latest_version;- 本地版本
<min_supported_version。
两者都不满足 → 非强制。
四、客户端行为(T-618)
- 强制且自动安装元数据完整:弹模态进度窗口,显示中文阶段、下载百分比/字节数和发布说明;点击「立即升级」后在工作线程下载、校验和暂存,再启动独立更新器并退出旧程序。更新器完成事务替换后自动启动新版。
- 强制但元数据不完整,或下载/校验/更新器启动失败:继续阻断主窗口,只允许「重试」或「退出程序」,不能降级放行旧版,也不再打开浏览器让用户手工覆盖。
- 非强制:不弹任何提示,直接进主界面(当前无"温和可跳过提示"分支;如需另立任务)。
- 失败放行:接口断网、超时、返回非法 JSON、缺
latest_version/min_supported_version时,客户端记诊断日志(data/logs/cmshopee.log,step=startup_update_check「已允许继续使用」)并放行,不因服务器故障导致全员打不开。
T-616 已实现但尚未接入GUI的安全暂存层:仅接受受信任域名的 HTTPS 地址,流式下载到安装目录 .cmshopee-update/,校验zip大小和SHA-256,安全解压后再按包内manifest逐文件校验。任一步失败都不修改当前程序或 data/;GUI接入由T-618完成。
T-617 已提供独立无控制台更新器和事务回滚能力:更新器从系统临时目录运行,旧主程序退出后才切换程序根项目,并在新版进程无法创建时恢复旧版。T-618 已将其接入启动强制升级进度窗口。
五、发版约定(服务端据此控制)
自动安装使用的全部字段必须放在同一个 release 对象内,不得把版本取自一个对象、hash 取自另一个对象。构建脚本生成的 release/release-metadata.json 是服务端录入模板;发布人员只补 HTTPS download_url、强制策略和中文发布说明,不得手工改写 hash、大小、包格式或协议版本。
| 想要的效果 | 服务端返回 |
|---|---|
| 强制升到最新(方案 A) | release.force_update: true + release.version 高于要淘汰的客户端版本 |
| 强制淘汰旧版(方案 B) | min_supported_version 设为要淘汰之上的版本(顶层或 release 里都可) |
| 不强制 | force_update/min_supported_version 都不给 → 客户端不弹(当前不提示) |
六、示例响应
强制升级(方案 A,推荐)
{
"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",
"sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"size_bytes": 123456789,
"package_format": "cmshopee-portable-v1",
"updater_protocol": 1,
"min_updater_protocol": 1,
"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)
{
"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 的一律强制升级。
不强制(有新版但不逼升)
{
"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...),系统浏览器能正确打开。- 若将来要"非强制也温和提示(可跳过、不阻断)",需在客户端加一个非强制分支,另立任务。
- 空
sha256只兼容 T-544 的人工下载引导,绝不能进入自动安装。自动安装还必须同时校验 HTTPS、size_bytes、包格式和更新器协议。 manifest_signature与signature_algorithm是预留字段;当前未启用数字签名,不能将 SHA-256 描述为发布者身份认证。