由于支付宝只支持websocket连接,在尝试了很多npm安装mqtt亦或是使用paho-mqtt.js、重新编译过后的mqtt.js多方无果后,最终决定自己做一个桥接的websocket服务,来作为mqtt的Borker和小程序的websocket的中转服务。最终实现了支付宝小程序可以收到和发送mqtt消息的目的。
2023-09-06 终于在网上找到了可以使用mqtt直连支付宝小程序的demo,所以在他的基础上我进行了整合,当然使用本篇的websocket中转也可以实现mqtt收发消息的功能。相对而言,感觉websocket的方式还是稳定性高的,想使用mqtt直连的可以直接参考下一篇。
支付宝小程序集成mqtt兼容IOS和安卓
1. 搭建一个springboot的简易版websocket服务端,同时连接mqtt的Broker作为mqtt的客户端。简称中转服务。
2. 小程序使用websocket连接中转服务。
3. 小程序发送websocket服务到中转服务,中转服务把收到的消息发送给mqtt的Broker。
4. 中转服务收到mqtt发送的消息,查找对应的websocket小程序用户唯一id是否存在。如果存在就通过websocket发送给小程序。
5. 小程序收到websocket消息,做对应的处理。
本章主要介绍支付宝小程序的处理方式,下一章介绍如何搭建springboot的中转服务。
wss地址
这里是我们自己搭建的中转服务websocket地址。
wss://xxxx.cn/netgate/密钥/pid/sn/openid
参数说明
| 参数名称 | 参数说明 |
|---|---|
| 密钥 | 自定义标识符,用于鉴权处理 |
| pid | 设备产品ID【设备二维码中包含此信息】 |
| sn | 设备序列号【设备二维码中包含此信息】 |
| openid | 用户自己的id。可以使用个人平台的用户唯一id。相同ID会挤掉前一个用户的ws连接 |
小程序示例UNIAPP方式
如果没有使用uniapp框架,使用原生技术
微信小程序: 需要把uni.替换成wx.
支付宝小程序:需要把uni.替换成my.
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;
<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>