7.6 KiB
7.6 KiB
IM 青少年模式前后端对接文档
1. 基本约定
青少年模式相关接口均为登录后接口。客户端需要携带用户登录 token、普通 API Key 和协议版本头。
公共 Header:
Authorization: Bearer <access_token>
X-MeetingIM-Auth: Bearer <access_token>
X-MeetingIM-APIKey: <api_key>
X-IM-Schema: 1
X-Request-ID: <uuid>
X-Tenant-Code: default
所有写接口还需要携带:
Idempotency-Key: <uuid>
测试环境验证码固定为 123456。action_token 为 5 分钟有效、单次消费,只能用于指定动作,不能在多个接口之间重复使用。
2. 开启青少年模式
2.1 查询当前状态
GET /v1/im/settings/youth-mode
成功响应:
{
"code": 0,
"data": {
"enabled": false,
"policy_version": 1,
"restrictions": ["night_quiet", "content_filter", "payment_guard"],
"password_set": false,
"can_enable": false,
"updated_at": "2026-08-20T09:00:00Z"
}
}
前端使用 policy_version 和 restrictions 渲染开启确认页。最终开启时需要提交用户确认过的 policy_version。
2.2 发起短信身份验证
POST /v1/im/security/challenges
请求体:
{
"scene": "set_independent_password",
"channel": "sms"
}
成功响应:
{
"code": 0,
"data": {
"challenge_id": "sec_chg_1",
"phone_mask": "+861****000",
"expires_in_seconds": 300,
"resend_after_seconds": 60
}
}
手机号由服务端从当前登录用户读取,客户端不提交目标手机号。
2.3 校验短信验证码
POST /v1/im/security/challenges/{challenge_id}/verify
请求体:
{
"code": "123456"
}
成功响应:
{
"code": 0,
"data": {
"action": "set_independent_password",
"action_token": "set_password_token",
"expires_at": "2026-08-20T09:05:00Z"
}
}
这里拿到的 action_token 只用于设置独立密码,不能直接用于开启青少年模式。
2.4 设置独立密码
POST /v1/im/settings/independent-password
请求体:
{
"password": "6439",
"purpose": "youth_mode",
"action_token": "set_password_token"
}
成功响应:
{
"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 开启青少年模式
POST /v1/im/settings/youth-mode/enable
请求体:
{
"policy_version": 1,
"action_token": "enable_token"
}
成功响应:
{
"code": 0,
"data": {
"enabled": true,
"policy_version": 1,
"password_set": true,
"restrictions": ["night_quiet", "content_filter", "payment_guard"],
"updated_at": "2026-08-20T09:00:00Z"
}
}
开启成功后,客户端应刷新本地设置页和 bootstrap 缓存。服务端会持久化状态,前端不能只依赖本地标志位。
3. 关闭青少年模式
3.1 校验独立密码
POST /v1/im/settings/independent-password/verify
请求体:
{
"password": "6439",
"purpose": "youth_mode",
"action": "close_youth_mode"
}
成功响应:
{
"code": 0,
"data": {
"action": "close_youth_mode",
"action_token": "close_token",
"expires_at": "2026-08-20T09:05:00Z"
}
}
3.2 关闭模式
POST /v1/im/settings/youth-mode/disable
X-Action-Token: close_token
请求体:
{}
成功响应:
{
"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 示例
开启流程:
curl -sS 'https://api.118im.com/v1/im/security/challenges' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access_token>' \
-H 'X-MeetingIM-Auth: Bearer <access_token>' \
-H 'X-MeetingIM-APIKey: <api_key>' \
-H 'X-IM-Schema: 1' \
-H 'X-Tenant-Code: default' \
-H 'X-Request-ID: <uuid>' \
-H 'Idempotency-Key: <uuid>' \
--data '{"scene":"set_independent_password","channel":"sms"}'
curl -sS 'https://api.118im.com/v1/im/security/challenges/<challenge_id>/verify' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access_token>' \
-H 'X-MeetingIM-Auth: Bearer <access_token>' \
-H 'X-MeetingIM-APIKey: <api_key>' \
-H 'X-IM-Schema: 1' \
-H 'X-Tenant-Code: default' \
-H 'X-Request-ID: <uuid>' \
-H 'Idempotency-Key: <uuid>' \
--data '{"code":"123456"}'
curl -sS 'https://api.118im.com/v1/im/settings/independent-password' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access_token>' \
-H 'X-MeetingIM-Auth: Bearer <access_token>' \
-H 'X-MeetingIM-APIKey: <api_key>' \
-H 'X-IM-Schema: 1' \
-H 'X-Tenant-Code: default' \
-H 'X-Request-ID: <uuid>' \
-H 'Idempotency-Key: <uuid>' \
--data '{"password":"6439","purpose":"youth_mode","action_token":"<set_password_token>"}'
curl -sS 'https://api.118im.com/v1/im/settings/youth-mode/enable' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access_token>' \
-H 'X-MeetingIM-Auth: Bearer <access_token>' \
-H 'X-MeetingIM-APIKey: <api_key>' \
-H 'X-IM-Schema: 1' \
-H 'X-Tenant-Code: default' \
-H 'X-Request-ID: <uuid>' \
-H 'Idempotency-Key: <uuid>' \
--data '{"policy_version":1,"action_token":"<enable_action_token>"}'
关闭流程:
curl -sS 'https://api.118im.com/v1/im/settings/independent-password/verify' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access_token>' \
-H 'X-MeetingIM-Auth: Bearer <access_token>' \
-H 'X-MeetingIM-APIKey: <api_key>' \
-H 'X-IM-Schema: 1' \
-H 'X-Tenant-Code: default' \
-H 'X-Request-ID: <uuid>' \
-H 'Idempotency-Key: <uuid>' \
--data '{"password":"6439","purpose":"youth_mode","action":"close_youth_mode"}'
curl -sS 'https://api.118im.com/v1/im/settings/youth-mode/disable' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <access_token>' \
-H 'X-MeetingIM-Auth: Bearer <access_token>' \
-H 'X-MeetingIM-APIKey: <api_key>' \
-H 'X-IM-Schema: 1' \
-H 'X-Tenant-Code: default' \
-H 'X-Request-ID: <uuid>' \
-H 'Idempotency-Key: <uuid>' \
-H 'X-Action-Token: <close_token>' \
--data '{}'