# WeCom Callback Debugging: Tunnel + Verification + IP Whitelist

## 快速诊断：请求到了哪一层？

```bash
curl -sI https://callback.gdcjgk.net/wecom/callback | grep -E "server:|HTTP/"
```

| Server 头 | 含义 | 动作 |
|-----------|------|------|
| `server: cloudflare` + `set-cookie: server_name_session` | Cloudflare 边缘拦截，未进入 tunnel | Dashboard 加 Public Hostname |
| `server: Python/3.11 aiohttp` | 到达 Hermes，Tunnel 正常 | 检查 Token/AES Key |
| `signature verification failed` (403) | Hermes 收到但签名不匹配 | 确认 Token/AES Key 与企微后台一致 |

## 三层排查清单

### 1. Tunnel 层

```bash
# Tunnel 是否在运行？
systemctl status cloudflared-tunnel

# 本机 Tunnel 路由了哪些 hostname？
grep -A10 "ingress:" ~/.cloudflared/config.yml
```

⚠️ config.yml 有 ingress 规则 ≠ 请求能到达。必须在 Cloudflare Zero Trust Dashboard **添加 Public Hostname**。

### 2. 端口层

```bash
# Hermes 是否在监听 8645？
ss -tlnp | grep 8645

# wecom_callback 配置
grep -A10 "wecom_callback:" ~/.hermes/config.yaml
```

### 3. Token/AES Key 层

```bash
# 看 Hermes 日志 — 是否有验证请求到达
grep -i "callback\|verify\|signature" ~/.hermes/logs/gateway.log | tail -10
```

如果看到 `signature verification failed` → Token 或 AES Key 不匹配。

## 回调验证通过但收不到回复

**现象**：企微后台回调 URL 验证通过，用户发消息 Hermes 能收到日志，但回复发不出去。

**诊断**：
```bash
curl -s "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=wwbcfb7cbc0f8912d7&corpsecret=2ad1mn5mqxMuopQxWpc0QCZG0EEfAlu9pr7DIA66p4s"
# errcode 60020 = IP 不在白名单
# errcode 0 = ok
```

**原因**：回调是企微主动 POST（入站，走 tunnel）。回复是 Hermes 调企微 API（出站，直连），企微验证来源 IP。迁移后新 IP 不在白名单。

**修复**：企微后台 → 应用管理 → 企业可信IP → 添加新服务器公网 IP。保存后立即生效。

## 双服务器 Tunnel 共享陷阱

同一 Tunnel ID 在两台服务器上运行 → Cloudflare 负载均衡。其中一台停机后：
- 存活服务器承接所有流量
- 停机服务器独有的服务 502

诊断：
```bash
journalctl -u cloudflared-tunnel --no-pager | grep "Registered tunnel connection"
```
