支付宝小程序集成MQTT
1. 前言
由于支付宝只支持websocket连接,在尝试了很多npm安装mqtt亦或是使用paho-mqtt.js、重新编译过后的mqtt.js多方无果后,最终决定自己做一个桥接的websocket服务,来作为mqtt的Borker和小程序的websocket的中转服务。最终实现了支付宝小程序可以收到和发送mqtt消息的目的。
2. 处理流程
1. 搭建一个springboot的简易版websocket服务端,同时连接mqtt的Broker作为mqtt的客户端。简称中转服务。
2. 小程序使用websocket连接中转服务。
3. 小程序发送websocket服务到中转服务,中转服务把收到的消息发送给mqtt的Broker。
4. 中转服务收到mqtt发送的消息,查找对应的websocket小程序用户唯一id是否存在。如果存在就通过websocket发送给小程序。
5. 小程序收到websocket消息,做对应的处理。
本章主要介绍支付宝小程序的处理方式,下一章介绍如何搭建springboot的中转服务。
3. 接口详情
-
wss地址
这里是我们自己搭建的中转服务websocket地址。wss://xxxx.cn/netgate/密钥/pid/sn/openid
-
参数说明
参数名称 参数说明 密钥 自定义标识符,用于鉴权处理 pid 设备产品ID【设备二维码中包含此信息】 sn 设备序列号【设备二维码中包含此信息】 openid 用户自己的id。可以使用个人平台的用户唯一id。相同ID会挤掉前一个用户的ws连接
4. 代码详解
小程序示例UNIAPP方式
如果没有使用uniapp框架,使用原生技术
微信小程序: 需要把uni.替换成wx.
支付宝小程序:需要把uni.替换成my.
1. 新建ws.js文件
var ws = {
};
const wsUrl= 'wss://xxxx.cn/netgate/密钥/';
var timeoutObj;
let connectStatus = 0;
//避免socket重复连接
let lockReconnect = false;
function heartCheck(){
console.log('准备心跳检测')
if(timeoutObj){
clearInterval(timeoutObj);
}
timeoutObj = setInterval(function () {
uni.sendSocketMessage({
data: 'H', // 需要发送的内容
success: (res) => {
console.log('心跳O(∩_∩)O')
},
});
}, 55000)
}
ws.initWs = (pid,sn,openid) => {
uni.onSocketOpen(function() {
// uni.showToast({title: 'WebSocket 连接已打开!'})
console.log('WebSocket 连接已打开!');
connectStatus = 1;
heartCheck()
});
uni.onSocketError(function(res){
// uni.showToast({title: 'WebSocket 连接打开失败,请检查!'})
console.log('WebSocket 连接打开失败,请检查!');
ws.reconnect()
});
uni.onSocketClose((res) => {
uni.showToast({
title: '连接已关闭'})
ws.reconnect()
console.log('连接已关闭')
});
uni.offSocketClose((res)=>{
uni.showToast({
title: '取消监听 WebSocket 关闭事件'})
console.log('取消监听 WebSocket 关闭事件')
connectStatus = 0;
});
uni.offSocketError((res) =>{
uni.showToast({
title: '取消监听 WebSocket 错误事件'})
console.log('取消监听 WebSocket 错误事件')
connectStatus =0;
});
uni.offSocketOpen((res)=>{
uni.showToast({
title: '取消监听 WebSocket 连接打开事件'})
console.log('取消监听 WebSocket 连接打开事件')
connectStatus = 0;
});
uni.offSocketMessage((res)=>{
uni.showToast({
title: '取消监听 WebSocket 接收到服务器的消息事件'})
console.log('取消监听 WebSocket 接收到服务器的消息事件')
});
uni.connectSocket({
url: wsUrl+ pid+ '/' +sn+ '/'+ openid,
success: (res) => {
console.log('连接成功')
uni.showToast({
title: '设备连接成功'})
},
fail:(res)=>{
console.log('connect fail:'+JSON.stringify(res))
}
})
}
ws.disconnect = ()=> {
console.log('关闭ws连接')
uni.closeSocket()
// 链接关闭后切断所有监听
// 支付宝小程序的ws连接问题,关闭连接时需关闭对于接受,防止关闭失败
uni.offSocketMessage();
uni.offSocketError();
uni.offSocketOpen();
uni.offSocketClose();
}
ws.reconnect = ()=> {
console.log('正在准备重新连接')
if (lockReconnect) return;
console.log('重新连接')
lockReconnect = true;
let self = this;
setTimeout(function () {
//没连接上会一直重连,设置延迟避免请求过多
self.connect();
lockReconnect = false;
}, 2000);
}
ws.sendMsg = function(msg) {
console.log('准备发送消息')
uni.sendSocketMessage({
data: msg, // 需要发送的内容
success: (res) => {
console.log('消息发送成功==='+msg)
},
});
}
export default ws;
2. 页面使用
<script>
import ws from "../../common/utils/ws";
export default {
onUnload(){
ws.disconnect()
},
onLoad(){
ws.initWs(this.curProId,this.curSn,userInfo.wxid)
let self = this;
uni.onSocketMessage(function(res) {
self.deviceReceiveMsgWs(res.data)
})
},
methods: {
//接收消息
deviceReceiveMsgWs(msgStr){
console.log('ws收到了消息'+msgStr)
},
//发送消息
sendMsg(){
ws.sendMsg('{"CMD":"STATE"}')
}
}
}
</script>