小程序-<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、多听听别人的意见,不能闭门造车,

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

相关推荐
Myli_ing3 分钟前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维20 分钟前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
雯0609~41 分钟前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ1 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
彭世瑜1 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish1 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five1 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序1 小时前
vue3 封装request请求
java·前端·typescript·vue