vue项目中扫码支付的实现示例(附demo)
作者:丸子啦 发布时间:2024-05-02 17:02:50
目录
需求背景
思路分析
UI展示
开始使用
一 编写支付组件模板
二 支付组件的JS相关代码和说明
附:组件JS完整的源码
需求背景
市场报告列表展示的报告有两种类型,一种是免费报告,另一种是付费报告。免费报告用户可以直接查看,付费报告需要用户购买之后才能查看。
思路分析
点击查看为付费报告,弹出支付二维码。
创建订单,二维码进行倒计时,其展示5秒后开始监听支付回调结果,频次为五秒一次。
倒计时第一次倒数到0秒,提醒二维码过期让用户点击刷新二维码。
继续倒计时并开始监听支付回调结果。
刷新之后倒数到0秒还没有监听到结果则关闭支付弹窗,让用户重新发起支付。
UI展示
支付弹窗未过期长这样子喔
支付弹窗过期时长这样子喔
开始使用
支付功能作为项目的公共功能,所以我们单独封装一个组件,这样其他模块使用的时候就以子组件的方式引入。
一 编写支付组件模板
下面是模板具体的源码,由于样式不是我们考虑的重点,所以就不展示样式的代码了,根据需要自行添加哈。
<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


猜你喜欢
- 前言现在很多地方都有使用到弹幕,最近在捣鼓自己的个人博客网站,也想着在里面加入一个弹幕模块,所以在这里封装了一个可复用的弹幕组件,目前已经实
- 目录互斥锁读写互斥锁先来看这样一段代码,所存在的问题:var wg sync.WaitGroupvar x int64func main()
- 使用torch.utils.data.Dataset类 处理图片数据时,1. 我们需要定义三个基本的函数,以下是基本流程class our_
- 实例是具象化的类,它可以作为类访问所有静态绑定到类上的属性,包括类变量与方法,也可以作为实例访问动态绑定到实例上的属性。实例1:class
- 爬取网址:http://www.ultramanclub.com/allultraman/使用工具:pycharm,requests进入网页
- YEAR() 函数返回一个整数值,它表示指定日期的年份,一般使用为:Year(时间),如:YEAR('2023-03-14
- Python3,开一个线程,间隔1秒把一个递增的数字写入队列,再开一个线程,从队列中取出数字并打印到终端#! /usr/bin/env py
- python 二维列表转置def transpose(self, matrix): new_matrix = []
- ipad的goodreader对JS文件支持不太好,虽然可以读取它但总是无法退出,回不了goodreader的主界面,因此我需要把js文件批
- 在视图中也有笨方法可以从数据库中获取数据。 很简单: 用现有的任何 Python 类库执行一条 SQL 查询并对结果进行一些处理。在本例的视
- 当我们修改一份代码的时候,也许会碰到修改后的代码还不如修改之前的代码能够满足自己的需求,那么这个时候我们就需要对代码进行回滚,下面我们来看一
- vue 页面卡死,点击无反应我在结合element做表单的时候,进入编辑页时,点击切换不生效,但是value值已改变,就是view视图层无反
- 索引的概念MySQL索引是一种用于加速数据库查询的数据结构,它类似于书籍的目录,能够快速指导我们找到需要的信息。MySQL索引可以根据一定的
- 远程服务器配置可以使得数据库管理员在服务器以外的主机上连接到一个SQL Server实例,以便管理员在没有建立单据连接的情况下在其他的SQL
- 1.我在一行结束后按回车键,就跳到隔一行的段落上,如何避免隔行跳到下一段落? A.在一行结束后先按着[Shift]键,再按回车就可以不隔行跳
- 一、命名元祖在python基础中, 我们学习元祖的时候,取元祖内部的元素都是通过索引来进行取值的。但是这种取值方式不够友好, 所以我们引入命
- 1.BeautifulSoup简介BeautifulSoup4和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解
- 不用说火爆一时,全网热议的Web3.0区块链技术,也不必说诸如微信支付、支付宝支付等人们几乎每天都要使用的线上支付业务,单是一个简简单单的注
- 一、安装PILPIL是Python Imaging Library简称,用于处理图片。PIL中已经有图片高斯模糊处理类,但有个bug(目前最
- 现在我将清除页面缓存的一些方法总结如下:1、在Asp页面首部加入<% Response.Buffer = True