本文是由Vue的SPA对接到外接设备的驱动进行交互,需要从后端接口获取支付链接传输到外接设备(大屏幕的智能设备)生成二维码。(当然也可以通过支付链接自己转成二维码)
首先定义一个单选组,有两种支付方式:“微信”,“支付宝”支付方式。paySucceed为true表示支付成功,则提示支付成功,隐藏掉支付单选
微信
支付宝
payWayChange校验 【vue递归轮询实现扫码支付】因为外接设备的电脑驱动服务主要是通过
websocket
进行数据交互的,所以需要在一开始通过webSocket.OPEN去验证websocket当前浏览器与驱动/设备是否正常连接中,如没连接上进行提示并中断当前的操作。当然在校验的时候需要重置(初始化)外接设备、支付状态、定时器。
开始支付 获取支付的一些参数并通过接口
(getPayStatus)
获取到支付的url链接,调用openQRcode
传递链接到外接设备上,显示出二维码进行支付(这里可以使用qrcode的js库转成二维码图片跳转页面的形式显示出二维码)。在这里是调用
openQRcode
方法只是个举例,外接设备一般都会有提供自己驱动以及对接驱动的js,按照自己的实际情况来。支付中(轮询) 当二维码成功显示后立即调用
queryStatus()
利用获取到的订单号为参数进入一个支付状态的查询(使用setTimeout
轮询)queryStatus
内部是一个没经过包装的请求,当请求返回payStatus表示当前未支付完成,或在支付中,否则为支付成功。每隔3秒轮询一次(尾递归
queryStatus
获取支付状态 成功
or 失败
):window.pollTimer = setTimeout(() => {
return queryStatus();
//轮询查询支付状态3s
}, 3000)
在queryStatus中的请求使用了
axios
,是因为这里的post包装请求pending过程中自动加上了“加载中。。。”的全屏界面动画,因为轮询是不断进行的不能显示加载动画,否则会造成每次获取状态都会一直出现加载动画关闭/显示的闪屏效果,所以这里使用原生axios支付完成 支付成功后就进行提示,达成递归终止条件,清除掉计时器,重置支付的状态。最后5s计时器是为了给个小延迟,防止设备上支付成功后就秒关掉了界面 ,没有显示支付成功的问题
if ((res.payStatus == 2) || (res.payStatus == 1)) { //支付成功,关闭弹窗
that.paySucceed = true;
window.pollTimer && window.clearTimeout(window.pollTimer);
//支付成功后干些事情。。。
setTimeout(() => {
that.common.cancelAll();
that.resetPay();
}, 5000)
}
payWayChange (val) {
//清除计时器轮询状态
clearTimeout(window.pollTimer);
window.pollTimer = null;
if (webSocket.readyState != webSocket.OPEN) {
this.$message({
message: '请正确连接设备或设备驱动未启动,请检查',
type: 'error'
});
this.resetPay();
return;
}this.common.cancelAll();
//关闭电子屏支付页//参数
let params = {
type: val === 'wechat' ? 'WeChatPay' : 'AliPay',
data: {
paymentType:1,
id:'123',
payMoney: '30.0',
payWay: this.payWay,
}
}
let that = this;
function queryStatus () {
window.clearTimeout(window.pollTimer)
axios({//使用axios,不显示加载中提示
method: 'post',
url: 'getPayStatus',
withCredentials: true,
timeout: 0,
hideLoading: true,
headers: {
"Content-Type": "application/json;
charset=UTF-8",
"token": sessionStorage.getItem('token')
},
data: {
typeCode: val === 'wechat' ? 'WeChat' : 'ali',
token: sessionStorage.getItem('token'),
data: {
order: params.order,
}
},}).then((res) => {
if (res.payStatus == 0) {
window.pollTimer = setTimeout(() => {
return queryStatus();
//轮询查询支付状态3s
}, 3000)
}if ((res.payStatus == 2) || (res.payStatus == 1)) { //支付成功,关闭弹窗that.paySucceed = true;
window.pollTimer && window.clearTimeout(window.pollTimer)
//支付成功后干些事情。。。
setTimeout(() => {
that.common.cancelAll();
that.resetPay();
}, 5000)
}})
}that.post({
params,//参数
})
.then(res => { //获取支付链接和订单信息
params = params.data;
params.order = res.order;
window.delayTimer = null;
window.clearTimeout(window.delayTimer);
window.delayTimer = setTimeout(() => {
//打开支付二维码
this.common.openQRcode(encodeURI(JSON.stringify(params)) ,encodeURI(res.url))}, 1000);
queryStatus();
//开始轮询支付的状态
});
},resetPay () {
this.paySucceed = false;
window.pollTimer && window.clearTimeout(window.pollTimer);
//清除计时器轮询状态
},