- 删除 VerificationCodeParser 及相关测试,短信捕获和推送不再解析验证码 - 飞书推送改为只发送短信原文,时间戳格式化为可读日期 - 移除主界面"只推送验证码"开关和"调试时上传完整短信正文"选项 - 移除"保存轮询间隔"按钮,开启轮询时自动保存间隔(未输入默认1秒) - 按钮文字从"开始1秒轮询验证码"改为"开始短信轮询" - 删除"打印最近30条短信"功能及相关 SmsInboxReader.logRecentMessages - SmsInboxReader 用 RecentSmsResult 替换 RecentCodeResult - FeishuWebhookConfigStore.Config 移除 filterVerificationCode/sendFullBodyDebug - 修复代码缩进不一致问题
68 lines
4.6 KiB
Markdown
68 lines
4.6 KiB
Markdown
## Why
|
||
|
||
当前 `SmsReceive` 已经具备短信原文接收、存储和本地诊断能力。新需求是在收到字符串内容后,把它发送到服务器。用户已经给出 Python 参考实现,目标服务器实际是飞书机器人 webhook:构造 interactive markdown 卡片,使用 `timestamp + "\n" + secret` 生成 HmacSHA256 + Base64 签名,然后 POST 到 `https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`。
|
||
|
||
这次变更的重点不是重新设计服务端协议,而是把 Python 中已经验证过的请求协议等价迁移到 Android,并与当前短信接收链路解耦。Android 侧应提供一个可测试、可诊断、可复用的发送模块,后续可以由 `SmsReceiver`、手动测试按钮或其它业务入口调用。
|
||
|
||
## What Changes
|
||
|
||
- 新增飞书 webhook 推送规格,覆盖:
|
||
- 签名算法:保持与 Python `generate_sign(secret, timestamp)` 完全一致。
|
||
- 请求体:保持 `msg_type=interactive`,卡片元素为 markdown content。
|
||
- URL:`https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`。
|
||
- 网络请求:Android 侧使用 OkHttp 作为首选实现,避免为了一个简单 POST 引入 Retrofit 接口层。
|
||
- 线程模型:所有网络请求必须在后台线程执行,不能阻塞 `BroadcastReceiver.onReceive` 或主线程。
|
||
- 结果判断:HTTP 200 且响应 JSON `code == 0` 才视为成功。
|
||
- 失败诊断:区分签名失败、参数缺失、HTTP 非 200、响应 JSON 异常、飞书业务错误码、网络异常和超时。
|
||
- 新增轻量配置入口:
|
||
- `webhook_id`、`secret` 不写死在代码中。
|
||
- 实际配置从 `/sdcard/Android/data/{applicationId}/config/feishu.json` 读取,便于动态调试。
|
||
- 如果 `feishu.json` 不存在,则生成默认模板 `/sdcard/Android/data/{applicationId}/config/def_config_feishu.json`。
|
||
- 后续实现可接入当前短信结果:
|
||
- 成功读取短信原文后,可以把短信内容、来源、时间和发送方掩码作为 markdown 内容推送。
|
||
- 默认推送完整短信原文,便于确认服务端收到的内容与本机短信一致。
|
||
|
||
## Capabilities
|
||
|
||
### New Capabilities
|
||
|
||
- `feishu-webhook-push`: 定义 Android 侧飞书机器人 webhook 推送能力,包括签名、请求体、网络执行、响应解析、错误诊断和隐私边界。
|
||
|
||
### Modified Capabilities
|
||
|
||
- `sms-code-capture`: 后续实现可以在短信原文读取成功后触发推送,但短信捕获本身不依赖网络成功。
|
||
- `sms-receiver-delivery-diagnostics`: 后续诊断应区分“短信接收/解析成功”和“远端推送成功/失败”,避免把网络失败误判为短信接收失败。
|
||
|
||
## Impact
|
||
|
||
- 预期后续会修改:
|
||
- `app/build.gradle`:新增 OkHttp 依赖,必要时新增 JSON 解析依赖或使用 `org.json`。
|
||
- `app/src/main/AndroidManifest.xml`:新增 `android.permission.INTERNET`。
|
||
- `app/src/main/java/com/smsreceive/app/`:新增飞书推送相关 Java 类,例如 `FeishuWebhookClient`、`FeishuWebhookConfigStore`、`FeishuWebhookPushResult`。
|
||
- `MainActivity`:新增 JSON 配置路径展示、配置输入、测试发送和最近推送结果展示。
|
||
- `SmsReceiver` 或统一结果处理层:在短信原文读取成功后触发异步推送。
|
||
- 推荐技术选择:
|
||
- 网络库:OkHttp。
|
||
- JSON 构造/解析:优先使用 Android 自带 `org.json`,降低依赖数量。
|
||
- 签名:`javax.crypto.Mac` + `SecretKeySpec` + `android.util.Base64.NO_WRAP`。
|
||
- 异步执行:小型 `ExecutorService` 或现有轻量后台执行器,不引入协程/RxJava。
|
||
- 隐私影响:
|
||
- 默认推送短信原文、来源、发送方掩码和时间。
|
||
- 不在 logcat 打印 secret、sign、完整 webhook URL 或完整短信正文。
|
||
|
||
## Validation
|
||
|
||
- OpenSpec 文档结构完整,包含 `proposal.md`、`design.md`、`tasks.md` 和 capability spec。
|
||
- 方案必须能解释以下问题:
|
||
- Python 签名算法如何在 Android 中等价实现。
|
||
- 为什么首选 OkHttp 而不是 Retrofit。
|
||
- 为什么网络请求不能直接在 `BroadcastReceiver.onReceive` 内同步执行。
|
||
- 如何判断推送成功,以及失败时如何诊断。
|
||
- 哪些短信内容可以上传,哪些默认不上传。
|
||
- 后续代码完成后:
|
||
- 签名单元测试使用固定 `secret` 和 `timestamp` 对比 Python 算法输出。
|
||
- 请求体构造测试验证 JSON 字段与 Python 参考实现一致。
|
||
- 响应解析测试覆盖 `code == 0`、业务错误码、非 JSON 响应。
|
||
- 不要求本轮编译;代码完成后通知用户即可。
|
||
- 每次 commit 或 push 前必须检查 diff,避免引入非预期 EOF newline 变化。
|