Implementation example of scan code payment in vue project (with demo)

Implementation example of scan code payment in vue project (with demo)

Demand background

There are two types of reports displayed in the market report list, one is free report and the other is paid report. Users can view free reports directly, while paid reports can only be viewed after users purchase them.

Thought Analysis

  • Click to view the paid report and a payment QR code will pop up.
  • Create an order, and the QR code will count down. After 5 seconds of display, it will start monitoring the payment callback result, with a frequency of once every five seconds.
  • The first countdown reaches 0 seconds, reminding the user that the QR code has expired and asking the user to click to refresh the QR code.
  • Continue the countdown and start monitoring payment callback results.
  • After refreshing, if the countdown reaches 0 seconds and no result is heard, the payment pop-up window will be closed to allow the user to re-initiate payment.

UI Display

The payment pop-up window looks like this if it has not expired.

The payment pop-up window expires like this

Get Started

The payment function is a public function of the project, so we encapsulate it in a separate component so that other modules can introduce it as a subcomponent when using it.

1. Write a payment component template

Below is the specific source code of the template. Since the style is not the focus of our consideration, the style code will not be displayed. You can add it as needed.

<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">
          Payment amount: <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>

2. JS code and description of payment component

1. Monitor whether the payment pop-up window is displayed in the child component through the props attribute, and receive the value passed from the parent component in the child component. Use watch to monitor pay.show. The payment pop-up window will be displayed only when it is true, and the method of monitoring payment results will be executed after 5 seconds of display.

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

2. The QR code starts counting down. The QR code starts a 60-second countdown. When it reaches 0 second, click Refresh to get the QR code again and the countdown will continue. At this time, if it reaches 0 second, the payment pop-up window will be closed, and the user will be prompted to wait too long and please re-initiate payment.

handleCountDown() {
  if (this.second == 1) {
    if (this.refresh) {
      this.second = 60
      this.btnDisabled = false
      this.btnText = 'Click refresh to get the QR code again'
      if (this.timer) {
        clearInterval(this.timer)
      }
    } else {
      this.$emit('closePay', { type: 'fail' })
      clearInterval(this.timer)
      this.$message.warning('Waiting time is too long, please re-initiate payment')
    }
  } else {
    this.second--
    this.btnDisabled = true
    this.btnText = `${this.second} seconds left until the QR code expires`
    this.downTimer = setTimeout(() => {
      this.handleCountDown()
    }, 1000)
  }
},

3. Close the monitoring payment pop-up window

handleClosePay() {
  if (this.timer) {
    clearInterval(this.timer)
  }
  if (this.downTimer) {
    clearTimeout(this.downTimer)
  }
  this.$emit('closePay', { type: 'fail' })
  this.$message.warning('You have canceled payment')
},

4. There are two types of callback results for monitoring payment. If the monitoring is successful within the normal range, the fn passed by the parent component will be executed and the timer will be cleared. If the corresponding result is not obtained when the number of monitoring times reaches 12, the payment pop-up window will be closed, prompting the user that the waiting time is too long, please re-initiate payment, and clear the timer.

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('Waiting time is too long, please re-initiate payment')
        }
      }, 5000)
    }

5. Clear the timer when the payment component is destroyed. This step is easy to overlook but needs to be done. Clear the timer in time when the component is destroyed.

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

Attachment: Complete source code of component 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: Refresh QR code*/
    handleRefreshCode() {
      this.$bus.$emit('refreshCode')
      this.handleCountDown()
      this.handleReportPayNotify()
      this.refresh = false
    },
    /**
     * @descripttion: QR code countdown*/
    handleCountDown() {
      if (this.second == 1) {
        if (this.refresh) {
          this.second = 60
          this.btnDisabled = false
          this.btnText = 'Click refresh to get the QR code again'
          if (this.timer) {
            clearInterval(this.timer)
          }
        } else {
          this.$emit('closePay', { type: 'fail' })
          clearInterval(this.timer)
          this.$message.warning('Waiting time is too long, please re-initiate payment')
        }
      } else {
        this.second--
        this.btnDisabled = true
        this.btnText = `${this.second} seconds left until the QR code expires`
        this.downTimer = setTimeout(() => {
          this.handleCountDown()
        }, 1000)
      }
    },
    /**
     * @descripttion: listen for payment pop-up window closing*/
    handleClosePay() {
      if (this.timer) {
        clearInterval(this.timer)
      }
      if (this.downTimer) {
        clearTimeout(this.downTimer)
      }
      this.$emit('closePay', { type: 'fail' })
      this.$message.warning('You have canceled payment')
    },
    /**
     * @descripttion: monitor payment callback results*/
    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('Waiting time is too long, please re-initiate payment')
        }
      }, 5000)
    }
  },
  beforeDestroy() {
    if (this.timer) {
      clearInterval(this.timer)
    }
    if (this.downTimer) {
      clearTimeout(this.downTimer)
    }
  }
}
</script>

This concludes this article about the implementation example of QR code payment in the Vue project (with demo). For more relevant Vue QR code payment content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Summary of using WeChat official account payment in vue project and the pitfalls encountered
  • Pitfalls encountered in implementing WeChat payment function in Vue
  • Vue imitates Alipay payment function
  • Vue.js WeChat payment front-end code sharing
  • How to get WeChat payment code in Vue and solve the problem of code being occupied
  • Payment function implementation in vue project (WeChat payment and Alipay payment)

<<:  Example analysis of mysql variable usage [system variables, user variables]

>>:  How to quickly build your own server detailed tutorial (Java environment)

Recommend

Detailed tutorial on installing MySQL 8.0.20 database on CentOS 7

Related reading: MySQL8.0.20 installation tutoria...

Learn more about MySQL indexes

1. Indexing principle Indexes are used to quickly...

JavaScript to implement login slider verification

This article example shares the specific code of ...

How to get the width and height of the image in WeChat applet

origin Recently, I am working on requirement A, i...

Linux debugging tools that developers and operators must look at [Recommended]

System performance expert Brendan D. Gregg update...

Two box models in web pages (W3C box model, IE box model)

There are two types of web page box models: 1: Sta...

Angular framework detailed explanation of view abstract definition

Preface As a front-end framework designed "f...

How to set a fixed IP in Linux (tested and effective)

First, open the virtual machine Open xshell5 to c...

How to lock a virtual console session on Linux

When you are working on a shared system, you prob...

Vue uniapp realizes the segmenter effect

This article shares the specific code of vue unia...

JavaScript plugin encapsulation for table switching

This article shares the encapsulation code of Jav...