背景:小程序未发布前,公司使用vue框架搭建了管理系统,为了减少开发成本,微信提供了web-view来帮助已有系统能在小程序上发布,详见web-view | 微信开放文档。因公司一直未打通嵌套H5小程序的支付功能,导致用户体验很不友好,所以为了解决这个问题,本人研究了一下,以下是研究过程中遇到的问题及解决办法。
解决思路:用JSSDK接口提供的wx.miniProgram.navigato({url: url}),跳转到过渡页面wePay,在wePay.js中处理调取微信支付接口的功能,支付成功与否,跳转到小程序包含web-view页面,动态修改url,就可跳转到H5中的指定页面,
第一步:如何本地调试?
开启小程序<web-view src="{{ url }}">
开启vue页面,这个使用本地服务,把支付页面的地址,写入上面的 url 里面
第二步: 因vue中已经提供在微信中的支付功能,所以另外只需判断若在小程序中,如何进行支付。
vue中点击支付按钮后的操作如下:(ps:这里是围绕我的业务需求,提供思路,不是通用。关键词搜索: 重点)
//isInWeixin: function () {
// let ua = window.navigator.userAgent.toLowerCase();
// return (ua.match(/MicroMessenger/i) == 'micromessenger');
// },
//
// isInWxMiniProgram: function () {
// return window.__wxjs_environment === 'miniprogram';
// },
data(){return{isInWxWeb: $.Util.isInWeixin() && !$.Util.isInWxMiniProgram(),isInMiniProgram: $.Util.isInWxMiniProgram(),}
},
doPayment () {if (this.paying) {$.Msg.info('正在支付中...');return;}// 检查积分if (this.paymentPointsSum && this.paymentPointsSum > this.memberPoints) {$.Msg.error('您的积分不够了');return;}// 检查金额if (this.paymentAmountSum < this.amountSumForVCard) {$.Dlg.error('储值卡支付金额不能大于支付总金额');return;}let paymentAmountForWx = $.Util.formatNum(this.paymentAmountSum - this.amountSumForVCard);if (paymentAmountForWx) {if ( ! this.hasWxMchId) {$.Dlg.error('该商户尚未申请开通微信支付权限,您还无法使用微信支付。');return;}// if ( ! this.isInWxWeb) {// $.Dlg.error('请通过微信公众号进入系统,然后再通过微信支付。');// return;// }}let productOrderList = [];for (let p of this.productList) {if (p.productCnt > 0) {productOrderList.push({productId: p.productId, count: p.productCnt});}}let paymentCards = [], idx = 0;for (let mc of this.memberCardList) {if (mc.payment && this.memberCardChecks[idx]) {paymentCards.push({mcId: mc.mcId, amount: mc.payment});}idx++;}if (this.orderRemark && this.orderRemark.length > 500) {$.Dlg.error('购买备注不能超过500字');return;}let args = {memberId: $.data.user.memberId,productOrderList: productOrderList,paymentMemberCardList: paymentCards,orderRemark: this.orderRemark,isFromMp: this.isInWxWeb ? null : true,};if (this.from && this.from === 'cart') {args.from = 'cart';}this.paying = true;$.Req.service($.SvName.MALL_ORDER_CREATE, args, (ret) => {if (ret.paymentCashAmount > 0) { // 启动微信支付this.callWxPay(ret.orderId, ret);} else {this.paying = false;$.Dlg.success('订单支付成功!');this.$router.push('/mall/member-mall-order');}}, true, (err) => {$.Dlg.error(err);this.paying = false;});},callWxPay (orderId, ret) {let args = {"appId": ret.wxParam.appId,"nonceStr": ret.wxParam.nonceStr,"package": null,//重点:因小程序和维系公众号获取package方式不同,这里须分开赋值"signType": ret.wxParam.signType,"timeStamp": ret.wxParam.timeStamp,"paySign": ret.wxParam.paySign,};let tradeNo = ret.wxParam.tradeNo;if(this.isInWxWeb){args.package = "prepay_id=" + ret.wxParam.prepayIdWeixinJSBridge.invoke('getBrandWCPayRequest', args,(res) => {if (res.err_msg === "get_brand_wcpay_request:ok") {let args2 = {tradeNo: tradeNo, orderId: orderId, from: this.from};$.Req.service($.SvName.MALL_ORDER_PAY_FINISH, args2, (ret) => {this.paying = false;$.Dlg.success('订单支付成功!');this.$router.push('/mall/member-mall-order');});} else {$.Dlg.error('支付失败,请稍候重试。');this.paying = false;}});} else if(this.isInMiniProgram){args.package = ret.wxParam.prepayId
//重点:作为路由参数,这里不能像上面一样'prepay_id=',因为要跳到小程序指定页面,小程序获取onload(options){} ,小程序会提前对路由参数进行处理,如,split('=')[0],只保留第一个“=”之前的字符串,之后的删除,所以这里不能有“=”,否则后面的参数全部都被删掉。let payDataStr = JSON.stringify(args);//因为要把参数传递给小程序,所以这里需要转为字符串const url = '../wePay/wePay?payDataStr='+ payDataStr;wx.miniProgram.navigateTo({url: url,})}}
Page({data: {options: null},//h5传过来的参数onLoad: function(options) {this.setData({options: JSON.stringify(options),});// 字符串转对象// let payData = JSON.parse(options.payDataStr)// this.goPay(payData);
//测试支付成功与否返回参数以便跳转到H5指定页面this.payOkTo()},//微信支付goPay(payData) {wx.requestPayment({timeStamp: payData.timeStamp,nonceStr: payData.nonceStr,package: 'prepay_id=' + payData.package,signType: payData.signType,paySign: payData.paySign,success(res) {console.log("支付成功", res)//你可以在这里支付成功以后,再跳会webview页,并把支付成功状态传回去wx.navigateTo({url: '../page/home?payOk=true',})},fail(res) {console.log("支付失败", res)}})},payOkTo(){
//测试支付成功与否返回参数以便跳转到H5指定页面wx.navigateTo({url: '../page/home?payOk=true',})},
})
页面之间跳转是没问题的,因后台接口也改了,要等老板上线了再做调试了。
闲言碎语,萝莉八所来一点:
1、三人行,必能有人帮我,多和同事交流,省很多事情。
开发者工具中,web-view中的h5页面若想看到打印日志,那是看不到的,于是和同事说了一下问题,他之前遇到过,和我说可以在vue中install vconsole试试。
2、多听听别人的意见,不能闭门造车,
我固执己见的反驳了同事的建议,最后啪啪打脸,确实可以看到打印日志