diff --git a/client/harmony/build-profile.json5 b/client/harmony/build-profile.json5 index ff11b4c..f85affb 100644 --- a/client/harmony/build-profile.json5 +++ b/client/harmony/build-profile.json5 @@ -5,6 +5,30 @@ name: 'default', type: 'HarmonyOS', material: { + /* + * ★★ 2026-10-02 真机推送排查:**这里签的是 CA 根证书,不是应用证书**。 + * + * 设备实测(平板 MRDI-W00,`bm dump`): + * "appSignType": "none" / "signatureKey": "" / "appProvisionType": "debug" + * ⇒ 包里**根本没有应用签名身份**,于是 HMS 的 + * `AuthService: cert finger empty, clientId: 2039846327155747840` + * 拿不到指纹,判成 `1000900010 Illegal application identity`, + * push token 因此永远取不到(`push_tokens` 表 0 行)。 + * + * 证书比对(本机实测的三个指纹): + * 本文件这个 .cer DF:21:A3:C0:…:DF:3A:37 CN=Huawei CBG Root CA G2 ← CA 根 + * profile 内嵌 dev cert FD:89:AC:53:…:FC:9D:09 CN=靳睿(…)\,Development ← 应用的 + * profile 的 type "debug" + * ⇒ 签的证书与 profile 绑定的**不是同一张**,这就是 "cert finger empty" 的来源。 + * + * ⚠️ 曾把它改成 profile 内嵌的单张 dev cert 想试,hvigor 直接报 + * `11013004 Profile cert must a cert chain` —— **certpath 要的是一条链** + * (应用证书 + 签发它的 CA),而 dev cert 的签发者 + * `Huawei CBG Developer Relations CA G2` **本机没有**(5 个 p7b 里都没有)。 + * ⇒ 要修好必须补齐 dev cert 的**签发链**(AGC/DevEco 后台导出的那套发布或调试证书), + * 然后把 certpath 指向那条链。在那之前这里保持原样, + * 因为改成一个编译不过的值只会连应用都装不上。 + */ certpath: '/root/.ohos/config/default_harmony_k2yruKTLaTiZOjublhUDTfveVx5uFoHqm96pwkUw=.cer', keyAlias: 'debugKey', keyPassword: '0000001b64d7bb074eed97bb2c6ad5ae60df2f72256b104361c3fd8c4f842eb42961fce4b712e7410dd208', diff --git a/docs/PUSH-DEVICE-DIAGNOSIS.md b/docs/PUSH-DEVICE-DIAGNOSIS.md new file mode 100644 index 0000000..61b46dd --- /dev/null +++ b/docs/PUSH-DEVICE-DIAGNOSIS.md @@ -0,0 +1,178 @@ +# 真机推送联合调试:诊断报告 + +日期:2026-10-01 +设备:HUAWEI MatePad Pro(MRDI-W00),HarmonyOS NEXT,`const.ohos.apiversion = 26` +连接:`hdc tconn 192.168.2.87:43679` +应用:`com.jianf.agentmail`(设备上已装、已登录 `jianf`、SSE 已连通) + +--- + +## 一 结论先说 + +**推送链路的每一段都正常,唯一断点是「平板取不到 HMS token」,而它与证书绑定有关。** + +已实测排除: + +| 环节 | 状态 | 证据 | +|---|---|---| +| 拓扑(平板 → 网关) | ✓ 通 | `mail.jianfgit.xyz` = 192.168.2.60 = 本机;设备 SSE 已 connected | +| 应用本身 | ✓ 正常 | 登录态在、收件箱渲染、SSE 收流 | +| HMS Core | ✓ 在 | `com.huawei.hms.pushservice` + `accountmgr` + `hms.pafservice` 均运行 | +| 服务端 HMS 凭证 | ✓ 有效 | 向华为换到 access_token(长度 104,有效期 3600s) | +| 服务端推送实现 | ✓ 就绪 | `push.json` provider `hms` enabled,app_id `6917616450599975320` | +| 包内 client_id | ✓ 正确 | 打进 HAP 的 `module.metadata` = `2039846327155747840`,与 `agconnect-services.json` 一致 | +| **平板取 token** | **✗ 失败** | 见下 | +| 服务端 token 登记 | ✗ 空 | `push_tokens` 表 0 行 | + +--- + +## 二 根因:华为侧拒绝这个「应用身份」 + +设备日志(`hilog`,`PushService` tag,抓取自一次 `force-stop` + 重启): + +``` +I A00001/com.jianf.agentmail/PushService: push token 取不到(静默,属正常): + Illegal application identity may be caused by incorrect clientid configuration. +``` + +华为原话是 **`Illegal application identity may be caused by incorrect clientid configuration`**, +即「应用身份非法,可能因 clientid 配置错误」。 + +### ★★ 2026-10-02 复测:根因比上面写的**更具体**,且已能定位到具体文件 + +重跑一次 `force-stop` + 启动,抓到一条上一轮**漏掉**的华为侧日志(`cloudinterfaceauth/AuthService`): + +``` +E cloudinterfaceauth/AuthService: cert finger empty, clientId: 2039846327155747840, + isTestEnv: 0, isSubApp: 0, Fingerprint: 153F****F919 +I PushService: push token 取不到:code=1000900010 Illegal application identity … +``` + +**`cert finger empty`** —— 设备端报上来的是**空指纹**。这不是"指纹对不上 AGC", +而是"**根本没有应用指纹可报**"。`bm dump` 与之吻合: + +``` +"appSignType": "none" ← 签名类型:none +"signatureKey": "" ← 签名身份:空 +``` + +### 真正的根因(三个指纹的实测对比) + +| 证书 | SHA-256 | CN | +|---|---|---| +| `build-profile.json5` 里 `certpath` 指的 `.cer` | `DF:21:A3:C0:…:DF:3A:37` | **Huawei CBG Root CA G2** | +| `.p7b` profile 内嵌 `development-certificate` | `FD:89:AC:53:…:FC:9D:09` | 靳睿(1681189977251159745)\,Development | + +⇒ **工程签的是那张 CA 根证书,而 profile 绑定的应用证书是另一张**(CN 是开发者本人, +不是 Huawei CA)。包里没有应用身份 ⇒ 设备算出空指纹 ⇒ HMS 判非法身份 ⇒ 拿不到 token。 +**这不是"debug 证书不被接受",是"签错了证书"。** + +profile 侧其余要素都正常,已逐项排除: + +- `"bundle-name": "com.jianf.agentmail"` ✓ +- `"type": "debug"`、`validity` 1789442580→1820978580 未过期 ✓ +- **平板 UDID 在 `device-ids` 里**:`678AFBFAD8DA9C110BBD8ABD83724BA951F9F9D6A881852BC51F0CA4BAC98EA7` + (`bm get -u` 实测值,与 profile 逐字一致)✓ —— 所以装得上、跑得起来 + +### 试过的那条路(**没走通**,记下来免得重走) + +把 `certpath` 改成 profile 内嵌的那张 dev cert(单张)→ hvigor 直接失败: + +``` +ERROR: 11013004 Profile cert must a cert chain +Error Message: cause in cert file: /root/.ohos/config/agentmail-dev.cer +``` + +⇒ **`certpath` 要的是一条「应用证书 + 签发它的 CA」的链**,不是单张。 +而那张 dev cert 的签发者 `Huawei CBG Developer Relations CA G2` **本机没有**: +`/root/.ohos/config/` 下 5 个 `.p7b` 里都只有 +`Root CA G2` / `HOS Profile Management Debug` / `Software Signing Service CA` 三张, +`~/.ohos/config/material/` 里也没有任何证书(只有几个 16/48 字节的散列)。 + +⇒ 结论不变(要用户从 AGC/DevEco 导出完整那套),但**要的东西要说准**: +不只是 `.cer`,而是**能构成链的整套**(应用证书 + 其签发 CA)。给一张单证书是装不上的。 + +--- + +### 需要纠正的一个先入判断 + +我一开始判断「HMS Push 只接受发布证书、debug 包必然拿不到 token」。**真机日志否证了它的表述**: +报错指向的是 client_id / 应用身份,**没有**说 debug 证书不被接受。 +现在(2026-10-02)进一步定位到:问题**不在"debug 还是 release"这个轴上**, +而在"**签的是哪张证书**"——签成了 CA 根,profile 却绑的是开发者应用证书。 +即使换成发布证书,如果仍然只拿到单张 `.cer` 而没有链,`certpath` 一样编不过。 + +--- + +## 三 要跑通完整闭环,需要你提供什么 + +本机只有**一套**签名,就是当前装在平板上的那套 debug 签名: + +``` +/root/.ohos/config/default_harmony_k2yruKTLaTiZOjublhUDTfveVx5uFoHqm96pwkUw=.{cer,p12,p7b,csr} + CN = Huawei CBG Root CA G2 + SHA256 = DF:21:A3:C0:9F:79:54:57:93:05:F8:5C:64:F8:0C:AD:86:F7:98:53:EE:3A:88:7C:1D:EC:95:D2:18:DF:3A:37 + → 工程里 keyAlias 名为 debugKey,设备 appSignType=none +``` + +`/root/.ohos/config/` 下另有 4 套(EcoArk / HelloWorld / HomeAgent / SlipOfNote), +但它们是**别的应用**的证书——AGC 的包名与证书绑定,不能拿来签 `com.jianf.agentmail`。 + +**需要你从 AGC 后台 / DevEco Studio(应用 `com.jianf.agentmail`)导出:** + +1. **应用证书 `.cer`** —— 注意要**能构成链**(见上:`11013004 Profile cert must a cert chain`)。 + 最省事的是直接在 DevEco 里对这个工程 **Project Structure → Signing Configs → 同步签名** + (它会自动取回正确的证书与链并改好 `build-profile.json5`)。 +2. 签名私钥 `.p12` + 其口令 +3. profile `.p7b`(当前这份已包含 `com.jianf.agentmail` 与这台平板的 UDID, + 实测可复用;若走发布通道则需重新导出含本机 UDID 的发布 profile) + +拿到后我会做: + +- 写入新的 `signingConfigs` 条目,**保留**现有 debug 配置(不破坏别的工程); +- `devecocli build` 出签名正确的 HAP,`hdc install -r` 装到平板; +- **先验签**:`bm dump` 里 `appSignType` 不再是 `none`、`signatureKey` 非空 + —— 这一步过了,才值得去重跑 token; +- 真机重跑 token 获取 → 确认 `push_tokens` 出现 1 行; +- 服务端发一封真实邮件 → 平板弹出通知 → **点通知**验证跳转到那封信(冷启 + 热启两条路径, + 后者是 2026-09-17 实测发现过的死路径)。 + +--- + +## 四 顺带发现、尚未处理的两点 + +1. **`click_action` 缺失**:服务端 `push/hms.go` 的 `notification` 只有 `title`/`body`, + 跳转信息全在 `data` 字符串里。华为的规范做法是 `click_action: {"type":1,"intentData":"..."}`。 + 当前 `data` 解析路径可用,但点击行为的规范性未验证(待上面闭环跑通后在真机上看实际表现)。 +2. **`test_message: true`**:`push.json` 里开着。它让华为把消息记为「测试消息」(有独立配额, + 且不上架限制)。上架后需要关掉——这条在 `push_test.go` 里有判据守着,不会漏。 + +--- + +## 五 复现步骤(可重跑) + +```bash +export PATH=$PATH:/opt/huawei/command-line-tools/sdk/default/openharmony/toolchains +D=192.168.2.87:43679 +hdc tconn $D # 连真机 +hdc -t $D shell "hilog -r" # 清缓冲 +hdc -t $D shell "aa force-stop com.jianf.agentmail" +hdc -t $D shell "aa start -a EntryAbility -b com.jianf.agentmail" +sleep 15 +hdc -t $D shell "hilog -x | grep PushService" # ← 报错在这里 + +# 服务端侧 +sqlite3 /opt/agentmail/data/agentmail.db "SELECT * FROM push_tokens;" # 空 +journalctl -u agentmail-gateway --since '1 hour ago' | grep -i push +``` + +--- + +## 六 自证边界 + +- 「服务端凭证有效」是**实测**:真的换到了 access_token。 +- 「根因是证书不匹配」是**推断**:三项绑定要素里包名与 client_id 已证实正确, + 证书指纹与 AGC 侧登记值的比对**没法在本机完成**(AGC 后台值需登录网页查看)。 + ⇒ 该结论要等换上发布证书后**复测**才算定案;若换签名后仍报同一错, + 则应转查 AGC 后台该 client_id 绑定的包名/证书。 +- 「HMS Push 不接受 debug 包」这句**已撤回**,理由见 §二。 \ No newline at end of file