Go
网站利用扫码关注公众号实现一键登录(下)
网站利用扫码关注公众号实现一键登录
上一篇跟大家分享了微信公众号部分的对接,今天这部分跟大家分享前端如何监听到用户扫码关注公众号,考虑到用户体验性跟系统压力,我们需要用到websocket,前端在获取到微信公众号二维码地址以及唯一ID之后,需要跟后端接口进行链接,监听唯一ID情况。
我们需要开发一个websocket链接给前端调用,并且需要开发一个主动发送消息的方法,在用户扫码关注之后,调用该接口,告诉前端用户已经扫码关注,可以进行登陆操作,我这里用的是go语言的iris框架开发,代码如下
package api
// 引入扩展
import (
"encoding/json"
"github.com/gorilla/websocket"
iris "github.com/kataras/iris/v12"
"log"
"sync"
"github.com/sirupsen/logrus"
"net/http"
)
// 初始化名称
type WSController struct {
Ctx iris.Context
}
// 设置跨域连接
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
// 允许所有跨域请求
return true
},
}
// WebSocket连接管理
var wsConnections = struct {
sync.RWMutex
connections map[string]*websocket.Conn
}{
connections: make(map[string]*websocket.Conn),
}
// 查询公众号扫描情况
func (c *WSController) WxPublicGetLogin(party iris.Party) {
party.Get("/info", func(ctx iris.Context) {
// 记录接入
logrus.Info("建立连接")
// 升级HTTP连接为WebSocket连接
conn, err := upgrader.Upgrade(ctx.ResponseWriter(), ctx.Request(), nil)
if err != nil {
logrus.Error("ws连接失败", err)
return
}
// 读取场景信息
var sceneStr string
// 处理WebSocket消息
for {
// 读取消息
_, message, err := conn.ReadMessage()
if err != nil {
logrus.Error("ws读取消息异常", err)
// 连接断开时移除对应的连接
if sceneStr != "" {
wsConnections.Lock()
delete(wsConnections.connections, sceneStr)
wsConnections.Unlock()
}
break
}
// 解析消息
var request map[string]string
if err := json.Unmarshal(message, &request); err != nil {
logrus.Error("ws解析消息失败", err)
conn.WriteMessage(websocket.TextMessage, []byte(`{"errorCode":-1,"message":"Invalid JSON","data":null,"success":false}`))
continue
}
// 获取 sceneStr
sceneStr = request["sceneStr"]
if sceneStr == "" {
conn.WriteMessage(websocket.TextMessage, []byte(`{"errorCode":-1,"message":"sceneStr is required","data":null,"success":false}`))
continue
}
// 打印 sceneStr
logrus.Printf("收到 sceneStr: %s", sceneStr)
// 存储连接到对应的 sceneStr
wsConnections.Lock()
wsConnections.connections[sceneStr] = conn
wsConnections.Unlock()
}
})
}
// sendMessage 向指定sceneStr对应的客户端发送消息
func WsSendWxPublicMessage(sceneStr string) error {
wsConnections.RLock()
conn, exists := wsConnections.connections[sceneStr]
wsConnections.RUnlock()
if !exists {
logrus.Error("ws没有找到对应的客户端连接", sceneStr)
return nil
}
// 检查连接是否仍然有效
if conn == nil {
logrus.Error("ws连接已关闭", sceneStr)
return nil
}
// 向客户端发送消息
err := conn.WriteMessage(websocket.TextMessage, []byte(`{"errorCode":0,"message":"登陆成功","data":null,"success":true}`))
if err != nil {
logrus.Error("ws发送消息失败", sceneStr)
// 发送失败时移除对应的连接
wsConnections.Lock()
delete(wsConnections.connections, sceneStr)
wsConnections.Unlock()
return nil
}
log.Printf("消息已发送到 sceneStr: %s", sceneStr)
return nil
}然后我们再设置路由
// 配置WebSocket路由
wsParty := app.Party("/ws/public/login")
wsController := new(api.WSController)
wsController.WxPublicGetLogin(wsParty)完成websocket开发之后,我们在公众号回调方法里面植入发送消息方法,将这个函数植入
// 通过 WebSocket 向客户端发送消息 WsSendWxPublicMessage(loginToken)
截图位置如下

这样便完成了最后的开发,前端通过与websocket链接,后端则通过公众号回调函数事件处理,将用户扫码关注操作通知给前端,前端收到消息后,完成后续登陆操作。
如果你是用Nginx代理的话,我们还需要加入这一段配置,让网站适配ws,配置如下
# WebSocket 代理配置
location /ws/ {
proxy_pass http://127.0.0.1:8082; # WebSocket 后端服务地址
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; # WebSocket 升级头
proxy_set_header Connection 'upgrade'; # 连接头,用于 WebSocket 升级
proxy_set_header Host $host; # 保持原始主机头
proxy_cache_bypass $http_upgrade; # 防止缓存
} 我们可以看看ws效果,截图如下

0条评论