vue项目中扫码支付的实现示例(附demo)

作者:丸子啦 时间:2024-05-02 17:02:50 

目录
  • 需求背景

  • 思路分析

  • UI展示

  • 开始使用

    • 一 编写支付组件模板

    • 二 支付组件的JS相关代码和说明

  • 附:组件JS完整的源码

    需求背景

    市场报告列表展示的报告有两种类型,一种是免费报告,另一种是付费报告。免费报告用户可以直接查看,付费报告需要用户购买之后才能查看。

    vue项目中扫码支付的实现示例(附demo)

    思路分析

    • 点击查看为付费报告,弹出支付二维码。

    • 创建订单,二维码进行倒计时,其展示5秒后开始监听支付回调结果,频次为五秒一次。

    • 倒计时第一次倒数到0秒,提醒二维码过期让用户点击刷新二维码。

    • 继续倒计时并开始监听支付回调结果。

    • 刷新之后倒数到0秒还没有监听到结果则关闭支付弹窗,让用户重新发起支付。

    UI展示

    支付弹窗未过期长这样子喔

    vue项目中扫码支付的实现示例(附demo)

    支付弹窗过期时长这样子喔

    vue项目中扫码支付的实现示例(附demo)

    开始使用

    支付功能作为项目的公共功能,所以我们单独封装一个组件,这样其他模块使用的时候就以子组件的方式引入。

    一 编写支付组件模板

    下面是模板具体的源码,由于样式不是我们考虑的重点,所以就不展示样式的代码了,根据需要自行添加哈。


    <template>
     <div>
       <el-dialog
         class="dialog-pay"
         title=""
         :visible.sync="dialogVisible"
         :show-close="false"
         @close="handleClosePay"
       >
         <div class="content">
           <p class="tip">{{ pay.title }}</p>
           <p class="tip">
             支付金额:<span class="small">¥</span
             ><span class="large">{{ pay.money }}</span>
           </p>
           <img
             class="pic"
             :style="{ opacity: btnDisabled ? 1 : 0.3 }"
             :src="pay.url"
           />
           <el-button
             class="btn"
             :class="btnDisabled ? 'disabled' : ''"
             type="primary"
             :disabled="btnDisabled"
             @click="handleRefreshCode"
             >{{ btnText }}</el-button
           >
         </div>
       </el-dialog>
     </div>
    </template>

    二 支付组件的JS相关代码和说明

    1. 监听支付弹窗是否显示
    子组件通过props属性,在子组件中接收父组件传过来的值。用watch监听pay.show,只有为true的时候显示支付弹窗,并且在显示5秒后开始执行监听支付结果的方法。


    watch: {
       'pay.show': {
         handler(val) {
           if (val) {
             this.dialogVisible = this.pay.show
             setTimeout(this.handleReportPayNotify(), 5000)
           }
         },
         immediate: true
       }
    },

    2. 二维码开始倒计时
    二维码开始进行60秒的倒计时,到0秒提示点击刷新重新获取二维码,继续开始倒计时,此时如果到0秒则关闭支付弹窗,提示用户等待时间过长,请重新发起支付。


    handleCountDown() {
     if (this.second == 1) {
       if (this.refresh) {
         this.second = 60
         this.btnDisabled = false
         this.btnText = '点击刷新重新获取二维码'
         if (this.timer) {
           clearInterval(this.timer)
         }
       } else {
         this.$emit('closePay', { type: 'fail' })
         clearInterval(this.timer)
         this.$message.warning('等待时间过长,请重新发起支付')
       }
     } else {
       this.second--
       this.btnDisabled = true
       this.btnText = `距离二维码过期剩余${this.second}秒`
       this.downTimer = setTimeout(() => {
         this.handleCountDown()
       }, 1000)
     }
    },

    3. 监听支付弹窗关闭


    handleClosePay() {
     if (this.timer) {
       clearInterval(this.timer)
     }
     if (this.downTimer) {
       clearTimeout(this.downTimer)
     }
     this.$emit('closePay', { type: 'fail' })
     this.$message.warning('您已取消支付')
    },

    4. 监听支付回调结果
    回调结果有两种,如果是正常范围内监听成功,则执行父组件传过来的fn,并清除定时器;如果监听到次数为12的时候还没有得到相应的结果,则关闭支付弹窗,提示用户等待时间过长,请重新发起支付,并清除定时器。


    handleReportPayNotify() {
         let num = 0
         this.timer = setInterval(() => {
           num++
           this.pay.fn().then(res => {
             if (res.status == 111111) {
               this.$emit('closePay', { type: 'success' })
               clearInterval(this.timer)
             }
           })
           if (num == 12) {
             this.$emit('closePay', { type: 'fail' })
             clearInterval(this.timer)
             this.$message.warning('等待时间过长,请重新发起支付')
           }
         }, 5000)
       }

    5. 支付组件销毁时清除定时器
    这一步是容易忽略但是也是需要做的,当组件销毁时将定时器及时的清除掉。


     beforeDestroy() {
       if (this.timer) {
         clearInterval(this.timer)
       }
       if (this.downTimer) {
         clearTimeout(this.downTimer)
       }
     }
    }

    附:组件JS完整的源码


    <script>
    export default {
     name: 'WechatPay',
     props: {
       pay: Object
     },
     data() {
       return {
         dialogVisible: false,
         btnDisabled: true,
         btnText: '',
         second: 60,
         timer: null,
         refresh: true
       }
     },
     watch: {
       'pay.show': {
         handler(val) {
           if (val) {
             this.dialogVisible = this.pay.show
             setTimeout(this.handleReportPayNotify(), 5000)
           }
         },
         immediate: true
       }
     },
     mounted() {
       this.handleCountDown()
     },
     methods: {
       /**
        * @descripttion: 刷新二维码
        */
       handleRefreshCode() {
         this.$bus.$emit('refreshCode')
         this.handleCountDown()
         this.handleReportPayNotify()
         this.refresh = false
       },
       /**
        * @descripttion: 二维码倒计时
        */
       handleCountDown() {
         if (this.second == 1) {
           if (this.refresh) {
             this.second = 60
             this.btnDisabled = false
             this.btnText = '点击刷新重新获取二维码'
             if (this.timer) {
               clearInterval(this.timer)
             }
           } else {
             this.$emit('closePay', { type: 'fail' })
             clearInterval(this.timer)
             this.$message.warning('等待时间过长,请重新发起支付')
           }
         } else {
           this.second--
           this.btnDisabled = true
           this.btnText = `距离二维码过期剩余${this.second}秒`
           this.downTimer = setTimeout(() => {
             this.handleCountDown()
           }, 1000)
         }
       },
       /**
        * @descripttion: 监听支付弹窗关闭
        */
       handleClosePay() {
         if (this.timer) {
           clearInterval(this.timer)
         }
         if (this.downTimer) {
           clearTimeout(this.downTimer)
         }
         this.$emit('closePay', { type: 'fail' })
         this.$message.warning('您已取消支付')
       },
       /**
        * @descripttion: 监测支付回调结果
        */
       handleReportPayNotify() {
         let num = 0
         this.timer = setInterval(() => {
           num++
           this.pay.fn().then(res => {
             if (res.status == 111111) {
               this.$emit('closePay', { type: 'success' })
               clearInterval(this.timer)
             }
           })
           if (num == 12) {
             this.$emit('closePay', { type: 'fail' })
             clearInterval(this.timer)
             this.$message.warning('等待时间过长,请重新发起支付')
           }
         }, 5000)
       }
     },
     beforeDestroy() {
       if (this.timer) {
         clearInterval(this.timer)
       }
       if (this.downTimer) {
         clearTimeout(this.downTimer)
       }
     }
    }
    </script>

    来源:https://juejin.cn/post/7002396727483301896

    标签:vue,扫码,支付
    0
    投稿

    猜你喜欢

  • python实现巡检系统(solaris)示例

    2022-03-01 20:32:11
  • PyTorch中的神经网络 Mnist 分类任务

    2023-04-07 00:34:49
  • 不得不看的JS基础知识(事件触发篇)

    2008-12-04 16:38:00
  • Python中针对函数处理的特殊方法

    2023-07-17 19:59:30
  • Python 实现文件读写、坐标寻址、查找替换功能

    2021-06-02 07:36:42
  • php for 循环语句使用方法详细说明

    2023-11-17 21:43:21
  • Vue新一代状态管理工具Pinia的具体使用

    2024-05-09 15:11:53
  • 详解Python用三种方式统计词频的方法

    2021-02-10 13:30:12
  • 基于PyQt5制作Excel文件数据去重小工具

    2023-10-14 05:44:58
  • Python中的数学运算操作符使用进阶

    2021-05-24 16:05:46
  • 关于Python 中的时间处理包datetime和arrow的方法详解

    2023-11-16 12:18:48
  • 基于php解决json_encode中文UNICODE转码问题

    2023-07-02 20:51:22
  • 完美解决phpdoc导出文档中@package的warning及Error的错误

    2023-10-07 10:07:49
  • pytorch实践线性模型3d详解

    2023-04-01 22:58:29
  • python爬虫中采集中遇到的问题整理

    2022-10-17 03:32:23
  • PHP设计模式之迭代器模式浅析

    2023-05-25 11:26:26
  • python中使用xlrd、xlwt操作excel表格详解

    2023-06-25 03:59:51
  • ASP用JAVASCRIPT脚本实现分页的办法

    2007-10-30 13:18:00
  • sql server对字段的添加修改删除、以及字段的说明

    2012-01-05 18:50:52
  • Python的dict字典结构操作方法学习笔记

    2022-10-27 10:56:21
  • asp之家 网络编程 m.aspxhome.com