likes
comments
collection
share

微信支付点金计划从试错到成功

作者站长头像
站长
· 阅读数 13

最近开发的公众号中,接入了微信的点金计划,就是在支付完成后,点击完成按钮会跳转到微信的一个页面,页面上可以展示订单和商户的基本信息,下部还有自带的广告信息,详细的可以了解下微信的官方文档:微信点金计划,文档里介绍了产品信息、接入方法等内容。

但是,众所周知某些开发文档对于初次开发的人员来说并不友好,甚至文档都快背下来了,依旧不知道怎么去开发,并且中途遇到问题在文档里也找不到合理的解决办法,这时候还得是靠广大的网友的聪明智慧了......

这里先上一下全部代码,然后再说明遇到的问题和解决问题思路。对于点金计划页面,可以使用路由做一个页面,也可以单独写个html页面,这里我使用的是html+万能的jquery

<!DOCTYPE html>
<html lang="en" data-design-width="750" data-design-font="100" >
<head>
  <meta charset="UTF-8">
  <link rel="icon" href="../favicon.png" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
  <title>支付完成页</title>
  <!-- 点金计划必须接入的js -->
  <script type="text/javascript" charset="UTF-8" src="https://wx.gtimg.com/pay_h5/goldplan/js/jgoldplan-1.0.0.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script>
    // 字号转换rem
    (function (window, undefined) { 
      var html_dom = document.getElementsByTagName('html')[0]; 
      var design_width = parseInt(html_dom.dataset.designWidth, 10); 
      var design_font = parseInt(html_dom.dataset.designFont, 10); 
      var isMobile = /Mobile/.test(window.navigator.userAgent); 
      window.onresize = function () { 
        resizeRoot(); 
      } 
      function resizeRoot() { 
        var client_width = document.documentElement.clientWidth; 
        if (client_width >= 750) { 
          client_width = 750; 
        } 
        var fs = client_width / design_width * design_font; 
        html_dom.style.fontSize = fs + "px"; 
      }; 
      resizeRoot(); 
    })(window)
  </script>
  <script th:inline="javascript">
  //获取url中返回参数
  function  getQueryString(name) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == name) {
            return pair[1];
        }
    }
    return null;
  }
  
  // 获取cookie
  function getck(sname) {  //获取单个cookies
    if(document.cookie){
      var acookie = document.cookie.split("; ");
      for (var i = 0; i < acookie.length; i++) {
        var arr = acookie[i].split("=");
        if (sname == arr[0]) {
          if (arr.length > 1) {
            console.log('arr', arr[1])
            return unescape(arr[1]);
          } else {
            return "";
          }
        }
      }
      return "";
    }
  }
  
  window.onload = function(){
    var out_trade_no = getQueryString("out_trade_no");   //商户订单号
    $.ajax({
      type: "POST",
      url: window.location.origin + '/payResult',
      data: JSON.stringify({
        orgId: out_trade_no
      }),
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      headers: {
        'token': getck('token')
      },
      success: function (res) {
        console.log('请求成功',res)
        if (res && res.code == 200 && res.data) {
            // 根据页面需要展示的内容进行修改
            $('.merTitle').html(res.data.merName)
            $('.name').html(res.data.nickName)
            $('.amt strong').html(res.data.amt)
            $('.headImg').attr('src', res.data.picUrl)
  
            var mchData = { action: 'onIframeReady', displayStyle: 'SHOW_CUSTOM_PAGE', height: 404 };
            let postData = JSON.stringify(mchData);
            // window.parent.postMessage(postData, 'https://payapp.weixin.qq.com');
            top.postMessage(postData, '*');
  
            // 注册点击事件,即点击页面上按钮跳转出去
            document.querySelector('#goOrder').onclick = function () {
              let pathname = window.location.pathname
              let pathnameArr = pathname.split('/')
              var mchData = {
                  action: 'jumpOut',
                  jumpOutUrl: window.location.origin + '/' + pathnameArr[1] + '/#/bbb?id=' + res.data.id   //跳转的页面
              }
              console.log('调用成功',mchData);
              var postData = JSON.stringify(mchData)
              // parent.postMessage(postData, "https://payapp.weixin.qq.com")
              top.postMessage(postData, "*")
            }
        }
      },
      error: function(err){
        console.log('请求出错',err)
      }
    });
  }
  </script>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    .pay_over .content {
      text-align: center;
      background-color: rgba(246, 246, 246, 1);
      width: 99%;
      margin: .5rem auto 0;
      position: relative;
    }

    .pay_over .content .headImg {
      width: 1.5rem;
      height: 1.5rem;
      border-radius: 50%;
      position: absolute;
      left: 50%;
      top: -.25rem;
      margin-left: -.75rem;
    }

    .pay_over .content .merTitle {
      font-size: .42rem;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 500;
      color: #333333;
      margin: 0 0 .56rem;
      padding-top: 1.5rem;
    }

    .pay_over .content .name {
      font-size: .42rem;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #333333;
      margin: 0 0 .16rem;
    }

    .pay_over .content .amt {
      font-size: .8rem;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 500;
      color: #333333;
      margin: 0 0 .4rem;
    }

    .pay_over .content .amt span {
      font-size: .36rem;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      padding-left: .1rem;
    }

    .pay_over .content .link {
      font-size: .32rem;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #1677FF;
      padding-bottom: .42rem;
    }

    .pay_over .content .link a {
      text-decoration: underline;
      font-family: PingFangSC-Regular, PingFang SC;
    }
  </style>
</head>
<body>
  <div class="pay_over">
    <div class="content">
      <img class="headImg" src="" alt="">
      <div class="merTitle"></div>
      <div class="name"></div>
      <div class="amt"><strong></strong><span></span></div>
      <div class="link" id="goOrder"><a href="javascript:void 0">查看订单详情</a></div>
    </div>
  </div>
</body>
</html>

上面就是出版的点金计划页面代码,在本地调试接口是没问题的,但是如果真的需要模拟点金计划完整页面的效果,需要把这个页面放到服务器上,并把路径配到微信商家配置里,才可以进行调试,这部分文档有相关方法,不再赘述。

重点说一下开发中遇到的问题,就是能够支付完成,也能够跳转到点金页面,但是部分(基本就是IOS)手机会显示无法获取订单信息,这也是小伙伴们遇到的最多的问题。

微信支付点金计划从试错到成功

针对这个问题,官方也给出了几条建议:

1、已打开特约商户的商家小票及点金计划开关

2、商家小票页面需调用父页面“onIframeReady事件”的jsapi,具体请查看商家小票开发指引

3、从加载商家小票到调用JSAPI之间的用时不可超过3s

4、调试时,扫描二维码的微信号和支付该笔测试订单的微信号需为同一个

5、商家小票页面可正常访问

6、检查商家小票请求的Response Headers中X-Frame-Options是否允许payapp.weixin.qq.com访问

7、如果是使用VUE,onIframeReady不能放在created里执行

8、如果上述方法都不行,请先编写一个最简单的demo页面,看看demo页面是否成功

9、商家URL是否有进行重定向,是否重定向到http的链接

不过这些建议有的可以验证,有的真的无从下手...所以针对上面的问题楼主联合了后端一起排查,通过日志发现,在请求的时候实际上已经报错了,问题就出在通过cookie获取token上面,此时cookie为空了,自然接口的登录信息校验就过不去了。

这里也是楼主的疏忽,本来觉得点金页面和实际业务页都在一个域名下,cookie是可以共享的,能够完美获取;但是实际上,到真实环境中上面开发的页面是通过iframe被嵌入到微信官方页面中的;大部分安卓和一部分IOS 能够正常显示页面,只有部分IOS无法正常显示,借用网上其他小伙伴的说法,这就是系统的差异,能够正常显示的在跳转时没有清除登录信息,但是IOS把登录信息都清掉了。所以如果涉及缓存存取,还是要慎重!!!

到这里问题原因就很明确了,后端做了相应的修改,给这个接口加白名单,不去校验token(当然是在业务允许的情况下),前端代码获取不获取token就无所谓了。

最后,在上边官方给出的九条建议上再加一条:

10、检查业务逻辑请求是否涉及到登录信息存取,如无业务需求,尽量避免登录相关校验