小程序-<web-view>嵌套H5页面支付功能

背景:小程序未发布前,公司使用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:这里是围绕我的业务需求,提供思路,不是通用。关键词搜索: 重点)

javascript 复制代码
//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,
                  })
              }
            }
javascript 复制代码
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、多听听别人的意见,不能闭门造车,

我固执己见的反驳了同事的建议,最后啪啪打脸,确实可以看到打印日志

相关推荐
EnCi Zheng9 分钟前
M5-markconv自定义CSS样式指南 [特殊字符]
前端·css·python
kyriewen13 分钟前
你的网页慢,用户不说直接走——前端性能监控教你“读心术”
前端·性能优化·监控
广州华水科技13 分钟前
北斗GNSS变形监测在大坝安全监测中的应用与优势分析
前端
前端老石人25 分钟前
前端开发中的 URL 完全指南
开发语言·前端·javascript·css·html
CAE虚拟与现实25 分钟前
五一假期闲来无事,来个前段、后端的说明吧
前端·后端·vtk·three.js·前后端
Sarvartha36 分钟前
三目运算符
linux·服务器·前端
晓晨的博客43 分钟前
ROS1录制的bag包转换为ROS2格式
前端·chrome
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
donecoding1 小时前
别再让 pnpm 跟着 nvm 跑了!独立安装终极指南
前端·node.js·前端工程化
GISer_Jing1 小时前
AI全栈转型_TS后端学习路线
前端·人工智能·后端·学习