XuqmGroup-Server/docs/STORE_MONITORING_V3.md

7.4 KiB

应用商店监测领域设计V3

1. 文档状态

  • 文档类型:服务端对内设计与实施交接
  • 当前迭代Android 全链路;租户平台 iOS/HarmonyOS 只读商店监测
  • 目标地区:中国大陆(CHN
  • 更新时间2026-07-28
  • 实施状态:进行中

本文件是 update-service 应用商店监测领域的权威设计。历史 storeReviewStatus JSON、APPROVED/liveOnStore 混合状态以及 StoreReviewImNotifier 只能作为迁移线索,不是新实现契约。

2. 当前迭代边界

2.1 必须实现

  1. 绑定 App Store Connect 与华为 AppGallery Connect 的只读监测凭据。
  2. 拉取当前在线、审核中、审核通过待发布、拒绝等官方版本。
  3. 分别保存官方版本 ID、展示版本号和平台原生构建号。
  4. 以中国大陆实际可下载作为 AVAILABLE 的唯一条件。
  5. 官方事件优先、定时轮询最终对账;相同状态不得重复产生通知事件。
  6. 已上架外部版本允许由管理员创建“跳转应用商店”型 Xuqm 更新草稿。
  7. 通知仅支持邮件和 Webhook,默认全部关闭。
  8. 所有商店状态、人工操作和投递结果必须可审计。

2.2 本期禁止伪实现

  1. 上传 IPA/HAP。
  2. 提交 iOS/HarmonyOS 审核。
  3. 对 iOS/HarmonyOS 执行立即发布、定时发布或撤回审核。
  4. 在页面保留能够点击但后端只写日志的按钮。

上述写操作只在设计文档中保留扩展边界,不进入当前可用能力。

3. 核心不变量

  1. 官方商店版本与 Xuqm 客户端更新版本是两个聚合,通过 update_store_update_link 显式关联。
  2. 官方资源 ID 是商店版本唯一标识;展示版本号不能代替资源 ID。
  3. iOS CFBundleVersion 是原始字符串,禁止强转为 Android int versionCode
  4. APPROVED_PENDING_RELEASE 不等于 AVAILABLE
  5. 调用官方发布接口成功也不能直接标记上架,必须由监测确认中国大陆可下载。
  6. 未识别的官方状态统一映射为 UNKNOWN,不得猜测成审核中或已上架。
  7. 凭据正文只能由 StoreSecretProvider 解析,控制器、实体视图和日志不得返回。
  8. 监测失败只更新同步健康状态,不覆盖最后一个已验证的商店版本状态。

4. 统一状态机

状态 含义 是否允许配置客户端更新
DISCOVERED 首次发现
PREPARING 商店后台准备中
SUBMITTED 已提交
WAITING_FOR_REVIEW 等待审核
IN_REVIEW 审核中
REJECTED 审核拒绝
APPROVED_PENDING_RELEASE 审核通过,尚未发布
RELEASE_SCHEDULED 已配置官方发布计划(后续版本)
RELEASE_REQUESTED 已请求官方发布(后续版本)
PROCESSING_DISTRIBUTION 商店分发处理中
PARTIALLY_AVAILABLE 非全部目标地区可用
AVAILABLE 中国大陆实际可下载
WITHDRAWN 已撤回
REMOVED 已下架或被替代
UNKNOWN 未识别官方状态
SYNC_FAILED 应用级同步失败视图

官方原始状态必须与统一状态同时保存。

5. 数据模型

5.1 商店与版本

  • update_store_applicationXuqm 应用与官方商店应用绑定。
  • update_store_version:官方版本库存。
  • update_store_region_availability:目标地区可用性。
  • update_store_state_event:状态变化的不可变事件历史。
  • update_store_update_link:官方版本与 Xuqm 更新版本的唯一有效关联。

5.2 凭据与通知

  • update_store_credential_profile:非敏感凭据元数据和 Secrets 引用。
  • update_store_secret:私有化默认 Secrets 后端的 AES-256-GCM 密文。
  • update_store_notification_policy:应用级邮件/Webhook 策略,默认关闭。
  • update_store_notification_outbox:异步投递、重试和最终结果。

公有化部署后续可替换 StoreSecretProvider 为 KMS/Vault 适配器;业务层不得感知后端类型。 公有化与私有化不允许自动回退到另一套 Secrets 服务。

6. API当前迭代

基础路径:/api/v1/updates/store-monitoring

方法 路径 用途
GET /bindings?appKey=... 查询已配置的只读绑定
PUT /bindings/{APP_STORE|HARMONY_APP}?appKey=... 保存绑定或替换监测凭据
POST /bindings/{storeType}/sync?appKey=... 人工立即同步
GET /bindings/{bindingId}/versions?appKey=... 查询官方版本库存
GET /bindings/{bindingId}/events?appKey=... 查询最近 100 条状态事件
POST /bindings/{bindingId}/versions/{storeVersionId}/update-draft?appKey=... 由 CHN 已上架版本创建 Xuqm 更新草稿
GET /notification-policy?appKey=... 查询通知策略;默认全部关闭
PUT /notification-policy?appKey=... 保存邮件/Webhook 通知策略

所有接口执行应用归属校验。凭据只在保存请求中出现一次,响应永不返回正文。

Webhook 请求包含 X-Xuqm-Event-IdX-Xuqm-TimestampX-Xuqm-Signature: sha256=<hex>。签名原文为 timestamp + "." + rawBody,使用租户保存的 Webhook 密钥执行 HMAC-SHA256。 同一商店事件、同一渠道只产生一条 Outbox;失败采用退避重试,达到 6 次后进入 DEAD 并保留审计记录,不影响商店状态和平台主流程。

创建更新草稿要求商店统一状态为 AVAILABLECHN 可用性为 AVAILABLE。该操作只生成 DRAFT,不会自动发布或强制更新。重复请求返回同一条 有效关联,不重复创建版本。App 更新版本使用以下统一标识:

  • AndroidversionCode
  • iOS/Harmony平台原生字符串 buildVersionversionCode 必须为空;
  • 所有平台:数据库原子分配 releaseSequence 负责服务端排序;
  • 外部商店草稿:updateSource=EXTERNAL_STOREinstallMode=STORE_REDIRECT

7. 配置与部署

必须通过运行环境提供:

  • SPRING_DATASOURCE_URL
  • SPRING_DATASOURCE_USERNAME
  • SPRING_DATASOURCE_PASSWORD
  • XUQM_JWT_SECRET
  • XUQM_STORE_SECRET_MASTER_KEY32 字节随机值的 Base64

可选配置:

  • XUQM_STORE_SECRET_KEY_VERSION,默认 v1
  • XUQM_STORE_MONITORING_POLL_DELAY_MS,默认 600000
  • XUQM_STORE_NOTIFICATION_DELAY_MS,默认 5000
  • SMTP_HOSTSMTP_PORTSMTP_USERNAMESMTP_PASSWORDSMTP_TLSSMTP_SSL:仅启用邮件通知时需要

禁止在 Git、普通文档、日志或容器镜像中写入真实值。

8. 当前验证记录

2026-07-28

  • ./mvnw -pl update-service -am test -DskipITs
  • 结果35 个测试通过,0 失败。
  • 已覆盖统一状态映射、iOS 在线/待发布分离、HarmonyOS 在线/审核中分离、 通知默认关闭、邮件/Webhook 独立入队、CHN 上架门禁、商店草稿不伪造 Android versionCode、现有 RN release-set 与鉴权回归。
  • 未验证:真实 App Store Connect、AppGallery Connect 账号联调;Flyway 对真实 MySQL 的 V5 迁移;真实 SMTP/Webhook 投递;租户平台 UI。

9. 下一实施顺序

  1. 租户平台接入绑定、同步、版本库存、事件时间线、更新草稿和通知配置。
  2. 增加真实 MySQL Flyway 集成测试与官方沙箱/测试账号联调。
  3. 完成旧 storeReviewStatus 数据一次性迁移并删除旧读写路径及旧直发 Webhook;Update 对 IM 的直接通知类已删除。