# 后端消息推送格式 ## 1. 文档说明 - 本文整理后端经极光推送发送到 Android 和 iOS 的通知消息格式。 - 当前内容基于截至 2026-07-23 的 Android、iOS 实际收包日志、两端客户端现有解析逻辑,以及后端开发人员提供的 `PushMsg` 类型定义。 - 后端当前定义了 `1`~`13`、`100`、`999` 共 15 个业务消息类型;目前已取得 `type = 1`(付款成功)、`type = 2`(退款成功)、`type = 6`(扫码成功)和 `type = 13`(新获客线索)的收包样本。 - 本文描述的是推送协议,不是普通 HTTP 接口响应格式。 ## 2. 统一业务结构 极光在 Android 和 iOS 上交付的原始结构不同,但当前消息都可以归一化为以下业务结构: ```json { "title": "通知标题", "content": "通知正文", "msg_id": 1858, "type": 6, "data": { "order_type": 14 } } ``` ### 2.1 公共业务字段 | 字段 | 当前类型 | 说明 | | --- | --- | --- | | `title` | string | 通知标题。Android 为 `notificationTitle`,iOS 为 `aps.alert.title`。 | | `content` | string | 通知正文。Android 为 `notificationContent`,iOS 为 `aps.alert.body`。 | | `msg_id` | int | 后端业务消息 ID。它与极光消息 ID 不是同一个字段。 | | `type` | int | 业务消息类型,是客户端业务分发的主要依据。 | | `data` | object | 随消息类型变化的业务数据。 | > “当前类型”表示现有样本中观察到的 JSON 类型。后端应保持字段类型稳定,避免同一个字段在不同推送中交替使用数字、字符串或 `null`。 ## 3. Android 收包格式 Android 通过极光 `JPushMessageReceiver.onNotifyMessageArrived` 收到通知。标题、正文和附加字段分别由 SDK 提供,其中 `extras` 是 JSON 字符串: ```text [onNotifyMessageArrived] msgId=<极光消息ID>, title=<标题>, content=<正文>, extras=<业务JSON字符串> ``` `extras` 的当前结构为: ```json { "data": {}, "msg_id": 0, "type": 0 } ``` ### 3.1 扫码成功原始日志 ```text [onNotifyMessageArrived] msgId=18103321643292031, title=扫码成功通知, content=扫码成功, extras={"data":{"order_type":14},"msg_id":1852,"type":6} ``` 对应的 `extras`: ```json { "data": { "order_type": 14 }, "msg_id": 1852, "type": 6 } ``` ### 3.2 付款成功原始日志 ```text [onNotifyMessageArrived] msgId=18103321644290274, title=付款成功通知, content=您的订单 #260722128005 已支付成功,支付金额 ¥0.01, extras={"data":{"order_amount":"0.01","order_number":"260722128005","order_type":14,"pay_time":1784711036,"remark":""},"msg_id":1853,"type":1} ``` 对应的 `extras`: ```json { "data": { "order_amount": "0.01", "order_number": "260722128005", "order_type": 14, "pay_time": 1784711036, "remark": "" }, "msg_id": 1853, "type": 1 } ``` ### 3.3 退款成功原始日志 ```text [onNotifyMessageArrived] msgId=18103321800527159, title=退款成功通知, content=您的订单 #260722128002 已成功退款,退款金额 ¥0.01, extras={"data":{},"msg_id":1867,"type":2} ``` 对应的 `extras`: ```json { "data": {}, "msg_id": 1867, "type": 2 } ``` ## 4. iOS 收包格式 iOS 通过 APNs/极光收到 `userInfo` 字典。与 Android 相比: - 标题和正文位于 `aps.alert`。 - Android `extras` 中的 `msg_id`、`type`、`data` 在 iOS 中位于 payload 顶层。 - `_j_*` 为极光传输层内部字段,不应作为业务分发依据。 通用结构如下: ```json { "_j_business": 1, "_j_data": "{\"data_msgtype\":1,\"push_type\":8,\"is_vip\":0}", "_j_msgid": 18103321726881995, "_j_uid": 86399144805, "aps": { "alert": { "body": "通知正文", "title": "通知标题" }, "sound": "default" }, "data": {}, "msg_id": 0, "type": 0 } ``` > 原始日志中该内部字段显示为 `*j\_data*`。本文按极光其他内部字段的命名方式记为 `_j_data`;后续联调时应以设备收到的真实字典 key 为准。该字段目前不参与业务解析。 ### 4.1 扫码成功 payload ```json { "_j_business": 1, "_j_data": "{\"data_msgtype\":1,\"push_type\":8,\"is_vip\":0}", "_j_msgid": 18103321726881995, "_j_uid": 86399144805, "aps": { "alert": { "body": "扫码成功", "title": "扫码成功通知" }, "sound": "default" }, "data": { "order_type": 14 }, "msg_id": 1858, "type": 6 } ``` ### 4.2 付款成功 payload ```json { "_j_business": 1, "_j_data": "{\"data_msgtype\":1,\"push_type\":8,\"is_vip\":0}", "_j_msgid": 18103321720587147, "_j_uid": 86399144805, "aps": { "alert": { "body": "您的订单 #260722128006 已支付成功,支付金额 ¥0.01", "title": "付款成功通知" }, "sound": "default" }, "data": { "order_amount": "0.01", "order_number": "260722128006", "order_type": 14, "pay_time": 1784712671, "remark": "" }, "msg_id": 1856, "type": 1 } ``` ### 4.3 退款成功 payload ```json { "_j_business": 1, "_j_data": "{\"data_msgtype\":1,\"push_type\":8,\"is_vip\":0}", "_j_msgid": 18103321792603316, "_j_uid": 86399144805, "aps": { "alert": { "body": "您的订单 #260722128005 已成功退款,退款金额 ¥0.01", "title": "退款成功通知" }, "sound": "default" }, "data": {}, "msg_id": 1862, "type": 2 } ``` ### 4.4 新获客线索 payload ```json { "_j_business": 1, "_j_data": "{\"data_msgtype\":1,\"push_type\":8,\"is_vip\":0}", "_j_msgid": 18103323696468714, "_j_uid": 86399144805, "aps": { "alert": { "body": "获客员哦啦啦提交了一条新线索,请及时查看并跟进", "title": "新获客线索通知" }, "sound": "default" }, "data": { "lead_id": 75, "sale_user_id": 6, "saler_name": "哦啦啦" }, "msg_id": 1869, "type": 13 } ``` ## 5. Android 与 iOS 字段对应关系 | 语义 | Android | iOS | 是否用于业务 | | --- | --- | --- | --- | | 极光消息 ID | SDK `message.msgId` | `_j_msgid` | 否,仅用于推送链路日志与排查 | | 通知标题 | SDK `message.notificationTitle` | `aps.alert.title` | 是,用于展示 | | 通知正文 | SDK `message.notificationContent` | `aps.alert.body` | 是,用于展示 | | 后端业务消息 ID | `extras.msg_id` | 顶层 `msg_id` | 是 | | 业务消息类型 | `extras.type` | 顶层 `type` | 是,作为业务分发主键 | | 业务数据 | `extras.data` | 顶层 `data` | 是,结构由 `type` 决定 | | 极光业务标记 | SDK 内部处理 | `_j_business` | 否 | | 极光附加元数据 | SDK 内部处理 | `_j_data` | 否 | | 极光用户 ID | SDK 内部处理 | `_j_uid` | 否 | | APNs 展示配置 | 不适用 | `aps` | 仅 iOS 系统使用 | ### 5.1 两种消息 ID 不可混用 - `msgId` / `_j_msgid`:极光生成的传输层消息 ID,当前样本为 17 位数字。 - `msg_id`:后端生成的业务消息 ID,当前样本为 `1852`、`1853`、`1856`、`1858`。 - 客户端日志、去重或上报时必须明确需要哪一种 ID,不能仅用名称相近而互相替代。 - 极光消息 ID 已超过 JavaScript 可安全表示的整数范围;若需要经过 JavaScript、WebView 或其他只能安全处理 53 位整数的链路,应按字符串传递。 ## 6. 消息类型清单 ### 6.1 后端 `PushMsg` 完整类型定义 定义位置:后端 `PushMsg.php` 第 49 行附近。 | `type` | 消息类型 | 后端备注 | 当前收包样本 | | ---: | --- | --- | --- | | `1` | 付款成功通知 | 上文实际示例即为此类型 | Android、iOS 均已取得 | | `2` | 退款成功通知 | — | Android、iOS 均已取得 | | `3` | 下单成功通知 | App 无需推送,当前未使用 | 暂无 | | `4` | 签到成功通知 | — | 暂无 | | `5` | 付尾款成功通知 | — | 暂无 | | `6` | 扫码成功通知 | — | Android、iOS 均已取得 | | `7` | 付定金成功通知 | — | 暂无 | | `8` | 订单核销成功通知 | — | 暂无 | | `9` | 剪辑完成通知 | — | 暂无 | | `10` | 修图完成通知 | — | 暂无 | | `11` | 跟拍签到通知 | — | 暂无 | | `12` | 剪辑师新任务通知 | 类型名称映射中漏配 | 暂无 | | `13` | 新获客线索通知 | 获客员提交新线索 | iOS 已取得,Android 暂无 | | `100` | 用户登出通知 | 账号在其他设备登录 | 暂无 | | `999` | 系统消息 | 当前未使用 | 暂无 | 后端特别说明: - `type` 表示业务消息类型,不代表推送渠道。 - 推送渠道的取值另有定义:`1` 为极光推送,`2` 为微信小程序,`999` 为不推送。 - `type = 12` 虽然已经定义,但尚未加入后端 `MAP_TYPE_NAMES`。后端调用 `getTypeName(12)` 时会返回“未知消息类型”,需要后端补充映射。 - “暂无收包样本”只表示当前文档还没有该类型的完整 payload,不能据此认为该类型未启用。收到后应继续补充其标题、正文、`data` 字段和点击行为。 ### 6.2 `type = 1`:付款成功 | 项目 | 当前值 | | --- | --- | | 标题示例 | `付款成功通知` | | 正文示例 | `您的订单 #260722128006 已支付成功,支付金额 ¥0.01` | | 客户端点击行为 | Android、iOS 均进入收款记录页 | `data` 字段: | 字段 | 类型 | 当前样本 | 说明 | | --- | --- | --- | --- | | `order_amount` | string | `"0.01"` | 支付金额。使用十进制字符串,避免浮点精度问题。 | | `order_number` | string | `"260722128006"` | 业务订单号。 | | `order_type` | int | `14` | 订单类型;当前值表示“摄影师跟拍线下扫码”。 | | `pay_time` | int | `1784712671` | 支付时间。当前样本为 Unix 秒级时间戳;Android 现有代码同时兼容秒和毫秒。 | | `remark` | string | `""` | 付款备注;没有备注时当前返回空字符串。 | 示例: ```json { "type": 1, "msg_id": 1856, "data": { "order_amount": "0.01", "order_number": "260722128006", "order_type": 14, "pay_time": 1784712671, "remark": "" } } ``` ### 6.3 `type = 2`:退款成功 | 项目 | 当前值 | | --- | --- | | 标题示例 | `退款成功通知` | | 正文示例 | `您的订单 #260722128005 已成功退款,退款金额 ¥0.01` | | 客户端点击行为 | Android、iOS 均进入消息中心 | `data` 字段: | 字段 | 类型 | 当前样本 | 说明 | | --- | --- | --- | --- | | — | object | `{}` | 当前 Android、iOS 样本均为空对象。 | 示例: ```json { "type": 2, "msg_id": 1862, "data": {} } ``` > 当前订单号和退款金额只存在于展示正文中,没有以结构化字段放入 `data`。客户端如果需要可靠地刷新指定订单、展示退款详情或执行金额计算,应由后端在 `data` 中提供字段,不应解析自然语言正文。 ### 6.4 `type = 6`:扫码成功 | 项目 | 当前值 | | --- | --- | | 标题示例 | `扫码成功通知` | | 正文示例 | `扫码成功` | | 客户端点击行为 | Android、iOS 均进入收款详情页 | `data` 字段: | 字段 | 类型 | 当前样本 | 说明 | | --- | --- | --- | --- | | `order_type` | int | `14` | 订单类型;`14` 在 Android 现有代码中表示“摄影师跟拍线下扫码”。 | 示例: ```json { "type": 6, "msg_id": 1858, "data": { "order_type": 14 } } ``` ### 6.5 `type = 13`:新获客线索 | 项目 | 当前值 | | --- | --- | | 标题示例 | `新获客线索通知` | | 正文示例 | `获客员哦啦啦提交了一条新线索,请及时查看并跟进` | | 客户端点击行为 | Android、iOS 均进入消息中心 | `data` 字段: | 字段 | 类型 | 当前样本 | 说明 | | --- | --- | --- | --- | | `lead_id` | int | `75` | 新增获客线索的唯一 ID。 | | `sale_user_id` | int | `6` | 提交线索的获客员 ID。 | | `saler_name` | string | `"哦啦啦"` | 获客员名称,与通知正文中的名称一致。 | 示例: ```json { "type": 13, "msg_id": 1869, "data": { "lead_id": 75, "sale_user_id": 6, "saler_name": "哦啦啦" } } ``` > 当前点击路由只根据 `type` 判断,`type = 13` 属于默认分支,因此进入消息中心;`data` 中的线索字段不会改变跳转页面。 ## 7. 客户端解析约定 1. Android、iOS 的通知点击路由只根据业务字段 `type` 判断,不读取标题、正文、`data`、`route`、`uri`、`action` 或极光内部字段决定页面。 2. `type = 1`:进入收款记录页。 3. `type = 6`:进入收款详情页。 4. 其他任意 `type`、缺少 `type`、类型无法解析或 payload 损坏:进入消息中心。 5. Android 从 `notificationExtras` 或厂商通道包装字段中提取 `type`;iOS 优先读取 payload 顶层 `type`,并兼容常见推送包装层中的 `type`。 6. `data` 仍可按消息类型用于页面内容刷新,但不参与通知点击路由。新增字段应保持向后兼容,客户端应忽略当前版本不认识的额外字段。 7. 金额继续使用字符串;时间戳建议统一为 Unix 秒级整数,并在协议中固定单位。 8. `remark` 等可空业务字段建议固定返回空字符串或明确约定 `null`,不要在多种表示之间切换。 ## 8. 新增消息类型记录模板 后续收到新类型时,复制以下内容追加到“消息类型清单”: ````markdown ### 6.x `type = <类型值>`:<消息名称> | 项目 | 当前值 | | --- | --- | | 首次发现日期 | `YYYY-MM-DD` | | 标题示例 | `` | | 正文示例 | `<content>` | | 客户端业务行为 | `<展示、刷新或跳转行为>` | `data` 字段: | 字段 | 类型 | 必有 | 说明 | | --- | --- | --- | --- | | `<field>` | `<type>` | `<是/否/待确认>` | `<说明>` | Android `extras` 示例: ```json { "data": {}, "msg_id": 0, "type": 0 } ``` iOS 业务字段示例: ```json { "data": {}, "msg_id": 0, "type": 0 } ``` ```` 记录新类型时至少保留以下信息: - Android 和 iOS 各一份原始收包日志。 - `type`、`msg_id` 和完整 `data`。 - 标题、正文以及消息点击后的期望页面。 - 每个字段的 JSON 类型、是否必有、空值表示方式和时间/金额单位。 - 同一业务事件在两端的字段是否一致。 ## 9. 待后端确认项 | 项目 | 当前观察 | 需要确认 | | --- | --- | --- | | `msg_id` | 与极光消息 ID 不同 | 是否对应消息中心记录 ID,以及是否用于已读/送达状态上报 | | `data` | `type = 1`、`2`、`6`、`13` 的样本中都存在;`type = 2` 为 `{}` | 所有业务推送是否保证存在;无业务字段时是否统一返回 `{}` | | 退款成功的 `data` | 当前为空对象,订单号和退款金额只在正文中 | 是否补充 `order_number`、`refund_amount`、`refund_time`、`order_type` 等结构化字段 | | 其他类型的 `data` | 后端已定义消息名称,但尚未提供 payload | 分别确认 `type = 3`~`5`、`7`~`12`、`100`、`999` 的字段结构、必填项及点击行为 | | `pay_time` | 当前为秒级时间戳 | 后端是否统一保证使用 Unix 秒,且时区语义固定为 UTC 时间戳 | | `remark` | 无备注时为空字符串 | 是否可能返回 `null` 或省略 | | `order_type` | 当前为 `14` | 完整枚举和值含义由哪份接口文档维护 | | 标题与正文 | 当前均存在 | 是否为所有通知消息的必有字段 | | 推送渠道字段 | 后端已给出渠道取值 `1`、`2`、`999` | payload 或发送接口中对应字段的准确名称 | | `type = 12` | `MAP_TYPE_NAMES` 中漏配 | 后端补充映射,避免 `getTypeName(12)` 返回“未知消息类型” | | 新增 `type` | 当前定义维护在 `PushMsg.php` | 后端新增类型前是否可同步类型值、字段结构和客户端行为 |