vue递归轮询实现扫码支付

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

首先定义一个单选组,有两种支付方式:“微信”,“支付宝”支付方式。paySucceed为true表示支付成功,则提示支付成功,隐藏掉支付单选

      
        微信
        支付宝
      

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); //清除计时器轮询状态
    },

你可能感兴趣的:(vue.js支付)