# IM 极光推送完整调用流程 更新时间:2026-09-04 ## 1. 流程目标 本文用于说明 IM 系统接入极光 JPush 后,离线消息、离线来电、系统通知和业务红点提醒从客户端注册设备、后端保存设备、服务端生成 Push 任务、调用极光 REST API 到客户端点击补偿拉取的完整链路。 官方参考: - 极光快速开始:https://docs.jiguang.cn/jpush/quickstart/ - 极光 REST API 概述:https://docs.jiguang.cn/jpush/server/push/server_overview - 极光创建推送 API:https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push ## 2. 整体链路 ```text 后台配置极光参数 -> 客户端集成 JPush SDK -> 客户端获得 registration_id -> 客户端登录 IM 后上报设备 Push Token -> IM Server 保存 user_id/device_id/provider/registration_id/platform -> 用户离线或目标设备不在线 -> IM Server 生成离线 Push 任务 -> Push worker 调用极光 POST /v3/push -> 极光下发通知到 Android/iOS/HarmonyOS -> 用户点击通知打开 App -> 客户端按 extras 中的 topic/seq/call_id 跳转并补偿拉取 ``` ## 3. 后台配置流程 配置建议存放在 HotGo 后台 `hg_sys_config`,分组建议使用 `im_jpush`。IM Server 通过 Admin 内部配置接口读取并缓存,配置变更后通过 Kafka 配置事件或进程内缓存过期生效。 | 配置项 | 示例 | 说明 | | --- | --- | --- | | `jpush_enabled` | `true` | 是否启用极光推送。 | | `jpush_app_key` | `xxxxxxxx` | 极光应用 AppKey。客户端 SDK 初始化也会用到,允许给客户端配置使用。 | | `jpush_master_secret` | `******` | 极光 REST API 密钥,只能后端保存和使用,不允许返回客户端。 | | `jpush_api_domain` | `https://api.jpush.cn` | 极光 REST API 域名。 | | `jpush_push_path` | `/v3/push` | 创建推送 API 路径。 | | `jpush_apns_production` | `false/true` | iOS APNs 环境,测试包用 false,生产包用 true。 | | `jpush_default_ttl_seconds` | `86400` | 离线 Push 默认保留时长。 | | `jpush_call_ttl_seconds` | `60` | 来电 Push 保留时长,建议短一些。 | | `jpush_use_alias` | `true` | 是否优先使用极光安全 alias 投递。 | | `jpush_test_model` | `false` | 极光测试模式,仅联调测试设备时开启。 | | `jpush_classification` | `1` | 重要业务通知建议按系统消息分类处理,需结合厂商通道规则确认。 | | `jpush_log_payload` | `false` | 生产关闭 payload 明文日志,避免敏感信息进入日志。 | ## 4. 客户端初始化流程 ### 4.1 获取极光配置 客户端安装包通常内置对应环境的 `AppKey`,也可以从 App 配置接口获取非敏感配置。`MasterSecret` 不允许下发。 客户端需要完成: 1. 集成 JPush SDK。 2. 初始化 SDK 使用 `jpush_app_key`。 3. 申请系统通知权限。 4. 取得 `registration_id`。 5. 登录 IM 后绑定 alias。极光 alias 不支持中横线 `-` 和下划线 `_`,客户端必须将当前 IM `user_id` 转成极光安全别名:`user_id.replace("-", ".").replace("_", "|")`。示例:`usrd6Ag5opa-ww` 对应 `usrd6Ag5opa.ww`。 6. 调用 IM 后端设备接口上报 Push Token。 ### 4.2 设备上报 ```http PUT /v1/im/devices/{device_id}/push-token Authorization: Bearer X-MeetingIM-APIKey: X-IM-Schema: 1 X-Tenant-Code: X-Request-ID: Idempotency-Key: Content-Type: application/json ``` 请求 Body: ```json { "provider": "jpush", "token": "registration_id_from_jpush", "platform": "android", "app_version": "1.0.0", "push_env": "test", "sdk_version": "5.0.0", "notification_permission": "granted" } ``` 成功响应: ```json { "code": 0, "data": { "device_id": "device_1", "provider": "jpush", "platform": "android", "app_version": "1.0.0", "updated_at": "2026-09-04T10:00:00Z" }, "request_id": "req_01K...", "server_time": "2026-09-04T10:00:00Z" } ``` ### 4.3 设备解绑 退出登录、删除设备、切换账号或 SDK 返回 registration_id 失效时,客户端应调用设备解绑接口或覆盖上报为空状态。后端要把该设备 token 标记为 disabled,避免继续推送到错误账号。 ## 5. 服务端 Push 任务生成 ### 5.1 触发场景 | 场景 | 触发条件 | Push 目标 | | --- | --- | --- | | P2P 离线消息 | 接收方当前无在线可投递设备,或需要离线提醒 | 接收方 user_id。 | | 群离线消息 | 成员离线且未免打扰,按 Topic seq 补偿 | 被提醒成员 user_id,不对万人群逐条广播无差别 Push。 | | @提醒 | 被 @ 用户离线或后台 | 被 @ 用户 user_id,高优先级。 | | 好友申请/审批 | 目标用户离线 | 目标用户 user_id。 | | 群申请/邀请/审批 | 审批人或目标成员离线 | 对应用户 user_id。 | | 系统通知 | 已写入系统通知表且用户离线 | 通知目标 user_id。 | | 语音/视频来电 | 被叫方当前无在线可响铃设备或 App 后台 | 被叫 user_id,短 TTL。 | | 未接来电 | 通话超时、取消或未接 | 被叫 user_id。 | ### 5.2 在线与离线判断 在线实时消息仍走 WebSocket。Push 不是消息正文真源,只负责提醒。客户端重连后必须按 Topic `seq` 或业务 ID 从 IM Server 拉取补偿,不能只依赖 Push payload 展示最终状态。 推荐判断: - 当前用户存在可投递在线会话:优先 WS,下发 Push 可按用户设置降级或不发。 - 用户全离线:生成 Push 任务。 - 用户在线但 App 后台状态不可判定:可生成低干扰 Push,客户端本地去重。 - 群万人场景:实时 fanout 走 Redis/Kafka/Topic 路由,离线只对需要提醒的成员生成 Push。 ### 5.3 任务状态机 ```text pending -> sending -> sent pending -> sending -> retry_wait -> sending pending -> sending -> failed pending -> skipped ``` | 状态 | 说明 | | --- | --- | | `pending` | 已生成,等待 worker 发送。 | | `sending` | worker 已领取,正在请求极光。 | | `sent` | 极光 API 返回成功并记录 `msg_id`。 | | `retry_wait` | 临时错误,等待退避重试。 | | `failed` | 永久失败或超过最大重试次数。 | | `skipped` | 用户免打扰、无有效设备、消息已过期或策略不允许发送。 | 任务需保存 `dedupe_key`,例如 `tenant_code:user_id:topic:seq:push_type`,避免重复生成离线提醒。 ## 6. 服务端调用极光 REST API 极光创建推送 API: ```http POST https://api.jpush.cn/v3/push Authorization: Basic base64(app_key + ":" + master_secret) Content-Type: application/json ``` 官方说明中,创建推送 API 使用 HTTPS、HTTP Basic Authentication 和 JSON 请求体;推送目标支持 `alias`、`registration_id`、`tag` 等方式,`alias` 单次最多 1000 个,`registration_id` 单次最多 1000 个;返回成功时包含 `sendno` 和 `msg_id`。 ### 6.1 普通离线消息 Push ```json { "platform": ["android", "ios", "hmos"], "audience": { "alias": ["usr_target"] }, "notification": { "alert": "你收到一条新消息", "android": { "title": "MeetingIM", "alert": "你收到一条新消息", "extras": { "type": "im_message", "tenant_code": "default", "topic": "p2p...", "seq": "128", "sender_id": "usr_sender", "message_type": "text" } }, "ios": { "alert": { "title": "MeetingIM", "body": "你收到一条新消息" }, "sound": "default", "badge": "+1", "extras": { "type": "im_message", "tenant_code": "default", "topic": "p2p...", "seq": "128", "sender_id": "usr_sender", "message_type": "text" } }, "hmos": { "title": "MeetingIM", "alert": "你收到一条新消息", "category": "IM", "extras": { "type": "im_message", "tenant_code": "default", "topic": "p2p...", "seq": "128", "sender_id": "usr_sender", "message_type": "text" } } }, "options": { "time_to_live": 86400, "apns_production": false, "classification": 1 } } ``` ### 6.2 群消息 Push 群消息 Push 只提醒,不携带完整消息正文。万人群不建议按群全员同步投递,只对离线且需要提醒的人生成任务,例如被 @、特别关注、管理员公告、未免打扰小群等。 ```json { "platform": "all", "audience": { "alias": ["usr_mentioned"] }, "notification": { "alert": "群里有人提到了你", "android": { "title": "项目群", "alert": "群里有人提到了你", "extras": { "type": "group_mention", "tenant_code": "default", "topic": "grp...", "seq": "56001", "sender_id": "usr_sender", "mention": "1" } }, "ios": { "alert": { "title": "项目群", "body": "群里有人提到了你" }, "badge": "+1", "sound": "default", "extras": { "type": "group_mention", "tenant_code": "default", "topic": "grp...", "seq": "56001", "sender_id": "usr_sender", "mention": "1" } } }, "options": { "time_to_live": 86400, "apns_production": false, "classification": 1 } } ``` ### 6.3 来电 Push 语音/视频来电需要短 TTL。普通离线 Push 只做提醒;如后续要实现系统级强提醒、VoIP 样式或厂商 VoIP,需要额外开通并按平台单独配置。 ```json { "platform": "all", "audience": { "alias": ["usr_callee"] }, "notification": { "alert": "收到一通语音通话", "android": { "title": "语音通话", "alert": "张三邀请你语音通话", "extras": { "type": "call_invite", "tenant_code": "default", "topic": "p2p...", "seq": "30", "call_id": "call_01K...", "call_type": "audio", "caller_id": "usr_caller" } }, "ios": { "alert": { "title": "语音通话", "body": "张三邀请你语音通话" }, "sound": "default", "badge": "+1", "extras": { "type": "call_invite", "tenant_code": "default", "topic": "p2p...", "seq": "30", "call_id": "call_01K...", "call_type": "audio", "caller_id": "usr_caller" } } }, "options": { "time_to_live": 60, "apns_production": false, "classification": 1 } } ``` ## 7. 客户端点击与补偿拉取 客户端收到或点击 Push 后按 `extras.type` 分发: | `extras.type` | 客户端动作 | | --- | --- | | `im_message` | 打开 `topic` 对应会话,按本地最后 `seq + 1` 拉取消息。 | | `group_mention` | 打开群会话并定位到 `seq`,若本地无该消息先拉取。 | | `call_invite` | 如果通话仍有效,打开来电页;同时通过 IM 登录和会话补偿确认通话状态。 | | `call_missed` | 打开通话记录或对应会话。 | | `system_notification` | 打开系统消息列表或 `action` 指定页面,再调用 HTTP 拉取详情。 | | `friend_request` | 打开新朋友列表并刷新未处理数。 | | `group_request` | 打开群审批入口并刷新列表。 | Push 中的 `topic`、`seq`、`call_id` 只用于定位和补偿,不作为业务真源。客户端必须重新登录 IM 并拉取服务端数据确认状态,例如通话是否已取消、消息是否已撤回、系统通知是否已读。 ## 8. 隐私与安全 1. `jpush_master_secret` 只在后端配置和请求极光时使用,不返回客户端。 2. Push 通知栏默认不展示敏感正文,可按用户隐私设置决定是否展示摘要。 3. `extras` 不放身份证号、手机号、文件直链、完整消息正文、审核原因明细等敏感数据。 4. 日志只记录 `task_id/user_id/provider/status/msg_id/error_code`,不记录完整 Push payload。 5. 推送失败后按错误类型禁用无效 registration_id,避免持续打失败请求。 6. 多租户场景下 `tenant_code` 必须进入任务、payload、dedupe_key 和日志,禁止跨租户复用设备 token。 ## 9. 联调验收 | 验收项 | 期望结果 | | --- | --- | | 客户端初始化 | SDK 返回 registration_id,alias 绑定为 `user_id.replace("-", ".").replace("_", "|")`。 | | 设备上报 | `PUT /v1/im/devices/{device_id}/push-token` 返回成功,服务端记录 provider=`jpush`。 | | 普通离线消息 | 用户离线后收到 Push,点击后进入会话并补齐 Topic seq。 | | 群 @ 提醒 | 被 @ 用户离线时只收到一次提醒,重连后定位到对应消息。 | | 语音来电 | 被叫离线时收到短 TTL 来电 Push,通话取消后点击不会进入过期通话。 | | 免打扰 | 免打扰会话不产生普通 Push,@ 或强提醒按策略例外。 | | 幂等重试 | 同一 `dedupe_key` 不重复发,极光临时失败可重试。 | | 无效设备 | 极光返回无效 token 后设备记录被禁用或待清理。 | | iOS 环境 | 测试包 `apns_production=false`,生产包为 true。 |