場景:小程序頁面有一個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 頁面代碼
<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 方法
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);
//這個請求是去拿小程序支付需要的相關參數用的,具體怎么獲取這些參數,看文檔吧兄台。 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 的