|
|
@@ -61,6 +61,10 @@
|
|
|
</view>
|
|
|
</template>
|
|
|
<script>
|
|
|
+/**
|
|
|
+ * 扫码支付组件(供货商App/微信端)
|
|
|
+ * 优化被扫支付时转圈卡住问题,提供自动、低频复查机制
|
|
|
+ */
|
|
|
import { mapGetters } from "vuex";
|
|
|
import { IMGHOST } from '@/config'
|
|
|
import { cancel,debtPay,getDetail,codePay,codePayCheck} from "@/api/order";
|
|
|
@@ -80,21 +84,29 @@ export default {
|
|
|
isCashier:false,
|
|
|
orderInfo:{orderType:0},
|
|
|
expire:0,
|
|
|
- goPay:0,
|
|
|
+ goPay:0, // 0: 请扫付款码,1: 请求中/自动复查中,2: 支付失败或异常提示
|
|
|
textscan: '扫码',
|
|
|
typescan: 'scan-listener',
|
|
|
remindText:'',
|
|
|
- returnCode:''
|
|
|
+ returnCode:'',
|
|
|
+ pollingTimer:null, // 后台自动复查定时器
|
|
|
+ pollingCount:0, // 自动复查次数
|
|
|
+ isPaymentProcessing:false // 防重复扫码标志
|
|
|
};
|
|
|
},
|
|
|
mounted() {
|
|
|
},
|
|
|
- onUnload() {
|
|
|
- },
|
|
|
+ onUnload() {
|
|
|
+ this.clearPolling()
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ this.clearPolling()
|
|
|
+ },
|
|
|
onLoad(option) {
|
|
|
this.orderId = option.orderId
|
|
|
this.actPrice = option.actPrice
|
|
|
this.orderSn = option.orderSn
|
|
|
+ this.option = option // 保存 option 变量,防止 detail 跳转报错
|
|
|
if(!this.$util.isEmpty(option.orderId)){
|
|
|
getDetail({ id: option.orderId }).then(res=>{
|
|
|
if(res.code == 1){
|
|
|
@@ -169,8 +181,10 @@ export default {
|
|
|
this.$util.pageTo({url: "/pagesOrder/detail?id="+id,type:2})
|
|
|
},
|
|
|
beginScan(){
|
|
|
+ this.clearPolling()
|
|
|
this.remindText = ''
|
|
|
this.returnCode = ''
|
|
|
+ this.isPaymentProcessing = false
|
|
|
// #ifdef MP-WEIXIN
|
|
|
this.toScan()
|
|
|
// #endif
|
|
|
@@ -195,7 +209,6 @@ export default {
|
|
|
if(that.$util.isEmpty(newPayCode)){
|
|
|
that.$msg('没扫到,请重新扫哦')
|
|
|
return false
|
|
|
- return false
|
|
|
}
|
|
|
if(!that.isAllDigits(newPayCode)){
|
|
|
that.$msg('没扫到,请重新扫')
|
|
|
@@ -209,26 +222,99 @@ export default {
|
|
|
return /^\d+$/.test(str)
|
|
|
},
|
|
|
requestCodePay(authCode){
|
|
|
+ if(this.isPaymentProcessing){
|
|
|
+ this.$msg('支付处理中,请稍候')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
let that = this
|
|
|
this.goPay = 1
|
|
|
+ this.isPaymentProcessing = true
|
|
|
+ this.remindText = ''
|
|
|
+ this.returnCode = ''
|
|
|
+ this.clearPolling()
|
|
|
+
|
|
|
codePay({id:this.orderId,authCode:authCode}).then(res=>{
|
|
|
if(res.code == 1){
|
|
|
if(res.data.returnStatus == 'SUCCESS'){
|
|
|
+ that.isPaymentProcessing = false
|
|
|
setTimeout(function(){
|
|
|
that.payFinish()
|
|
|
},1200)
|
|
|
}else{
|
|
|
- that.remindText = res.msg
|
|
|
- that.goPay = 2
|
|
|
- that.returnCode = res.data.returnCode ? res.data.returnCode : ''
|
|
|
+ that.remindText = res.msg || '等待支付...'
|
|
|
+ that.returnCode = res.data.returnCode ? res.data.returnCode : ''
|
|
|
+ that.goPay = 2
|
|
|
+
|
|
|
+ // 11105(用户输入密码中) 或 10000(其它密码状态),启动4秒一次、最多8次(32秒)的自动复查定时器
|
|
|
+ if (that.returnCode == 'BBS11105' || that.returnCode == 'BBS10000') {
|
|
|
+ that.startPolling()
|
|
|
+ } else {
|
|
|
+ that.isPaymentProcessing = false
|
|
|
+ }
|
|
|
}
|
|
|
+ } else {
|
|
|
+ that.isPaymentProcessing = false
|
|
|
+ that.remindText = res.msg || '支付请求失败'
|
|
|
+ that.goPay = 2
|
|
|
}
|
|
|
+ }).catch(err=>{
|
|
|
+ // 请求超时或网络断开时,重置支付状态,同时自动运行一轮轮询查询,防万一扣款成功
|
|
|
+ that.isPaymentProcessing = false
|
|
|
+ that.remindText = '网络异常,正在自动复查支付结果...'
|
|
|
+ that.goPay = 2
|
|
|
+ that.startPolling()
|
|
|
})
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 启动低频后台付款复查定时器
|
|
|
+ * 4秒轮询一次,限查8次,极大地减轻服务器压力的同时保证业务流闭环
|
|
|
+ */
|
|
|
+ startPolling(){
|
|
|
+ this.clearPolling()
|
|
|
+ this.pollingCount = 0
|
|
|
+ this.isPaymentProcessing = true
|
|
|
+ this.goPay = 1 // 显示请求中
|
|
|
+
|
|
|
+ let that = this;
|
|
|
+ this.pollingTimer = setInterval(() => {
|
|
|
+ that.pollingCount++
|
|
|
+ if (that.pollingCount > 8) {
|
|
|
+ that.clearPolling()
|
|
|
+ that.isPaymentProcessing = false
|
|
|
+ that.goPay = 2
|
|
|
+ that.remindText = '支付确认超时,请确认顾客扣款,并点【查询结果】'
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ that.remindText = `正在自动复查支付结果 (${that.pollingCount}/8)...`
|
|
|
+
|
|
|
+ codePayCheck({id:that.orderId}).then(res=>{
|
|
|
+ if(res.code == 1){
|
|
|
+ if(res.data && res.data.returnStatus == 'SUCCESS'){
|
|
|
+ that.clearPolling()
|
|
|
+ that.isPaymentProcessing = false
|
|
|
+ setTimeout(function(){
|
|
|
+ that.payFinish()
|
|
|
+ },1000)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).catch(err=>{
|
|
|
+ console.error('Code pay check failed', err)
|
|
|
+ })
|
|
|
+ }, 4000)
|
|
|
+ },
|
|
|
+ clearPolling(){
|
|
|
+ if(this.pollingTimer){
|
|
|
+ clearInterval(this.pollingTimer)
|
|
|
+ this.pollingTimer = null
|
|
|
+ }
|
|
|
+ },
|
|
|
init(){
|
|
|
|
|
|
},
|
|
|
payFinish(){
|
|
|
+ this.clearPolling()
|
|
|
this.$util.pageTo({ url: '/admin/billing/result',type:2,query: {orderId:this.orderId,orderSn:this.orderSn,title:'支付成功'}})
|
|
|
},
|
|
|
changePayWay(payWay){
|
|
|
@@ -254,6 +340,8 @@ export default {
|
|
|
uni.hideLoading()
|
|
|
if(res.code == 1){
|
|
|
if(res.data.payStatus == 1){
|
|
|
+ that.clearPolling()
|
|
|
+ that.isPaymentProcessing = false
|
|
|
this.$msg('付款成功')
|
|
|
setTimeout(function(){
|
|
|
that.payFinish()
|
|
|
@@ -265,6 +353,7 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
goBack(){
|
|
|
+ this.clearPolling()
|
|
|
uni.navigateBack()
|
|
|
},
|
|
|
toCancel(){
|
|
|
@@ -273,7 +362,10 @@ export default {
|
|
|
if(this.returnCode == 'BBS11105' || this.returnCode == 'BBS10000'){
|
|
|
content = '客户正在付款,提醒客户退出付款界面,再点确认'
|
|
|
}
|
|
|
+ // 取消支付时,必须清除定时器和支付占用状态
|
|
|
that.$util.confirmModal({content:content,cancelText:'返回'},() => {
|
|
|
+ that.clearPolling()
|
|
|
+ that.isPaymentProcessing = false
|
|
|
cancel({id:this.orderId}).then(res=>{
|
|
|
if(res.code == 1){
|
|
|
that.$msg(res.msg)
|
|
|
@@ -284,9 +376,6 @@ export default {
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
- },
|
|
|
-};
|
|
|
-</script>
|
|
|
<style lang="scss" scoped>
|
|
|
.app-content {
|
|
|
.callback-wrap {
|