乐趣区

关于vue.js:vue递归轮询实现扫码支付

本文是由 Vue 的 SPA 对接到外接设备的驱动进行交互,须要从后端接口获取领取链接传输到外接设备(大屏幕的智能设施)生成二维码。(当然也能够通过领取链接本人转成二维码)

首先定义一个单选组,有两种领取形式:“微信”,“支付宝”领取形式。paySucceed 为 true 示意领取胜利,则提醒领取胜利,暗藏掉领取单选

      <el-radio-group v-model="payWay" @change="payWayChange" v-if='paySucceed === false'>
        <el-radio label="wechat" > 微信 </el-radio>
        <el-radio label="ali"> 支付宝 </el-radio>
      </el-radio-group>

payWayChange 校验

因为外接设备的电脑驱动服务次要是通过 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); // 革除计时器轮询状态
    },
退出移动版