feat: add wechat miniprogram webview login
This commit is contained in:
@@ -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. 首页全屏打开 H5,URL 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` 的会话记录。
|
||||
|
||||
Reference in New Issue
Block a user