最近在研究微信小程序的开发,中间遇到了不少问题,趟了不少坑,这里和大家分享一下我的一些经验,希望能给大家提供一些帮助。
这一部分不是本文的重点,均以示例代码+注释带过。
import * as websocket from "websocket"; import * as http from "http"; const WebSocketServer: typeof websocket.server = websocket.server; // 创建一个http Server let httpServer: http.Server = http.createServer((request, response) => { console.log("received a request"); response.writeHead(404); response.end(); }); // 创建一个websocket Server,websocket Server需要建立在http server之上 let wsServer: websocket.server = new WebSocketServer({ httpServer: httpServer, autoAcceptConnections: true }); // 事件监听 wsServer.on("connect", (connection) => { console.log(">>>come from: " + connection.remoteAddress); // 显示连接客户端的ip地址 connection.on("message", (message) => { console.log(message.type); console.log(">>>message: ", message); // 接收到信息的类型和内容,注意都是utf8编码 connection.sendUTF(message.utf8Data); // 把接收到的信息发回去 }); connection.on("close", (reasonCode, description) => { console.log(connection.remoteAddress + " has disconnected."); }); }); // 启动服务器 httpServer.listen(80, () => { console.log(">>>Http Server is listening on port 80!"); });
使用上述代码就可以非常方便的建立一个简单的服务器用于和微信小程序的通信,接下来简单的介绍一下微信小程序如何与服务器进行通信。
微信小程序官方文档给出了以下几个API,具体请参阅 http://mp.weixin.qq.com/debug/wxadoc/dev/api/network-socket.html
下面还是用代码来体现用法,我们把他们写在onLoad事件里:
onLoad: function () { this.setData({ }); var that = this; wx.connectSocket({ url: 'ws://xxx.xxx.com' // 这里是服务器的地址 }), wx.onSocketOpen(function (res) { // callback console.log("WebSocket连接已打开!"); // 打开WebSocket连接,在进行通信之前必须先打开一个连接 }), wx.onSocketError(function (res) { // WebSocket错误监听 console.log('WebSocket连接打开失败,请检查!') }), wx.onSocketMessage(function (msg) { // WebSocket数据接收监听 // CallBack console.log(msg); }), wx.onSocketClose(function () { // WebSocket关闭监听 // callback console.log('WebSocket服务器已经关闭!'); }), wx.sendSocketMessage({ // 向服务器发送数据,注意这个方法之必须在调用wx.connectSocket和wx.onSocketOpen回调之后 data: "string" // 官方文档里data可以是string或者ArrayBuffer,但是注意这个ArrayBuffer并不是Array }); }
这里值得一提的是,官方文档关于 wx.sendSocketMessage 的说明中data的类型包含的ArrayBuffer并不是Array,如果你把data误写成Array类型的话在开发工具中调试不会报错且表现正常,但是到手机端就会出现问题而且不会报错!
二、SSL证书申请和使用 这一部分算是本文的重点了,首先说一下SSL证书是什么和为什么要SSL证书。
SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。因为配置在服务器上,也称为SSL服务器证书。
SSL 证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能。
SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socket layer(SSL)安全协议是由Netscape Communication公司设计开发。该安全协议主要用来提供对用户和服务器的认证;对传送的数据进行加密和隐藏;确保数据在传送中不被改变,即数据的完整性,现已成为该领域中全球化的标准。由于SSL技术已建立到所有主要的浏览器和WEB服务器程序中,因此,仅需安装服务器证书就可以激活该功能了),即通过它可以激活SSL协议,实现数据信息在客户端和服务器之间的加密传输,可以防止数据信息的泄露。保证了双方传递信息的安全性,而且用户可以通过服务器证书验证他所访问的网站是否是真实可靠。数位签名又名数字标识、签章 (即 Digital Certificate,Digital ID ),提供了一种在网上进行身份验证的方法,是用来标志和证明网路通信双方身份的数字信息文件,概念类似日常生活中的司机驾照或身份证相似。 数字签名主要用于发送安全电子邮件、访问安全站点、网上招标与投标、网上签约、网上订购、安全网上公文传送、网上办公、网上缴费、网上缴税以及网上购物等安全的网上电子交易活动。 (以上来源:http://baike.baidu.com/item/SSL%E8%AF%81%E4%B9%A6/5201468?fr=aladdin)
为什么要SSL证书其实也很简单,微信的官方文档里面对网络请求和通信有以下要求:
简单总结:
1.微信小程序使用的网络连接必须是http加密的安全连接(需要SSL证书)
2.微信小程序使用的服务器地址只能是备案过的域名
3.微信小程序使用的服务器地址不能包括端口(由于采用了http所以默认是443,不是80不是80不是80!)
4.开发过程中可以没有以上限制
SSL证书很多是要收费的,部分免费的微信小程序还不支持……
这里给大家推荐一个网站,这里提供的免费SSL证书可以在微信小程序中使用,但是每3个月需要renew一次:http://www.sslforfree.com/
首先我们在主页输入需要申请的域名(SSL For Free的证书只能绑定一个域名),然后点Create。
在进行了域名检查之后会出现如下的验证方式,用以确认你是申请域名的所有者,三种方式分别是FTP自动验证(输入FTP信息自动确认)、人工验证(上传指定文件通过是否能够访问进行验证)、DNS解析验证(在域名解析中添加txt记录进行验证)。前面两种方式比较方便(可能?),但是实测还是挺容易失败的,这里推荐用第三种方式进行验证,下面进行简单说明。
这里以腾讯云作为案例,在点击DNS验证之后会出现如下页面:
马赛克的部分就是需要添加的txt记录,这里我们进入腾讯云的云解析对DNS解析进行记录添加,如下图添加一个txt记录:
主机记录这里需要着重说明一下,比如我们需要绑定的域名是abc.com或者www.abc.com这样的一级域名,这里就需要按照要求写成_acme-challenge.abc.com;但是如果是123.abc.com这样的二级域名,那么这里按要求就是_acme-challenge.123.abc.com。
线路类型忽略即可,记录值填写要求的string,也就是页面截图中打马赛克的部分,TTL用默认值,然后记得保存。
完成以上操作之后我们回到SSL For Free页面,等待10分钟之后(和TTL有关,但是也可能要更久)点击第三步中的链接,如果链接打开的一个页面中有要求的String,那么就说明txt记录添加成功,可以点击最下面的按钮进行下载。同时我们可以在下载的页面里面填入自己的电子邮箱,以便在SSL证书到期时自动提醒。
下载成功之后记得把之前的域名解析换成正常的设定指向自己的服务器。
下载的文件是一个压缩包,解压之后应该包括如下三个文件,这三个文件在一起可以作为一个有效证书,同时node.js可以直接使用这三个文件来创建http服务器。
下面是使用了这三个文件的http服务器的代码:
import * as websocket from "websocket"; import * as http from "http"; import * as fs from "fs"; // 需要引用node.js的fs来读取三个SSL证书文件 const WebSocketServer: typeof websocket.server = websocket.server; // http Server let options: any = { key: fs.readFileSync("./key/private.key", "utf8"), // 这里设置三个证书的位置,记得指明“utf8”编码,key、cert、ca三个属性必须都有且对应三个文件 cert: fs.readFileSync("./key/certificate.crt", "utf8"), ca: fs.readFileSync("./key/ca_bundle.crt", "utf8") }; let httpServer: any = http.createServer(options, (request, response) => { // 注意这里已经是http了 console.log("received a request"); response.writeHead(200); response.end("hello worldn"); }); // websocket Server let wsServer: websocket.server = new WebSocketServer({ httpServer: httpServer, // 对应的这里的httpServer后面也应该是对应的httpSrver(名称无所谓但是本体应该是httpServer) autoAcceptConnections: true }); // 事件监听 wsServer.on("connect", (connection) => { console.log(">>>come from: " + connection.remoteAddress); connection.on("message", (message) => { console.log(message.type); console.log(">>>message: ", message); connection.sendUTF(message.utf8Data); // 把接收到的信息发回去 }); connection.on("close", (reasonCode, description) => { console.log(connection.remoteAddress + " has disconnected."); }); }); // 启动服务器 httpServer.listen(443, () => { // 端口 console.log(">>>Https Server is listening on port 443!"); });
微信小程序的通信与http是一致的,但是这里需要提醒,这个监听端口必须是443,因为微信小程序要求的服务器地址是http://xxx.yyy.com 这样的只能是域名不能带端口且开头是http,那端口一定是默认的443,说默认端口是80的我也不知道是为什么……如果有谁知道原因还请留言。
以上便是本文的全部内容,个人水平有限,如有表述和技术错误欢迎指正。