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条评论