fix: normalize jpush aliases
This commit is contained in:
+1
-1
@@ -467,7 +467,7 @@ X-MeetingIM-APIKey: <预置的普通 API Key>
|
||||
客户端侧要求:
|
||||
|
||||
- App 集成 JPush SDK,初始化使用极光 `AppKey`,不接触 `MasterSecret`。
|
||||
- 登录 IM 后将极光 alias 绑定为当前 `user_id`,例如 `usr...`;同一用户多设备允许绑定同一个 alias。
|
||||
- 登录 IM 后将极光 alias 绑定为当前 `user_id` 的安全别名:`user_id.replace("-", ".").replace("_", "|")`,例如 `usrd6Ag5opa-ww` 绑定为 `usrd6Ag5opa.ww`;同一用户多设备允许绑定同一个 alias。
|
||||
- SDK 返回 `registration_id` 后调用 `PUT /v1/im/devices/{device_id}/push-token` 上报,`provider` 固定传 `jpush`。
|
||||
- 点击 Push 后按 `extras.type` 跳转,再按服务端数据补偿,不能只凭 Push payload 渲染最终状态。
|
||||
|
||||
|
||||
@@ -24,7 +24,15 @@
|
||||
- iOS:配置 APNs 证书或 Token Authentication,申请通知权限。
|
||||
- HarmonyOS:按鸿蒙 SDK 文档初始化并配置通知分类。
|
||||
|
||||
客户端启动后取得 `registration_id`,登录 IM 后把 alias 绑定为当前 `user_id`。同一用户多设备允许绑定同一个 alias。
|
||||
客户端启动后取得 `registration_id`,登录 IM 后把 alias 绑定为当前 `user_id` 的极光安全别名。同一用户多设备允许绑定同一个 alias。
|
||||
|
||||
极光 alias 不支持中横线 `-` 和下划线 `_`,而 IM `user_id` 可能包含这两个字符。客户端和后端统一使用以下映射:
|
||||
|
||||
```text
|
||||
jpush_alias = user_id.replace("-", ".").replace("_", "|")
|
||||
```
|
||||
|
||||
示例:`usrd6Ag5opa-ww` 对应极光 alias `usrd6Ag5opa.ww`。
|
||||
|
||||
### 2.2 上报 Push Token
|
||||
|
||||
@@ -306,7 +314,7 @@ Content-Type: application/json
|
||||
| 步骤 | 操作 | 验证 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 客户端初始化 JPush SDK | 能拿到 `registration_id`。 |
|
||||
| 2 | 登录 IM 并绑定 alias=`user_id` | 极光控制台能查到别名或设备。 |
|
||||
| 2 | 登录 IM 并绑定 alias=`user_id.replace("-", ".").replace("_", "|")` | 极光控制台能查到别名或设备。 |
|
||||
| 3 | 调用设备上报接口 | 服务端设备记录 provider=`jpush`。 |
|
||||
| 4 | 目标用户退出或断网 | IM 判断为离线或不可 WS 投递。 |
|
||||
| 5 | 发送 P2P 消息 | 离线用户收到 Push。 |
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
| `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_use_alias` | `true` | 是否优先使用极光安全 alias 投递。 |
|
||||
| `jpush_test_model` | `false` | 极光测试模式,仅联调测试设备时开启。 |
|
||||
| `jpush_classification` | `1` | 重要业务通知建议按系统消息分类处理,需结合厂商通道规则确认。 |
|
||||
| `jpush_log_payload` | `false` | 生产关闭 payload 明文日志,避免敏感信息进入日志。 |
|
||||
@@ -59,7 +59,7 @@
|
||||
2. 初始化 SDK 使用 `jpush_app_key`。
|
||||
3. 申请系统通知权限。
|
||||
4. 取得 `registration_id`。
|
||||
5. 登录 IM 后绑定 alias,建议 alias 使用当前 IM `user_id`,例如 `usr...`。
|
||||
5. 登录 IM 后绑定 alias。极光 alias 不支持中横线 `-` 和下划线 `_`,客户端必须将当前 IM `user_id` 转成极光安全别名:`user_id.replace("-", ".").replace("_", "|")`。示例:`usrd6Ag5opa-ww` 对应 `usrd6Ag5opa.ww`。
|
||||
6. 调用 IM 后端设备接口上报 Push Token。
|
||||
|
||||
### 4.2 设备上报
|
||||
@@ -357,7 +357,7 @@ Push 中的 `topic`、`seq`、`call_id` 只用于定位和补偿,不作为业
|
||||
|
||||
| 验收项 | 期望结果 |
|
||||
| --- | --- |
|
||||
| 客户端初始化 | SDK 返回 registration_id,alias 绑定为当前 `usr...`。 |
|
||||
| 客户端初始化 | SDK 返回 registration_id,alias 绑定为 `user_id.replace("-", ".").replace("_", "|")`。 |
|
||||
| 设备上报 | `PUT /v1/im/devices/{device_id}/push-token` 返回成功,服务端记录 provider=`jpush`。 |
|
||||
| 普通离线消息 | 用户离线后收到 Push,点击后进入会话并补齐 Topic seq。 |
|
||||
| 群 @ 提醒 | 被 @ 用户离线时只收到一次提醒,重连后定位到对应消息。 |
|
||||
|
||||
@@ -360,7 +360,7 @@ func preparePayloads(rcpt *push.Receipt, config *configType) ([]*jpushPayload, [
|
||||
}
|
||||
var audience map[string][]string
|
||||
if useAlias {
|
||||
audience = map[string][]string{"alias": {uid.UserId()}}
|
||||
audience = map[string][]string{"alias": {aliasForUid(uid)}}
|
||||
} else {
|
||||
var registrationIDs []string
|
||||
for _, device := range devices[uid] {
|
||||
@@ -584,6 +584,12 @@ func containsString(values []string, target string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func aliasForUid(uid t.Uid) string {
|
||||
// JPush alias does not accept '-' or '_'. Tinode user IDs are base64url-like,
|
||||
// so map them to legal characters which never appear in the original alphabet.
|
||||
return strings.NewReplacer("-", ".", "_", "|").Replace(uid.UserId())
|
||||
}
|
||||
|
||||
func providerDevicesForUsers(tenantID t.TenantID, provider string, uids ...t.Uid) (map[t.Uid][]t.DeviceDef, int, error) {
|
||||
if tokens, ok := store.DevicePushTokens.(store.DevicePushTokenProviderQueryInterface); ok {
|
||||
return tokens.GetAllByProvider(tenantID, provider, uids...)
|
||||
|
||||
@@ -97,7 +97,7 @@ func TestPreparePayloadsUsesAliasAndNormalizesP2PTopic(t *testing.T) {
|
||||
t.Fatalf("unexpected payload count: %d %#v", len(payloads), uids)
|
||||
}
|
||||
payload := payloads[0]
|
||||
if got := payload.Audience["alias"][0]; got != callee.UserId() {
|
||||
if got := payload.Audience["alias"][0]; got != aliasForUid(callee) {
|
||||
t.Fatalf("unexpected alias: %s", got)
|
||||
}
|
||||
userTopic, _ := types.P2PNameForUser(callee, topic)
|
||||
@@ -109,6 +109,16 @@ func TestPreparePayloadsUsesAliasAndNormalizesP2PTopic(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAliasForUidUsesJPushSafeCharacters(t *testing.T) {
|
||||
uid := types.ParseUserId("usrd6Ag5opa-ww")
|
||||
if uid.IsZero() {
|
||||
t.Fatal("test user id did not parse")
|
||||
}
|
||||
if got, want := aliasForUid(uid), "usrd6Ag5opa.ww"; got != want {
|
||||
t.Fatalf("unexpected alias: got %s want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreparePayloadsCanUseRegistrationID(t *testing.T) {
|
||||
oldTokens := store.DevicePushTokens
|
||||
uid := types.Uid(42)
|
||||
|
||||
Reference in New Issue
Block a user