背景:小程序未发布前,公司使用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.prepayId
WeixinJSBridge.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、多听听别人的意见,不能闭门造车,
我固执己见的反驳了同事的建议,最后啪啪打脸,确实可以看到打印日志