logo
0
0
WeChat Login

微信扫码登录方案 - 完整实现

🎯 方案说明

这是一个反向扫码登录方案,解决了电脑浏览器无法扫描二维码的问题。

核心思路:

  • 网站主动发起登录 (而不是小程序传递token)
  • 用户用微信扫描网站生成的二维码
  • 小程序确认登录后,网站通过轮询获取登录状态

🔄 完整流程

┌─────────────┐
│ 1. 网站请求 │  POST /api/session/create
│  创建会话    │  返回: sessionId
└──────┬──────┘
       │
       ↓
┌─────────────┐
│ 2. 网站展示 │  生成二维码
│   二维码     │  内容: https://site.com/scan?sessionId=xxx
└──────┬──────┘
       │
       ↓
┌─────────────┐
│ 3. 网站轮询 │  GET /api/session/poll/:sessionId
│  登录状态    │  每2秒查询一次
└──────┬──────┘
       │
       ↓  (同时进行)
       │
┌──────────────┐
│ 4. 用户扫码  │  微信扫一扫
│  打开小程序  │  跳转到 pages/scan-login/scan-login?sessionId=xxx
└──────┬───────┘
       │
       ↓
┌──────────────┐
│ 5. 小程序     │  - 用户填写/确认信息
│  确认登录    │  - 调用 wx.login() 获取 code
│              │  - POST /api/session/bind
└──────┬───────┘
       │
       ↓
┌──────────────┐
│ 6. 后端处理  │  - 用 code 换 openid
│              │  - 生成 token
│              │  - 更新会话状态为 confirmed
└──────┬───────┘
       │
       ↓
┌──────────────┐
│ 7. 网站轮询  │  - 检测到状态为 confirmed
│  检测到登录  │  - 获取 token
│              │  - 设置 cookie
│              │  - 跳转到首页
└──────────────┘

📦 已创建的文件

后端 Go 文件:

小程序文件:

🚀 使用步骤

1. 后端设置

安装依赖

go get github.com/gin-gonic/gin
go get github.com/google/uuid
go get gorm.io/gorm
go get gorm.io/driver/mysql

创建数据库表

-- 用户表(已存在)
CREATE TABLE `users` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `open_id` varchar(100) NOT NULL,
  `union_id` varchar(100) DEFAULT NULL,
  `nick_name` varchar(100) DEFAULT NULL,
  `avatar_url` varchar(500) DEFAULT NULL,
  `create_time` datetime(3) DEFAULT NULL,
  `last_login_time` datetime(3) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `open_id` (`open_id`),
  KEY `idx_users_union_id` (`union_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 登录会话表(新增)
CREATE TABLE `login_sessions` (
  `id` varchar(50) NOT NULL,
  `token` varchar(1000) DEFAULT NULL,
  `status` varchar(20) DEFAULT 'pending',
  `user_id` bigint unsigned DEFAULT NULL,
  `create_time` datetime(3) DEFAULT NULL,
  `expire_time` datetime(3) DEFAULT NULL,
  `scanned_at` datetime(3) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_status` (`status`),
  KEY `idx_expire_time` (`expire_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

运行后端

go run backend-scan-login.go

2. 访问网站登录页面

打开浏览器访问:

http://localhost:8080/wxamp/login

你会看到一个登录页面,显示二维码。

3. 微信扫码

使用微信扫一扫功能扫描二维码(注意:需要配置小程序二维码跳转)。

4. 小程序确认登录

扫码后会打开小程序的确认登录页面:

  • 如果已登录过,直接显示头像昵称
  • 如果首次登录,需要选择头像和输入昵称
  • 点击"确认登录"按钮

5. 网站自动登录

小程序确认后,网站会自动:

  • 检测到登录成功
  • 设置登录 cookie
  • 跳转到 /dashboard

🔑 核心API说明

1. 创建登录会话

POST /wxamp/api/session/create

Response:
{
  "success": true,
  "data": {
    "sessionId": "uuid-string",
    "qrCodeURL": "pages/scan-login/scan-login?sessionId=xxx",
    "expireTime": 1234567890
  }
}

2. 轮询登录状态

GET /wxamp/api/session/poll/:sessionId

Response:
{
  "success": true,
  "data": {
    "status": "confirmed",  // pending | scanned | confirmed | expired
    "token": "jwt-token-string",
    "userId": 123
  }
}

3. 绑定会话(小程序调用)

POST /wxamp/api/session/bind

Request:
{
  "sessionId": "uuid-string",
  "code": "wx-login-code",
  "userInfo": {
    "nickName": "用户昵称",
    "avatarUrl": "头像URL"
  }
}

Response:
{
  "success": true,
  "data": {
    "token": "jwt-token-string",
    "userInfo": { ... }
  }
}

🎨 网站登录页面特性

  • ✅ 自动生成二维码
  • ✅ 实时轮询登录状态
  • ✅ 状态提示(等待扫码 → 已扫描 → 登录成功)
  • ✅ 二维码过期自动刷新
  • ✅ 登录成功自动跳转

📱 小程序页面特性

  • ✅ 自动读取 sessionId 参数
  • ✅ 支持新用户注册(头像+昵称)
  • ✅ 已登录用户直接确认
  • ✅ 绑定成功后返回
  • ✅ 优雅的错误处理

🔐 安全机制

  1. 会话过期: 10分钟自动过期
  2. Token签名: JWT签名防伪造
  3. 一次性会话: 每次扫码生成新会话
  4. 状态验证: 多重状态检查
  5. 自动清理: 定时清理过期会话

⚠️ 注意事项

关于小程序二维码

问题: 普通二维码无法直接打开小程序

解决方案有3种:

方案A: URL Scheme (推荐)

// 网站生成URL Scheme
const scheme = `weixin://dl/business/?t=${encodeURIComponent('your_scheme')}`

// 需要在微信公众平台配置 URL Scheme

方案B: 小程序码(需要后端生成)

// 调用微信接口生成小程序码
func generateMiniProgramCode(sessionId string) ([]byte, error) {
    url := "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken()

    body := map[string]interface{}{
        "scene": "sessionId=" + sessionId,
        "page":  "pages/scan-login/scan-login",
        "width": 280,
    }

    // 返回二维码图片
}

方案C: 短链跳转(临时方案)

网站二维码 → 短链 → H5页面 → 判断微信环境 → 跳转小程序

开发环境测试

由于无法生成真实小程序码,开发环境可以:

  1. 手动在小程序输入 sessionId
  2. 或在小程序添加测试入口
  3. 或使用微信开发者工具的二维码编译功能

生产环境配置

  1. 域名配置: 在微信公众平台配置服务器域名
  2. HTTPS: 生产环境必须使用HTTPS
  3. URL Scheme: 配置小程序的URL Scheme
  4. 业务域名: 配置H5业务域名(如果使用H5跳转)

🧪 测试流程

方法1: 直接测试小程序页面

  1. 运行后端
  2. 在微信开发者工具打开小程序
  3. 手动编译到 pages/scan-login/scan-login?sessionId=test-123
  4. 同时在浏览器打开 http://localhost:8080/wxamp/login
  5. 查看网站是否检测到登录

方法2: 完整流程测试

  1. 实现小程序码生成接口
  2. 网站访问 /wxamp/login
  3. 获取二维码
  4. 微信扫码
  5. 确认登录
  6. 网站自动登录

📊 数据库会话状态

状态说明
pending等待扫码
scanned已扫码,等待确认
confirmed已确认,登录成功
expired已过期

💡 优化建议

  1. WebSocket替代轮询: 使用WebSocket实现实时通知,减少服务器压力
  2. Redis缓存: 将会话数据存入Redis,提高查询性能
  3. 二维码美化: 添加logo,使用彩色二维码
  4. 多端支持: 同时支持APP、H5、PC
  5. 统计分析: 记录扫码、登录转化率

🔗 相关文档


这个方案完美解决了电脑浏览器无法扫码的问题!🎉

About

No description, topics, or website provided.
Language
HTML51.1%
Go47.7%
Dockerfile1.2%