front/docs/微信登录整合方案.md
zzh 5a26ae0048 feat: 小红书模块迁移、登录重构与 xhs-agent-desktop 桌面 Agent
- 新增小红书前端模块(启动服务、内容分析、爆款创作、发布记录、技能卡片、拟人设置、AI 助手)

- 新增 xhs-agent-desktop 独立桌面 Agent,对接 OMS 任务调度

- 登录页重构,整合微信登录与 OMS JWT 认证

- 订单、渠道、用户中心等页面与 API 增强

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 16:13:13 +08:00

25 KiB
Raw Blame History

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
}

后端逻辑:

  1. 校验 loginUuid 非空且格式合法(UUID)
  2. 构造 scene JSON:{"type":"login","loginUuid":"{loginUuid}"}
  3. 调用微信 qrCodeCreateTmpTicket(scene, 600)
  4. 返回二维码图片 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"
}

逻辑:

  1. code → access_token + openid(sns/oauth2/access_token)
  2. access_token + openid → 用户信息(sns/userinfo)
  3. 若该 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 角色

逻辑:

  1. 创建 RBAC User(Account 默认用手机号)
  2. 创建 t_customer,写入 WechatOpenid、WechatNickname、WechatAvatar、WechatBindTime
  3. 事务: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 必须为空
状态 客户非禁用/冻结

逻辑:

  1. FindCustomerByAccountAsync(account) + 密码 MD5 校验
  2. 更新 WechatOpenid、WechatNickname、WechatAvatar、WechatBindTime
  3. 可选同步 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 / WeChatSubscribeHandler
  • RedisWeChatLoginSessionStore
  • 数据库索引脚本

阶段 2:扫码登录闭环(2 天)

  • GET /wechat/mp/login-qrcode
  • POST /rbac/auth/wx-login
  • 前端 wechat-login.vue 对接
  • rbacUserStore.loginByWxResult

阶段 3:注册 / 绑定(2 天)

  • POST /wechat/oauth/user-info
  • POST /wechat/customer/register
  • POST /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 + 回调 → 扫码登录 → 注册绑定 → 公众号切流。