微信的网页受权指的是在微信公众号中访问第三方网页时获取用户地理、我的等信息的权限。对于开发了本身的网页app应用时,获取我的的信息很是重要。上篇博客讲到了注册时能够获取用户的信息,不少人会问为何还须要网页受权这种方式去获取呢,直接从数据库中读取不就能够了吗?这样的作的缘由是服务器会话时间终究是有限的,关注后咱们设置的会话通常在半个月左右,半个月后就须要从新生成会话,而这时就须要网页受权的openid帮忙了。何况,用户的信息也是会刷新的,虽然这种状况不多发生,可是咱们至少应该确保信息是有必定的更新机制的。综上所述,因为会话机制和更新机制,咱们须要用到网页受权。网页受权机制比较繁琐,步骤颇多,开发者在开发以前须要仔细阅读开发文档,否则会走不少弯路,卤煮也是吃了这方面的亏。本篇文章就来谈一谈微信的网页受权过程。javascript
不少接口须要用到这个access_token(1),之因此在后面加个(1)是为了区分另一个网页受权access_token(2),他们之间的概念是不同的,这里讲普通的access_token(1)。access_token(1)是你调用其余接口的凭证,它是经过如下接口生成的:html
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxxxxxx&secret=xxxxxxxxx
请求以上接口会给你返回一个access_toke(1), 它有个有效时间,为7200s,一旦过了这个时间,再去使用它会报错。所以,必须创建一个刷新机制。个人办法是在服务器启动的时候去生成一次token,把它存入数据库,而后创建一个定时器,每隔7200s就再次请求接口获取新的token存入数据库,这样能够保证服务器运行的阶段,数据库中的表最后一条记录的是最新的token。每次须要用到这个token时候就先去表中查最后一条记录。若是只是临时使用,彻底能够手动在浏览器调用接口生成toke,或者用postman工具。java
/*启动时 定时获取刷新微信的token 而且存入数据库*/ (function() { request(config('wechat').refreshUrl, function(err, res, body) { body = JSON.parse(body); var accessSql = 'INSERT INTO `access_token` (token) VALUES ("' + body.access_token + '")'; Query.call(res, accessSql, function() { setTimeout(arguments.callee, config('wechat').refreshTime * 1000); }); }); })();
建立网页菜单使用以下接口:node
https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
须要注意,菜单建立的接口只支持post发送的格式,所以,你的接口必须发送post请求。因为菜单不是一个常常须要变更的东西,卤煮建立菜单使用的是人工手动的方式进行建立。用的是postman发送特定数据到接口建立菜单。git
发送的数据如图所示,多级菜单只须要数据嵌套就行了。有个key值,我在上一篇文章中提到过,点击该菜单时发送的xml包中接收到这个值。github
因为在关注的时候咱们已经获取到用户的openid和用户信息(见前一篇张),所以,须要只须要用户的会话结束,咱们才须要中心获取openid来创建会话。获取openid第一步,会话过时后服务器后台跳转到下面地址web
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
appid不解释,redirect_uri即重定向后回掉的地址,通常写本身后台的接口地址。response_type写”code“就行了,scope指的是是否须要显示一个须要用户确认的界面以下所示:sql
若是是不须要直接填写snsapi_base获取openid,须要用户确认则获取全部信息请填写snsapi_userinfo,咱们这里只须要openid,其余信息都在关注的时候存到数据库里面了。最后一个写死来“wechat_redirect”。用户点击确认登陆或者在不须要点击确认的状况下过个几秒钟,微信会将地址重定向到你填写的url上,而且附带了两个参数redirect_uri?code=CODE&state=STATE。code是你换取access_toke(2)的票据,state表述状态,不须要关注。在你的回掉接口里面获取到code,而后将code做为参数post或者get请求如下链接,获取access_token(2):数据库
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
该请求会返回一段json数据,里面就包含了咱们须要的openid。json
{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
接下来,以此openid为凭据,调用如下接口获取用户最新的信息:
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
access_token指的是access_toke(2),openid是上面的获取的openid,lang指的是数据的语言。默认为中文。你会得到如下json数据:
将它们更新到原有的表中(视状况而定,若是你以为用户不常常更改本身的信息能够设置更新时间一个月或者半年),而后创建新的会话,至此,一个网页受权过程就结束了。
在网页受权的过程当中,也会遇到access_token(2)过时的问题,所以,咱们也必须为它创建一个刷新机制。(微信搞得真的是很麻烦)。
首先,在使用access_toke(2)以前,咱们先验证这个toke是否有效,请求如下接口进行验证:
https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID
错误的时候会返回以下数据
{ "errcode":40003,"errmsg":"invalid openid"}
这时候,咱们就须要刷新这个token了,如下是刷新的接口:
https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
这里有一个refresh_toke指的是你去请求access_token(2)的接口返回的数据中的一个值。grant_tyoe直接填写为”refresh_token“。这样就刷新了一个token(2)。该token只是在网页受权时使用,能够不须要储存在表中,临时使用便可。
我在这里使用的是一个第三方开发的模块,来处理一整套的token维护流程,它叫wechat-oauth。使用起来比较方便,源码也很好调试,本身稍微改了改。后面会贴出github的地址来,这个系列有不少,包括自动回复,图文消息等,你们有兴趣本身下载使用。固然,不嫌麻烦能够本身写。
var user = req.session['user'] || req.query._user; //未登陆的状况或者登陆失效 网页调试无需走微信通道 if (user === undefined && !config('app').webDebug) { var wxconfig = config('wechat');
//使用模块 var client = new OAuth(wxconfig.appId, wxconfig.appSecret); var url = client.getAuthorizeURL(config('app').url + wxconfig.callbackUrl, 'snsapi_userinfo');
//后台跳转 res.redirect(url); return; } fn.call(null, req, res, next);
获取code而后发送请求获取opeind
var client = new OAuth(wxConfig.appId, wxConfig.appSecret);
//................
//获取微信返回的网页TOKEN 该接口为回掉接口 app.get('/login/getpagetokenkey', function(req, res, next) { var code = req.query.code; //微信返回的code值,做为下一步的票券 //获取票券 client.getAccessToken(code, function(err, result) { var openid = result.data.openid; //查询数据库有没有该用户 var sql = 'SELECT * FROM `wechat` WHERE openid= "' + openid + '"'; Query.call(res, sql, function(err, rows, filed) { if(rows.length) {
//从新创建会话跳转到主界面 setSession(openid, res, req); } }); }); return; });
在获取用户信息的时候的时候千万不要调试断点nodejs,由于微信会在发送给你的接口后设置一个等待时限,大概是6s,一旦过了这时限没有返回数据,而此时你若是在调试代码的话,很容易就会超过等待时间,接着微信就会再次发送一次请求给你的接口,这样会致使程序报错或者至少让你处理两次信息。卤煮吃了大亏,调了一个下午,接近奔溃的边缘。但愿诸位要牢记此点,切记在获取受权的时候不要调试nodejs。