详解基于Koa2开发微信二维码扫码支付相关流程(5)

第二种虽然麻烦,但是保证了安全。所有的支付结果都必须等微信主动向后端通知,后端存完数据库后再返回给前端消息。这样哪怕用户支付成功的同时关闭了页面,下次再打开的时候,由于数据库已经写入了,所以拿到的也是支付成功的结果。

所以 付款成功自动刷新页面 这个部分我们分为两个部分来说:

前端部分

Vue的data部分

data: {
 payStatus: false, // 未支付成功
 retryCount: 0, // 轮询次数,从0-200
 orderNo: 'xxx', // 从后端传来的order_no
 codeUrl: 'xxx' // 从后端传来的code_url
}

在methods里写一个查询订单信息的方法:

// ...
handleCheckBill () {
 return setTimeout(() => {
 if (!this.payStatus && this.retryCount < 120) {
 this.retryCount += 1
 axios.post('/api/check-bill', { // 向后端请求订单支付信息
 orderNo: this.orderNo
 })
 .then(res => {
 if (res.data.success) {
 this.payStatus = true
 location.reload() // 偷懒就用reload重新刷新页面
 } else {
 this.handleCheckBill()
 }
 }).catch(err => {
 console.log(err)
 })
 } else {
 location.reload()
 }
 }, 1000)
}

在打开二维码Dialog的时候,这个方法就启用了。然后就开始轮询。我订了一个时间,200s后如果还是没有付款信息也自动刷新页面。实际上你可以自己根据项目的需要来定义这个时间。

后端部分

前端到后端只有一个接口,但是后端有两个接口。一个是用来接收微信的推送,一个是用来接收前端的查询请求。

先来写最关键的微信的推送请求处理。由于我们接收微信的请求是在Koa的路由里,并且是以流的形式传输的。需要让Koa支持解析xml格式的body,所以需要安装一个rawbody 来获取xml格式的body。

// 处理微信支付回传notify
// 如果收到消息要跟微信回传是否接收到
const handleNotify = async (ctx) => {
 const xml = await rawbody(ctx.req, {
 length: ctx.request.length,
 limit: '1mb',
 encoding: ctx.request.charset || 'utf-8'
 })

 const res = await parseXML(xml) // 解析xml

 if (res.return_code === 'SUCCESS') {
 if (res.result_code === 'SUCCESS') { // 如果都为SUCCESS代表支付成功
 // ... 这里是写入数据库的相关操作

 // 开始回传微信
 ctx.type = 'application/xml' // 指定发送的请求类型是xml
 // 回传微信,告诉已经收到
 return ctx.body = `<xml>
 <return_code><![CDATA[SUCCESS]]></return_code>
 <return_msg><![CDATA[OK]]></return_msg>
 </xml>
 `
 }
 }

 // 如果支付失败,也回传微信
 ctx.status = 400
 ctx.type = 'application/xml'
 ctx.body = `<xml>
 <return_code><![CDATA[FAIL]]></return_code>
 <return_msg><![CDATA[OK]]></return_msg>
 </xml>
 `
}

router.post('/api/notify', handleNotify)
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/309.html