微信公众号之:JSSDK接入以及invalid signature等常见错误问题

最近在搞微信公众号开发,进行到网页开发部分被坑了一天,最坑的问题就是invalid signature,而网上大部分解答这个问题的都没有说清楚,都直接丢文档。博主认为这样很很差。本文是博主结合自身遇到的问题所写,整个流程跟问题都很详细,虽然排版可能有点很差。可是绝对对遇到相似问题的朋友有所帮助。请认真看下去javascript

1、绑定JS接口安全域名

生产号绑定方法:登陆微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
测试号绑定方法:进入测试号管理页面,找到JS接口安全域名项绑定
JS接口安全域名官方说法是:开发者可在该域名下调用微信开放的JS接口
域名格式:若是你的项目域名是http://test.domain.com,那么JS接口安全域名为test.domain.com。切记!
域名绑定失败或者域名不存在会报错误:invalid url domain前端

2、引入微信js文件

引入方法:在须要调用JS接口的页面引入JS文件,用script标签引入便可
JS文件路径:http://res.wx.qq.com/open/js/jweixin-1.2.0.js(支持https)java

3、经过wx.config接口注入权限验证

一、每一个须要使用jssdk的页面都要使用config接口注入配置信息,wx.config调用方法以下:node

 

  1.  
    wx.config({
  2.  
    debug: true, // 开启调试模式,调用的全部api的返回值会在客户端alert出来,若要查看传入的参数,能够在pc端打开,参数信息会经过log打出,仅在pc端时才会打印。
  3.  
    appId: '', // 必填,公众号的惟一标识
  4.  
    timestamp: , // 必填,生成签名的时间戳,精确到秒
  5.  
    nonceStr: '', // 必填,生成签名的随机串
  6.  
    signature: '',// 必填,签名
  7.  
    jsApiList: [] // 必填,须要使用的JS接口列表,例如:['chooseImage','previewImage','uploadImage']
  8.  
    })

其中appId,timestamp,nonceStr,signature必须从后台获取jquery

 

4、后台生成并返回前端所需参数

一、jsapi_ticketajax

jsapi_ticket是公众号用于调用js接口的临时票据。有效期7200秒,跟公众号普通access_token同样,必须全局缓存起来,由于这个ticket获取次数有限,超过次数将没法使用。建议设置缓存时间为7198秒,由于当请求微信端生成jsapi_ticket返回给后台保存这个动做须要时间,若是设置7200秒,实际上最后一两秒时,缓存里面还存在,但实际在微信那边已通过期了,再拿这个ticket会出错。生成jsapi_ticket以下:算法

(1)获取普通access_token(GET请求): api

 

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

 

(2)用第一步获取的access_token使用GET请求获取jsapi_ticket浏览器

 

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi 

正确获取信息以下:缓存

  1.  
    {
  2.  
    "errcode":0,
  3.  
    "errmsg":"ok",
  4.  
    "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  5.  
    "expires_in":7200
  6.  
    }

二、生成签名(signature)

 

签名规则:一、参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分)。二、对全部待签名参数按照字段名的ASCII 码从小到大排序(字典序,sort()便可)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串(string)。三、使用sha1加密拼接成的字符串string。注意:字段名和字段值都要使用原值,不要进行url转义

参与的字段示例:

  1.  
    noncestr=Wm3WZYTPz0wzccnW
  2.  
    jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
  3.  
    timestamp= 1414587457
  4.  
    url=http: //mp.weixin.qq.com?params=value

拼接完成的字符串:

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value

使用sha1加密后的signature:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

三、签名生成完后将appId、timestamp、nonceStr、signature一块儿返回到前端。格式示例:

 

  1.  
    {
  2.  
    appId:appId,
  3.  
    timestamp:timestamp,
  4.  
    nonceStr: noncestr,
  5.  
    signature: signature
  6.  
    }

前端拿到值后,写入到wx.config中相应字段便可

注意:

一、前端wx.config配置中的nonceStr字段名称的's'是大写。可是后台生成签名的noncestr字段的‘s’是小写,千万要注意,博主在这里浪费了很多时间。囧囧

二、时间戳(timestamp)值要记住精确到秒,不是毫秒。

三、生成签名的url(使用jssdk的页面地址,这个页面地址能够在浏览器访问),包含“?”号后面的全部参数,不包含“#”号后面的值。

若是是静默受权或者受权页面赞成受权后跳转到的页面,页面路径会添加两个参数:code和state。

即受权后跳转页面为http://redirect.page.com,则完整路径为

http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE。

那么生成签名的url必须为受权后跳转页面的完整路径。前端获取这个路径:location.href.split('#')[0]

注意注意:这里有个大坑。。若是前端使用ajax(使用jquery)获取wx.config配置所需的几个参数的值,能够这样作:

  1.  
    $.ajax({
  2.  
    url: 'http://backend.com?fullUrl=' + location.href.split('#')[0], //这里的参数fullUrl是当前页面的完整url(除去#后面部分)
  3.  
    type: 'GET',
  4.  
    success: function(res) {
  5.  
    //操做后台返回值
  6.  
    }
  7.  
    })

 

后台要怎么操做前端传过来的query值呢?你们确定一眼看出来 获取query中的fullUrl字段不就好了。

博主也是这么作的,请看博主后台代码(使用nodejs的koa框架)

  1.  
    let query = this.request.query;//获取查询字符串
  2.  
    let fullUrl = query.fullUrl;//获取查询字符串中的fullUrl字段

 

怎么样,有没有看出什么不对劲的地方?没有?

博主把全部后续的获取access_token、jsapi_ticket、计算签名、返回值到前端、前端wx.config配置好这些全部操做作完,信心满满的开始用测试号访问页面。结果直接弹出config: invalid signature(开启debug模式)。WTF ???

固然,搞这一行早就作好了遇到问题的心理准备。。。。开始排错呗。。

首先在后台将获取access_token、jsapi_ticket、计算签名的参数字典序排序后的字符串、sha1加密后的字符串所有console.log出来。

发现,没有错误的地方。那行,看来有多是我代码那个地方写错了,或者签名算错了?

到微信在线接口调试把刚刚打印的计算签名的几个参数分别填好。生成。。。发现跟个人代码生成的是同样的。

结果博主是各类排错,各类百度,各类google。结果仍是config: invalid signature...................................此处省略博主内心一万句话

又这样过了一个多小时,无果。。。。。。博主一脸颓废的到茶水间泡了杯咖啡。。提提神。。又回到了岗位,准备从头开始跑一遍再仔细看看。

从前端请求获取签名接口开始,博主打印了query的值。。也就是let query  = this.request.query的值。。结果发现。query值为:

  1.  
    {
  2.  
    fullUrl: 'http://redirect.page.com?code=kdijafdhjaikeiu20kaiela',
  3.  
    state: 'STATE'
  4.  
    }

 

好吧,问题在这里,有没有人早就看出来的?前面说过,微信网页受权后跳转的页面完整路径为

http://redirect.page.com?code=kdijafdhjaikeiu20kaiela&state=STATE

有没有注意路径最后面的'&state=STATE'。当咱们把这个完整路径当作查询字符串传到后台的时候,由于没有对这个路径进行encodeURIComponent.因此后台将'&state=STATE'单独当作了一个查询字符串参数,问题点在这里。。

后来查看公众号文档发现'附录5-常见错误及解决方法'第六条有说明

问题解决

使用encodeURIComponent(location.href.split('#')[0])便可

5、调用接口

wx.config配置完成后会执行wx.ready方法,全部接口必需要在config返回结果以后操做。config是一个客户端的异步操做,因此若是须要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则能够直接调用,不须要放在ready函数中。当前页面要使用的接口,要写入到config配置中的jsApiList中

一、拍照或从手机相册中选图接口

  1.  
    document.getElementById('chooseImage').onclick = function(){
  2.  
    wx.chooseImage({
  3.  
    count: 1, // 默认9
  4.  
    sizeType: [ 'original', 'compressed'], // 能够指定是原图仍是压缩图,默认两者都有
  5.  
    sourceType: [ 'album', 'camera'], // 能够指定来源是相册仍是相机,默认两者都有
  6.  
    success: function (res) {
  7.  
    var localIds = res.localIds; // 返回选定照片的本地ID列表,localId能够做为img标签的src属性显示图片
  8.  
    }
  9.  
    });
  10.  
    }

 

6、常见问题

一、invalid url domain:

js接口安全域名错误。能够看看第一项

二、invalid signature:

要么是jsapi_ticket错误,要么是签名算法问题,要么是算法的参数有问题,注意noncestr中的's'是小写的。若是都是对的。那就是前端传的url有问题了。。。好好检查一下,不要像博主同样啊。。。。

三、permission denied:

这个问题通常是没有接口权限的问题,有的接口是要认证以后才可使用,固然,测试号不会有这个问题

 

转:

https://blog.csdn.net/u011225099/article/details/76460197

相关文章
相关标签/搜索