微信登录 API
为网站(PC 扫码)、移动 App(原生 SDK)、桌面端提供统一的微信登录与账号绑定能力。认人以微信 unionid 为准(同一开放平台主体下跨端一致)。
待确认账号归并
以下端点处理微信身份首次出现、需要通过已验证手机号或邮箱归并账号的场景。均使用短期 state 关联待处理登录会话,并受 IP 限流保护。
POST /auth/wechat/web/pending/phone/send-otp
请求体提供 state 与手机号,向该手机号发送登录用途验证码。
POST /auth/wechat/web/pending/phone/verify
使用 state、手机号和验证码确认目标账号,并完成微信身份归并;存在覆盖冲突时不会自动覆盖。
POST /auth/wechat/web/pending/email/send-otp
请求体提供 state、邮箱及可选语言,发送邮箱验证码。
POST /auth/wechat/web/pending/email/verify
使用 state、邮箱和六位验证码确认目标账号,并完成微信身份归并。
POST /auth/wechat/web/pending/confirm-override
用户明确确认覆盖冲突后完成归并。只有待处理会话已经记录冲突目标时才可调用,否则返回 409 invalid_state。
管理端移动应用凭据
站点管理员可在 /admin/app-settings 的「微信登录」区域管理移动应用 AppID/AppSecret。 对应管理 API 为:
GET /admin/app-settings/wechat-login:返回服务状态、公开 AppID 和 Secret 是否已配置,不返回 AppSecret 明文。PUT /admin/app-settings/wechat-login:更新 AppID、显式轮换 AppSecret或切换微信登录服务状态;省略 Secret 表示保留原值。
凭据继续保存到 service_provider:wechat_login 的 mobile_app_id / mobile_app_secret slots。 服务开关由网站扫码与移动 App 登录共用;半配置、凭证组禁用或服务商禁用时运行时均 fail-closed。
端点总览
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
| POST | /auth/wechat/web/start | 公开 | 生成扫码 state + 二维码 URL |
| GET | /auth/wechat/web/callback | 公开 | 微信扫码登录回调(微信重定向至此) |
| GET | /auth/wechat/web/status | 公开 | 前端轮询登录结果 |
| POST | /oauth/token | 公开 | 移动 App 用微信 code 换 wno- token(grant_type=…:wechat) |
| POST | /my/wechat/bind/start | 登录 | PC 扫码绑定:生成二维码 |
| GET | /my/wechat/bind/status | 登录 | PC 扫码绑定轮询 |
| GET | /auth/wechat/bind/callback | 公开 | 微信扫码绑定回调 |
| POST | /my/wechat/bind | 登录 | 移动端用 code 直接绑定 |
| GET | /my/wechat | 登录 | 查询绑定状态 |
| DELETE | /my/wechat | 登录 | 解绑 |
/my/wechat/*仅接受用户 JWT(不接受 Agent Token / API Key)。
网站 PC 扫码登录
前端 start 拿二维码 → 用户扫码 → 微信重定向到后端 callback → 前端轮询 status 拿会话。
POST /auth/wechat/web/start
生成扫码 state + 二维码 URL(公开)。
{ "success": true, "data": { "state": "<hex>", "qrUrl": "https://open.weixin.qq.com/connect/qrconnect?...", "expiresIn": 300 } }GET /auth/wechat/web/callback
微信扫码登录回调(公开,微信携带 ?code&state 重定向至此)。换取微信身份 → 按 unionid 建/复用用户 → 签发 Supabase 兼容 JWT 并加密写入 session,返回提示用户切回原页面的 HTML。state 无效 / 过期 / 节点不匹配时返回失败提示页(结果由前端轮询 status 取回)。
GET /auth/wechat/web/status
前端轮询登录结果(公开,query 带 state)。pending 时只返回状态;confirmed 时一次性返回会话(再次轮询返回 consumed):
{ "success": true, "data": {
"status": "confirmed",
"user": { "id": "<uuid>" },
"team": { },
"project": { },
"created": false,
"session": { "accessToken": "<jwt>", "tokenType": "bearer", "expiresIn": 3600 }
} }status 取值:pending | confirmed | consumed | expired。
前端将 session.accessToken 持久化到本地,业务请求以 Authorization: Bearer <token> 携带(与手机号验证码登录一致)。
移动 App 登录(OAuth)
App 通过微信 SDK 唤起授权拿到 code,调用 OAuth token 端点换取长期会话:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:wainao:params:oauth:grant-type:wechat&client_id=<id>&code=<wechat_code>&app_type=app&scope=<scopes>响应(同标准 OAuth):
{ "access_token": "wno-...", "refresh_token": "wno-rt-...", "token_type": "Bearer", "expires_in": 3600, "scope": "..." }| 错误 | 含义 |
|---|---|
invalid_grant | 微信授权失败(code 无效/过期) |
unauthorized_client | 该应用未开通 wechat_grant 能力 |
invalid_scope | scope 非法 |
绑定 / 解绑微信(已登录)
/my/wechat/* 仅接受用户 JWT(拒绝 Agent Token / API Key)。提供 PC 扫码、移动端 code 直绑两种方式,遵循「一账号一微信」。
PC 扫码绑定流程:bind/start 拿二维码 → 用户扫码 → 微信回调 bind/callback → 前端轮询 bind/status 取结果。
POST /my/wechat/bind/start
PC 扫码绑定:生成 state + 二维码(绑定目标为当前登录用户)。
{ "success": true, "data": { "state": "<hex>", "qrUrl": "https://open.weixin.qq.com/connect/qrconnect?...", "expiresIn": 300 } }GET /auth/wechat/bind/callback
PC 扫码绑定回调(公开,微信携带 ?code&state 重定向至此)。待绑用户取自 session 中记录的 bind_user_id,执行绑定后返回提示页(结果由前端轮询 bind/status 取回)。
GET /my/wechat/bind/status
PC 扫码绑定轮询(query 带 state)。校验 state 归属当前用户;confirmed 时原子消费一次。
{ "success": true, "data": { "status": "confirmed", "bound": true } }绑定失败时返回 { "status": "confirmed", "bound": false, "reason": "wechat_taken" | "already_bound" };status 同样可能为 pending | consumed | expired。
POST /my/wechat/bind
移动端用微信 code 直接绑定(无需扫码轮询)。
Body:{ "code": "...", "appType": "app" | "web" }(appType 默认 app)
| 响应 | 含义 |
|---|---|
200 { bound: true } | 绑定成功 |
409 already_bound | 当前账号已绑其它微信(一账号一微信,需先解绑) |
409 wechat_taken | 该微信已被其他账号绑定 |
502 internal_error | 微信授权异常 |
GET /my/wechat
查询当前用户微信绑定状态。
{ "success": true, "data": { "bound": true, "nickname": "...", "avatarUrl": "..." } }DELETE /my/wechat
解绑微信。若微信是唯一登录方式,返回 409 last_login_method(需先绑定其它登录方式,避免账号锁死);尚未绑定返回 404 not_bound。
{ "success": true, "data": { "unbound": true } }