手机短信验证码系统 (2026-06-02)

变更概览

  1. 新增手机短信验证码发送和验证接口
  2. 新增绑定/解绑/修改手机号接口
  3. 支持国际手机号,通过 area_code 区号字段区分不同国家
  4. 验证码有效期默认 10 分钟
  5. 系统以邮箱为主账户体系,手机号仅用于短信消息通知
  6. user/info 接口新增返回 phonearea_code 字段

业务流程

绑定手机号流程

用户首次绑定手机号,需要先获取验证码,验证通过后执行绑定。

解绑手机号流程

用户解绑手机号,支持通过手机短信或邮箱验证码两种方式验证。

修改手机号流程

修改手机号需要对新手机号进行验证码验证。


使用指引

前置条件

  • 所有接口均需要用户登录(Bearer Token)
  • 用户只能绑定一个手机号

典型使用场景

场景 1:用户首次绑定手机号

适用于用户注册后希望绑定手机号以接收短信通知。

接口调用顺序:

  1. POST /send_phone_verify_code (type: bind_phone) - 发送验证码
  2. POST /bind_phone - 绑定手机号(会自动验证验证码)

提示: bind_phone 接口内部会先验证验证码再执行绑定,无需单独调用 verify_phone_verify_code

场景 2:用户更换手机号

适用于用户更换手机号后需要更新绑定。

接口调用顺序:

  1. POST /send_phone_verify_code (type: change_phone) - 向新手机号发送验证码
  2. POST /change_phone - 修改手机号(会自动验证验证码)

场景 3:用户解绑手机号

适用于用户不再需要短信通知,希望解绑手机号。

接口调用顺序:

  1. POST /send_phone_verify_code (type: unbind_phone) - 向当前手机号发送验证码
  2. POST /unbind_phone - 解绑手机号(会自动验证验证码)

场景 4:仅验证验证码有效性

适用于前端需要在执行操作前先验证用户输入的验证码是否正确。

接口调用顺序:

  1. POST /send_phone_verify_code - 发送验证码
  2. POST /verify_phone_verify_code - 验证验证码(不执行绑定/解绑操作)

接口列表

所有接口均需登录(Bearer Token)

接口说明
POST /api/user/send_phone_verify_code发送短信验证码
POST /api/user/verify_phone_verify_code验证短信验证码(仅验证)
POST /api/user/bind_phone绑定手机号
POST /api/user/unbind_phone解绑手机号
POST /api/user/change_phone修改手机号

相关接口变更

接口说明
GET /api/user/info响应新增 phonearea_code 字段
POST /api/user/send_email_verify_code新增支持 type: unbind_phone
POST /api/user/verify_email_verify_code新增支持 type: unbind_phone

接口详情

POST /api/user/send_phone_verify_code

  • 功能说明:发送手机短信验证码
  • 鉴权:需要登录

请求参数

字段类型必填说明
phonestring手机号(纯数字,5-20位)
area_codestring区号,如 +86+1+81
typestring验证码类型,见下方说明

type 取值

类型说明
bind_phone首次绑定手机号
unbind_phone解绑手机号(验证原手机号)
change_phone修改手机号(验证新手机号)

请求示例

{
  "phone": "13800138000",
  "area_code": "+86",
  "type": "bind_phone"
}

响应示例

{
  "ok": true
}

错误码

错误码说明
30014短信发送失败
30016手机号已被其他用户绑定(bind_phone/change_phone 时)
30017手机号与当前用户不匹配(unbind_phone 时)

POST /api/user/verify_phone_verify_code

  • 功能说明:验证手机短信验证码(仅验证,不执行操作)
  • 鉴权:需要登录

请求参数

字段类型必填说明
phonestring手机号
area_codestring区号
codestring验证码(6位数字)
typestring验证码类型(同上)

请求示例

{
  "phone": "13800138000",
  "area_code": "+86",
  "code": "123456",
  "type": "bind_phone"
}

响应示例

{
  "ok": true
}

错误码

错误码说明
30012验证码不存在或已使用
30013验证码已过期
30015验证尝试次数过多(10次/2分钟)

POST /api/user/bind_phone

  • 功能说明:绑定手机号(首次绑定)
  • 鉴权:需要登录
  • 前置条件:用户尚未绑定手机号
  • 注意: 此接口会自动验证验证码,无需单独调用 verify_phone_verify_code

请求参数

字段类型必填说明
phonestring要绑定的手机号
area_codestring区号
codestring验证码

请求示例

{
  "phone": "13800138000",
  "area_code": "+86",
  "code": "123456"
}

响应示例

{
  "status": "success",
  "message": "Bind Phone Success",
  "code": 200
}

错误码

错误码说明
30012验证码不存在或已使用
30013验证码已过期
30016用户已绑定手机号,或手机号已被其他用户绑定

POST /api/user/unbind_phone

  • 功能说明:解绑手机号
  • 鉴权:需要登录
  • 前置条件:用户已绑定手机号
  • 注意: 此接口会自动验证验证码,无需单独调用 verify_phone_verify_codeverify_email_verify_code

请求参数

字段类型必填说明
channelstring验证渠道:phone(手机短信)或 email(邮箱)
codestring验证码

请求示例

使用手机验证码:

{
  "channel": "phone",
  "code": "654321"
}

使用邮箱验证码:

{
  "channel": "email",
  "code": "A1B2C3"
}

发送验证码接口

  • 手机短信:POST /api/user/send_phone_verify_code(type: unbind_phone
  • 邮箱:POST /api/user/send_email_verify_code(type: unbind_phone

响应示例

{
  "status": "success",
  "message": "Unbind Phone Success",
  "code": 200
}

错误码

错误码说明
30012验证码不存在或已使用
30013验证码已过期
30017手机号与当前用户不匹配

POST /api/user/change_phone

  • 功能说明:修改绑定的手机号
  • 鉴权:需要登录
  • 前置条件:用户已绑定手机号
  • 注意: 此接口会自动验证验证码,无需单独调用 verify_phone_verify_code

请求参数

字段类型必填说明
phonestring新手机号
area_codestring区号
codestring新手机号的验证码

请求示例

{
  "phone": "13900139000",
  "area_code": "+86",
  "code": "111222"
}

响应示例

{
  "status": "success",
  "message": "Change Phone Success",
  "code": 200
}

错误码

错误码说明
30012验证码不存在或已使用
30013验证码已过期
30016新手机号已被其他用户绑定

常用区号

国家/地区区号
中国大陆+86
美国/加拿大+1
英国+44
日本+81
韩国+82
中国香港+852
中国台湾+886

注意事项

  1. 区号必填: 所有接口都需要传入 area_code 参数,前端默认传 +86
  2. 验证码有效期: 10 分钟,过期需重新获取
  3. 验证码覆盖: 同一手机号(区号+手机号)同一类型下,发送新验证码会自动使旧验证码失效
  4. 频率限制: 2 分钟内最多 10 次验证尝试,超出后需等待
  5. 简化流程: bind_phoneunbind_phonechange_phone 接口会自动验证验证码,无需单独调用 verify_phone_verify_code
  6. 账户体系: 系统以邮箱为主账户体系,手机号仅用于短信消息通知,不作为登录凭证

相关接口变更

GET /api/user/info

  • 变更说明:响应新增 phonearea_code 字段,用于展示用户当前绑定的手机号信息

响应新增字段

字段类型说明
phonestring|null绑定的手机号,未绑定时为 null
area_codestring|null区号,未绑定时为 null

响应示例(部分)

{
  "id": 1,
  "name": "张三",
  "email": "zhangsan@example.com",
  "phone": "13800138000",
  "area_code": "+86",
  "avatar": "https://..."
}

POST /api/user/send_email_verify_code

  • 变更说明:新增支持 type: unbind_phone,用于解绑手机号时发送邮箱验证码
  • 鉴权:需要登录
  • 前置条件:用户已绑定手机号,且传入的邮箱必须是当前用户的邮箱

新增 type 取值

类型说明
unbind_phone解绑手机号(向当前用户邮箱发送验证码)

请求示例

{
  "email": "zhangsan@example.com",
  "type": "unbind_phone"
}

错误码

错误码说明
30017用户未绑定手机号
30009邮箱与当前用户不匹配

POST /api/user/verify_email_verify_code

  • 变更说明:新增支持 type: unbind_phone,用于验证解绑手机号的邮箱验证码

新增 type 取值

类型说明
unbind_phone解绑手机号

请求示例

{
  "email": "zhangsan@example.com",
  "code": "A1B2C3",
  "type": "unbind_phone"
}

短信通知发送

功能说明

当系统发送 SystemNotificationScene 通知时,会自动检查 notification_templates 是否关联了 smsTemplate。如果关联了且模板已审核通过(canSend()),则通过 EasySms 异步发送短信通知。

工作流程

支持短信通知的场景

以下场景在发送系统通知时,会同时发送短信(前提是用户绑定了手机号且开启了短信通知):

场景接收方短信内容摘要
service_request.createdartist新的服务申请
service_request.artist_accepteduser画师已接申请,请支付
service_request.artist_rejecteduser服务申请已被拒绝
service_request.user_canceledartist客户已取消申请
service_request.user_paidartist已收到用户付款
project_request.createdartist, user企划邀请/提交成功
project_request.user_choosenartist已被选中参与企划
project_request.artist_canceleduser画师已取消企划
project_request.artist_rejecteduser画师已谢绝企划
project_request.artist_accepteduser画师已加入企划
project_request.user_paidartist, user客户已支付/支付成功
worktask.file_createduser画师上传了新稿件
worktask.artist_canceleduser, group画师已取消约稿
worktask.user_canceledartist, group客户已取消约稿
worktask.user_confirm_stageartist, group客户已确认节点
worktask.finishedartist, user, group约稿已完成
work_task_file_change_request.createdartist客户提出修改意见
work_task_file_change_request.updatedartist客户提出修改意见
admin.joined_groupgroup创作助手已加入群组
group.remindergroup发送了提醒
price_change.*user/artist/group改价相关
deadline_change.*user/artist/group交稿日期变更相关
artist_rec_review.createdartist收到客户评价
user_rec_review.createduser收到画师评价
user_applicant.accepteduser通过画师审核
wallet.alipay_publishuser支付宝支付公告
report.processeduser举报处理完成

SMS 模板变量格式

短信模板内容使用 ${variable} 语法,变量值从通知的 meta 数据中提取:

(PIPIPEN) Commission-${work_task_id} | 画师上传了新的稿件,请及时查看。

常用变量:

变量说明
${work_task_id}工作任务 ID
${service_id}服务 ID

注意事项

  1. 异步发送: 短信通过 SendSmsJob 异步发送,不阻塞主流程
  2. 前置条件: 用户必须绑定手机号(phone + area_code)才会发送短信
  3. 模板审核: smsTemplate 需要 platform_statusapproved 且有 platform_template_code 才会发送
  4. 通知开关: 受用户通知设置中的 sms 开关控制