找回密码
 立即注册

QQ登录

只需一步,快速开始

微信公众号开发资源

关注:848

所属分类: 微信开发 微信公众号开发资源

本版块为微信公众号开发教程与公众号开发相关技术分享板块,技术提问请到其他对应的问答板块发帖:)

[公众号开发博客] 微信jssdk使用中遇到invalid signature签名错误,解决方法

[复制链接]
查看: 4931|回复: 7
最佳答案
0 

6

主题

32

帖子

175

积分

新人求带

积分
175
 楼主| 发表于 2016-5-31 14:54:37 | 显示全部楼层 |阅读模式
一、问题说明

如果出现 invalid signature,首先可以确定的是你的签名算法有问题。

建议:首先查看微信官方网站给出的解决方案,链接为 http://mp.weixin.qq.com/wiki/7/a ... f8dd9148dd613f.html

invalid signature签名错误。建议按如下顺序检查:

确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。也就是你自己后台生成签名要和微信校验算法生成的签名一致才可以(可能大小写不同)。

注意:

签名生成规则如下:

参与签名的字段包括有效的 jsapi_ticket(获取方式详见微信 JSSDK 文档), noncestr (随机字符串,由开发者随机生成),timestamp (由开发者生成的当前时间戳), url(当前网页的URL,不包含#及其后面部分。注意:对于没有只有域名没有 path 的 URL ,浏览器会自动加上 / 作为 path,如打开 http://qq.com 则获取到的 URL 为 http://qq.com/)。

特别注意:你在利用参数生成签名的时候,要对所有待签名参数按照字段名的 ASCII 码从小到大排序(字典序)后,使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串 string1。这里需要注意的是所有参数名均为小写字符。

我的最开始的错误就是没有注意到生成签名的那几个参数要按照key=value的样式连接成一个字符串,然后在sha1加密生成。
  1. /****Java写的参数拼接算法***/
  2. String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
  3.                 "timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl };
  4. Arrays.sort(paramArr);
  5. // 将排序后的结果拼接成一个字符串
  6. String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
  7.                 .concat("&"+paramArr[3]);
  8. System.out.println("拼接之后的content为:"+content);
复制代码

确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。

确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。

确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。

确保一定缓存access_token和jsapi_ticket。

确保你获取用来签名的url是动态生成的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。

错误2、每次后台网页更新之后,微信访问效果没有出来。

问题:手机端,网页缓冲导致。

解决方案:重启手机,再试一下。

错误3、微信分享接口,可以在自己的网页上面自定义一个按钮,当用户点击的时候完成分享。

问题:我最开始也是这样想的,后来发现,原来不是这样的,只有当你用微信客户端打开,在最上面右边的 “分享到朋友圈”按钮按的时候效果才会出来。

错误4、微信图像接口 permission denied

首先查看微信给出的错误说明:该公众号没有权限使用这个JSAPI(部分接口需要认证之后才能使用)。

说明:只要通过了公众号认证,都不会有问题。

检查对象:如果出现这个说明程序上基本上不会有问题 微信后台已经返回了数据。

第一、要检查 你的config 文件中相应的 jsapilist  是否包含了该接口哟。
  1. /***用户打开页面的时候就加载**/
  2. $(document).ready(function(){
  3. initPage();
  4. });
  5. function initPage() {
  6. //alert(window.location.href);/***用于获得当前连接url用**/
  7. /***用户点击分享到微信圈后加载接口接口*******/
  8. $.post("http://******",{"url":window.location.href},function(data,status){
  9. data=eval("("+data+")");
  10. wx.config({
  11.           debug: false,
  12.           appId: 'wxa7a1ad4cc5116437',
  13.           timestamp:data.timestamp,
  14.           nonceStr:data.noncestr,
  15.           signature:data.signature,
  16.           jsApiList: [
  17.           'checkJsApi',
  18.           'onMenuShareTimeline',
  19.           'hideOptionMenu',
  20.           ]
  21.       });
  22. wx.ready(function(){
  23.     wx.hideOptionMenu();/***隐藏分享菜单****/
  24. });       
  25. });

  26. };
复制代码

说明:这一块我是通过写一个方法,然后用户用AJax 的post 获得这样的请求,然后参数是URL。

二、实例说明

获得jsticket
  1. public static String getjsTicket(String accesstoken) {
  2.         String appid = "XXXXXXX";
  3.         String appsecret = "XXXX";
  4.         String result = "";
  5.         String url = js_ticketurl.replace("ACCESS_TOKEN", accesstoken);
  6.         System.out.println("查看js_url:" + url);
  7.         // 调用接口返回json字符串
  8.         JSONObject jsonObject = httpRequest(url, "GET", "");
  9.         System.out.println("查看红的js_ticket:" + jsonObject.toString());
  10.         if (null != jsonObject) {
  11.             result = jsonObject.getString("ticket");// 获得ticket
  12.             System.out.println("ticket为:" + result);
  13.         }
  14.         return result;
  15.     }
复制代码

获得signature
  1. // 获得js signature
  2.     public static String getSignature(String jsapi_ticket, String timestamp,
  3.             String nonce, String jsurl) throws IOException {
  4.         /****
  5.          * 对 jsapi_ticket、 timestamp 和 nonce 按字典排序 对所有待签名参数按照字段名的 ASCII
  6.          * 码从小到大排序(字典序)后,使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串
  7.          * string1。这里需要注意的是所有参数名均为小写字符。 接下来对 string1 作 sha1 加密,字段名和字段值都采用原始值,不进行
  8.          * URL 转义。即 signature=sha1(string1)。
  9.          * **如果没有按照生成的key1=value&key2=value拼接的话会报错
  10.          */
  11.         String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,
  12.                 "timestamp=" + timestamp, "noncestr=" + nonce, "url=" + jsurl };
  13.         Arrays.sort(paramArr);
  14.         // 将排序后的结果拼接成一个字符串
  15.         String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2])
  16.                 .concat("&"+paramArr[3]);
  17.         System.out.println("拼接之后的content为:"+content);
  18.         String gensignature = null;
  19.         try {
  20.             MessageDigest md = MessageDigest.getInstance("SHA-1");
  21.             // 对拼接后的字符串进行 sha1 加密
  22.             byte[] digest = md.digest(content.toString().getBytes());
  23.             gensignature = byteToStr(digest);
  24.         } catch (NoSuchAlgorithmException e) {
  25.             e.printStackTrace();
  26.         }
  27.         // 将 sha1 加密后的字符串与 signature 进行对比
  28.         if (gensignature != null) {
  29.             return gensignature;// 返回signature
  30.         } else {
  31.             return "false";
  32.         }
  33.         // return (String) (ciphertext != null ? ciphertext: false);
  34.     }

  35.     /**
  36.      * 将字节数组转换为十六进制字符串
  37.      *
  38.      * @param byteArray
  39.      * @return
  40.      */
  41.     private static String byteToStr(byte[] byteArray) {
  42.         String strDigest = "";
  43.         for (int i = 0; i < byteArray.length; i++) {
  44.             strDigest += byteToHexStr(byteArray[i]);
  45.         }
  46.         return strDigest;
  47.     }

  48.     /**
  49.      * 将字节转换为十六进制字符串
  50.      *
  51.      * @param mByte
  52.      * @return
  53.      */
  54.     private static String byteToHexStr(byte mByte) {
  55.         char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
  56.                 'B', 'C', 'D', 'E', 'F' };
  57.         char[] tempArr = new char[2];
  58.         tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
  59.         tempArr[1] = Digit[mByte & 0X0F];
  60.         String s = new String(tempArr);
  61.         return s;
  62.     }
复制代码

回复

使用道具 举报

最佳答案
0 

0

主题

4682

帖子

50

积分

新人求带

积分
50
发表于 2018-5-7 22:02:11 | 显示全部楼层
真真的正需要这个~
回复 支持 反对

使用道具 举报

最佳答案
0 

0

主题

4682

帖子

50

积分

新人求带

积分
50
发表于 2018-5-7 22:08:52 | 显示全部楼层
我擦  不能便宜点?
回复 支持 反对

使用道具 举报

最佳答案
0 

0

主题

4682

帖子

50

积分

新人求带

积分
50
发表于 2018-5-7 22:11:45 | 显示全部楼层
看看,谢谢分享
回复 支持 反对

使用道具 举报

最佳答案
0 

0

主题

4682

帖子

50

积分

新人求带

积分
50
发表于 2018-5-7 23:33:25 | 显示全部楼层
好不好啊,看看如何了
回复 支持 反对

使用道具 举报

最佳答案
0 

0

主题

4682

帖子

50

积分

新人求带

积分
50
发表于 2018-5-7 23:58:12 | 显示全部楼层
好东西,亲测可用,教程也很详细
回复 支持 反对

使用道具 举报

最佳答案
0 

0

主题

4682

帖子

50

积分

新人求带

积分
50
发表于 2018-5-8 00:12:23 | 显示全部楼层
这个要学习一下
回复 支持 反对

使用道具 举报

最佳答案
0 

0

主题

1

帖子

30

积分

等待验证会员

积分
30
发表于 2019-6-1 09:35:36 | 显示全部楼层
32225669_201905221116170040639541.png

32225669_201905221302110589488984.png

32225669_201905221330350530263838.png


32225669_201905221447040592896421.png


32225669_201905221504350818218293.png

32225669_201905310751320431286709.png

32225669_201906010714180992903932.jpg


32225669_201905221447040592896421.png
32225669_201906010714180992903932.jpg
32225669_201905221116170040639541.png
32225669_201905221447040592896421.png
32225669_201906010714180992903932.jpg
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



www.henkuai.com—微信开发者的分享交流平台,专注微信开发生态。

天津市滨海新区
中新生态城中成大道生态建设公寓9号楼3层301

微信公众号

广告推广
QQ:805874290

市场合作
zhongcong@henkuai.com