Files
cmhub/docs/tasks/T-632.md
T

4.2 KiB

T-632 会员订阅三阶段启用与简化运营

背景

cmhub 已具备软件套餐、用户权益、软件订单、支付回调、授权事件和设备观测能力,但开发与线上测试阶段若要求运营逐个给存量用户绑定长期套餐,操作成本高且容易误伤已有用户。

当前 CMSHOPEE_SUBSCRIPTION_ENFORCEMENT=false 只保证产品专属生成接口不阻断;订阅状态接口仍返回真实的 required / expired,且响应缺少桌面端已依赖的账号、套餐代码、顶层有效期、会员中心和通知字段,因此桌面端可能把有效 API Key 误判为“需要配置会员账号”。

目标

  1. 用 open、shadow、enforce 三种明确模式分阶段启用账号订阅。
  2. 开发测试阶段无需批量创建虚假 SoftwareEntitlement,存量有效 API Key 可继续使用。
  3. 订阅状态接口返回桌面端可直接消费的完整、向后兼容结构。
  4. django-admin 软件授权首页只展示“会员套餐”和“用户会员”两个日常入口,其他模型保留数据与直接管理地址。

范围

配置

  • 新增 CMSHOPEE_SUBSCRIPTION_MODE,仅接受 open / shadow / enforce。
  • 新配置缺失时兼容旧 CMSHOPEE_SUBSCRIPTION_ENFORCEMENT:旧值 true 等价于 enforce,否则等价于 open。
  • 非法模式必须在 Django 启动配置阶段明确报错,不能静默回退。

授权

  • open:有效 API Key 统一获得开发测试访问,不要求数据库权益,不写入虚假权益。
  • shadow:有真实有效权益时返回真实套餐;无权益或过期时继续放行并返回兼容访问,同时记录真实权益状态。
  • enforce:只有真实有效或仍处于宽限期的权益可提交产品专属任务。
  • 通用 /api/v1/generate/* 不应用软件订阅限制。
  • 已接受的异步任务详情、轮询和下载不追加订阅拦截。

状态接口

GET /api/v1/cmshopee/subscription/status 保留现有 product_code、status、allowed、code,并补齐:

  • account.display_name / account.username
  • plan.code / plan.display_name
  • 顶层 expires_at / grace_expires_at
  • manage_url
  • notice_id
  • access_source
  • entitlement_status

其中 status 表示当前运行模式下的最终访问状态,entitlement_status 表示数据库真实权益状态;两者在 open / shadow 下允许不同。

admin

  • 将 SoftwarePlan 展示名改为“会员套餐”。
  • 将 SoftwareEntitlement 展示名改为“用户会员”。
  • admin 应用索引只展示上述两个模型。
  • SoftwareOrder、LicenseEvent、ClientDevice、DeviceSession、DeviceBindingAudit 以及 T-631 已隐藏的历史授权模型继续注册,保留权限控制、历史数据和直接管理地址。

实施约束

  • 模式切换不得创建、续期、撤销或批量修改用户权益。
  • 不修改用户 API Key、钱包、点数流水、充值订单或软件订单状态。
  • 不删除授权、订单、设备或审计表。
  • 日志不得记录 API Key、prompt、原始设备标识或图片。
  • 响应新增字段保持向后兼容,不能删除 T-630 已发布字段。
  • manage_url 只能由服务端 PUBLIC_BASE_URL 构造。

验收条件

  1. open 下无真实权益用户的状态接口返回有效访问,产品专属 submit 可用,数据库不新增权益。
  2. shadow 下无真实权益用户继续可用,响应和结构化日志能区分最终放行与真实权益缺失。
  3. enforce 下无权益与过期用户分别返回 subscription_required / subscription_expired,且拒绝发生在预扣与上游调用前。
  4. 有效与宽限期权益返回真实套餐、稳定套餐代码和正确顶层有效期。
  5. 状态接口包含桌面端要求的账号、套餐、有效期、会员中心和通知字段;旧字段仍存在。
  6. 新配置缺失时兼容旧布尔开关;非法模式不能通过配置检查。
  7. admin 首页仅显示“会员套餐”和“用户会员”;隐藏模型的直接管理地址和历史数据仍可访问。
  8. 通用生成、点数、充值、软件订单和异步任务读取回归通过。
  9. manage.py check、目标测试、迁移一致性、编译检查和 git diff --check 通过。

状态

TODO。