# IM 青少年模式前后端对接文档 ## 1. 基本约定 青少年模式相关接口均为登录后接口。客户端需要携带用户登录 token、普通 API Key 和协议版本头。 公共 Header: ```http Authorization: Bearer X-MeetingIM-Auth: Bearer X-MeetingIM-APIKey: X-IM-Schema: 1 X-Request-ID: X-Tenant-Code: default ``` 所有写接口还需要携带: ```http Idempotency-Key: ``` 测试环境验证码固定为 `123456`。`action_token` 为 5 分钟有效、单次消费,只能用于指定动作,不能在多个接口之间重复使用。 当前默认策略项为 `night_quiet`、`content_filter`、`payment_guard` 三条。现阶段后端已完成状态持久化、开启/关闭校验和策略返回;`night_quiet` 已接入音视频呼叫发起限制,`content_filter` 已接入消息发送前内容安全审核,响应中的这两项 `restriction_items[].enforced=true`。`payment_guard` 当前仍为预留项,`enforced=false`。 ## 2. 开启青少年模式 ### 2.1 查询当前状态 ```http GET /v1/im/settings/youth-mode ``` 成功响应: ```json { "code": 0, "data": { "enabled": false, "policy_version": 1, "restrictions": ["night_quiet", "content_filter", "payment_guard"], "restriction_items": [ { "code": "night_quiet", "title": "深夜免打扰", "description": "夜间减少消息提醒打扰,帮助用户保持健康作息。", "enforced": true }, { "code": "content_filter", "title": "内容过滤", "description": "对不适合青少年的内容进行识别和限制展示。", "enforced": true }, { "code": "payment_guard", "title": "支付守护", "description": "限制或确认支付、充值等敏感消费行为。", "enforced": false } ], "password_set": false, "can_enable": false, "updated_at": "2026-08-20T09:00:00Z" } } ``` 前端优先使用 `restriction_items` 渲染开启确认页,`restrictions` 保留为兼容旧客户端的 code 数组。最终开启时需要提交用户确认过的 `policy_version`。 ### 2.2 发起短信身份验证 ```http POST /v1/im/security/challenges ``` 请求体: ```json { "scene": "set_independent_password", "channel": "sms" } ``` 成功响应: ```json { "code": 0, "data": { "challenge_id": "sec_chg_1", "phone_mask": "+861****000", "expires_in_seconds": 300, "resend_after_seconds": 60 } } ``` 手机号由服务端从当前登录用户读取,客户端不提交目标手机号。 ### 2.3 校验短信验证码 ```http POST /v1/im/security/challenges/{challenge_id}/verify ``` 请求体: ```json { "code": "123456" } ``` 成功响应: ```json { "code": 0, "data": { "action": "set_independent_password", "action_token": "set_password_token", "expires_at": "2026-08-20T09:05:00Z" } } ``` 这里拿到的 `action_token` 只用于设置独立密码,不能直接用于开启青少年模式。 ### 2.4 设置独立密码 ```http POST /v1/im/settings/independent-password ``` 请求体: ```json { "password": "6439", "purpose": "youth_mode", "action_token": "set_password_token" } ``` 成功响应: ```json { "code": 0, "data": { "status": "ok", "password_set": true, "purpose": "youth_mode", "enable_action_token": "enable_token", "enable_action_expires_at": "2026-08-20T09:05:00Z", "next_action": "enable_youth_mode" } } ``` 服务端会消费 `set_password_token`,并返回新的 `enable_action_token`。前端下一步必须使用 `enable_action_token`,不要复用 `set_password_token`。 独立密码规则: - 必须是 4 位数字。 - 不能是明显连续或重复组合。 - 服务端只保存强哈希,不返回明文密码。 - 前端离开页面后应清空输入内容,不落普通存储。 ### 2.5 开启青少年模式 ```http POST /v1/im/settings/youth-mode/enable ``` 请求体: ```json { "policy_version": 1, "action_token": "enable_token" } ``` 成功响应: ```json { "code": 0, "data": { "enabled": true, "policy_version": 1, "password_set": true, "restrictions": ["night_quiet", "content_filter", "payment_guard"], "restriction_items": [ { "code": "night_quiet", "title": "深夜免打扰", "description": "夜间减少消息提醒打扰,帮助用户保持健康作息。", "enforced": true }, { "code": "content_filter", "title": "内容过滤", "description": "对不适合青少年的内容进行识别和限制展示。", "enforced": true }, { "code": "payment_guard", "title": "支付守护", "description": "限制或确认支付、充值等敏感消费行为。", "enforced": false } ], "updated_at": "2026-08-20T09:00:00Z" } } ``` 开启成功后,客户端应刷新本地设置页和 `bootstrap` 缓存。服务端会持久化状态,前端不能只依赖本地标志位。 ## 3. 关闭青少年模式 ### 3.1 校验独立密码 ```http POST /v1/im/settings/independent-password/verify ``` 请求体: ```json { "password": "6439", "purpose": "youth_mode", "action": "close_youth_mode" } ``` 成功响应: ```json { "code": 0, "data": { "action": "close_youth_mode", "action_token": "close_token", "expires_at": "2026-08-20T09:05:00Z" } } ``` ### 3.2 关闭模式 ```http POST /v1/im/settings/youth-mode/disable X-Action-Token: close_token ``` 请求体: ```json {} ``` 成功响应: ```json { "code": 0, "data": { "enabled": false, "policy_version": 1, "password_set": true, "updated_at": "2026-08-20T09:00:00Z" } } ``` 关闭接口的 `action_token` 通过 Header `X-Action-Token` 传递,不放在 Body 中。 ## 4. Token 使用规则 | 来源 | action | 用途 | 传递方式 | 是否单次消费 | | --- | --- | --- | --- | --- | | `security/challenges/{id}/verify` | `set_independent_password` | 设置独立密码 | Body `action_token` | 是 | | `independent-password` | `enable_youth_mode` | 开启青少年模式 | Body `action_token` | 是 | | `independent-password/verify` | `close_youth_mode` | 关闭青少年模式 | Header `X-Action-Token` | 是 | 常见错误: - `ACTION_TOKEN_INVALID`:token 已消费、过期、action 不匹配、target 不匹配或用户不匹配。 - `CODE_INVALID`:短信验证码错误。 - `CHALLENGE_EXPIRED`:短信 challenge 已过期。 - `TOO_MANY_ATTEMPTS`:独立密码或验证码错误次数过多。 - `VERIFICATION_RATE_LIMITED`:发码过于频繁,按 `retry_after_seconds` 倒计时。 ## 5. curl 示例 开启流程: ```bash curl -sS 'https://api.118im.com/v1/im/security/challenges' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ -H 'X-MeetingIM-Auth: Bearer ' \ -H 'X-MeetingIM-APIKey: ' \ -H 'X-IM-Schema: 1' \ -H 'X-Tenant-Code: default' \ -H 'X-Request-ID: ' \ -H 'Idempotency-Key: ' \ --data '{"scene":"set_independent_password","channel":"sms"}' ``` ```bash curl -sS 'https://api.118im.com/v1/im/security/challenges//verify' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ -H 'X-MeetingIM-Auth: Bearer ' \ -H 'X-MeetingIM-APIKey: ' \ -H 'X-IM-Schema: 1' \ -H 'X-Tenant-Code: default' \ -H 'X-Request-ID: ' \ -H 'Idempotency-Key: ' \ --data '{"code":"123456"}' ``` ```bash curl -sS 'https://api.118im.com/v1/im/settings/independent-password' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ -H 'X-MeetingIM-Auth: Bearer ' \ -H 'X-MeetingIM-APIKey: ' \ -H 'X-IM-Schema: 1' \ -H 'X-Tenant-Code: default' \ -H 'X-Request-ID: ' \ -H 'Idempotency-Key: ' \ --data '{"password":"6439","purpose":"youth_mode","action_token":""}' ``` ```bash curl -sS 'https://api.118im.com/v1/im/settings/youth-mode/enable' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ -H 'X-MeetingIM-Auth: Bearer ' \ -H 'X-MeetingIM-APIKey: ' \ -H 'X-IM-Schema: 1' \ -H 'X-Tenant-Code: default' \ -H 'X-Request-ID: ' \ -H 'Idempotency-Key: ' \ --data '{"policy_version":1,"action_token":""}' ``` 关闭流程: ```bash curl -sS 'https://api.118im.com/v1/im/settings/independent-password/verify' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ -H 'X-MeetingIM-Auth: Bearer ' \ -H 'X-MeetingIM-APIKey: ' \ -H 'X-IM-Schema: 1' \ -H 'X-Tenant-Code: default' \ -H 'X-Request-ID: ' \ -H 'Idempotency-Key: ' \ --data '{"password":"6439","purpose":"youth_mode","action":"close_youth_mode"}' ``` ```bash curl -sS 'https://api.118im.com/v1/im/settings/youth-mode/disable' \ -H 'Content-Type: application/json' \ -H 'Authorization: Bearer ' \ -H 'X-MeetingIM-Auth: Bearer ' \ -H 'X-MeetingIM-APIKey: ' \ -H 'X-IM-Schema: 1' \ -H 'X-Tenant-Code: default' \ -H 'X-Request-ID: ' \ -H 'Idempotency-Key: ' \ -H 'X-Action-Token: ' \ --data '{}' ```