There are two common login logics for wechat scanning code

1. Wechat open platform

2. Wechat service number

Enterprise information are both need certification, there is no permission for individual developers, inadvertently saw the tencent document scan code login open is a small program, thought only of tencent have permissions (funny laugh 😄), then a search, found this logic is our daily development of the small program code function of small programs, Add a Websocket feature

This article was first published on my blog, welcome to come to see 🚀️ 🚀️ college

Realize the principle of

  • The blogger clicks the wechat login popup and establishes a Websocket connection. After the connection is successfully established, the blogger sends a message to obtain a random ID with time stamp from the server. After receiving the ID, the blogger carries the ID request applet code (ID is used for the communication binding between the web page and the applet).
  • After the user clicks on the login through wechat scanning code, the user information, code and ID are submitted to the server.
  • The server obtains the OpenID according to the code, then determines whether to create or update the user information according to the OpenID, and then generates the token and broadcasts it to the front-end web page with a unique ID through websocket
  • The front-end receives the token, stores the token, reloads the page to obtain user information, and disconnects the Websocket connection

Front-end code implementation

The front end I use is VUE

// Initialize weoSocket
        initWebSocket() {
            if (this.websock) {
                this.websock.close();
            }
            // Websocket message processing
            const messageHandler = {
                // Get the codeId
                CODE_ID: async (res) => {
                    let $res = await wxcodeUrl({ scene: res.data.uuid });
                    this.wxCodeSrc = "http://localhost:3000/" + $res.data.url;
                    this.codeLoading = false;
                    this.isFailure = false;
                    this.desccontent = "Please use wechat to scan";
                },
                // The QR code is scanned and waiting for client confirmation
                SCANNED: () = > {
                    this.isLoadingScan = true;
                    this.desccontent = "Please click on wechat to confirm login.";
                },
                // The login succeeds, and the obtained token is saved
                SUCCESS: (res) = > {
                    this.$store.commit("user/SET_TOKEN", res.data.token);
                    setToken(res.data.token);
                    location.reload();
                    this.$notify({
                        title: "Success".message: "Login successful ~".type: "success"});this.codeLoading = false;
                    this.websock.close(); }};// Initialize weoSocket
            this.websock = new WebSocket("ws://localhost:3000/webSocket");
            this.websock.onmessage = (e) = > {
                const res = JSON.parse(e.data);
                const handlerFn = messageHandler[res.data.type];
                // Match the corresponding function and execute it
                if (typeof handlerFn === "function") { handlerFn(res); }};// The connection was successfully established
            this.websock.onopen = () = > {
                // Send a message requesting a random ID
                this.websock.send("GET_CODE");
            };
            this.websock.onerror = this.websocketonerror;
            this.websock.onclose = this.websocketclose;
        },
        // Failed to establish the connection
        websocketonerror() {
            this.initWebSocket();
        },
        // Close the connection
        websocketclose() {
            this.isFailure = true;
            this.isLoadingScan = false;
            this.desccontent = "";
        },
Copy the code

Server code

I use KOA on the server side and THE webSocket connection uses the WS plug-in. Only part of the code is posted, such as the generated small program code is the interface call. Since I use the same port number for KOA and webSocket, I initialize the webSocket when KOA starts

app.listen(3000); app.on('error', onError); app.on('listening', onListening); Const WSS = createWss(server); initWebsocket(wss);Copy the code
  • The WebSocket Server object
const WebSocket = require('ws');

// WebSocket Server object
let wss = null;

// Create WSS object, we can pass in the Koa Server object, to share the port,
// For the first time, we will assign the result to the above WSS,
// The advantage of this is that it is easy to get the WSS object in the interface layer and match the correct client
const createWss = (server) = > {
    if(! wss) { wss =new WebSocket.Server({
            server: server
        })
        return wss;
    } else {
        returnwss; }}// Get the WSS object
const getWss = () = > {
    return wss;
}


module.exports = {
    createWss: createWss,
    getWss: getWss
}
Copy the code
  • Events after initialization
// Send a message
const sendData = (client, status, data) = > {
    if (client && client.send) {
        client.send(JSON.stringify({
            status: status,
            data: data })); }}// Service initialization
const initWebsocket = (wss) = > {
    wss.on("connection".(ws) = > {
        console.log(`[SERVER] connection`);
        // Data is received
        ws.on('message'.(msg) = > {
            console.log(`[SERVER] Received: ${msg}`);
            // Send data
            const fn = loginMessageHandler[msg];
            if (fn) {
                fn(ws);
            } else {
                ws.send("bad command!"); }}); }); }// Process the login message and match the corresponding business logic operation function according to the message sent by the client
const loginMessageHandler = {
    "GET_CODE": (ws) = > {
        const uid = new Date().getTime();
        console.log("Obtain qr code ----" + uid);
        ws.loginCondition = {
            uuid: uid,
            status: 0
        }
        sendData(ws, "ok", {
            uuid: uid,
            type: "CODE_ID"}); }}module.exports = {
    initWebsocket: initWebsocket,
    sendData: sendData
}
Copy the code

Wechat scan code login

/** * wechat scan code login *@param {*} ctx 
     */
    static async wxscanLogin(ctx) {
        const { scene: uuid } = ctx.request.body;
        let payload = ctx.state.user;
        try {
            const token = tools.generatorToken({ id: payload.id });
            const wss = getWss();
            if (wss && wss.clients && token) {
                The corresponding client can be found in wss.clients
                const clients = wss.clients;
                // Find the corresponding WS client
                let targetClient = [...clients].find((client) = > client.loginCondition.uuid == uuid);
                if (targetClient) {
                    if (targetClient.loginCondition.status == 0) {
                        sendData(targetClient, "ok", {
                            uuid: uuid,
                            type: "SUCCESS".token: token }); } } ctx.success(); }}catch(err) { ctx.fail(); }}Copy the code

It’s at youxiubiji.com