跳至主要内容

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

原文链接

实现方式和主要流程

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

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

上面已经提到如果需要小程序的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组件内网页就可以实现微信支付了。





评论

此博客中的热门博文

Resolving errSecInternalComponent errors during code signing

原文链接 One code signing issue I commonly see, both here on DevForums and in my Day Job™ with DTS, is that the codesign command fails with errSecInternalComponent. This issue crops up in a wide variety of circumstances and the correct fix depends on the specific problem. This post is my attempt to clarify the potential causes of this error and help folks resolve it. If you have any questions or comments about this, please start a new thread, tagging it with Code Signing so that I see it. Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" Resolving errSecInternalComponent errors during code signing In some circumstances the codesign command might fail with the error errSecInternalComponent. For example: % codesign -s "Apple Development" "MyTrue" MyTrue: errSecInternalComponent This typically affects folks who are signing code in a nonstandard environm...

iOS:检测使用VPN或Proxy

参考链接: https://www.jianshu.com/p/c3b950dbf86a https://gist.github.com/PramodJoshi/4faad4c91f7dcb4eb9b06be8390c01db http://noodlecode.net/2018/04/check-if-ios-app-is-connected-to-vpn 第一种方法 需要导入框架CFNetwork 然后,这个方法是mrc的:需要添加-fno-objc-arc的flag 代码如下: + ( BOOL )getProxyStatus { NSDictionary *proxySettings = NSMakeCollectable ([( NSDictionary *) CFNetworkCopySystemProxySettings () autorelease]); NSArray *proxies = NSMakeCollectable ([( NSArray *) CFNetworkCopyProxiesForURL (( CFURLRef )[ NSURL URLWithString: @"http://www.google.com" ], ( CFDictionaryRef )proxySettings) autorelease]); NSDictionary *settings = [proxies objectAtIndex: 0 ]; NSLog ( @"host=%@" , [settings objectForKey:( NSString *)kCFProxyHostNameKey]); NSLog ( @"port=%@" , [settings objectForKey:( NSString *)kCFProxyPortNumberKey]); NSLog ( @"type=%@" , [settings objectForKey:( NSString *)kCFProxyTypeKey]); if ([[settings object...

去广告DNS设置,国内ADGuard DNS方案,手机电脑iOS去广告,保护隐私

 原文链接 之前分享过使用mac系统搭建adguard home,这几个月用下来零零散散基本上也被弃用了。主要原因是因为需要保持电脑一直开机。但是我的电脑是笔记本,存在移动各个地域的情况,也就是说只能够屏蔽电脑自身,对于手机而言不太现实。今天偶然发现dnspod推出了高级版的公共解析。dnspod背靠腾讯云,肯定是合法合规的公共解析服务,这个高级版用起来不错。 国内自己搭建解析服务是违法行为,所以这也是为什么使用dnspod的原因。 后台截图 开始使用 首先我们先进入dnspod的公共解析页面,点击开始使用。 专业版公共解析 dnspod会提供几种预设,我们选择「开发者」即可 开发者 然后你就成功的申请到自己个人使用的dns了! 更新拦截规则 我们可以将常见的广告过滤规则加入到dns中。我们在顶部选项卡中选择「拦截规则」。 拦截规则设置 打开adguard adguard 绑定iOS设备 推荐使用描述文件的方式,删除配置时删除描述文件即可。 描述文件 绑定macOS 推荐使用描述文件的方式,删除配置时删除描述文件即可。 描述文件 mac需要在「系统偏好设置」的「网络」中查看是否正在运行。 代理 如果没有运行需要点击「···」来启动服务。 启动服务 绑定路由器 找到自己路由器的DHCP设置,修改dns,然后记得绑定自己的ip。 修改dns 绑定ip 费用 目前有300万次/月的免费额度,但没有超出之后的价格。300万次一个人比较难用完,可以放心使用。 我个人使用iOS设备两台、智能家居、电脑两台,日均请求数大致2万/日。 判断是否搭建成功 可以通过查看日志的方式,日志大概有半小时到一小时的延迟,请耐心等待。