# TNG Money Packet 领取台说明

> 更新：2026-08-04  
> 相关代码：`TngMoneyPacketHook.java`、`debug-server/server.py`、`AppConfig.DEBUG_SERVER_URLS`

## 目标

抓取 TNG eWallet **Money Packet（红包）** 的领取排行：谁领了、领了多少，并在 PC 调试台按**单个红包**展示。

## 手机端领取台

主 App 首页有 **红包领取台（独立）** 入口（`MmpClaimActivity`）：

- Hook 收到 `[MMP统计]` 后写入本地 `MmpPacketStore`，**不进入**通用「情况」监听台、也不走正式上传
- 手机数据可同步到 PC：打开领取台会自动同步，也可点「同步电脑」；PC 打开 http://127.0.0.1:8765/mmp 即可看（落盘 `mmp_packets.json`，重启调试台不丢）
- PC 调试台红包数据走独立队列，与 `/` 通用消息台隔离
- 列表支持筛选（全部/领取中/已领完 + 关键词）、详情/卡片显示手气（领完）或目前最高/最低（领取中）
- 点进看领取排行；支持清空（仅红包）
- 需监听列表勾选 TNG，且 Xposed 模块生效
- **功能说明页**：手机顶栏「说明」→ `MmpHelpActivity`；电脑 http://127.0.0.1:8765/mmp/help

PC 页 http://127.0.0.1:8765/mmp ；手机浏览器也可访问（USB reverse 或局域网 IP）。

---

## 页面与地址

| 入口 | 地址 |
|------|------|
| 本机（USB + `adb reverse`） | http://127.0.0.1:8765/mmp |
| 功能说明 | http://127.0.0.1:8765/mmp/help |
| 局域网 / USB 共享网 | http://&lt;电脑IP&gt;:8765/mmp （当前常见：`http://10.151.104.25:8765/mmp`） |
| 通用消息台 | http://127.0.0.1:8765/ |

手机推送会同时尝试：

- `http://127.0.0.1:8765`（需 `adb reverse tcp:8765 tcp:8765`）
- `http://10.151.104.25:8765`（USB 共享网段；若电脑 IP 变了，改 `AppConfig.DEBUG_SERVER_URLS`）

启动调试台：

```powershell
powershell -ExecutionPolicy Bypass -File scripts/start-debug-server.ps1
```

## 红包唯一标识

正式字段是 **`activityId`**（UUID），例如：

- `b8c37a58-bb2c-4aa2-83ef-f15466b9211e`
- `e5dcf293-4062-4df4-a692-e3bf194d9a37`

领取台左侧按 `activityId` 分条；详情页会显示完整 ID。  
转发正文格式示例：

```text
[MMP统计] packet=<activityId> | sender=... | total=1.00 | via=rpc | src=moneyPacketDetail
昵称A -> 0.71
昵称B -> 0.29
```

金额在 App 内多为 Money 对象 `{"amount":"0.71","cent":"71",...}`，Hook / 调试台会规范成数字再展示。

## 数据从哪来

| 来源 | Quake op / 方法 | 内容 |
|------|-----------------|------|
| 历史列表 | `moneyPacketHistoryList` / `ap.tngdwallet.moneyPacket.list.retrieve` | 仅摘要：`activityId`、总额、时间等，**无领取排行** |
| 红包详情 | `moneyPacketDetail` / `ap.tngdwallet.moneyPacket.retrieve` | 含 `activityPoolInfos`（领取人 + 金额） |

外部 mitm 因证书 pinning **解不开** TNG API 正文；必须用进程内 Xposed（`TngMoneyPacketHook`）。

消费端详情领取列表字段主要是 **`activityPoolInfos`**（`receiverName` + `amount`），不是商户版的 `receiverList`。

## 推荐操作流程（自动拉历史 + 详情）

登录后**无需再手动点详情灌模板**，也**不必反复进历史页**：

1. 打开 TNG 并完成登录 / PIN（任意前台页面即可）  
2. Hook 从 `ILoginStorage` / 历史请求自动取 `sessionId`；`Activity.onResume` 按设置冷却主动调 `moneyPacketHistoryList`  
3. 历史返回后自动按 `activityId` 串行拉详情（间隔见设置），推送到领取台  
4. 仅打开 **Money Packet 历史页**时，App 自己的列表响应也会立刻触发步骤 3  
5. 打开 http://127.0.0.1:8765/mmp ；点 **设置** 可调刷新速度，保存后约 10 秒内生效

日志期望：

- `hooked ILoginStorage getters` / `login from storage session=…` / `cached history request template`  
- `history hit → schedule auto detail` 或 `auto-history ok → schedule details`  
- `auto-detail ok activityId=… claims=N`  

若仍无数据：确认已安装最新 Xposed 模块并强停重启 TNG；看是否出现 `auto-detail empty claims` / `no sessionId`。

## 去重与刷新行为

冷却时间可在领取台 **设置** 面板调整（`/mmp` → 设置），保存后约 **10 秒内**手机 Hook 生效。默认偏快（历史/详情约 8 秒）。

| 规则 | 说明 |
|------|------|
| 标识 | 以 `activityId` 区分红包 |
| sessionId | 自动：`ILoginStorage` / Repository.loginStorage；有真实请求时也会缓存 |
| 自动历史 | 前台 `onResume` 触发；冷却见设置「历史列表冷却」 |
| 短时去重 | 同一 `activityId` + **相同领取名单**，「相同名单去重」秒内不重复推送 |
| 自动拉冷却 | 同一 `activityId` 自动拉详情成功后，「详情刷新冷却」内不重复自动拉 |
| 包间间隔 | 自动拉详情串行，「详情请求间隔」毫秒/条 |
| 无模板 | 「无模板时自动打开历史页」可关，避免突然跳转 |
| 调试台 | 同一 `activityId` 只保留最新完整快照；双通道短时内容去重 |

预设：**极速**（约 5s）/ **标准**（约 8s）/ **省流**（约 30–45s）。

日志里若出现 `skip dup activityId=...`，表示短时去重生效，不是没抓到。
`settings applied hist=…` 表示 Hook 已拉到新配置。

| 已领完停刷 | `remainingCount<=0` / `claimed>=total` / status FINISH·COMPLETE·EXPIRE / 金额凑齐，且**已有领取名单**后不再自动拉该包详情 |
| 断线重连 | session 丢失或 RPC 鉴权/网络失败 → 标记断开；session 恢复或 Activity resume 时**强制**重拉历史 |

日志：`packet DONE stop-refresh`、`session lost`、`session recovered → force re-fetch`。

---

## 排障

### 打开 TNG 闪退

装了 Xposed / 防护相关模块后，TNG 偶发一打开就闪退，属常见现象：

1. **多点几次**图标再打开（前几次崩、后面能进的情况不少见）
2. 仍不行：系统设置 → 应用 → TNG → **强制停止**，再重新打开
3. 还不行：强制停止后清「缓存」（尽量别清「数据」，否则要重新登录）
4. 推送 / 更新过 Hook 模块后：务必强制停止再开 TNG，否则新逻辑可能不生效或更易闪
5. 连续闪退：先关掉 LSPosed 里本模块对 TNG 的作用域试能否正常打开，确认后再勾回并强停重开

手机 / PC 功能说明页也写了同样步骤（「说明」或 `/mmp/help`）。

```text
adb logcat | findstr TngMmp
```

常见日志：

| 日志 | 含义 |
|------|------|
| `TngMmp installed` | Hook 已加载 |
| `cached RPC task MoneyPacketRpcTask` | 已缓存 RPC 代理 |
| `cached detail request template` | 已缓存手动详情请求（可选加速） |
| `login from storage session=…` | 已从 ILoginStorage 自动取到 session |
| `auto-history ok → schedule details` | 已自动拉历史列表 |
| `auto-detail empty claims ... totalCount:0` | 请求缺登录态或服务端空结果 |
| `auto-detail ok activityId=... claims=N` | 自动拉详情成功 |
| `captured activityId=... claims=N` | 已转发到 notiMessage / 调试台 |

其它检查：

1. LSPosed 作用域包含 `my.com.tngdigital.ewallet`，模块为最新 APK（期望 **1.2.0 / versionCode 3**）  
2. 强停后再开 TNG，使新 Hook 生效；领取台状态栏应显示「运行中：最新」  
3. 领取人重名时看详情里的 `ID`（`receiverId`），不要只看昵称  
4. 调试台进程在跑；USB 时执行过 `adb reverse`  
5. notiMessage 监听列表勾选了 TNG（Hook 转发依赖主 App 接收广播）  
6. 电脑 USB 共享 IP 变化后更新 `AppConfig.DEBUG_SERVER_URLS` 并重装主 App  

## 相关文件

| 文件 | 作用 |
|------|------|
| `xposed-module/.../hook/TngMoneyPacketHook.java` | Quake RPC Hook、自动拉详情、轮询领取台设置 |
| `app/.../mmp/MmpHookStatus.java` | 检测 TNG 内 Hook 是否最新模块 |
| `app/.../mmp/MmpClaim.java` | 领取人含 `userId`（receiverId） |
| `debug-server/server.py` | `/mmp` 领取台、`/api/mmp`、`/api/mmp/settings` |
| `debug-server/mmp_settings.json` | 领取台刷新设置（自动生成） |
| `app/.../AppConfig.java` | `DEBUG_SERVER_URLS` 双地址 |
| `app/.../network/DebugForwarder.java` | 向多个调试地址推送 |
| `scripts/start-debug-server.ps1` | 启动调试台 + adb reverse |
