分享

微信小程序开发之webview组件内网页实现微信原生支付

 昵称21532077 2018-03-26


前言、背景

本人目前的工作岗位是安卓工程师,在这之前对于前端和后台的知识基本是白纸,只是在日常的工作项目中有需要和小伙伴进行对接的时候接触了那么一丢丢,对于前端和后台的一些专业描述和理解有不当之处还请各位指正。


目前部门的主营项目是一个电商项目,在本人入职之前整个项目系统的主营业务流程已经完备,也已经在正式运营,不过因为各种原因平台主要是在PC端和微信公众号进行运营。小程序其实出来的挺早的,但是优先级对于我们目前的规划来说其实还是很低的。直到17年11月的时候小程序推出了**web-view**组件,在当时被誉为移动电商的福音&&&&$$$...此处省略五千字。


有了web-view那什么公众号内容、官网、网页有域名的那种直接就可以扔到小程序的webview组件了,极大的减少了开发成本,就是一把梭。。。。




关于小程序web-view组件

先奉上传送门小程序webview相关说明和api使用

官方解释:web-view 组件是一个可以用来承载网页的容器,会自动铺满整个小程序页面。**个人类型与海外类型的小程序暂不支持使用**。
web-view组件开放时间并不久,所以目前的还是有很多局限性的。  
关于webview配置指向的链接的去小程序后台进行配置就好(不配置webview是访问不了的)必须支持https 如图:  
小程序wevbiew服务器域名配置

示例代码:
示例代码

做过微信公众号的童鞋应该都知道,在公众号里商家H5页面内调用JSSDK就可以实现微信支付功能。但是看过webview组件的API的文档的童鞋应该知道:webview 里面的网页(公众号迁移的网页)是调用不了外部的微信支付what.......  虽然微信支付也确实是提供了小程序的微信支付API,但是因为我们整个小程序的内容就是一个webview嵌入公众号内容的网页,在网页内下订单的过程中是无法通过webview的api接口通知小程序调起微信支付的。 查看微信支付小程序的支付文档,我们小程序如果要调用微信支付只需要得到以下参数就可以。  
如图:小程序调用微信支付参数
小程序调用微信支付参数
以及示例代码

示例代码



看到这些一切就明朗了,在小程序端只要能通过某种方式得到webview内网页下单后的生成的相关参数就能调起微信支付从而实现webview组件内网页微信支付。

实现方式和主要流程

1. 先说明一下整个小程序实现webview调用支付的代码结构如图:
项目代码结构


整个结构很清晰、简单,不做过多解释。微信小程序采用的MVVM的模式。  
`xxxx.wxml`类似于安卓activity的xml文件。  
`xxxx.js`类似于安卓中MVC模式的控制层。  
`xxxx.wxss`类似于前端的CSS样式。我们目前几乎没用到,因为只用到了小程序的webview组件。     


2. 原理分析
  
我们来看一下微信小程序支付的的业务流程:  
支付流程时序图
上面已经提到如果需要小程序的webview组件调起微信支付,需要网页内部统一下单得到支付参数,然后通过小程序API调起微信支付,如下: 

  1. wx.requestPayment(  
  2. {  
  3. 'timeStamp': '',  
  4. 'nonceStr': '',  
  5. 'package': '',  
  6. 'signType': 'MD5',  
  7. 'paySign': '',  
  8. 'success':function(res){},  
  9. 'fail':function(res){},  
  10. 'complete':function(res){}  
  11. })  


那么小程序如何得到支付参数呢,查看webview的API文档发现 webview的内部网页可以通过JSSDK的该API 实现webview网页内部控制小程序。  
`wx.miniProgram.navigateBack` 进行小程序页面的跳转比如我们的项目在 index.wxml 的 webview 网页内部使用该API就可以控制小程序从index page 跳转到wxpay page。

具体实现步骤

1. 在index.wxml文件添加webview组件,用来装载原公众号里面的网页内容    
 
  1. <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页面,具体伪代码实现如下(注释很清楚):  

[javascript] view plain copy
print?
  1. //判断是否是在wx小程序环境  
  2. if(small_wx  && data.resultCode=='success'){  
  3. //点击微信支付后,调取统一下单接口生成微信小程序支付需要的支付参数  
  4. var params = '?timestamp='+data.jsparams.timeStamp+'&nonceStr='+data.jsparams.nonceStr  
  5.              +'&'+data.jsparams.pkg+'&signType='+data.jsparams.signType  
  6.              +'&paySign='+data.jsparams.paySign+'&orderId='+data.orderid+'&pType=0';  
  7. //定义path 与小程序的支付页面的路径相对应  
  8. var path = '/pages/wxpay/wxpay'+params;  
  9. //通过JSSDK的api使小程序跳转到指定的小程序页面  
  10. wx.miniProgram.navigateTo({url: path});      
  11. }  

    
4. 小程序端wxpay页面逻辑实现(wxpay.js),webview内的网页通过`wx.miniProgram.navigateTo({url: path})`携带参数使小程序跳转到wxpay页面。wxpay.js 对url中携带的参数进行处理,然后通过`wx.requestPayment`调起微信支付并对支付的回调通知进行处理,具体代码实现如下(注释很详细不做过多赘述):  

  1. onLoad: function (options) {  
  2.     var that = this;  
  3.     //页面加载调取微信支付(原则上应该对options的携带的参数进行校验)  
  4.     that.requestPayment(options);  
  5.   },  
  6.  //根据 obj 的参数请求wx 支付  
  7.   requestPayment: function (obj) {  
  8.     //获取options的订单Id  
  9.     var orderId = obj.orderId;  
  10.     //调起微信支付  
  11.     wx.requestPayment({  
  12.       //相关支付参数  
  13.       'timeStamp': obj.timestamp,  
  14.       'nonceStr': obj.nonceStr,  
  15.       'package': 'prepay_id=' + obj.prepay_id,  
  16.       'signType': obj.signType,  
  17.       'paySign': obj.paySign,  
  18.       //小程序微信支付成功的回调通知  
  19.       'success': function (res) {  
  20.         //定义小程序页面集合  
  21.         var pages = getCurrentPages();  
  22.         //当前页面 (wxpay page)  
  23.         var currPage = pages[pages.length - 1];    
  24.         //上一个页面 (index page)   
  25.         var prevPage = pages[pages.length - 2];    
  26.         //通过page.setData方法使index的webview 重新加载url  有点类似于后台刷新页面  
  27.         //此处有点类似小程序通过加载URL的方式回调通知后端 该订单支付成功。后端逻辑不做赘述。  
  28.           prevPage.setData({  
  29.             url: "https:///wx_isPayment.jhtml?orderId=" + orderId  + '&ispay=0',  
  30.               
  31.           }),  
  32.           //小程序主动返回到上一个页面。即从wxpay page到index page。此时index page的webview已经重新加载了url 了  
  33.           //微信小程序的page 也有栈的概念navigateBack 相当于页面出栈的操作  
  34.           wx.navigateBack();   
  35.       },  
  36.       //小程序支付失败的回调通知  
  37.       'fail': function (res) {  
  38.         console.log("支付失败"),  
  39.           console.log(res)  
  40.           var pages=getCurrentPages();  
  41.           var currPage = pages[pages.length - 1];     
  42.           var prevPage = pages[pages.length - 2];    
  43.           console.log("准备修改数据")  
  44.           prevPage.setData({  
  45.             url: "https://xxxxxxxxxx/wx_isPayment.jhtml?orderId=" + orderId + '&ispay=0' ,  
  46.           }),  
  47.             console.log("准备结束页面")  
  48.         wx.navigateBack();   
  49.       }  
  50.     })  
  51.   },  
           
5. 微信支付后的回调通知,当wxpay页面调用`navigateBack`的时候回到index页面的时候webview 已经加载`https://xxxxxxxxxx/wx_isPayment.jhtml?orderId=" + orderId + '&ispay=0' ` 这个网页,后台实现相关逻辑。通过orderId查询该订单是否支付成功。如果支付成功就网页重定向到支付成功的页面,如果支付失败还是待支付页面。用户依旧可以点击微信支付按钮进行微信支付。
6. 至此小程序的webview组件内网页就可以实现微信支付了。

see you agin

如果用原生小程序组件实现商城支付就没这么麻烦,但是工作量会非常巨大。直接把公众号的网页移植到小程序的webview里面,极大的节省了开发时间,对于小商户来说还是非常方便的。我们现在也算是偷懒把,毕竟投入不大、优先级不够、先弄个东西出来可以用,小程序没有一个向服务端的`wx.request`请求。但是我内心其实拒绝的。。。。。因为用户体验和产品角度都很low.........
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多