feat: add wechat miniprogram webview login

This commit is contained in:
2026-05-03 19:05:45 +08:00
parent 9baa515a75
commit ce98a29c4d
17 changed files with 758 additions and 42 deletions

View File

@@ -6,11 +6,18 @@
本次先用微信小程序 `web-view` 承载现有 H5不重写 React/Vite 主前端,也不把 SpacetimeDB SDK 或业务规则搬进小程序端。
当前小程序壳只承担件事:
当前小程序壳只承担件事:
1. 提供微信开发者工具可识别的 `miniprogram/` 工程根目录。
2. 用一个全屏 `web-view` 打开现有 H5 入口
3. 给 H5 URL 附加来源标记,便于后续识别 `wechat_mini_program` 宿主
2. 在原生小程序壳中调用 `wx.login` 获取小程序 `code`
3. 调用服务器域名下的 `/api/auth/wechat/miniprogram-login`,由 Rust `api-server` 兑换微信身份并签发系统登录态
4. 用一个全屏 `web-view` 打开现有 H5 入口,并把系统 `auth_token` 放入 H5 现有登录回调 hash。
重要边界:
1. `openid` 只作为后端微信身份绑定依据,不直接暴露给 H5 当登录凭证。
2. H5 继续消费本系统 JWT也就是 `#auth_provider=wechat&auth_token=...&auth_binding_status=...`
3. 这与 [`WECHAT_LOGIN_AXUM_IMPLEMENTATION_DESIGN_2026-04-21.md`](./WECHAT_LOGIN_AXUM_IMPLEMENTATION_DESIGN_2026-04-21.md) 中“微信只提供三方身份Axum 签发系统 JWT”的边界一致。
## 2. 文件入口
@@ -20,6 +27,8 @@
| `miniprogram/app.json` | 小程序全局配置,注册 `pages/web-view/index`。 |
| `miniprogram/config.js` | 业务域名入口配置,需要部署时填写。 |
| `miniprogram/pages/web-view/index.*` | 最小 web-view 页面。 |
| `server-rs/crates/api-server/src/wechat_auth.rs` | 新增小程序登录接口 `/api/auth/wechat/miniprogram-login`。 |
| `server-rs/crates/platform-auth/src/lib.rs` | 新增 `jscode2session` 兑换能力。 |
## 3. 需要手工填写的配置
@@ -27,14 +36,36 @@
```js
const WEB_VIEW_ENTRY_URL = 'https://你的H5业务域名/';
const API_BASE_URL = 'https://你的服务器域名/';
const MINI_PROGRAM_APP_ID = '你的微信小程序 AppID';
const MINI_PROGRAM_ENV = 'develop';
```
约束:
1. 必须是 `https`
2. 不能是 `localhost` 或 IP。
3. 域名需要在微信小程序后台配置为业务域名。
4. H5 页面里的 API、图片、音视频、iframe 等外链也要满足微信侧域名与证书要求
3. `WEB_VIEW_ENTRY_URL` 域名需要在微信小程序后台配置为业务域名。
4. `API_BASE_URL` 域名需要在微信小程序后台配置为 request 合法域名
5. H5 页面里的 API、图片、音视频、iframe 等外链也要满足微信侧域名与证书要求。
`api-server` 环境变量中填写:
```bash
WECHAT_AUTH_ENABLED=true
WECHAT_AUTH_PROVIDER=real
WECHAT_MINI_PROGRAM_APP_ID="你的微信小程序 AppID"
WECHAT_MINI_PROGRAM_APP_SECRET="你的微信小程序 AppSecret"
```
如果开放平台网页 OAuth 与小程序使用同一个 AppID/Secret也可以继续使用已有
```bash
WECHAT_APP_ID="你的微信 AppID"
WECHAT_APP_SECRET="你的微信 AppSecret"
```
但正式部署建议把小程序配置写到 `WECHAT_MINI_PROGRAM_APP_ID``WECHAT_MINI_PROGRAM_APP_SECRET`,避免和网页 OAuth 配置混淆。
`WEB_VIEW_SOURCE_QUERY` 默认附加:
@@ -43,19 +74,61 @@ clientType=mini_program
clientRuntime=wechat_mini_program
```
后续如果 H5 或 `api-server` 需要更严格地区分来源,应优先使用请求头或登录态中的客户端身份字段,不要只信任 URL query。
小程序壳调用登录接口时会补传:
## 4. 微信后台配置
```text
x-client-type=mini_program
x-client-runtime=wechat_mini_program
x-client-platform=ios|android|unknown
x-client-instance-id=<小程序本地持久化随机值>
x-mini-program-app-id=<MINI_PROGRAM_APP_ID>
x-mini-program-env=<MINI_PROGRAM_ENV>
```
这些字段会进入 refresh session 的客户端身份快照URL query 只作为 H5 识别宿主来源的轻量标记,不作为鉴权依据。
## 4. 登录链路
当前登录链路固定为:
1. 小程序页面启动。
2. 调用 `wx.login` 获取一次性 `code`
3. 小程序壳请求:
```http
POST /api/auth/wechat/miniprogram-login
Content-Type: application/json
{
"code": "wx.login code"
}
```
4. `api-server` 调用微信 `jscode2session` 兑换 `openid/unionid`
5. `api-server` 复用现有微信身份逻辑:
- 先按 `unionid` 命中已有身份
- 再按 `openid` 命中已有身份
- 都没有命中时创建 `pending_bind_phone` 的微信壳账号
6. `api-server` 签发系统 access token并写入 refresh session。
7. 小程序壳打开:
```text
https://你的H5业务域名/#auth_provider=wechat&auth_token=<系统JWT>&auth_binding_status=active|pending_bind_phone
```
8. H5 复用 `consumeAuthCallbackResult()` 消费 `auth_token` 并进入现有登录态恢复流程。
## 5. 微信后台配置
至少需要在小程序后台配置:
1. `业务域名`:承载 H5 的域名。
2. `request 合法域名`H5 里如果仍有小程序原生层直接请求 API才需要配置当前 web-view 壳本身不直接请求业务 API
2. `request 合法域名``API_BASE_URL` 对应的服务器域名
3. `socket 合法域名`:若后续小程序原生层直连 WebSocket 才需要;当前不启用。
当前仓库的 H5 仍建议通过同域 `/api/*` 访问 Rust `api-server`,避免在小程序和 H5 中分别维护跨域白名单。
## 5. 当前不做的事
## 6. 当前不做的事
本次不做原生小程序页面迁移,原因是当前主前端依赖:
@@ -66,9 +139,14 @@ clientRuntime=wechat_mini_program
这些能力不能稳定原样运行在原生小程序宿主中。后续如要原生化,应新建小程序端宿主,复用 `packages/shared` 契约和 `api-server` BFF而不是把 `src/` 整体搬过去。
## 6. 验收口径
本次也不做 `openid` query 直登。原因是 `openid` 不是本系统签发的登录凭证,不能表达 token 版本、会话 ID、绑定状态、角色与过期时间也不能被 H5 直接信任。
## 7. 验收口径
1. 微信开发者工具打开项目根目录后,识别 `miniprogram/` 为小程序源码目录。
2. 未填写 `WEB_VIEW_ENTRY_URL` 时,页面显示配置提示,不出现空白页。
3. 填写已配置业务域名后,首页全屏打开 H5
4. H5 内登录、SSE、图片资源等能力按 H5 自身部署域名和 `/api/*` 代理链路验证。
2. 未填写 `WEB_VIEW_ENTRY_URL``API_BASE_URL` 时,页面显示配置提示,不出现空白页。
3. 填写已配置业务域名后,小程序先请求 `/api/auth/wechat/miniprogram-login`
4. 后端返回 `token/bindingStatus/user`,并写入 refresh cookie。
5. 首页全屏打开 H5URL hash 中包含 `auth_provider=wechat``auth_token``auth_binding_status`
6. H5 内 `consumeAuthCallbackResult()` 消费 hash 后,`/api/auth/me` 能返回当前用户。
7. `/api/auth/sessions` 能看到来源为 `mini_program / wechat_mini_program` 的会话记录。