uniapp在小程序连接webScoket实现余额支付
webScoket文档:uni.connectSocket(OBJECT) | uni-app官网
/plugins/event.js
const Dep = function() {
this.Evens = Object.create(null);
}
class Event {
constructor({
dep = new Dep()
} = {}) {
if (dep.constructor === Object && Object.keys(dep).length === 0) {
dep.Evens = Object.create(null);
}
this.Dep = dep;
}
/** 绑定事件 可以重复绑定
* @param {Object} handler 需要绑定的事件名称
* @param {Object} fn 事件处理函数
*/
onNotify(handler, fn, oneEv = false) {
try{
this.off(handler,()=>{});
}catch(e){};
if (typeof fn != 'function') {
return console.error(`The registered custom event type must be a function \r\n ${fn.toString()}`);
}
if (this instanceof Event) {
let typeArr = this.Dep.Evens[handler];
if (!typeArr) {
this.Dep.Evens[handler] = [];
}
const eventArr = this.Dep.Evens[handler]
if (oneEv) {
eventArr.splice(0, eventArr.length);
}
eventArr.push(fn);
} else {
console.error(`You can't manually modify the 'this' pointer is '${handler}' Event type \r\n ${fn.toString()}`)
}
return this
}
/** 绑定事件 仅会绑定一次事件,如果发现有重名的事件则全部移除
* @param {Object} handler 需要绑定的事件名称
* @param {Object} fn 事件处理函数
*/
one(handler, fn) {
if (this instanceof Event) {
this.on(handler, fn, true);
} else {
console.error(`You can't manually modify the 'this' pointer is '${handler}' Event type \r\n ${fn.toString()}`)
}
return this
}
/** 解除已经绑定事件
* @param {Object} handler 指定需要解除的事件类型 不传则清楚全部
* @param {Object} callback 解除事件后的回调函数
*/
off(handler, callback) {
if (this instanceof Event) {
let callInfo = {
0: {
success: false,
msg: `'${handler}' event is not defined`
},
1: {
success: true,
msg: 'Successful ok'
}
};
if (!handler) {
this.Dep.Evens = {};
return true;
}
let typeArr = this.Dep.Evens[handler];
if (typeArr) {
delete this.Dep.Evens[handler];
return callback.call(this, callInfo[1]);
}
return callback.call(this, callInfo[0]);
} else {
console.error(`You can't manually modify the 'this' pointer`)
}
return this
}
/** 触发指定事件
* @param {Object} type 需要触发的事件
* @param {Object} options 为此事件传递的参数
*/
onPublish(type, options) {
if (this instanceof Event) {
let eventArr = this.Dep.Evens[type];
if (!eventArr || eventArr.length == 0) {
return console.error(`The specified event does not exist is '${type}'`)
}
let i = eventArr.length - 1;
while (true) {
eventArr[i].call(this, options);
i--
if (i < 0) {
break
}
}
} else {
console.error(`You can't manually modify the 'this' pointer`)
}
return this
}
}
export default Event;
/utils/socket.js
import Events from '@/plugins/event';
class webScoket extends Events {
constructor(uri) {
super()
this.isConnected = false //socket连接记录
this.timer = null //心跳定时器
this.uri = uri
this.url = `wss://changecabinet.yunheznkj.com/websocket/${uri}`
// 创建WebSocket连接。
this.ws = uni.connectSocket({
url: this.url,
success(res) {
console.log('链接成功')
console.log(res)
},
fail(err) {
console.log('链接失败')
console.error(err)
},
complete: () => {}
});
// 连接打开事件
this.ws.onOpen(res => {
console.log(`WebSocket 已连接:${this.url}`)
this.isConnected = true;
});
// 接受到服务器的消息事件
this.ws.onMessage(res => {
this.onPublish(this.uri, JSON.parse(res.data))
});
// 连接关闭事件
this.ws.onClose(res => {
console.warn('WebSocket 已断开')
this.isConnected = false;
});
}
close() {
return new Promise((resolve, reject) => {
if (this.isConnected) {
clearInterval(this.timer);
this.ws.close()
}
resolve()
})
}
send(data) {
this.ws.send({
data: data.msg
})
}
}
export default webScoket
页面调用
实现逻辑:前端点击支付按钮,同时调起webScoket连接和发送支付接口。如果余额不足和支付失败,后端通过接口通知前端。如果支付成功,后端通过webScoket通知前端。
<script>
import WS from '@/utils/socket'
import {
payAndGet
} from '@/api/user.js'
export default {
data() {
return {
orderNo: '',
$ws: null
}
},
onLoad(e) {
this.orderNo = e.orderNo
},
onHide() {
if (this.$ws) {
this.$ws.close()
}
},
beforeDestroy() {
if (this.$ws) {
this.$ws.close()
}
},
methods: {
// 支付
async payAndGet() {
this.socketInit()
const res = await payAndGet({
orderNo: this.orderNo
})
if (res.code == 1001) { // 余额不足
this.$ws.close()
} else if (res.code == 200) { // 支付成功
} else {// 支付失败
this.$ws.close()
}
},
// 链接设备
socketInit() {
let uri = `gzyh_device_result_` + this.orderNo
this.$ws = new WS(uri)
this.$ws.onNotify(uri, res => {
if (res.code == 200) {
// 支付成功执行逻辑
}
})
},
}
}
</script>