|
|
@@ -15,7 +15,7 @@
|
|
|
- 当前工作分支为 `test-202609v2`;用户要求不创建新分支。保留工作区已有未提交修改,尤其不修改与功能无关的 `InfoUserController.java` 测试接口。
|
|
|
- `business-push.mode` 只允许 `uni`/`native`,缺省为 `uni`,切换后重启生效;不做后台实时开关。默认模式不能要求原生凭据。
|
|
|
- `cid` 仅用于 uniPush,`deviceToken` 仅用于普通 FCM/APNs,`voIPToken` 不参与;单账号单设备,不改数据库结构。
|
|
|
-- 三端 Firebase 服务账号属于不同项目,必须初始化三个命名 `FirebaseApp`;iOS 使用三端各自的普通推送 `.p12`,按部署环境选择 APNs 开发/生产地址。凭据路径和密码从外部环境注入,不提交密钥内容。
|
|
|
+- 三端 Firebase 服务账号属于不同项目,必须初始化三个命名 `FirebaseApp`;iOS 使用三端各自的普通推送 `.p12`,按部署环境选择 APNs 开发/生产地址。2026-09-29 追加要求将三端真实凭据明确命名后提交 `resources/business-push/`,随 JAR 打包;仓库及构建产物按含密钥材料管理,禁止日志输出私钥或密码。
|
|
|
- 只迁移在用的普通业务通知;音视频通话、已废弃入口和临时测试推送接口保持原行为。已有 `PushEvent` 入库时机与次数不改变,外发失败不影响业务且不自动转发 uniPush。
|
|
|
- 后端集成代码放在 `ruoyi-admin`,不让 `ruoyi-system` 反向依赖应用层;不执行数据库 SQL。仅当前 Maven 命令临时使用 JDK 21,保留现有换行风格。
|
|
|
|
|
|
@@ -24,7 +24,7 @@
|
|
|
1. 原生模式有 `deviceToken`、无 `cid` 的用户仍能被收件人筛选并发送;默认 uni 模式仍按 CID 判断。
|
|
|
2. 用户、骑手、商家(含夜市及子账号)不会混用 Firebase 项目或 APNs topic;相同设备的商家收件人去重按当前通道地址。
|
|
|
门店订单收件人仍是分管账号优先、主账号兜底,不同时发给两类账号。
|
|
|
-3. iOS 开发/生产证书与网关一致;缺失、过期、无法解锁或无私钥的证书在原生模式启动时明确失败。
|
|
|
+3. iOS 开发/生产网关切换复用同端证书;缺失、过期、无法解锁或无私钥的证书在原生模式启动时明确失败。
|
|
|
4. LINE Pay/OMG 等本来已经自行发布 `PushEvent` 的路径不会因迁移产生第二条消息记录,且 CID 为空时原生发送仍可进行。
|
|
|
5. `VideoCallController`、`/testPushMessage` 和测试批量接口继续走现有行为;业务通知 payload 的 `ddId/state/type/pushType` 不丢失。
|
|
|
|
|
|
@@ -39,7 +39,7 @@
|
|
|
|
|
|
## External Configuration Contract
|
|
|
|
|
|
-`application.yml` 仅保留 `business-push.mode: uni` 和环境变量占位符;部署时分别提供 `business-push.apps.user`、`business-push.apps.merchant`、`business-push.apps.rider` 下的 `fcm-credentials-path`、`apns-certificate-path`、`apns-certificate-password`、`apns-topic`。`business-push.apns-environment` 为 `development` 或 `production`。只有 `native` 模式校验并加载三端凭据;配置中没有凭据内容。iOS 证书须对应所选环境与 topic。
|
|
|
+`application.yml` 保持 `business-push.mode: uni`,三端文件路径设为有 `user`、`merchant`、`rider` 前缀的 `classpath:business-push/...` 资源。三端各提交一份独立 FCM 服务账号、一份 APNs 普通 `.p12` 和一份含 `packetName/pwd` 的配置 JSON;原生模式从该配置读取 topic 和证书密码。`business-push.apns-environment` 为 `development` 或 `production`,两环境使用每端同一张证书,只切换网关。原有外部文件路径及显式密码/topic 配置继续兼容。默认 `uni` 模式不读取凭据。
|
|
|
|
|
|
FCM 请求的 data 至少包含字符串形式的 `title`、`body`、原始 `payload`,并保留现有可解析 payload 的 `ddId/state/type/pushType` 字段;APNs 使用 `aps.alert.title/body`、普通通知 sound 和同名业务字段。iOS 骑手端沿用现有 `pushsound.caf`,其余 iOS 端使用默认声音;Android FCM 使用默认声音,并为骑手标记 `qsRing` 通知渠道,最终自定义铃声取决于 App 是否创建该渠道(App 端不在本任务内)。过大或无法解析的 payload 必须记录可定位的失败类别,不得以截断方式改变业务字段。
|
|
|
|
|
|
@@ -48,7 +48,7 @@ FCM 请求的 data 至少包含字符串形式的 `title`、`body`、原始 `pay
|
|
|
| 文件 | 职责 |
|
|
|
|---|---|
|
|
|
| `ruoyi-admin/src/main/java/com/ruoyi/app/push/RecipientApp.java` | USER / MERCHANT / RIDER 显式接收端标识 |
|
|
|
-| `ruoyi-admin/src/main/java/com/ruoyi/app/push/BusinessPushProperties.java` | 全局模式、APNs 环境、三端外部凭据路径与 topic 的配置绑定和原生模式校验 |
|
|
|
+| `ruoyi-admin/src/main/java/com/ruoyi/app/push/BusinessPushProperties.java` | 全局模式、APNs 环境、三端 classpath/外部凭据路径与 APNs 配置路径绑定和原生模式校验 |
|
|
|
| `ruoyi-admin/src/main/java/com/ruoyi/app/push/FcmPushSender.java` | 三个命名 FirebaseApp;Android 单发、请求构造与失效错误分类 |
|
|
|
| `ruoyi-admin/src/main/java/com/ruoyi/app/push/ApnsPushSender.java` | 三个证书型 HTTP/2 客户端;APNs alert、custom payload 与响应处理 |
|
|
|
| `ruoyi-admin/src/main/java/com/ruoyi/app/push/BusinessPushService.java` | 统一外发路由、当前账号读取、通道地址判断及安全日志 |
|
|
|
@@ -77,7 +77,7 @@ FCM 请求的 data 至少包含字符串形式的 `title`、`body`、原始 `pay
|
|
|
|
|
|
- [ ] Write tests: each app resolves its own named Firebase project; sends to `token`, never CID; title/content plus existing payload fields survive as string data; `UNREGISTERED` and project mismatch are classified without full token logging; repeated initialization does not conflict.
|
|
|
- [ ] Run `mvn -pl ruoyi-admin -am -Dtest=FcmPushSenderTest -Dsurefire.failIfNoSpecifiedTests=false test` with JDK 21 and verify failure before implementation.
|
|
|
-- [ ] Initialize credentials from protected filesystem paths, build FCM notification + Android high-priority data, and send through the app-specific `FirebaseMessaging` instance; do not adopt CTE's single-default-app/CID assumptions.
|
|
|
+- [ ] Initialize credentials from the configured classpath or filesystem path, build FCM notification + Android high-priority data, and send through the app-specific `FirebaseMessaging` instance; do not adopt CTE's single-default-app/CID assumptions.
|
|
|
- [ ] Re-run the same directed command and confirm pass; inspect staged names, commit only Task 2 files.
|
|
|
|
|
|
## Task 3: 三端 iOS APNs 普通通知
|
|
|
@@ -88,7 +88,7 @@ FCM 请求的 data 至少包含字符串形式的 `title`、`body`、原始 `pay
|
|
|
|
|
|
- [ ] Write tests: each app selects its own topic/certificate; DEVELOPMENT/PRODUCTION selects sandbox/production host; alert title/body, sound and custom payload preserve business fields; malformed/expired/no-private-key PKCS#12 fails initialization; non-2xx response is categorized without printing secrets.
|
|
|
- [ ] Run `mvn -pl ruoyi-admin -am -Dtest=ApnsPushSenderTest -Dsurefire.failIfNoSpecifiedTests=false test` with JDK 21 and verify failure before implementation.
|
|
|
-- [ ] Load selected-environment PKCS#12 into per-app TLS client, reuse JDK HTTP/2 connections, send to `/3/device/{token}`; use ordinary alert push, not VoIP; use rider `pushsound.caf` and the existing default sound for other apps.
|
|
|
+- [ ] Load the app-specific PKCS#12 into per-app TLS client, reuse JDK HTTP/2 connections, send to `/3/device/{token}` on the selected environment's gateway; use ordinary alert push, not VoIP; use rider `pushsound.caf` and the existing default sound for other apps.
|
|
|
- [ ] Re-run the same directed command and confirm pass; inspect staged names, commit only Task 3 files.
|
|
|
|
|
|
## Task 4: 统一外发路由与现有包装方法
|
|
|
@@ -117,7 +117,7 @@ FCM 请求的 data 至少包含字符串形式的 `title`、`body`、原始 `pay
|
|
|
|
|
|
**Files:** Create `specs/033-native-push-routing/quickstart.md`; update `specs/012-im-user-integration/code-status.md`, `docs/order-push-overview.md`, `specs/033-native-push-routing/tasks.md`.
|
|
|
|
|
|
-- [ ] Document credential deployment (paths/env vars only, no values), dev/prod APNs selection, default-off, restart cutover/rollback, certificate expiry monitoring and real-device smoke checklist.
|
|
|
+- [ ] Document bundled classpath credentials (filenames only, no secret values), dev/prod APNs gateway selection, default-off, restart cutover/rollback, certificate expiry monitoring and real-device smoke checklist.
|
|
|
- [ ] Run `mvn -pl ruoyi-admin -am -Dtest=BusinessPushPropertiesTest,FcmPushSenderTest,ApnsPushSenderTest,BusinessPushServiceTest,MerchantNotificationRouterTest,DeliveryOrderNotificationServiceTest,OmgPaymentNotifyServiceTest,PosOrderShOprateControllerTest,PosOrderQsOprateControllerTest,PosOrderAdminStatusControllerTest,LinePayControllerTest -Dsurefire.failIfNoSpecifiedTests=false test` under JDK 21; then run `mvn -pl ruoyi-admin -am -DskipTests package` and inspect exit codes.
|
|
|
- [ ] Inspect `git diff --check`, full diff and staged file list for unrelated edits, secrets, encoding or line-ending churn; commit only documentation/verification updates. Record any unrun live FCM/APNs test explicitly.
|
|
|
|
|
|
@@ -132,4 +132,13 @@ FCM 请求的 data 至少包含字符串形式的 `title`、`body`、原始 `pay
|
|
|
|
|
|
## Verification Command Setup
|
|
|
|
|
|
-PowerShell 中仅对当前命令临时设置 `$env:JAVA_HOME='C:\Users\99029\.jdks\graalvm-jdk-21.0.12+7.1'` 和 `$env:PATH="$env:JAVA_HOME\bin;$env:PATH"`。2026-09-29 已运行 13 类定向测试(83 个用例,0 失败)及 `mvn -pl ruoyi-admin -am -DskipTests package`,退出码均为 0;真实 FCM/APNs 凭据、设备投递和 App 展示未在本机验证,启用前按 `quickstart.md` 执行真机验收。
|
|
|
+PowerShell 中仅对当前命令临时设置 `$env:JAVA_HOME='C:\Users\99029\.jdks\graalvm-jdk-21.0.12+7.1'` 和 `$env:PATH="$env:JAVA_HOME\bin;$env:PATH"`。2026-09-29 已运行 13 类定向测试(83 个用例,0 失败)、本次全模块 933 个测试(0 失败)及 `mvn -pl ruoyi-admin -am -DskipTests package`,退出码均为 0;已验证三端随包凭据可在本地加载,真实 FCM/APNs 设备投递和 App 展示未在本机验证,启用前按 `quickstart.md` 执行真机验收。
|
|
|
+
|
|
|
+## Task 7: 随包 classpath 凭据(2026-09-29 追加)
|
|
|
+
|
|
|
+**Files:** `BusinessPushProperties.java`、`FcmPushSender.java`、`ApnsPushSender.java`、对应测试、`application.yml`、`resources/business-push/` 九个按端命名的凭据文件、`spec.md`/`tasks.md`/`quickstart.md`。
|
|
|
+
|
|
|
+- [x] 先写失败测试:三端 classpath 凭据可独立读取;APNs 配置的 topic/密码用于证书和请求;缺失/无效资源原生模式启动失败,默认 uni 不加载。
|
|
|
+- [x] 从用户给出的三端文件各复制一份 FCM JSON、一份普通 `.p12`、一份配置 JSON 到资源目录,名字含接收端;`ios.p12` 与 `iosdev.p12` 内容相同,不重复提交,不使用 VoIP 证书。
|
|
|
+- [x] 保留外部文件路径兼容,增加 classpath InputStream 加载;`application.yml` 默认指向按端命名资源且模式为 `uni`。不更改并行地图配置。
|
|
|
+- [x] JDK 21 运行定向测试、模块构建,核对 JAR 中的九个资源和 Git 暂存范围;文档说明凭据入库风险及真机未验证,形成单独提交。
|