基於Electron + nodejs + 小程序 實現彈幕小工具(中篇)

前言

上兩篇文章,分別對產品需求和Electron端的實現作了相關的介紹,有興趣的朋友能夠看看以前的文章。本文,將介紹服務端的實現。html

需求分析

以前的文章也有提到,服務端的主要任務是對數據進行轉發以及生成小程序二維碼。node

對數據進行轉發,主要是把用戶在小程序端發送的消息,推送給Electron接收端。所以,咱們須要建立一個websocket服務。在這裏,咱們選擇使用ws模塊。git

生成小程序二維碼,咱們須要使用到微信的API。咱們將使用request這個模塊向微信服務器發起相關的請求。github

建立websocket服務

入口文件代碼以下:web

const WebSocketServer = require('ws').Server;
const port = require('./config').port;
const log4js = require('./helpers/logger');
const logger = log4js.Logger('APP');
const wsServer = new WebSocketServer({ port });

logger.info("Server listening on port:" + port);

wsServer.on('connection', function (ws) {
    logger.debug('a client connect');

    ws.on('message', async function (message) {
        // 消息處理邏輯
    });

    ws.on('close', function () {
        logger.info('ws斷開');
    })

    ws.on('error', function (error) {
        ws.close();
        logger.error(error);
    })
});
複製代碼

鏈接上這個服務的客戶端,有多是小程序發送端,也有多是Electron接收端,因此咱們須要對收到的消息進行了簡單的類型判斷。redis

根據以前的約定,若是消息的類型type爲INIT,咱們就認爲是接收端初始化的消息。傳遞的參數中,包含接收端的UID,咱們將會使用這個id做爲參數,生成帶參數的小程序二維碼。npm

因爲咱們會在公衆場合使用彈幕,因此咱們須要對內容進行校驗,防止一些不符合社會主義核心價值觀的言論出如今彈幕中。這裏,咱們直接使用微信的msgSecCheck接口。小程序

ws.on('message', async function (message) {
    try {
        const data = JSON.parse(message);
        if (data.type === "INIT") {
            logger.info('獲取二維碼', data);
            // 將接收端的clientId做爲鏈接的標識
            ws.danmuId = data.clientId;
            // 獲取微信小程序二維碼
            const result = await WechatService.getQrcode(data.clientId);
            if(result){
                const respMsg = {
                    type: 'qrcode',
                    data: result
                }
                ws.send(JSON.stringify(respMsg));                    
            }
        } else {
            logger.info('收到消息', ws.danmuId, message);
            // 對消息內容進行安全性校驗
            const isSecurity = await WechatService.checkContentSecurity(data.content);
            if(isSecurity){
                // 將消息轉發給對應的接收端
                wsServer.clients.forEach(function (client) {
                    if (client.danmuId === data.scene && client.readyState === 1) {
                        client.send(message);
                    }
                });
            }
        }
    } catch (error) {
        logger.error(error);
    }
});
複製代碼

生成帶參數的小程序二維碼

微信提供生成二維碼的接口有三個,分別應用於不一樣的應用場景。具體見小程序官方文檔微信小程序

本項目使用getWXACodeUnlimit這個API來獲取小程序碼,經過該接口生成的小程序碼,永久有效,數量暫無限制。api

請求地址

POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
複製代碼

若是調用成功,會直接返回圖片***二進制內容***,若是請求失敗,會返回 JSON 格式的數據。

WTF,官方文檔說了,會返回二進制的內容,可是爲何個人請求返回亂碼呢?

既然亂碼,那應該就是編解碼的問題了,看看所用的請求模塊request是否有相關的參數設置,果不其然:

encoding - encoding to be used on setEncoding of response data. If null, the body is returned as a Buffer. Anything else (including the default value of undefined) will be passed as the encoding parameter to toString() (meaning this is effectively utf8 by default). (Note: if you expect binary data, you should set encoding: null.)

默認是utf8,若是咱們須要二進制內容,那須要將encoding設置爲null。結果輸出以下:

看起來是好點了,咱們經過Buffer的toString方法將其轉爲base64,而後傳給Electron端進行展現,生成二維碼的功能就完成了。

access_token獲取與緩存

有微信開發經驗的朋友都知道,基本上全部的微信API,請求的時候都須要帶上access_token。而天天請求access_token的次數是有限制的,超出必定的限制則沒法獲取,只能坐等明天的到來。因此咱們須要對access_token進行緩存。

因爲咱們的項目是單機部署,因此咱們能夠簡單處理,將access_token存在內存中,每次先判斷內存中的access_token是否過時,未過時則使用,反之則向微信服務器請求最新的,並同步更新到內存中。

若是考慮多實例部署,能夠將access_token存儲到redis中。

日誌打印

魯迅曾經說過,沒有打印日誌的服務都是耍流氓。日誌,是後臺服務不可或缺的一部分,這裏咱們使用log4js進行日誌的打印。

最簡單的使用示例:

var log4js = require('log4js');
var logger = log4js.getLogger();
logger.level = 'debug';
logger.debug("Some debug messages");
複製代碼

詳情請查看官方文檔

GitHub項目地址

項目地址

咱們將陸續整理各端的代碼放在GitHub上,有興趣的能夠查閱一下。

總結

本文使用ws模塊搭建了一個簡單的websocket服務,並使用request進行微信API的請求,用於獲取小程序碼等。在日誌打印方面,咱們使用log4js,記錄一些關鍵信息。

下一篇文章,咱們將會探討小程序端的實現。

以上,若有錯漏,歡迎指正!

@Author: TDGarden

相關文章
相關標籤/搜索