- 新增小红书前端模块(启动服务、内容分析、爆款创作、发布记录、技能卡片、拟人设置、AI 助手) - 新增 xhs-agent-desktop 独立桌面 Agent,对接 OMS 任务调度 - 登录页重构,整合微信登录与 OMS JWT 认证 - 订单、渠道、用户中心等页面与 API 增强 Co-authored-by: Cursor <cursoragent@cursor.com>
25 KiB
OMS 微信登录整合方案
版本:v1.0
日期:2026-06-24
策略:B — 公众号回调独占 OMS(不与 WMS 共用同一套公众号服务器配置,WMS 微信能力逐步下线或改用独立公众号)
1. 背景与目标
1.1 背景
WMS 已实现基于微信公众号临时二维码 + 扫码事件回调 + Redis 桥接 + 前端轮询的登录方案。OMS 客户门户登录页已预留微信入口(wechat-login.vue),但当前为 UI 占位,后端无微信相关接口。
OMS 后端为 C#(SimpleAdmin.Api + JWT),客户实体 t_customer 已预留 WechatOpenid 等字段,仓储层已有 GetByWechatOpenidAsync,具备约 40% 基础能力。
1.2 目标
| 目标 | 说明 |
|---|---|
| PC 客户扫码登录 | 客户门户 / 切换微信登录,扫码后自动签发 JWT |
| 微信授权注册 | 未绑定用户通过公众号菜单进入 H5 注册页 |
| 微信授权绑定 | 已有 OMS 客户账号,绑定当前微信 openId |
| 沿用同一公众号 | AppId / Secret / Token 与现网 WMS 使用同一公众号,但服务器 URL 改指向 OMS |
| 仅客户门户 | 管理端 /admin 不提供微信扫码登录 |
1.3 策略 B 说明
微信公众平台服务器配置 URL
旧:WMS → https://{wms}/apiwechat/{appId}
新:OMS → https://api.nanafa.com/admin/wechat/mp/{appId}
- 同一公众号的 AppId、Secret、Token、EncodingAESKey 配置迁移到 OMS(Consul / appsettings)
- 微信服务器回调只由 OMS 处理,无需
system=wms/oms分流 - WMS 侧微信扫码登录、模板消息等能力需单独下线或改用其他公众号(不在本方案范围)
2. 总体架构
2.1 登录时序(PC 扫码)
sequenceDiagram
participant PC as 客户浏览器
participant FE as OMS 前端
participant API as OMS API (C#)
participant Redis as Redis
participant WX as 微信公众号
participant DB as MySQL
PC->>FE: 客户登录页 → 微信扫码
FE->>FE: 生成 loginUuid (UUID v4)
FE->>API: GET /admin/wechat/mp/login-qrcode?loginUuid=xxx
API->>WX: 创建临时二维码 ticket (scene, 600s)
API-->>FE: { qrCodeUrl }
FE->>FE: 展示二维码,每 3s 轮询
Note over WX: 用户微信扫码
WX->>API: POST /admin/wechat/mp/{appId} (SCAN / SUBSCRIBE)
API->>DB: 按 openId 查 t_customer.WechatOpenid
alt 未绑定
API-->>WX: 回复文本「请注册或绑定账号」
else 已绑定
API->>Redis: SET oms:wechat:login:{loginUuid} = openId, TTL 600s
end
FE->>API: POST /admin/rbac/auth/wx-login { loginUuid }
API->>Redis: GET openId
API->>DB: 查客户 + 校验状态
API->>API: 签发 JWT (OmsLoginType.Customer)
API-->>FE: LoginResultDto
FE->>PC: 存 Token,跳转 /home/workplace
2.2 模块划分
┌─────────────────────────────────────────────────────────┐
│ OMS 前端 (Vue3 + Arco Design) │
│ login/wechat-login.vue │ wechat/register │ bind │
└──────────────────────────┬──────────────────────────────┘
│ HTTPS
┌──────────────────────────▼──────────────────────────────┐
│ SimpleAdmin.Api │
│ ┌─────────────┐ ┌──────────────────┐ ┌────────────┐ │
│ │ AuthService │ │ WeChatMpController│ │WeChatOAuth │ │
│ │ + wx-login │ │ 回调/二维码 │ │ 注册/绑定 │ │
│ └──────┬──────┘ └────────┬─────────┘ └─────┬──────┘ │
│ │ │ │ │
│ ┌──────▼───────────────────▼───────────────────▼──────┐ │
│ │ WeChatMpService / ScanHandler / SubscribeHandler │ │
│ └──────┬───────────────────────────────┬──────────────┘ │
│ │ │ │
│ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │ Redis │ │ MySQL │ │
│ │ 扫码会话桥接 │ │ t_customer │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
▲
│ 微信服务器推送
┌──────┴──────┐
│ 微信公众号 │
└─────────────┘
2.3 技术选型
| 组件 | 选型 |
|---|---|
| 微信 SDK | Senparc.Weixin.MP 或 SKIT.FlurlHttpClient.Wechat.Api |
| 扫码会话 | IDistributedCache + Redis(StackExchange.Redis) |
| 认证 | 复用现有 JWT(AuthService / SimpleJwtService) |
| 配置 | Consul idwms/admin 增加 WeChat:Mp 节点 |
3. 数据库设计
3.1 主表:t_customer(扩展现有表)
OMS 不单独建 sys_user_wechat,微信绑定信息直接落在客户表(与领域模型 Customer 一致)。
现有字段(已存在)
| 字段 | 类型 | 说明 |
|---|---|---|
WechatOpenid |
varchar(64) NULL |
公众号 openId,登录主键 |
WechatNickname |
varchar(64) NULL |
微信昵称 |
WechatAvatar |
varchar(255) NULL |
微信头像 URL |
建议新增字段(可选,便于扩展)
| 字段 | 类型 | 说明 |
|---|---|---|
WechatUnionid |
varchar(64) NULL |
开放平台 unionId(若后续接开放平台) |
WechatBindTime |
datetime NULL |
微信绑定时间 |
建议索引
-- openId 唯一(允许多条 NULL)
CREATE UNIQUE INDEX uk_customer_wechat_openid
ON t_customer (WechatOpenid);
-- 辅助查询(若尚未存在)
CREATE INDEX idx_customer_phone ON t_customer (Phone);
CREATE INDEX idx_customer_email ON t_customer (Email);
业务约束
| 规则 | 说明 |
|---|---|
| 一微信绑一客户 | WechatOpenid 全局唯一(非 NULL 时) |
| 一客户绑一微信 | 更新绑定时校验该客户 WechatOpenid 为空 |
| 仅主客户可微信登录 | ParentCustomerId IS NULL;子客户拒绝扫码登录 |
| 子客户 | 不走微信扫码,继续账号密码登录 |
3.2 Redis 键设计(非持久化表)
| Key | Value | TTL | 说明 |
|---|---|---|---|
oms:wechat:login:{loginUuid} |
openId |
600s | PC 扫码登录桥接 |
oms:wechat:oauth:state:{state} |
随机 nonce | 300s | OAuth state 防 CSRF(可选) |
3.3 与 WMS sys_user_wechat 的映射关系
| WMS | OMS | 迁移说明 |
|---|---|---|
officialaccounts_openid |
t_customer.WechatOpenid |
按手机号/邮箱/客户编码对齐后一次性导入 |
nickname |
WechatNickname |
同步 |
headimgurl |
WechatAvatar |
同步 |
vip_id → sys_user |
Customer.UserId → RBAC user |
需业务侧建立客户映射,非本方案自动完成 |
4. 后端方案
4.1 目录结构(建议)
src/SimpleAdmin.Api/
├── WeChat/
│ ├── Options/
│ │ └── WeChatMpOptions.cs
│ ├── Controllers/
│ │ ├── WeChatMpController.cs # 公众号回调 + 二维码
│ │ └── WeChatCustomerController.cs # 注册 / 绑定
│ ├── Handlers/
│ │ ├── IWeChatMessageHandler.cs
│ │ ├── WeChatScanHandler.cs
│ │ └── WeChatSubscribeHandler.cs
│ ├── Services/
│ │ ├── IWeChatMpService.cs
│ │ ├── WeChatMpService.cs
│ │ ├── IWeChatLoginSessionStore.cs
│ │ └── RedisWeChatLoginSessionStore.cs
│ └── Dtos/
│ ├── WxLoginInput.cs
│ ├── WxLoginQrcodeOutput.cs
│ ├── WeChatOAuthUserInfoOutput.cs
│ ├── WeChatCustomerRegisterInput.cs
│ └── WeChatCustomerBindInput.cs
└── Auth/
└── AuthService.cs # 新增 WxLoginAsync
4.2 配置项
Consul / appsettings 示例:
{
"WeChat": {
"Mp": {
"AppId": "wxd5141ba46c856e1f",
"Secret": "********",
"Token": "********",
"EncodingAesKey": "********",
"OAuthRedirectBase": "https://oms.nanafa.com"
}
},
"Redis": {
"ConnectionString": "localhost:6379,defaultDatabase=0"
}
}
4.3 接口清单
所有接口前缀与现网 OMS API 一致:https://api.nanafa.com/admin(ASPNETCORE_PATHBASE=/admin)。
4.3.1 公众号服务器回调
| 方法 | 路径 | 鉴权 | 说明 |
|---|---|---|---|
| GET | /wechat/mp/{appId} |
匿名 | 微信接入验签,返回 echostr |
| POST | /wechat/mp/{appId} |
匿名 | 接收消息/事件(SCAN、SUBSCRIBE 等) |
GET 参数: signature, timestamp, nonce, echostr
POST 参数: 同微信文档;Body 为 XML(明文或 AES 加密)
路由分发:
| 事件 | Handler | 行为 |
|---|---|---|
SCAN |
WeChatScanHandler |
已关注用户扫码 |
subscribe |
WeChatSubscribeHandler |
未关注用户扫码关注(需处理 qrscene_ 前缀) |
| 其他 | 默认空响应或客服消息 | 按需扩展 |
4.3.2 获取登录二维码
| 方法 | 路径 | 鉴权 |
|---|---|---|
| GET | /wechat/mp/login-qrcode |
匿名 |
Query:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
loginUuid |
string | 是 | 前端生成的 UUID,标识一次登录会话 |
Response 200:
{
"qrCodeUrl": "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=xxx",
"expiresIn": 600
}
后端逻辑:
- 校验
loginUuid非空且格式合法(UUID) - 构造 scene JSON:
{"type":"login","loginUuid":"{loginUuid}"} - 调用微信
qrCodeCreateTmpTicket(scene, 600) - 返回二维码图片 URL
4.3.3 微信扫码登录(轮询)
| 方法 | 路径 | 鉴权 |
|---|---|---|
| POST | /rbac/auth/wx-login |
匿名 |
Request:
{
"loginUuid": "550e8400-e29b-41d4-a716-446655440000"
}
Response 200(LoginResultDto,与密码登录一致):
{
"accessToken": "eyJ...",
"refreshToken": "eyJ...",
"tokenType": "Bearer",
"expiresIn": 3600,
"userId": "guid"
}
错误码(业务异常 message):
| 场景 | message |
|---|---|
| Redis 无值 | 请扫码登录 |
| openId 未绑定客户 | 未绑定微信,请先注册或绑定账号 |
| 客户已禁用/冻结 | 客户已禁用 / 客户已冻结 |
| 子客户 | 子客户不支持微信扫码登录 |
| 未关联 RBAC 用户 | 客户未关联用户 |
核心逻辑(AuthService.WxLoginAsync):
1. openId = Redis.Get("oms:wechat:login:{loginUuid}")
2. customer = CustomerRepository.GetByWechatOpenidAsync(openId)
3. 校验:customer != null && ParentCustomerId == null
4. 校验:Status 非 Disabled / Frozen
5. 更新 LastLoginIp、LastLoginTime
6. userGuid = GetRbacUserGuidByMapIdAsync(customer.UserId)
7. claims = BuildClaimsAsync(userGuid, OmsLoginType.Customer)
8. return BuildLoginResult(userGuid, claims)
9. (可选)Redis.Delete(loginUuid) 防止重复使用
与 LoginCustomerAsync 的差异:跳过密码校验,JWT 签发流程相同。
4.3.4 OAuth 获取微信用户信息
| 方法 | 路径 | 鉴权 |
|---|---|---|
| POST | /wechat/oauth/user-info |
匿名 |
Request:
{
"code": "微信 OAuth 回调 code"
}
Response 200:
{
"openid": "oXXXX",
"nickname": "张三",
"sex": 1,
"province": "广东",
"city": "深圳",
"country": "中国",
"headimgurl": "https://...",
"unionid": "uXXXX"
}
逻辑:
code→access_token+openid(sns/oauth2/access_token)access_token+openid→ 用户信息(sns/userinfo)- 若该
openid已绑定客户,返回业务提示码供前端展示「已绑定」
4.3.5 微信授权注册客户
| 方法 | 路径 | 鉴权 |
|---|---|---|
| POST | /wechat/customer/register |
匿名 |
Request:
{
"customerCode": "C20260001",
"customerName": "张三",
"phone": "13800138000",
"email": "a@example.com",
"password": "Abc@12345",
"wechat": {
"openid": "oXXXX",
"nickname": "张三",
"avatar": "https://...",
"unionid": "uXXXX"
}
}
Response 200: 空体或 { "customerId": 1 }
校验:
| 项 | 规则 |
|---|---|
| openid | 必填;GetByWechatOpenidAsync 不得已存在 |
| customerCode / phone / email | 复用 CustomerService 唯一性校验 |
| password | 强度校验(与现网一致) |
| 角色 | 自动分配 Customer 角色 |
逻辑:
- 创建 RBAC User(Account 默认用手机号)
- 创建
t_customer,写入WechatOpenid、WechatNickname、WechatAvatar、WechatBindTime - 事务:User + Customer 同成功同回滚
4.3.6 微信授权绑定已有客户
| 方法 | 路径 | 鉴权 |
|---|---|---|
| POST | /wechat/customer/bind |
匿名 |
Request:
{
"account": "13800138000",
"password": "******",
"wechat": {
"openid": "oXXXX",
"nickname": "张三",
"avatar": "https://...",
"unionid": "uXXXX"
}
}
Response 200: 空体
校验:
| 项 | 规则 |
|---|---|
| 账号密码 | 等同客户密码登录校验 |
| openid | 不得已被其他客户绑定 |
| 目标客户 | 主客户;WechatOpenid 必须为空 |
| 状态 | 客户非禁用/冻结 |
逻辑:
FindCustomerByAccountAsync(account)+ 密码 MD5 校验- 更新
WechatOpenid、WechatNickname、WechatAvatar、WechatBindTime - 可选同步 RBAC User 头像
4.3.7 微信公众号内免密登录(可选,二期)
| 方法 | 路径 | 鉴权 |
|---|---|---|
| POST | /rbac/auth/wx-public-login |
匿名 |
Request: { "openid": "oXXXX" }
说明: 用于微信内 H5 页(如充值审核),Token 短时效(24h),非持久 Cookie。一期可不做。
4.4 事件处理逻辑
4.4.1 SCAN(已关注用户扫码)
输入:FromUserName = openId, EventKey = scene JSON 字符串
1. customer = GetByWechatOpenidAsync(openId)
2. if customer == null → 回复「未绑定账号,请通过菜单注册或绑定」
3. 解析 EventKey JSON:type == "login"
4. loginUuid = json.loginUuid
5. Redis.Set("oms:wechat:login:{loginUuid}", openId, 600s)
6. 可选回复「登录成功,请返回电脑端」
4.4.2 SUBSCRIBE(未关注用户扫码后关注)
输入:EventKey = "qrscene_{sceneJson}"
1. content = EventKey.Replace("qrscene_", "")
2. 其余逻辑同 SCAN
WMS 已知缺陷:未处理
qrscene_前缀导致未关注用户扫码失败。OMS 必须实现。
4.4.3 二维码 scene 格式
{
"type": "login",
"loginUuid": "550e8400-e29b-41d4-a716-446655440000"
}
策略 B 下不需要 system 字段。
4.5 鉴权白名单
以下路径 [AllowAnonymous],且 JWT 中间件不拦截:
GET /wechat/mp/{appId}
POST /wechat/mp/{appId}
GET /wechat/mp/login-qrcode
POST /rbac/auth/wx-login
POST /wechat/oauth/user-info
POST /wechat/customer/register
POST /wechat/customer/bind
4.6 领域层改动清单
| 文件 | 改动 |
|---|---|
Customer.cs |
可选增加 WechatUnionid、WechatBindTime |
ICustomerRepository |
已有 GetByWechatOpenidAsync,无需改 |
CustomerRepository.cs |
已有实现 |
CustomerService.cs |
抽取 BuildCustomerEntity 支持写入 WechatOpenid;或注册逻辑放 WeChatCustomerController 专用 Service |
AuthService.cs |
新增 WxLoginAsync |
CreateCustomerInput |
微信注册走独立 DTO,不污染管理端创建接口 |
5. 前端方案
5.1 页面与路由
| 路由 | 组件 | 门户 | 说明 |
|---|---|---|---|
/ |
views/login/index.vue |
客户 | 已有;微信 Tab 对接真实接口 |
/admin |
同上 | 管理端 | 不展示微信入口(已实现 isCustomerLogin) |
/wechat/register |
views/wechat/register/index.vue |
公开 H5 | 公众号菜单「注册」 |
/wechat/bind |
views/wechat/bind/index.vue |
公开 H5 | 公众号菜单「绑定账号」 |
路由注册(src/router/index.ts):
{
path: '/wechat/register',
name: 'WechatRegister',
component: () => import('@/views/wechat/register/index.vue'),
meta: { requiresAuth: false },
},
{
path: '/wechat/bind',
name: 'WechatBind',
component: () => import('@/views/wechat/bind/index.vue'),
meta: { requiresAuth: false },
},
5.2 API 封装
新建 src/api/wechat/index.ts:
| 方法 | 请求 | 说明 |
|---|---|---|
getLoginQrcode(loginUuid) |
GET /wechat/mp/login-qrcode?loginUuid= |
获取二维码 |
wxLogin(loginUuid) |
POST /rbac/auth/wx-login |
轮询登录 |
getOAuthUserInfo(code) |
POST /wechat/oauth/user-info |
H5 授权 |
registerByWechat(data) |
POST /wechat/customer/register |
注册 |
bindByWechat(data) |
POST /wechat/customer/bind |
绑定 |
请求走现有 RBAC axios 实例(OpenAPI.BASE = admin API),微信登录相关接口需 skipAuth: true(不携带 Token)。
5.3 wechat-login.vue 改造要点
参考 WMS wms0414/src/views/Login/components/wechat-login.vue,适配 OMS:
1. onMounted → loadQrCode()
2. loginUuid = uuidv4()
3. GET login-qrcode → 展示 qrCodeUrl
4. setInterval 每 3s → POST wx-login
5. 成功 → rbacUserStore 存 Token + setLoginPortalType(Customer) + getCurrentUser() + 跳转首页
6. setTimeout 600000 → 停止轮询(二维码过期)
7. 刷新按钮 → 重新 loadQrCode()
rbacUserStore 扩展:
async function loginByWxResult(result: LoginResultDto) {
saveTokens(result);
setLoginPortalType(OmsLoginType.Customer);
await getCurrentUser();
}
5.4 H5 注册页流程
公众号菜单 → 微信 OAuth 授权
→ 回调 https://oms.nanafa.com/wechat/register?code=xxx
→ POST /wechat/oauth/user-info { code }
→ 若 openid 已绑定 → 提示已注册
→ 否则展示表单(客户编码、名称、手机、邮箱、密码)
→ POST /wechat/customer/register
→ 成功提示「可返回 PC 扫码登录」
5.5 H5 绑定页流程
公众号菜单 → OAuth → /wechat/bind?code=xxx
→ getOAuthUserInfo
→ 表单:账号 + 密码
→ POST /wechat/customer/bind
→ 成功提示
5.6 国际化
在 src/views/login/locale/zh-CN.ts / en-US.ts 补充:
| Key | 中文 |
|---|---|
login.wechat.qrValid |
二维码十分钟有效 |
login.wechat.scanPending |
请使用微信扫一扫 |
login.wechat.notBound |
未绑定微信,请先在公众号注册或绑定 |
5.7 前端文件清单
| 操作 | 路径 |
|---|---|
| 改造 | src/views/login/components/wechat-login.vue |
| 新增 | src/api/wechat/index.ts |
| 新增 | src/views/wechat/register/index.vue |
| 新增 | src/views/wechat/bind/index.vue |
| 修改 | src/store/modules/rbac-user.ts(loginByWxResult) |
| 修改 | src/router/index.ts(H5 路由) |
| 修改 | src/views/login/locale/*.ts |
6. 微信公众号配置
6.1 服务器配置(迁移到 OMS)
| 配置项 | 值 |
|---|---|
| URL | https://api.nanafa.com/admin/wechat/mp/{AppId} |
| Token | 与 WeChat:Mp:Token 一致 |
| EncodingAESKey | 与配置一致 |
| 消息加解密方式 | 安全模式(推荐)或明文 |
6.2 网页授权域名
oms.nanafa.com
6.3 自定义菜单(示例)
| 菜单 | 类型 | 链接 |
|---|---|---|
| 注册账号 | 网页授权 | https://open.weixin.qq.com/connect/oauth2/authorize?appid={AppId}&redirect_uri={encode(oms.nanafa.com/wechat/register)}&response_type=code&scope=snsapi_userinfo&state=register#wechat_redirect |
| 绑定账号 | 网页授权 | 同上,redirect_uri 指向 /wechat/bind |
6.4 迁移检查清单
- 微信公众平台服务器 URL 从 WMS 改为 OMS
- 点击「启用」后 OMS 验签接口返回正确
echostr - WMS 侧公众号相关定时任务/模板消息评估停用或迁移
- 确认 AppId / Secret 写入 OMS Consul
7. 部署与 Nginx
7.1 API 路径
现网 OMS API:https://api.nanafa.com/admin/*
微信回调完整 URL:
https://api.nanafa.com/admin/wechat/mp/wxd5141ba46c856e1f
无需额外 nginx 规则(已代理到 admin 服务),需确认:
proxy_read_timeout≥ 30s(微信回调一般足够)- 支持 POST
application/xml或text/xml
7.2 前端 H5
oms.nanafa.com 静态站点已存在;新增 /wechat/* 走路由回退 index.html(与 SPA 一致)。
8. 实施阶段
阶段 1:后端基础(2 天)
- 引入微信 SDK + Redis
WeChatMpOptions+ Consul 配置WeChatMpController验签 + 消息入口WeChatScanHandler/WeChatSubscribeHandlerRedisWeChatLoginSessionStore- 数据库索引脚本
阶段 2:扫码登录闭环(2 天)
GET /wechat/mp/login-qrcodePOST /rbac/auth/wx-login- 前端
wechat-login.vue对接 rbacUserStore.loginByWxResult
阶段 3:注册 / 绑定(2 天)
POST /wechat/oauth/user-infoPOST /wechat/customer/registerPOST /wechat/customer/bind- H5 页面 + 路由
- 公众号菜单配置
阶段 4:切流与验收(1 天)
- 公众号服务器 URL 切换到 OMS
- 全链路测试(见第 9 节)
- WMS 微信登录入口下线或隐藏
- (可选)WMS openId 数据迁移脚本
9. 测试用例
| # | 场景 | 预期 |
|---|---|---|
| 1 | 已绑定客户 PC 扫码 | 3s 内轮询成功,跳转首页,JWT 有效 |
| 2 | 未绑定客户扫码 | 公众号收到提示;PC 轮询返回「请扫码登录」或超时 |
| 3 | 二维码 10 分钟过期 | 前端停止轮询;刷新可重新获取 |
| 4 | 未关注公众号用户扫码 | SUBSCRIBE 事件正确处理 qrscene_ |
| 5 | 微信注册新客 | 客户表写入 openId,随后可扫码登录 |
| 6 | 微信绑定已有账号 | 绑定后扫码可登录 |
| 7 | 重复绑定同一 openId | 拒绝 |
| 8 | 子客户 openId 绑定主客户流程外 | 子客户扫码登录被拒绝 |
| 9 | 禁用/冻结客户扫码 | 登录失败,明确提示 |
| 10 | 管理端 /admin |
不显示微信入口 |
| 11 | 公众号验签 GET | 返回 echostr |
| 12 | Token 刷新 | 微信登录后 refresh-token 正常 |
10. 风险与回滚
| 风险 | 缓解 |
|---|---|
| 公众号 URL 切换后 WMS 微信能力立即失效 | 选低峰期切换;提前通知;准备回滚 URL |
| Redis 不可用 | 扫码登录不可用;密码登录不受影响 |
| 老客户无 openId | 提供绑定 H5 + 可选批量迁移脚本 |
| 多实例 API | 必须使用 Redis,禁止 IMemoryCache 做单机桥接 |
回滚: 微信公众平台服务器 URL 改回 WMS 地址,OMS 前端隐藏微信入口。
11. 附录:与 WMS 接口对照
| 能力 | WMS (Java) | OMS (C#) |
|---|---|---|
| 二维码 | GET /apiwechat/loginqrcode |
GET /wechat/mp/login-qrcode |
| 轮询登录 | POST /wxlogin |
POST /rbac/auth/wx-login |
| 公众号回调 | GET/POST /apiwechat/{appId} |
GET/POST /wechat/mp/{appId} |
| OAuth 用户信息 | POST /wechat/officialAccounts/getWxUserinfo |
POST /wechat/oauth/user-info |
| 注册 | POST /wechat/wxUserAdd |
POST /wechat/customer/register |
| 绑定 | POST /wechat/wxUserBinding |
POST /wechat/customer/bind |
| 绑定存储 | sys_user_wechat |
t_customer.WechatOpenid |
| 会话桥接 | Redis loginuuid→openId |
Redis oms:wechat:login:{loginUuid} |
| 认证 | Sa-Token | JWT LoginResultDto |
12. 总结
本方案采用策略 B:同一公众号的服务器配置独占 OMS,不做 WMS/OMS 双系统回调分流。OMS 复用 WMS 已验证的「二维码 + 事件 + Redis + 轮询」模式,结合现有 t_customer.WechatOpenid 与 JWT 认证体系,实现客户门户微信扫码登录及 H5 注册绑定。实施顺序建议:Redis + 回调 → 扫码登录 → 注册绑定 → 公众号切流。