Files
MailUI4Agents/docs/PUSH-DEVICE-DIAGNOSIS.md
JianFeeeee b2a0a42c91 docs(harmony): ★★ 推送根因定位到"**签错了证书**",不是"debug 证书不被接受"
平板复测抓到一条上一轮漏掉的华为侧日志,它把根因从推断变成实测:

    E cloudinterfaceauth/AuthService: cert finger empty, clientId: 2039846327155747840
    I PushService: push token 取不到:code=1000900010 Illegal application identity

★ `cert finger empty` = 设备报上来的是**空指纹**,不是"指纹对不上"。
  与 `bm dump` 完全吻合:appSignType=none、signatureKey=""。
  ⇒ 包里根本没有应用签名身份。

三个指纹实测对比(本机 openssl 算出):
  build-profile.json5 的 certpath → DF:21:A3:C0:…:DF:3A:37  CN=Huawei CBG Root CA G2
  .p7b 内嵌 development-cert    → FD:89:AC:53:…:FC:9D:09  CN=靳睿(…)\,Development
⇒ 工程签的是 **CA 根证书**,profile 绑的是**开发者应用证书**,两者根本不是同一张。

profile 侧其余要素已逐项排除为无关:bundle-name 对、type=debug、validity 未过期、
平板 UDID(bm get -u)逐字出现在 device-ids 里。

★★ 顺带记下走不通的那条路,免得下次重走:
  把 certpath 改成 profile 内嵌的单张 dev cert → hvigor 报
  `11013004 Profile cert must a cert chain`。
  **certpath 要的是一条链**,而那张 dev cert 的签发者
  `Huawei CBG Developer Relations CA G2` 本机没有(5 个 p7b 里都没有,
  material/ 里也没有任何证书)。
  ⇒ 给用户要材料时要说准:要**能构成链的整套**,单张 .cer 装不上;
    最省事是 DevEco 里 Project Structure → Signing Configs 直接同步签名。

服务端侧本轮复验仍正常:与 hms.go 同形(不带 scope)请求华为换到
access_token,长度 104、有效期 3600s ⇒ 断点确实只在设备侧签名。

build-profile.json5 的 certpath 保持原值并加了注释:改成单张 dev cert 会编译不过,
留着编不过的值只会连应用都装不上。
2026-10-02 00:32:21 +08:00

178 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 真机推送联合调试:诊断报告
日期: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 包」这句**已撤回**,理由见 §二。