Files
cmshoppe/docs/tasks/T-686.md
T

94 lines
8.6 KiB
Markdown
Raw Normal View History

2026-07-21 17:20:06 +08:00
---
id: T-686
title: 会员订阅状态接入与启动访问门禁
phase: 8
deps: []
status: DONE
2026-07-21 17:20:06 +08:00
created: 2026-07-21
---
# T-686 会员订阅状态接入与启动访问门禁
## 问题 / 背景
cmshopee 将从卡密和固定设备绑定切换为“cmhub 账号 API Key + 软件订阅权益”。同一账号可在多台电脑使用,设备信息只用于观测和风控,不参与授权。客户端当前只有 cmhub 网关 Key 配置,没有统一订阅状态模型、启动账号接入流程、顶部会员信息或生成前订阅预检。
cmhub 需提供 `GET /api/v1/cmshopee/subscription/status`。2026-07-21 无凭据探测 `https://cm.833729.com/api/v1/cmshopee/subscription/status` 返回 `404`,说明接口尚未上线;本任务必须保证发布过渡期的旧服务不会让现有客户端全部锁死。
## 方案
### 1. 订阅状态客户端与接口契约
- 在 `app/` 新增独立订阅状态模块,复用当前 cmhub Base URL、共享 HTTP 会话和 Bearer API Key;不得把 API Key 放入 URL、状态对象 `repr`、日志、异常或 GUI 文案。
- 调用 `GET /api/v1/cmshopee/subscription/status`,解析 `product_code`、`account.display_name`、`plan.code/display_name`、`status`、`expires_at`、`grace_expires_at`、`manage_url`、`notice_id`。
- 状态至少归一化为:未配置 Key、订阅有效、宽限期、未订阅、已到期、已撤销、账号禁用、Key 无效、暂时不可用、旧服务未启用订阅接口。
- 仅接受 cmshopee 产品状态;成功响应缺少必要字段、产品不符、时间格式错误、`manage_url` 非受控 HTTPS 地址时按“暂时不可用”处理,不猜测权益。
- `404` 或明确的“功能未启用”响应归为过渡兼容状态:启动和现有工作流继续按旧行为运行,但不显示伪造的会员有效信息;写脱敏诊断。接口上线后不再走该兼容路径。
- 网络超时、5xx 或非法响应归为“暂时无法确认会员状态”,不得错误显示为 Key 无效或会员到期。
### 2. 启动访问状态与界面
- 强制升级检查完成后,在不阻塞 Qt 主线程的 worker 中查询订阅状态;账户验证和窗口销毁必须防止陈旧回调覆盖新状态。
- 当订阅接口已启用时:未配置 Key、Key 无效、账号禁用、未订阅、订阅到期或撤销自动切到“设置”并在状态栏提示;不弹出阻断式“需要配置会员账号”窗口,不启动新的产品工作流。
2026-07-21 17:20:06 +08:00
- 订阅有效或处于宽限期时进入正常工作区;在现有应用顶部标题区域右侧使用紧凑只读标签展示“账号名 · 套餐名 · 有效至日期”。不得修改 Windows 原生窗口标题来承载长文本。
- “前往会员中心”只能使用默认浏览器打开服务端 `manage_url`;客户端不新增登录、支付、订单或密码输入页面。所有新文案为中文,不能展示 API Key、设备摘要、支付数据或原始 HTTP 报错。
- 旧服务未启用接口时显示低干扰中文兼容提示,不弹出阻断式会员窗口;接口可用后首次状态/`notice_id` 变化再提示,避免每次启动重复弹窗。
### 3. 生成前预检与服务端错误映射
- 在 AI 生成和商品套图的所有“新提交”入口统一预检订阅状态;切换 cmhub API Key 后立即重新检查。自定义网关直连也必须配置 cmhub 账号 Key 并走相同的客户端软校验。
- 收到服务端 `subscription_required`、`subscription_expired`、`account_disabled` 或 `subscription_revoked` 时,停止创建后续新提交项,使用中文提示和线上会员中心入口;已接受的异步任务仍允许轮询、下载和查看。
- 客户端预检只是体验控制;cmhub 产品专属 submit 必须由服务端做最终授权裁决。不得在本任务实现 cmhub BYOK 代理、卡密、设备凭证、固定设备限制或本地可篡改的“硬授权”。
### 4. 文档、测试与发布兼容
- 更新 `docs/04-architecture.md`、`docs/routes.md`,说明账号订阅边界、启动状态、受限恢复路径、生成预检和自定义网关软校验边界;不更新 `docs/current-state.md`。
- 新增订阅状态解析与错误映射单测,扩展启动/生成入口测试,覆盖有效、宽限、未配置、无订阅、过期、禁用、网络失败、非法响应、旧服务 `404` 兼容、状态变更和 Key 打码。
- 发布前使用测试 API Key 对已上线订阅接口实测;接口未上线时只能验证 `404` 兼容,不得声明真实会员门禁已验收。
## 验收要点
- [ ] 同一有效 cmhub 账号在多台电脑均可通过订阅检查;没有任何设备数量或设备凭证判断。
- [ ] API Key 有效且订阅有效/宽限期内时,顶部标题区域正确展示账号名、套餐和有效期,且不泄露敏感信息。
- [ ] 当订阅接口已启用时,未配置 Key、Key 无效、账号禁用、未订阅、到期和撤销均不能进入新的产品工作流,并有中文设置/线上会员中心恢复路径。
- [ ] 网络失败和非法响应不会误报为无订阅;`404` 旧服务兼容不锁死当前工作流。
- [ ] AI 生成、AI 帮写、商品套图和自定义网关直连的新提交均经过同一订阅预检;已接受异步任务不被到期状态中断。
- [ ] 服务端授权错误映射为中文且不暴露 URL、API Key 或原始响应。
- [ ] 测试 API Key 可对已上线接口完成真实验证;接口未上线时执行记录明确保留该外部验证缺口。
## 验证
```bash
py -3.10 -m unittest discover -s tests -p test_subscription.py
py -3.10 -m unittest discover -s tests -p test_ai.py
py -3.10 -m unittest discover -s tests -p test_image_studio_generation.py
py -3.10 -m unittest discover -s tests -p test_gui.py
2026-07-21 17:20:06 +08:00
py -3.10 -m unittest discover -s tests
py -3.10 -m ruff check app tests main.py
py -3.10 -m compileall app main.py
git diff --check
```
## 边界(不改什么)
- 不实现 cmhub 服务端订阅表、套餐、支付、7 天赠送权益、状态接口或产品接口硬拦截。
- 不实现卡密、激活、设备绑定、换机、设备凭证、席位限制、自动续费或 BYOK 代理。
- 不修改 Chrome/CDP、采集和更新蝦皮业务逻辑;订阅受限只阻止新的产品工作流,不删除或破坏本地数据和已接受异步任务。
- 不把直连自定义网关的本地预检描述为不可绕过的授权保护。
## 关联
- Obsidian《cmhub-账号订阅与多设备授权方案》§3、§6、§8、§9。
- T-685:设备登记与会话观测可保留为遥测,但不是本任务依赖或授权前置。
- T-678/T-679:自定义网关与商品套图来源;本任务只增加客户端软校验。
## 执行记录
- 2026-07-21:任务创建;cmhub 订阅状态接口尚未上线,需在实现中保持 `404` 旧服务兼容。
- 2026-07-21:新增 `app/subscription.py` 和 `SubscriptionCheckWorker`,复用 cmhub 共享 HTTP 会话查询订阅状态;主窗口在显示后异步检查,顶部显示账号/套餐/有效期,受限状态只保留设置恢复入口。② AI生成、⑥商品套图和 AI帮写的新提交接入同一预检,旧服务 `404` 放行既有工作流。
- 2026-07-21:验证通过:`py -3.10 -m compileall app main.py`、`py -3.10 -m ruff check app tests main.py`、订阅/应用配置/AI/套图/GUI 定向测试,以及 `py -3.10 -m unittest discover -s tests`(664 项)。无凭据请求线上订阅状态接口返回 `404`,已由单测和运行时兼容分支覆盖;服务端上线后需使用测试 API Key 做一次真实有效/到期/未订阅联调,不属于本仓库可完成的接口发布工作。
- 2026-07-22:产品决策调整:移除未配置或未开通会员时的阻断式弹窗;保留工作流访问限制、自动切换“设置”和状态栏提示,避免每次启动或新提交被会员配置窗口打断。
- 2026-07-22:验证通过:`py -3.10 -m compileall app main.py`、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m unittest discover -s tests -p test_gui.py`,以及完整单测 `py -3.10 -m unittest discover -s tests`(664 项)。
- 2026-07-22:为测试其他完整功能,临时设置 `app.gui.main_window.SUBSCRIPTION_CHECK_ENABLED = False`:启动和保存设置不查询订阅接口,AI生成、AI帮写和商品套图的新提交不做客户端预检;顶部明确显示“会员:订阅检测已暂停”。订阅模块与服务端最终授权设计保留,恢复发布前需重新启用并验证。
- 2026-07-22:验证通过:`py -3.10 -m compileall app main.py`、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m unittest discover -s tests -p test_gui.py`(217 项)以及完整单测 `py -3.10 -m unittest discover -s tests`(665 项)。