基于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

相关文章
相关标签/搜索