微信小程序web-view(webview) 嵌套H5页面 唤起微信支付的实现方案

知识标签: Js/Css/jQuery 微信小程序 微信支付

场景:小程序页面有一个web-view组件,组件嵌套的H5页面,要唤起微信支付。

 

先讲一下我的项目,首先我是自己开发的一个H5触屏版的商城系统,里面含有购物车,订单支付等功能。然后刚开始,我们公众号里面点击官网导航,其实就是访问的 https://m.xxxx.com

然后支付的时候,我判定了如果是微信浏览器则只展示微信公众号支付,如果是外部浏览器则展示支付宝、微信H5支付 2个选项。

小提示:(微信支付分了 微信公众号支付和微信H5支付,微信H5支付是后期才出的,早期没有。微信公众号支付是在微信浏览器内访问H5页面发起支付,微信H5支付是外部手机浏览器唤起微信客户端发起支付。)

然后后来,公司觉得,公众号的直达性不够好,也就是用户扫一扫出现公众号后,还需要点一下官网才能访问官网,而我们希望用户在海报上扫一下二维码就打开官网,而不要和公众号产生关系。所以就去申请了一个小程序,并且与我们公众号绑定。然后人手不足,我们不打算重新开发一个小程序,所以直接拿小程序的web-view嵌套我们的官网地址 https://m.xxxx.com 这个域名。

嵌套好了以后,一切没问题,但是在支付这块有问题,调用微信公众号支付没法用,一片空白,调用微信H5支付,提示我需要在外部浏览器打开。

然后我在此不得不吐槽一下微信支付,自家的产品,自家的小程序,为什么不能让我们开发者用得省心点?明明是web-view组件,嵌套H5页面,也满足了微信内部浏览器访问才对,愣是不给我调用微信公众号支付,还得自己去实现新的支付。醉了。按道理来说,开发者调用你的jssdk,最省心的就是,我不需要管我当前的环境,只负责调用你的jssdk的某个方法,你自己管好当前是微信浏览器,还是外部浏览器,选择合适的方式弹出微信支付确认框即可。但是,特么的为了集成你一个微信支付,我愣是对接了一个微信公众号支付,微信H5支付,现在又要多一个小程序支付,明明明明他们都是一个H5支付而已。吐槽完毕,步入正题。他们这样做毕竟有他们的道理,我等开发者只有老老实实按别人说的做就可以了。

现在明确知道的小程序嵌套H5页面,引用微信的jssdk后,支持的接口如下链接展示 https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html

可以知道是支持不了微信公众号支付的。其实,微信公众号支付,也就是统一下单后,再调用  WeixinJSBridge.invoke('getBrandWCPayRequest 这个方法唤起支付确认框,可以明确知道这个方法并没有被小程序web-view支持。

同时,如果调用微信H5支付,会被提示在微信外浏览器打开,我估计是因为微信H5支付的那个支付地址(H5支付会让用户去访问一个mweb_url 这个 mweb_url地址我估计是判定了useragent,小程序web-view的useragent带了 MicroMessenger)

 

综上,各位开发者们,就不要再想歪门邪道的方法在小程序web-view页面嵌套的H5页面上唤起 微信公众号支付或者微信H5支付了,不可能的!就目前(20180930)而言肯定不可能。如果你还想想办法让它兼容你的网页,你就慢慢想吧,有办法了告诉我。所以,我的结论是:唯一的办法就是,想办法让H5页面,唤起小程序支付。

根据上面说的,唯一的路子就是你的H5页面唤起小程序支付,其实也简单,我是按下面这么干的。

首先,小程序放一个页面,叫做 orderPay.js ,这个是发起小程序支付用的页面,然后我们在H5页面发起支付的时候,把页面导到这个小程序页面即可,这点是可以做到的,接口是 wx.miniProgram.navigateTo ,大家可以看下这个接口的描述,是允许你带参数的。所以,一切就很明了了。

我的流程是:判定当前环境是否小程序-->跳转到 miniProgramPaySend.aspx ,这个页面将程序导向小程序原生页面 orderPay ,并且带着一个参数 orderId(我商城系统的订单id)

miniProgramPaySend.aspx 页面代码 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
    <script type="text/javascript">
        wx.miniProgram.getEnv(function (res) {
            if (res.miniprogram) { //只有在小程序环境下,才跳转到小程序支付页面去支付,否则的话都是跳转到订单详情去让它重新选支付方式。
                wx.miniProgram.navigateTo({ //这将唤起小程序的原生页面
                    url: '/pages/pay/orderpay?orderId=<%=Request.QueryString["orderId"]%>&username=<%=new Cookies().Username%>&token=<%=new Cookies().Token%>'
                })
            }
            else {
                var ok = confirm("非微信小程序环境,请选择在公众号处支付。");
                if(true){ //不管用户点哪个按钮都是去订单详情
                    location.href = "/muserCenter/myWebsiteOrder/detail/?orderId="+<%=Request.QueryString["orderId"]%>;
                }
            }
        })

  

然后,小程序 orderPay 页面 onload 的时候,获取这个单号,然后用 wx.request 方法请求我自己的接口,这个接口去请求微信 统一下单接口,返回小程序支付需要的相关参数 ,比如 package timeStamp 等 然后再用  wx.requestPayment 来发起请求支付即可正常弹出支付请求页面了。

代码片段我贴一点吧。 以下是我小程序 orderPay  页面的 onLoad 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  onLoad: function (option) {
    //console.log("orderId:" + option.orderId);
    var openid = wx.getStorageSync("openid"); //我在app.js里面登录然后换好了openId保存在了本地缓存中了
    var orderId=option.orderId; //这是我商城系统的orderId
    var username=option.username; //这是我商城系统鉴权的username
    var token=option.token; //这是我商城系统鉴权用的 token
    console.log("orderId:" + orderId + "|username:" + username + "|token:" + token);
<br>//这个请求是去拿小程序支付需要的相关参数用的,具体怎么获取这些参数,看文档吧兄台。
    wx.request({
      url: config.api_baseDomain +'/musercenter/wxMiniProgram/ApiRequest.aspx?action=getPayInfo&orderId='+orderId+'&openid='+openid+'&username='+username+'&token='+token,
      dataType: 'json',
      success(res) {
        console.log("支付信息:" + JSON.stringify(res.data));
 
        if (typeof (res.data.package) == "undefined") { //说明统一下单失败了,由小程序页面唤起 web-view 页面,并指定web-view 访问的地址,其实吧,也就是打开一个H5页面
          console.log("发起支付异常,原因:"+res.data);
          var urlTemp = config.api_baseDomain + '/muserCenter/myWebsiteOrder/detail/?orderId=' + orderId + '&msg=' + res.data.errorMsg;
 
          webviewUtils.GoToWebViewWithUrl(urlTemp);
 
        }
        else{  //如果相关参数请求正确的话,就开始发起小程序支付
        wx.requestPayment(
          {
            'timeStamp''' + res.data.timeStamp + '',
            'nonceStr''' + res.data.nonceStr + '',
            'package''' + res.data.package '',
            'signType''' + res.data.signType + '',
            'paySign''' + res.data.paySign + '',
            'success'function (res) //支付成功的话,打开一个H5地址
            {
              var urlTemp = config.api_baseDomain + '/muserCenter/myWebsiteOrder/detail/?orderId=' + orderId + '&msg=支付成功!'
              console.log(JSON.stringify(res))
              webviewUtils.GoToWebViewWithUrl(urlTemp);
             
            },
            'fail'function (res) //同上
            {
              var msg="支付失败";
              if (res.errMsg.indexOf("fail cancel"))
              {
                msg="支付取消";
              }
              var urlTemp = config.api_baseDomain + '/muserCenter/myWebsiteOrder/detail/?orderId=' + orderId + '&msg='+msg
              console.log(JSON.stringify(res))
              webviewUtils.GoToWebViewWithUrl(urlTemp);
            },
            'complete'function (res) { }
          })
        
 
      }
    })
 
  
 
  },

整个支付撸明白了就不算难了。当时花了好长的时间再那里求证web-view到底能不能唤起微信公众号支付,当时一脸蒙蔽的认为都是微信的东西,应该 不用做任何修改就能直接唤起微信公众号支付。。。。其实本来应该要可以才对的。。。。

哦,对了,还有关于统一下单的,用户openId的问题,这个openId,你不能拿公众号的那套方法去获取,获取出来的虽然能用来统一下单,但是不能用小程序来支付,会提示你appid不正确,因为你统一下单拿公众号的appid,然后支付的时候用的是小程序的appid,铁定不行,应该要按小程序的办法获取openId来做统一下单才行,我是在小程序启动,即 app.js 的 

onLaunch 方法中调用了 wx.login 拿到code,然后用 wx.request 请求我自己的一个接口去调用  code2Session 方法换好openId返回给小程序,让它保存在缓存中备用。

还有,小程序开通微信支付,你肯定是和我一样绑定之前公众号那个微信支付商户,然后签名的时候,用的key是 微信商户支付的key,是你自己设定的那个东西,不是小程序的appkey也不是appsecret。 

 

对接小程序支付整个流程就是这样,有问题可以留言给我

仅记录一下自己开发碰到的问题,同时也给各位马上和我一样的情况的人的一点提示,以免各位开发者和我一样走弯路。


沪ICP备09053415号 © 赶知识网