7.4 KiB
7.4 KiB
应用商店监测领域设计(V3)
1. 文档状态
- 文档类型:服务端对内设计与实施交接
- 当前迭代:Android 全链路;租户平台 iOS/HarmonyOS 只读商店监测
- 目标地区:中国大陆(
CHN) - 更新时间:2026-07-28
- 实施状态:进行中
本文件是 update-service 应用商店监测领域的权威设计。历史
storeReviewStatus JSON、APPROVED/liveOnStore 混合状态以及
StoreReviewImNotifier 只能作为迁移线索,不是新实现契约。
2. 当前迭代边界
2.1 必须实现
- 绑定 App Store Connect 与华为 AppGallery Connect 的只读监测凭据。
- 拉取当前在线、审核中、审核通过待发布、拒绝等官方版本。
- 分别保存官方版本 ID、展示版本号和平台原生构建号。
- 以中国大陆实际可下载作为
AVAILABLE的唯一条件。 - 官方事件优先、定时轮询最终对账;相同状态不得重复产生通知事件。
- 已上架外部版本允许由管理员创建“跳转应用商店”型 Xuqm 更新草稿。
- 通知仅支持邮件和 Webhook,默认全部关闭。
- 所有商店状态、人工操作和投递结果必须可审计。
2.2 本期禁止伪实现
- 上传 IPA/HAP。
- 提交 iOS/HarmonyOS 审核。
- 对 iOS/HarmonyOS 执行立即发布、定时发布或撤回审核。
- 在页面保留能够点击但后端只写日志的按钮。
上述写操作只在设计文档中保留扩展边界,不进入当前可用能力。
3. 核心不变量
- 官方商店版本与 Xuqm 客户端更新版本是两个聚合,通过
update_store_update_link显式关联。 - 官方资源 ID 是商店版本唯一标识;展示版本号不能代替资源 ID。
- iOS
CFBundleVersion是原始字符串,禁止强转为 Androidint versionCode。 APPROVED_PENDING_RELEASE不等于AVAILABLE。- 调用官方发布接口成功也不能直接标记上架,必须由监测确认中国大陆可下载。
- 未识别的官方状态统一映射为
UNKNOWN,不得猜测成审核中或已上架。 - 凭据正文只能由
StoreSecretProvider解析,控制器、实体视图和日志不得返回。 - 监测失败只更新同步健康状态,不覆盖最后一个已验证的商店版本状态。
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_application:Xuqm 应用与官方商店应用绑定。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-Id、X-Xuqm-Timestamp 和
X-Xuqm-Signature: sha256=<hex>。签名原文为
timestamp + "." + rawBody,使用租户保存的 Webhook 密钥执行 HMAC-SHA256。
同一商店事件、同一渠道只产生一条 Outbox;失败采用退避重试,达到 6 次后进入
DEAD 并保留审计记录,不影响商店状态和平台主流程。
创建更新草稿要求商店统一状态为 AVAILABLE 且 CHN 可用性为
AVAILABLE。该操作只生成 DRAFT,不会自动发布或强制更新。重复请求返回同一条
有效关联,不重复创建版本。App 更新版本使用以下统一标识:
- Android:
versionCode; - iOS/Harmony:平台原生字符串
buildVersion,versionCode必须为空; - 所有平台:数据库原子分配
releaseSequence负责服务端排序; - 外部商店草稿:
updateSource=EXTERNAL_STORE、installMode=STORE_REDIRECT。
7. 配置与部署
必须通过运行环境提供:
SPRING_DATASOURCE_URLSPRING_DATASOURCE_USERNAMESPRING_DATASOURCE_PASSWORDXUQM_JWT_SECRETXUQM_STORE_SECRET_MASTER_KEY:32 字节随机值的 Base64
可选配置:
XUQM_STORE_SECRET_KEY_VERSION,默认v1XUQM_STORE_MONITORING_POLL_DELAY_MS,默认600000XUQM_STORE_NOTIFICATION_DELAY_MS,默认5000SMTP_HOST、SMTP_PORT、SMTP_USERNAME、SMTP_PASSWORD、SMTP_TLS、SMTP_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. 下一实施顺序
- 租户平台接入绑定、同步、版本库存、事件时间线、更新草稿和通知配置。
- 增加真实 MySQL Flyway 集成测试与官方沙箱/测试账号联调。
- 完成旧
storeReviewStatus数据一次性迁移并删除旧读写路径及旧直发 Webhook;Update 对 IM 的直接通知类已删除。