微信小程序:web-view嵌套H5实现微信支付功能解决方案及填坑

itlao6 原创 开发&源码 微信小程序91,057字数 2696阅读8分59秒阅读模式

最近一个多月加班比较严重,偶尔休息一天也是在补睡眠+陪家人,比较长时间没有来进行总结记录了。今天不加班,开始为这段时间做的东西进行下经验总结。
这段时间因为公司需要,接触了一些.Net前后台开发,慢慢了解了一些WCF、H5站点、WebService、Soap、Linq等,也了解了一些BLL、DAL相关内容。同时也参与了微信支付、微信医保支付相关功能的改版,以及为微信小程序增加微信支付、微信医保支付功能。
下面主要记录下小程序支付相关方案、实现及填坑。

一. 产品现状

首先,在接入微信支付功能以前,我们的产品情况是这样的:
1 有公众号和app的h5站点及相关配套功能
2 小程序已经有一些基础功能,这些功能没有使用web-view
3 小程序之前的服务器是与现有公众号h5站点不同的一个webapi站点文章源自IT老刘-https://wp.itlao6.com/608.html

二. 备选方案

基于以上几点,当时提出了两套解决方案:
方案1. 支付相关功能使用小程序代码进行开发,并在webapi站点增加相应接口
方案2. 使用web-view嵌入公众号h5站点的支付功能,包括订单列表、订单详情、支付确认、支付下单、支付结果展示、支付历史等,仅实际支付时使用小程序代码进行开发文章源自IT老刘-https://wp.itlao6.com/608.html

最终我们使用的是第二套方案,本来以为有了现成的h5页面,需要解决的仅仅是h5站点与webapi站点的登录同步以及小程序的支付界面唤起这两个问题,结果发现,坑还是不少的。文章源自IT老刘-https://wp.itlao6.com/608.html

三. 方案实现

微信小程序:web-view嵌套H5实现微信支付功能解决方案及填坑
微信小程序web-view嵌套h5接入支付功能

基本流程如上述示意图,订单相关页面及微信支付下单过程都在h5,下单成功后通过wx.program.navigateTo跳转回小程序,小程序执行wx.requestPayment唤起支付页面,获取的结果以h5展示。同时,在下单时会设置支付结果回调页(PayNotify),实际支付成功后,微信会主动调用PayNotify页面,在该页面操作订单支付表的支付状态。
小程序代码如下:文章源自IT老刘-https://wp.itlao6.com/608.html

// 直接在onLoad中唤起支付页面(中间的部分参数需要用decodeURIComponent解码) 
onLoad: function(options) { 
  var payType = options.type; 
  var timeStamp = options.timeStamp; 
  var nonceStr = decodeURIComponent(options.nonceStr); 
  var package = decodeURIComponent(options.package); 
  var signType = options.signType; 
  var paySign = decodeURIComponent(options.paySign); 
  if(type == 1) { 
    // 微信支付 
    this.wxPay(timeStamp, nonceStr, package, signType, paySign); 
  }else { 
    var payAppId = options.appid; 
    var payUrl = decodeURIComponent(options.payUrl); 
    // 医保支付,需要跳转到医保小程序进行支付,需要获取医保小程序appid和payurl 
  } 
} 

// 唤起微信支付窗口 
wxPay: function(timeStamp, nonceStr, package, signType, paySign) { 
  wx.requestPayment({ 
    'timeStamp': timeStamp, 
    'nonceStr': nonceStr, 
    'package': package, 
    'signType': signType,//'MD5', 
    'paySign': paySign, 
    'success':function(res){ 
      // 成功跳转到h5结果页面 
    }, 'fail':function(res){ 
      // 失败提示并返回订单页 
    }, 'complete': function(res){ 
      // 较早版本,用户取消支付,不进入fail回调,仅回调complete 
      // res.errMsg为requestPayment:fail cancel 
      if(res.errMsg=='requestPayment:fail cancel') { 
        // 用户取消返回订单页 
      } 
    } 
  }) 
}

注意:文章源自IT老刘-https://wp.itlao6.com/608.html

  1. 在生成订单表,下单成功后,即进入支付中状态
  2. 建议区分订单表和支付表
  3. 实际支付页面的唤起只能在小程序中进行,不能使用h5唤起微信支付页面
  4. 支付结果必须以微信回调为准,不能直接使用wx.program.navigateTo返回的结果
  5. 因为公众号和小程序使用的是同一套h5代码,所以必须将appid等设置为配置项,不同的入口,使用不同的appid;而且在支付表中,必须能明确是小程序还是公众号支付的,不然会出现无法退款等情况。(退款的appid必须是支付的appid)

四. 填坑

坑1 支付商户和小程序主体不一致,而且我们的商户是特约商户,导致小程序无法进行M-A授权并开通微信支付功能文章源自IT老刘-https://wp.itlao6.com/608.html

解决方案:

这里有多种解决方案,最快捷的是找腾讯内部人员提交申请,提交信息后他们会帮忙进行M-A授权(我们下午提交第二天就ok了)
坑2
appid等信息不同导致需要h5站点兼容文章源自IT老刘-https://wp.itlao6.com/608.html

解决方案:

增加支付相关的配置,不同的入口读取不同的配置项,包含appid, appsecret,mchid,回调地址等配置。
坑3
由于之前是在webapi进行登录,h5站点存在未登录的问题文章源自IT老刘-https://wp.itlao6.com/608.html

解决方案:

我们webapi和h5使用的是同一个数据库,所以我们只是在h5站点再进行一次openid的绑定,当然,这里需要考虑的是小程序和公众号都存在openid,我们得分开建立绑定关系。
这是我们产品之前设计存在的问题,其实是可以通过unionid来建立绑定关系(因为这个才是对微信用户而言唯一不变的标识),同时也可以考虑缓存不同来源的openid
坑4
历史记录及退款问题文章源自IT老刘-https://wp.itlao6.com/608.html

解决方案:

需要在支付记录中存储是哪个端下的订单,因为如果小程序支付的,一定要用小程序的appid等信息去退款,公众号也一样。所以支付记录表中应该有payType字段,最好支付的订单号生成时前两位用于记录支付方式,比如01开头的是公众号支付,02开头是小程序支付。
我们的订单号生成规则是 2位支付方式+1位交易订单类型(支付、退款等)+2位商品类型 + 时间戳 + 其他
原文:简书ThinkinLiu 博客: IT老五文章源自IT老刘-https://wp.itlao6.com/608.html


ps 时间有点紧张,还有一些具体方案实现和坑没总结,后续再补充。有什么错误或者不足欢迎指出...
另外,使用web-view在体验上感觉有点坑,坑1. h5加载比纯使用小程序要慢很多 坑2. 无法准确捕获到h5页面加载的进度...文章源自IT老刘-https://wp.itlao6.com/608.html

文章源自IT老刘-https://wp.itlao6.com/608.html文章源自IT老刘-https://wp.itlao6.com/608.html
继续阅读
weinxin
我的微信公众号
微信扫一扫关注公众号,不定时更新
itlao6
  • 本文由 发表于 2018年 10月 20日 23:28:24
  • 转载请务必保留本文链接:https://wp.itlao6.com/608.html
评论  9  访客  9
    • 奇洛郁金香
      奇洛郁金香 6

      1.timeStamp, nonceStr, package, signType, paySign这几个参数都是从H5传给小程序的是吧?
      2.因为公众号和小程序使用的是同一套h5代码,所以必须将appid等设置为配置项,不同的入口,使用不同的appid,这是怎么配置的?

        • Thinkin
          Thinkin

          @ 奇洛郁金香 1. 上面几个参数是H5传给小程序(其实你也可以小程序中通过api接口去后台生成)
          2. 配置可以在你数据库或者配置文件中进行,代码中判断当前是小程序或者公众号然后读取对应的配置(通过window.__wxjs_environment === ‘miniprogram’ 或者 通过入口来源传递)

        • t shirts in Dubai
          t shirts in Dubai 6

          It’s nearly impossible to find educated people on this subject, however, you sound like you know what you’re talking about!
          Thanks

          • Inlocuire Parbriz
            Inlocuire Parbriz 6

            Have you ever thought about creating an ebook or guest authoring on other blogs?
            I have a blog centered on the same information you discuss and would love
            to have you share some stories/information. I know my visitors would appreciate your work.
            If you are even remotely interested, feel free to send me an email.

            • joker123
              joker123 6

              I tгduly loᴠe your websіte.. Pⅼeasant colors & theme.
              Did yyou develop this weЬ sіte yourself? Please rreply back аs I’m lookinbg to create myy own personal
              site and want too find оut where you g᧐t this from
              or exactly whаt the theme is named. Aρpreciate it!

                • Thinkin
                  Thinkin

                  @ joker123 Newslite

                • vintage house restaurant
                  vintage house restaurant 6

                  This information is worth everyone’s attention. How can I find
                  out more?

                  • 农夫三拳有点痛_089e
                    农夫三拳有点痛_089e 6

                    大佬 我们公司也有这个需求 然后也想到了 使用web-view嵌入h5 发起支付到第三方公司(财务公司),因为没有做过这种,就考虑到 是不是可以在小程序管理平台中把微信支付的对象换成 第三方公司, 不知道这样行不行得通? 求大佬指点

                      • Thinkin
                        Thinkin

                        @ 农夫三拳有点痛_089e 你这里支付到第三方公司是通过微信支付?这个涉及到微信支付商户号问题,如果商户号是特约商户,则需要主体和微信小程序主体一致…如果是普通商户,则在支付的第三方公司微信商户号进行关联后才能支付…

                    匿名

                    发表评论

                    匿名网友

                    :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

                    确定