微信二次分享报错invalid signature问题及解决方法

  • Post category:http

微信二次分享报错invalidsignature问题及解决方法

问题现象描述

在进行微信二次分享时,发现页面出现了报错信息“invalid signature”,导致分享失败。无法正常将内容分享给朋友圈、微信群或者微信好友。

问题原因

微信二次分享的过程需要进行签名验证,如果签名不正确就会出现“invalid signature”错误。造成签名错误的原因有很多种,比如:

  • 签名算法不正确
  • 签名参数传递不正确
  • 服务器生成的签名与微信服务器传回的签名不一致
  • URL编码问题等

解决方法

1. 签名算法

在进行微信二次分享的签名算法中,有一个名为“jsapi_ticket”的参数需要加入签名。此参数是在微信端调用JS API时的必要参数之一,只有在页面调用JS API成功后,才可以获得这个参数。

以下是获取jsapi_ticket的过程:

  1. 在代码中调用微信提供的getJsApiTicket接口
  wx.request({
    url: 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token='+ACCESS_TOKEN,
    success: function(res){
      var ticket = res.data.ticket;
      // 对获取到的ticket进行使用
    }
  });
  1. 在第一步中获取到jsapi_ticket后,还需要按照如下方式进行签名:
  var string1 = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + url;
  var shaObj = new jsSHA("SHA-1", "TEXT");
  shaObj.update(string1);
  var signature = shaObj.getHash("HEX");

其中,noncestr是一段随机字符串,timestamp为当前时间戳,url为当前页面的URL地址。

2. 签名参数

在进行签名时需要注意一些参数的传递方式:

  • URL参数需要进行urlencode,比如将“&”转换为“%26”,防止签名错误;
  • 签名参数需要进行字典序排序,否则也会出现错误;
  • 签名参数需要按照key=value的方式进行拼接,中间使用&符号连接。

以下为示例代码:

  var noncestr = '123456';  // 随机字符串
  var timestamp = Math.round(new Date().getTime()/1000).toString();  // 签名时间戳
  var url = window.location.href.split("#")[0];
  url = encodeURIComponent(url);
  var signature = '';

  // 字典序排序
  var params = {
    jsapi_ticket: jsapi_ticket,
    noncestr: noncestr,
    timestamp: timestamp,
    url: url
  };
  var keys = Object.keys(params);
  keys.sort();

  // 拼接字符串
  var string1 = '';
  for (var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var value = params[key];
    if (string1.length === 0) {
      string1 += (key + '=' + value);
    } else {
      string1 += ('&' + key + '=' + value);
    }
  }

  // sha1签名
  var shaObj = new jsSHA("SHA-1", "TEXT");
  shaObj.update(string1);
  signature = shaObj.getHash("HEX");

3. 服务器签名错误

当服务器生成的签名和微信服务器传回的签名不一致时,也会出现“invalid signature”错误。此时需要检查一下服务器生成签名的代码是否有问题,或者与微信服务器的时间戳不一致。如果服务器与微信服务器的时间戳不同,可以使用以下方法解决:

  1. 在请求微信JS SDK时,加上config参数并传递服务器时间戳
  wx.config({
    debug: false,
    appId: '<%= appId %>',  // 公众号唯一标识
    timestamp: '<%= timestamp %>',  // 必填,生成签名的时间戳
    nonceStr: '<%= noncestr %>',  // 必填,生成签名的随机串
    signature: '<%= signature %>',  // 必填,签名,见附录1
    jsApiList: [
      // 需要使用的JS接口列表
    ]
  });

其中,appId是公众号的唯一标识,signature是通过上一步生成的签名字符串。

  1. 在签名算法中加入服务器时间戳
  var string1 = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + noncestr + '&timestamp=' + <%= timestamp %> + '&url=' + url;

示例代码

以下是一个完整的签名代码示例,包含了获取jsapi_ticket、进行签名以及调用微信JS SDK的代码:

  function wxShare(){
    var url = window.location.href.split("#")[0];
    url = encodeURIComponent(url);

    // 获取jsapi_ticket
    wx.request({
      url: '/api/getJsApiTicket',
      data: {
        url: url
      },
      success: function(res){
        var jsapi_ticket = res.data.ticket;
        var noncestr = '123456';
        var timestamp = Math.round(new Date().getTime()/1000).toString();
        var signature = '';

        // 字典序排序
        var params = {
          jsapi_ticket: jsapi_ticket,
          noncestr: noncestr,
          timestamp: timestamp,
          url: url
        };
        var keys = Object.keys(params);
        keys.sort();

        // 拼接字符串
        var string1 = '';
        for (var i = 0; i < keys.length; i++) {
          var key = keys[i];
          var value = params[key];
          if (string1.length === 0) {
            string1 += (key + '=' + value);
          } else {
            string1 += ('&' + key + '=' + value);
          }
        }

        // sha1签名
        var shaObj = new jsSHA("SHA-1", "TEXT");
        shaObj.update(string1);
        signature = shaObj.getHash("HEX");

        // 调用微信JS SDK
        wx.config({
          debug: false,
          appId: '<%= appId %>',
          timestamp: timestamp,
          nonceStr: noncestr,
          signature: signature,
          jsApiList: [
            'onMenuShareTimeline',
            'onMenuShareAppMessage',
            'onMenuShareQQ',
            'onMenuShareWeibo',
            'onMenuShareQZone'
          ]
        });

        wx.ready(function(){
          // 自定义分享内容
          wx.onMenuShareTimeline({
            title: '分享标题',
            link: '分享链接',
            imgUrl: '分享图标',
            success: function () { },
            cancel: function () { }
          });

          wx.onMenuShareAppMessage({
            title: '分享标题',
            desc: '分享描述',
            link: '分享链接',
            imgUrl: '分享图标',
            type: '',
            dataUrl: '',
            success: function () { },
            cancel: function () { }
          });

          wx.onMenuShareQQ({
            title: '分享标题',
            desc: '分享描述',
            link: '分享链接',
            imgUrl: '分享图标',
            success: function () { },
            cancel: function () { }
          });

          wx.onMenuShareWeibo({
            title: '分享标题',
            desc: '分享描述',
            link: '分享链接',
            imgUrl: '分享图标',
            success: function () { },
            cancel: function () { }
          });

          wx.onMenuShareQZone({
            title: '分享标题',
            desc: '分享描述',
            link: '分享链接',
            imgUrl: '分享图标',
            success: function () { },
            cancel: function () { }
          });
        });
      }
    });
  }

总结

微信二次分享报错invalidsignature问题是一个比较常见的问题,但是它的错误原因和解决方法却比较复杂。在进行微信二次分享时,需要对签名的算法和传递参数进行仔细的检查,以保证签名的正确性。