BeeX H5 离线包双渠道技术设计
1. 核心决策
BeeX 不再按“测试环境包 / 正式环境包”构建 H5。一次流水线从同一个 commit 同时产出
INTERNAL 和 RELEASE 两个包渠道。Native 版本只决定包渠道;
只有 INTERNAL 包才读取 Native 当前选择的业务环境。
一句话真值:
88.88.88 → INTERNAL;其他 Native 版本
→ RELEASE。请求来自哪个 API Host、Query 里的 envCode 是什么,
都不能改变这个结论。
2. 两个独立维度
| 维度 | 可选值 | 决定什么 | 不能决定什么 |
|---|---|---|---|
| 包渠道 | INTERNAL / RELEASE |
包内是否包含测试配置、中文、调试工具和环境切换能力。 | 不代表当前正在调用测试 API 还是生产 API。 |
| 业务环境 | production / id-test |
INTERNAL 包本次运行使用哪组 API、WhatsApp 和业务配置。 | 不能让非 88 Native 获得 INTERNAL 包。 |
env_code=id-test 与 env_code=id 在 H5 包表中保留为渠道分区兼容字段:
前者存 INTERNAL,后者存 RELEASE。它不再表达客户端当前业务环境。
3. 唯一判定表
| Native 版本 | 请求的业务 API | 服务端返回渠道 | H5 最终业务配置 |
|---|---|---|---|
88.88.88 | 生产 API | INTERNAL | 默认生产;Native 当前为生产时使用生产配置。 |
88.88.88 | 测试 API | INTERNAL | Native 当前为 id-test 时使用 id-test 配置。 |
任意非 88.88.88 | 生产 API | RELEASE | 只存在生产配置。 |
任意非 88.88.88 | 测试 API | RELEASE | 仍只存在生产配置;请求 Host 不能提升渠道。 |
禁止的实现:不能用 API Host、
envCode、管理后台当前切换环境或 CDN 域名决定
INTERNAL / RELEASE。否则正式 App 误连测试 API 时可能拿到内部包。
4. 一次构建两个产物
统一流水线:同版本、同 commit、两个独立 ZIP
flowchart LR
G["Git commit"] --> P["云效统一 H5 流水线 4987658"]
P --> I["INTERNAL ZIP\n生产+id-test 配置\n仅 88.88.88"]
P --> R["RELEASE ZIP\n仅生产配置\n非 88"]
I --> IT["INTERNAL manifest\nmin=max=88.88.88"]
R --> RT["RELEASE manifest\n无 Native 范围"]
IT --> REG1["登记到 INTERNAL 分区"]
RT --> REG2["登记到 RELEASE 分区"]
| 内容 | INTERNAL | RELEASE |
|---|---|---|
| 包渠道 | INTERNAL | RELEASE |
| Native 适用范围 | min=max=88.88.88 | 无范围字段,由服务端按“非 88”选择 |
| 业务配置 | 生产 + id-test,默认生产 | 仅生产/default |
| 中文及调试能力 | 包含 | 不包含 |
| 环境切换 | 允许生产 / id-test | 不提供入口,也没有测试配置 |
| 版本与 commit | 必须完全相同;SHA256 必须分别计算且通常不同。 | |
5. Native 与 H5 启动
INTERNAL 包启动时选择业务环境;RELEASE 不执行环境选择
sequenceDiagram
participant App as "Native"
participant Store as "Native 环境存储"
participant H5 as "本地 H5"
participant API as "BeeX API"
App->>Store: "启动前读取当前环境"
alt "Native = 88.88.88"
Store-->>App: "production 或 id-test,缺省 production"
App->>H5: "注入 packageChannel=INTERNAL + environmentId"
H5->>H5: "从包内两组配置选择对应配置"
else "Native != 88.88.88"
Store-->>App: "强制 production,并清理内部环境状态"
App->>H5: "注入 packageChannel=RELEASE"
H5->>H5: "使用唯一 production/default 配置"
end
H5->>API: "按已确定配置发起请求"
- Native 在创建 WebView 之前读取当前环境。
- 非 88 版本会清除历史测试环境、调试 H5、语言覆盖和内部开关,强制生产。
- Native 向 H5 注入不可变的
h5PackageChannel与当前environmentId。 - INTERNAL 读取
environmentId选择包内配置;缺失或非法值回退生产。 - RELEASE 忽略环境输入,因为包内根本不存在测试配置。
6. 服务端下发规则
业务 API Host 与包渠道解耦
flowchart TD
Q["GET /api/v1/app/h5-package/latest"] --> V{"nativeVersion == 88.88.88?"}
V -- "是" --> IC["查询 INTERNAL 分区\n兼容 env_code=id-test"]
V -- "否" --> RC["查询 RELEASE 分区\n兼容 env_code=id"]
IC --> G["按状态、灰度目标、当前版本选择候选"]
RC --> G
G --> O["返回 packageUrl / sha256 / releaseNotes"]
服务端必须忽略请求中的 envCode 来选择渠道。它只信任已安装 Native 的
nativeVersion:精确等于 88.88.88 查询 INTERNAL,其余查询 RELEASE。
同一统一流水线会把两个渠道登记到测试与生产管理服务,使 88 从任一业务 API 查询时都能找到 INTERNAL, 非 88 从任一业务 API 查询时都只能找到 RELEASE。
发布状态仍由渠道权威版本池维护:INTERNAL 以内部版本池为准,RELEASE 以线上版本池为准。
请求落在非权威 API 时,业务服务携带内部路由标记与 X-ADMIN-TOKEN 查询权威版本池;
权威服务失败时返回 hasUpdate=false,绝不改查另一个渠道。内部路由标记不能由公网请求单独伪造。
7. 安全与防误发
| 风险 | 门禁 |
|---|---|
| 正式 App 获得测试配置 | RELEASE 构建阶段不写入任何测试 API、测试 WhatsApp 或内部工具;服务端非 88 永不查询 INTERNAL。 |
| 88 测试线上时拿到 RELEASE | 服务端按 Native 版本强制选择 INTERNAL,不看 API Host 和请求 envCode。 |
| 转线上重新构建导致漂移 | 生产晋级只复用同版本、同 commit 的预构建 RELEASE;候选不存在则失败并要求重跑统一流水线。 |
| 旧测试状态污染正式 App | 非 88 启动时主动清除本地环境切换、调试 H5、语言覆盖与内部开关。 |
| 两个渠道内容相同或配错 | 流水线校验 manifest、Native 范围、内嵌 Host、测试号码与两个 ZIP 的独立 SHA256。 |
| 公网伪造内部路由身份 | 内部转发同时校验路由标记和共享管理令牌;缺失或不匹配时拒绝,不信任转发的用户与联盟码。 |
| 权威版本池不可用 | 返回无更新并继续使用本地离线包;禁止为了“有包可下”而跨渠道降级。 |
8. 后续演进原则
- 新增国家时仍按国家数据中心独立发布,但包渠道规则保持 INTERNAL / RELEASE 两类。
- 新增内部工具只进入 INTERNAL,不通过运行时远程开关塞进 RELEASE。
- 新增生产配置应进入 RELEASE 的 default 配置,同时进入 INTERNAL 的 production 配置。
- 任何需要修改“渠道判定”的需求必须同时更新 Native、业务服务、管理后台、流水线校验和本文档。