网站利用扫码关注公众号实现一键登录(下)

网站利用扫码关注公众号实现一键登录

      上一篇跟大家分享了微信公众号部分的对接,今天这部分跟大家分享前端如何监听到用户扫码关注公众号,考虑到用户体验性跟系统压力,我们需要用到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)

截图位置如下

WX20250303-163750@2x.png

这样便完成了最后的开发,前端通过与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效果,截图如下

2.png

    

0条评论

发表评论