Files
im_server/docs/third/IM-极光推送完整调用流程.md
T

13 KiB
Raw Blame History

IM 极光推送完整调用流程

更新时间:2026-09-04

1. 流程目标

本文用于说明 IM 系统接入极光 JPush 后,离线消息、离线来电、系统通知和业务红点提醒从客户端注册设备、后端保存设备、服务端生成 Push 任务、调用极光 REST API 到客户端点击补偿拉取的完整链路。

官方参考:

2. 整体链路

后台配置极光参数
-> 客户端集成 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=user_id 投递。
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,例如 usr...。
  6. 调用 IM 后端设备接口上报 Push Token。

4.2 设备上报

PUT /v1/im/devices/{device_id}/push-token
Authorization: Bearer <IM token>
X-MeetingIM-APIKey: <api_key>
X-IM-Schema: 1
X-Tenant-Code: <tenant_code>
X-Request-ID: <request_id>
Idempotency-Key: <idempotency_key>
Content-Type: application/json

请求 Body:

{
  "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"
}

成功响应:

{
  "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 任务状态机

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:

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

{
  "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 只提醒,不携带完整消息正文。万人群不建议按群全员同步投递,只对离线且需要提醒的人生成任务,例如被 @、特别关注、管理员公告、未免打扰小群等。

{
  "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,需要额外开通并按平台单独配置。

{
  "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 绑定为当前 usr...。
设备上报 PUT /v1/im/devices/{device_id}/push-token 返回成功,服务端记录 provider=jpush。
普通离线消息 用户离线后收到 Push,点击后进入会话并补齐 Topic seq。
群 @ 提醒 被 @ 用户离线时只收到一次提醒,重连后定位到对应消息。
语音来电 被叫离线时收到短 TTL 来电 Push,通话取消后点击不会进入过期通话。
免打扰 免打扰会话不产生普通 Push,@ 或强提醒按策略例外。
幂等重试 同一 dedupe_key 不重复发,极光临时失败可重试。
无效设备 极光返回无效 token 后设备记录被禁用或待清理。
iOS 环境 测试包 apns_production=false,生产包为 true。