第二种虽然麻烦,但是保证了安全。所有的支付结果都必须等微信主动向后端通知,后端存完数据库后再返回给前端消息。这样哪怕用户支付成功的同时关闭了页面,下次再打开的时候,由于数据库已经写入了,所以拿到的也是支付成功的结果。
所以 付款成功自动刷新页面
这个部分我们分为两个部分来说:
前端部分
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)
内容版权声明:除非注明,否则皆为本站原创文章。