一个微商城的项目,前端用的是vue.js,涉及到微信支付的前端代码大概是这样子的:
const mixinPay = { computed: { ...mapGetters(['l', 'user', 'config', 'mock']) }, methods: { payByWechat ({shoppingOrderId, successCallback}) { const _this = this const endPoint = '/pay/getWeixinPayInfo.action' _this.wait(true) const requestData = { openId: _this.user.openid, id: shoppingOrderId } return doPost(endPoint, requestData).done(data => { if (data.status === '200' && !data.errorCode) { const options = { appId: data.responseBody.appid, timeStamp: data.responseBody.timestamp, nonceStr: data.responseBody.nonceStr, package: data.responseBody.package, signType: 'MD5', paySign: data.responseBody.paySign } // _this.alert({ text: JSON.stringify(options) }) if (typeof window.WeixinJSBridge === 'undefined') { if (window.document.addEventListener) { window.document.addEventListener('WeixinJSBridgeReady', onBridgeReady.bind(null, options), false) } else if (window.document.attachEvent) { window.document.attachEvent('WeixinJSBridgeReady', onBridgeReady.bind(null, options)) window.document.attachEvent('onWeixinJSBridgeReady', onBridgeReady.bind(null, options)) } } else { onBridgeReady(options) } } else if (data.errorCode) { _this.alert({ text: `${data['errorMsg' + _this.l]}` }) } else { _this.alert({ text: _this.l === 'En' ? 'Server responds abnormally' : '服务器响应异常' }) } }).fail((jqXHR, textStatus, errorThrown) => { _this.alert({ text: _this.l === 'En' ? 'Failed to payment parameters' : '微信支付参数失败' }) }).always(() => { _this.wait(false) }) function onBridgeReady (options) { window.WeixinJSBridge.invoke( 'getBrandWCPayRequest', options, function (data) { if (data && data.err_msg === 'get_brand_wcpay_request:ok') { _this.toUpdateReceipt(shoppingOrderId, successCallback) } else if ( data && ( data.err_msg === 'get_brand_wcpay_request:cancel' || data.err_msg === 'get_brand_wcpay_request:fail' ) ) { _this.alert({ text: _this.l === 'En' ? 'Failed to pay' : '未成功支付' }) } else if (data && data.err_desc) { _this.alert({ text: data.err_desc }) } else { _this.alert({ text: _this.l === 'En' ? 'Failed to pay' : '支付失败' }) } } ) } }, toUpdateReceipt (shoppingOrderId, successCallback) { const _this = this const endPoint = '/orderInfo/updateReceipt.action' _this.wait(true) const requestData = { id: shoppingOrderId, status: 4 } doPost(endPoint, requestData).done(data => { if (data.status === '200' && !data.errorCode) { _this.alert({ text: _this.l === 'En' ? 'Paid successfully' : '支付成功', callback () { if (successCallback && typeof successCallback === 'function') { successCallback() } } }) } else { _this.alert({ text: _this.l === 'En' ? 'Paied successfully, but failed to update order status, please contact the service' : '付款成功,送货单状态更新失败,请联系客服', callback () { if (successCallback && typeof successCallback === 'function') { successCallback() } } }) } // else if (data.errorCode) { // _this.alert({ text: `${data['errorMsg' + _this.l]}` }) // } else { // _this.alert({ text: JSON.stringify(data) }) // } }).fail(() => { _this.alert({ text: _this.l === 'En' ? 'Paied successfully, but failed to update order status, please contact the service' : '付款成功,送货单状态更新失败,请联系客服', callback () { if (successCallback && typeof successCallback === 'function') { successCallback() } } }) }).always(() => { _this.wait(false) }) }, ...mapActions(['alert', 'wait']) } }
这里的【微信内H5调起支付】的官网参考文档地址为https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6&pass_ticket=EiPbYJmbbMTWltjRY8XQq5dwQ4DbztpbsIE0i11BE6JDeykgQ3arpgnA55tR3RZC
大体的支付流程:
- 前端用送货单id和openid从后台获取支付信息(后台通过请求统一制服下单接口获取这些信息);
- 前端根据支付信息采用【微信内H5调起支付】的方式进行微信支付,支付成功后修改送货单状态为【支付中】;
- 后端回调根据微信返回信息作判断,只有送货单状态为【支付中】时进行状态更新,将送货单的状态更新为【已支付】或【未支付】。
- 后续在管理平台上增加一个操作,对【支付中】的送货单,可以手动查询送货单状态。
这里说点前端碰到的问题,就是支付时微信提示【当前页面的URL未注册:http://www.example.com/a/b/c/d/index.html#/home/index】,然而在微信公众号平台上配置的支付目录已经是【http://www.example.com/a/b/c/d/】(末尾有个斜杠),并无错误。联想到以前在公司项目里写过类似的代码但是没有问题,但是那个项目是在微信菜单上的地址是那种微信跳转地址,而且自己另外试了下发现只要我的项目地址index.html后面加上一些随便什么都行的查询参数就可以支付了,于是让修改微信菜单地址为index.html后面加上一些随意的查询参数(不走微信跳转,每次都走影响访问速度,只在本地没有用户openid时由js发起页面跳转,跳到微信跳转地址上以便获得code进而查询openid)。这样修改后页面就能正常进行微信支付了。成功的原因,目测应该是http://www.example.com/a/b/c/d/index.html#/home/index这样的地址里,可能微信会把锚后面的斜杠这些都作为路径进行识别,导致与我们配置的支付目录不一致,从而无法成功支付。加上问号后,微信不再将问号后面的部分视为路径,从而可以成功支付。