vue項(xiàng)目中掃碼支付的實(shí)現(xiàn)示例(附demo)
需求背景
市場(chǎng)報(bào)告列表展示的報(bào)告有兩種類(lèi)型,一種是免費(fèi)報(bào)告,另一種是付費(fèi)報(bào)告。免費(fèi)報(bào)告用戶可以直接查看,付費(fèi)報(bào)告需要用戶購(gòu)買(mǎi)之后才能查看。

思路分析
- 點(diǎn)擊查看為付費(fèi)報(bào)告,彈出支付二維碼。
- 創(chuàng)建訂單,二維碼進(jìn)行倒計(jì)時(shí),其展示5秒后開(kāi)始監(jiān)聽(tīng)支付回調(diào)結(jié)果,頻次為五秒一次。
- 倒計(jì)時(shí)第一次倒數(shù)到0秒,提醒二維碼過(guò)期讓用戶點(diǎn)擊刷新二維碼。
- 繼續(xù)倒計(jì)時(shí)并開(kāi)始監(jiān)聽(tīng)支付回調(diào)結(jié)果。
- 刷新之后倒數(shù)到0秒還沒(méi)有監(jiān)聽(tīng)到結(jié)果則關(guān)閉支付彈窗,讓用戶重新發(fā)起支付。
UI展示
支付彈窗未過(guò)期長(zhǎng)這樣子喔

支付彈窗過(guò)期時(shí)長(zhǎng)這樣子喔

開(kāi)始使用
支付功能作為項(xiàng)目的公共功能,所以我們單獨(dú)封裝一個(gè)組件,這樣其他模塊使用的時(shí)候就以子組件的方式引入。
一 編寫(xiě)支付組件模板
下面是模板具體的源碼,由于樣式不是我們考慮的重點(diǎn),所以就不展示樣式的代碼了,根據(jù)需要自行添加哈。
<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相關(guān)代碼和說(shuō)明
1. 監(jiān)聽(tīng)支付彈窗是否顯示
子組件通過(guò)props屬性,在子組件中接收父組件傳過(guò)來(lái)的值。用watch監(jiān)聽(tīng)pay.show,只有為true的時(shí)候顯示支付彈窗,并且在顯示5秒后開(kāi)始執(zhí)行監(jiān)聽(tīng)支付結(jié)果的方法。
watch: {
'pay.show': {
handler(val) {
if (val) {
this.dialogVisible = this.pay.show
setTimeout(this.handleReportPayNotify(), 5000)
}
},
immediate: true
}
},
2. 二維碼開(kāi)始倒計(jì)時(shí)
二維碼開(kāi)始進(jìn)行60秒的倒計(jì)時(shí),到0秒提示點(diǎn)擊刷新重新獲取二維碼,繼續(xù)開(kāi)始倒計(jì)時(shí),此時(shí)如果到0秒則關(guān)閉支付彈窗,提示用戶等待時(shí)間過(guò)長(zhǎng),請(qǐng)重新發(fā)起支付。
handleCountDown() {
if (this.second == 1) {
if (this.refresh) {
this.second = 60
this.btnDisabled = false
this.btnText = '點(diǎn)擊刷新重新獲取二維碼'
if (this.timer) {
clearInterval(this.timer)
}
} else {
this.$emit('closePay', { type: 'fail' })
clearInterval(this.timer)
this.$message.warning('等待時(shí)間過(guò)長(zhǎng),請(qǐng)重新發(fā)起支付')
}
} else {
this.second--
this.btnDisabled = true
this.btnText = `距離二維碼過(guò)期剩余${this.second}秒`
this.downTimer = setTimeout(() => {
this.handleCountDown()
}, 1000)
}
},
3. 監(jiān)聽(tīng)支付彈窗關(guān)閉
handleClosePay() {
if (this.timer) {
clearInterval(this.timer)
}
if (this.downTimer) {
clearTimeout(this.downTimer)
}
this.$emit('closePay', { type: 'fail' })
this.$message.warning('您已取消支付')
},
4. 監(jiān)聽(tīng)支付回調(diào)結(jié)果
回調(diào)結(jié)果有兩種,如果是正常范圍內(nèi)監(jiān)聽(tīng)成功,則執(zhí)行父組件傳過(guò)來(lái)的fn,并清除定時(shí)器;如果監(jiān)聽(tīng)到次數(shù)為12的時(shí)候還沒(méi)有得到相應(yīng)的結(jié)果,則關(guān)閉支付彈窗,提示用戶等待時(shí)間過(guò)長(zhǎng),請(qǐng)重新發(fā)起支付,并清除定時(shí)器。
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('等待時(shí)間過(guò)長(zhǎng),請(qǐng)重新發(fā)起支付')
}
}, 5000)
}
5. 支付組件銷(xiāo)毀時(shí)清除定時(shí)器
這一步是容易忽略但是也是需要做的,當(dāng)組件銷(xiāo)毀時(shí)將定時(shí)器及時(shí)的清除掉。
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: 二維碼倒計(jì)時(shí)
*/
handleCountDown() {
if (this.second == 1) {
if (this.refresh) {
this.second = 60
this.btnDisabled = false
this.btnText = '點(diǎn)擊刷新重新獲取二維碼'
if (this.timer) {
clearInterval(this.timer)
}
} else {
this.$emit('closePay', { type: 'fail' })
clearInterval(this.timer)
this.$message.warning('等待時(shí)間過(guò)長(zhǎng),請(qǐng)重新發(fā)起支付')
}
} else {
this.second--
this.btnDisabled = true
this.btnText = `距離二維碼過(guò)期剩余${this.second}秒`
this.downTimer = setTimeout(() => {
this.handleCountDown()
}, 1000)
}
},
/**
* @descripttion: 監(jiān)聽(tīng)支付彈窗關(guān)閉
*/
handleClosePay() {
if (this.timer) {
clearInterval(this.timer)
}
if (this.downTimer) {
clearTimeout(this.downTimer)
}
this.$emit('closePay', { type: 'fail' })
this.$message.warning('您已取消支付')
},
/**
* @descripttion: 監(jiān)測(cè)支付回調(diào)結(jié)果
*/
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('等待時(shí)間過(guò)長(zhǎng),請(qǐng)重新發(fā)起支付')
}
}, 5000)
}
},
beforeDestroy() {
if (this.timer) {
clearInterval(this.timer)
}
if (this.downTimer) {
clearTimeout(this.downTimer)
}
}
}
</script>
到此這篇關(guān)于vue項(xiàng)目中掃碼支付的實(shí)現(xiàn)示例(附demo)的文章就介紹到這了,更多相關(guān)vue 掃碼支付內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue項(xiàng)目中輪詢(xún)狀態(tài)更改方式(鉤子函數(shù))
這篇文章主要介紹了vue項(xiàng)目中輪詢(xún)狀態(tài)更改方式(鉤子函數(shù)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
Element el-table的formatter和scope?template不能同時(shí)存在問(wèn)題解決辦法
本文主要介紹了ElementUI?el-table?的?formatter?和?scope?template?不能同時(shí)存在問(wèn)題解決辦法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
Vue使用lodash進(jìn)行防抖節(jié)流的實(shí)現(xiàn)
本文主要介紹了Vue使用lodash進(jìn)行防抖節(jié)流的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
elementui使用el-upload組件如何實(shí)現(xiàn)自定義上傳
這篇文章主要介紹了elementui使用el-upload組件如何實(shí)現(xiàn)自定義上傳,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
vue 將多個(gè)過(guò)濾器封裝到一個(gè)文件中的代碼詳解
這篇文章主要介紹了vue 將多個(gè)過(guò)濾器封裝到一個(gè)文件中實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-09-09
vue頁(yè)面加載時(shí)的進(jìn)度條功能(實(shí)例代碼)
這篇文章主要介紹了vue頁(yè)面加載時(shí)的進(jìn)度條功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01
uni-app中vue3表單校驗(yàn)失敗的問(wèn)題及解決方法
最近遇到這樣的問(wèn)題在app中使用uni-forms表單,并添加校驗(yàn)規(guī)則,問(wèn)題是即使輸入內(nèi)容,表單校驗(yàn)依然失敗,本文給大家分享uni-app中vue3表單校驗(yàn)失敗的問(wèn)題及解決方法,感興趣的朋友一起看看吧2023-12-12
vue用h()函數(shù)創(chuàng)建Vnodes的實(shí)現(xiàn)
Vue提供了一個(gè)h()函數(shù)用于創(chuàng)建vnodes,本文就來(lái)介紹一下vue用h()函數(shù)創(chuàng)建Vnodes的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01

