微信小程式開發之webview元件內網頁實現微信原生支付

淺Y發表於2018-01-05

前言、背景

本人目前的工作崗位是安卓工程師,在這之前對於前端和後臺的知識基本是白紙,只是在日常的工作專案中有需要和小夥伴進行對接的時候接觸了那麼一丟丟,對於前端和後臺的一些專業描述和理解有不當之處還請各位指正。

目前部門的主營專案是一個電商專案,在本人入職之前整個專案系統的主營業務流程已經完備,也已經在正式運營,不過因為各種原因平臺主要是在PC端和微信公眾號進行運營。小程式其實出來的挺早的,但是優先順序對於我們目前的規劃來說其實還是很低的。直到17年11月的時候小程式推出了web-view元件,在當時被譽為移動電商的福音&&&&$$$...此處省略五千字。

有了web-view那什麼公眾號內容、官網、網頁有域名的那種直接就可以扔到小程式的webview元件了,極大的減少了開發成本,就是一把梭。。。。

關於小程式

小程式的解釋什麼的不巴拉巴拉,直接上乾貨開發文件就不做過多解釋 微信小程式

關於小程式web-view元件

先奉上傳送門小程式 webview相關說明和API使用 官方解釋:web-view 元件是一個可以用來承載網頁的容器,會自動鋪滿整個小程式頁面。個人型別與海外型別的小程式暫不支援使用。 web-view元件開放時間並不久,所以目前的還是有很多侷限性的。
關於webview配置指向的連結的去小程式後臺進行配置就好(不配置webview是訪問不了的)必須支援https 如圖:

微信小程式開發之webview元件內網頁實現微信原生支付

示例程式碼:

微信小程式開發之webview元件內網頁實現微信原生支付
做過微信公眾號的童鞋應該都知道,在公眾號裡商家H5頁面內呼叫JSSDK就可以實現微信支付功能。但是看過webview元件的API的文件的童鞋應該知道:webview 裡面的網頁(公眾號遷移的網頁)是呼叫不了外部的微信支付what....... 雖然微信支付也確實是提供了小程式的微信支付API,但是因為我們整個小程式的內容就是一個webview嵌入公眾號內容的網頁,在網頁內下訂單的過程中是無法通過webview的api介面通知小程式調起微信支付的。 檢視微信支付小程式的支付文件,我們小程式如果要呼叫微信支付只需要得到以下引數就可以。
如圖:小程式呼叫微信支付引數
微信小程式開發之webview元件內網頁實現微信原生支付
以及示例程式碼:

微信小程式開發之webview元件內網頁實現微信原生支付
看到這些一切就明朗了,在小程式端只要能通過某種方式得到webview內網頁下單後的生成的相關引數就能調起微信支付從而實現webview元件內網頁微信支付。

實現方式和主要流程

  1. 先說明一下整個小程式實現webview呼叫支付的程式碼結構如圖

微信小程式開發之webview元件內網頁實現微信原生支付
整個結構很清晰、簡單,不做過多解釋。微信小程式採用的MVVM的模式。
xxxx.wxml類似於安卓activity的xml檔案。
xxxx.js類似於安卓中MVC模式的控制層。
xxxx.wxss類似於前端的CSS樣式。我們目前幾乎沒用到,因為只用到了小程式的webview元件。

  1. 原理分析

我們來看一下微信小程式支付的的業務流程:

微信小程式開發之webview元件內網頁實現微信原生支付
上面已經提到如果需要小程式的webview元件調起微信支付,需要網頁內部統一下單得到支付引數,然後通過小程式API調起微信支付,如下:

wx.requestPayment(
{
'timeStamp': '',
'nonceStr': '',
'package': '',
'signType': 'MD5',
'paySign': '',
'success':function(res){},
'fail':function(res){},
'complete':function(res){}
})
複製程式碼

那麼小程式如何得到支付引數呢,檢視webview的API文件發現 webview的內部網頁可以通過JSSDK的該API 實現webview網頁內部控制小程式。
wx.miniProgram.navigateBack 進行小程式頁面的跳轉比如我們的專案在 index.wxml 的 webview 網頁內部使用該API就可以控制小程式從index page 跳轉到wxpay page。

  1. 具體實現步驟

1 在index.wxml檔案新增webview元件,用來裝載原公眾號裡面的網頁內容
<web-view src="{{url}}"></web-view>
該url是index.js裡面data定義的一個變數``,方便通過index.js的setData方法對webview的網頁進行動態載入

2 新建wxpay目錄,並新建wxpay的page頁面用來處理支付邏輯。(該頁面目前是空白的,功能上分析該頁面只是為了收到webview網頁的支付引數,從使用者使用角度上來說該頁面是一個支付頁面應該需要新增一些使用者互動的,比如轉圈QAQ)

3 webview網頁使用者在生成訂單後,選擇微信支付即走微信的統一下單流程,生成微信支付的引數和sgin。在webview網頁內部通過path攜帶引數跳轉到wxpay頁面,具體虛擬碼實現如下(註釋很清楚): 這部分是後端程式碼 即小程式內部網頁的程式碼(在java工程中為 .ftl檔案)。我的這個方案是需要後端進行邏輯更改的。看懂的朋友應該知道只有當後端微信支付下單流程完成後才能得到調起微信支付需要的引數。這部分都是後端實現的。 只有後端下單流程完成,然後判斷是不是小程式是小程式就是下面的程式碼。不是就繼續走公眾號的微信支付

//判斷是否是在wx小程式環境
if(small_wx  && data.resultCode=='success'){
  //點選微信支付後,調取統一下單介面生成微信小程式支付需要的支付引數
  var params = '?timestamp='+data.jsparams.timeStamp+'&nonceStr='+data.jsparams.nonceStr
               +'&'+data.jsparams.pkg+'&signType='+data.jsparams.signType
               +'&paySign='+data.jsparams.paySign+'&orderId='+data.orderid+'&pType=0';
  //定義path 與小程式的支付頁面的路徑相對應
  var path = '/pages/wxpay/wxpay'+params;
  //通過JSSDK的api使小程式跳轉到指定的小程式頁面
  wx.miniProgram.navigateTo({url: path});				   			
  }
複製程式碼

4 小程式端wxpay頁面邏輯實現(wxpay.js),webview內的網頁通過wx.miniProgram.navigateTo({url: path})攜帶引數使小程式跳轉到wxpay頁面。wxpay.js 對url中攜帶的引數進行處理,然後通過wx.requestPayment調起微信支付並對支付的回撥通知進行處理,具體程式碼實現如下(註釋很詳細不做過多贅述):

onLoad: function (options) {
   var that = this;
   //頁面載入調取微信支付(原則上應該對options的攜帶的引數進行校驗)
   that.requestPayment(options);
 },
//根據 obj 的引數請求wx 支付
 requestPayment: function (obj) {
   //獲取options的訂單Id
   var orderId = obj.orderId;
   //調起微信支付
   wx.requestPayment({
     //相關支付引數
     'timeStamp': obj.timestamp,
     'nonceStr': obj.nonceStr,
     'package': 'prepay_id=' + obj.prepay_id,
     'signType': obj.signType,
     'paySign': obj.paySign,
     //小程式微信支付成功的回撥通知
     'success': function (res) {
       //定義小程式頁面集合
       var pages = getCurrentPages();
       //當前頁面 (wxpay page)
       var currPage = pages[pages.length - 1];  
       //上一個頁面 (index page) 
       var prevPage = pages[pages.length - 2];  
       //通過page.setData方法使index的webview 重新載入url  有點類似於後臺重新整理頁面
       //此處有點類似小程式通過載入URL的方式回撥通知後端 該訂單支付成功。後端邏輯不做贅述。
         prevPage.setData({
           url: "https://xxxxxxxxxx.com/wx_isPayment.jhtml?orderId=" + orderId  + '&ispay=0',
           
         }),
         //小程式主動返回到上一個頁面。即從wxpay page到index page。此時index page的webview已經重新載入了url 了
         //微信小程式的page 也有棧的概念navigateBack 相當於頁面出棧的操作
         wx.navigateBack(); 
     },
     //小程式支付失敗的回撥通知
     'fail': function (res) {
       console.log("支付失敗"),
         console.log(res)
         var pages=getCurrentPages();
         var currPage = pages[pages.length - 1];   
         var prevPage = pages[pages.length - 2];  
         console.log("準備修改資料")
         prevPage.setData({
           url: "https://xxxxxxxxxx/wx_isPayment.jhtml?orderId=" + orderId + '&ispay=0' ,
         }),
           console.log("準備結束頁面")
       wx.navigateBack(); 
     }
   })
 },
複製程式碼
  1. 微信支付後的回撥通知,當wxpay頁面呼叫navigateBack的時候回到index頁面的時候webview 已經載入https://xxxxxxxxxx/wx_isPayment.jhtml?orderId=" + orderId + '&ispay=0' 這個網頁,後臺實現相關邏輯。通過orderId查詢該訂單是否支付成功。如果支付成功就網頁重定向到支付成功的頁面,如果支付失敗還是待支付頁面。使用者依舊可以點選微信支付按鈕進行微信支付。
  2. 至此小程式的webview元件內網頁就可以實現微信支付了。

see you agin

如果用原生小程式元件實現商城支付就沒這麼麻煩,但是工作量會非常巨大。直接把公眾號的網頁移植到小程式的webview裡面,極大的節省了開發時間,對於小商戶來說還是非常方便的。我們現在也算是偷懶把,畢竟投入不大、優先順序不夠、先弄個東西出來可以用,小程式沒有一個向服務端的wx.request請求。但是我內心其實拒絕的。。。。。因為使用者體驗和產品角度都很low.........

補上支付的截圖嗯哼

  • 1 webview內的網頁下單成功

小程式webview頁面下單成功

熟悉開發的小夥伴應該知道出現這個頁面的時候。其實只是後端生成了一個訂單而已,這個時候和支付還沒有一毛錢關係(微信支付時序圖中的生成商戶訂單)。 此時使用者點選微信支付按鈕即為時序圖中的 5 呼叫統一下單API()---》生成預付單----》返回預付單資訊(prepay_id). 6 生成JSAPI頁面呼叫的支付引數並簽名() 返回支付引數(prepay_id, paySgin等) 以上其實都還是微信公眾號的下單,生成支付邏輯 只有當得到支付引數後,判斷是小程式環境才通過

var path = '/pages/wxpay/wxpay'+params;

//通過JSSDK的api使小程式跳轉到指定的小程式頁面

wx.miniProgram.navigateTo({url: path});

這個API 將支付引數傳到wxpay page頁面。 至此通訊流程完成

附上微信公眾號支付的 時序圖 微信公眾號支付時序圖參考

  • 2 當index的微信支付下單流程完成後,通過jssdk的 wx.miniProgram.navigateTo API 將資料傳遞到wxpay page頁面。 當wxpay得到引數後,驗證引數無誤就呼叫 wx.requestPayment 調起微信支付

微信支付

如何聯絡我:部落格主頁

相關文章