微信的网页授权指的是在微信公众号中访问第三方网页时获取用户地理、个人等信息的权限。对于开发了自己的网页app应用时,获取个人的信息非常重要。上篇博客讲到了注册时可以获取用户的信息,很多人会问为什么还需要网页授权这种方式去获取呢,直接从数据库中读取不就可以了吗?这样的做的原因是服务器会话时间终究是有限的,关注后我们设置的会话一般在半个月左右,半个月后就需要重新生成会话,而这时就需要网页授权的openid帮忙了。况且,用户的信息也是会刷新的,虽然这种情况很少发生,但是我们至少应该确保信息是有一定的更新机制的。综上所述,由于会话机制和更新机制,我们需要用到网页授权。网页授权机制比较繁琐,步骤颇多,开发者在开发之前需要仔细阅读开发文档,不然会走很多弯路,卤煮也是吃了这方面的亏。本篇文章就来谈一谈微信的网页授权过程。

access_token(1)更新机制

很多接口需要用到这个access_token(1),之所以在后面加个(1)是为了区分另外一个网页授权access_token(2),他们之间的概念是不一样的,这里讲普通的access_token(1)。access_token(1)是你调用其他接口的凭证,它是通过以下接口生成的:

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工具。

/*启动时 定时获取刷新微信的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);
});
});
})();

创建网页菜单

创建网页菜单使用如下接口:

 https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

需要注意,菜单创建的接口只支持post发送的格式,因此,你的接口必须发送post请求。由于菜单不是一个经常需要变动的东西,卤煮创建菜单使用的是人工手动的方式进行创建。用的是postman发送特定数据到接口创建菜单。

发送的数据如图所示,多级菜单只需要数据嵌套就好了。有个key值,我在上一篇文章中提到过,点击该菜单时发送的xml包中接收到这个值。

网页授权获取用户openid

由于在关注的时候我们已经获取到用户的openid和用户信息(见前一篇张),因此,需要只需要用户的会话结束,我们才需要中心获取openid来建立会话。获取openid第一步,会话过期后服务器后台跳转到下面地址

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指的是是否需要显示一个需要用户确认的界面如下所示:

如果是不需要直接填写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。

{
"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_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。

参考资料

wechat-oauth NodeJS开发微信交互模块

微信公众号开发官方文档

NodeJs 开发微信公众号(四)微信网页授权的更多相关文章

  1. 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...

  2. C#版微信公众号支付|微信H5支付|微信扫码支付问题汇总及解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存.代码在文章结尾处,有需要的 ...

  3. JAVA版开源微信管家—JeeWx捷微3.2版本发布,支持微信公众号,微信企业号,支付窗、小程序

    JeeWx捷微3.2微信企业号升级版本发布^_^ JeeWx捷微V3.2——多触点管理平台(支持微信公众号,微信企业号,支付窗.小程序)   JeeWx捷微V3.2.0版本引入了更多新特性,支持微信公 ...

  4. JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗——JAVA版开源微信管家

    支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1——多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗)   JeeWx捷微V3.1.0版本紧跟微信小程序更新,在 ...

  5. JAVA版开源微信管家—JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗

    支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1--多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗) JeeWx捷微V3.1.0版本紧跟微信小程序更新,在原有 ...

  6. JAVA开源微信管家平台——JeeWx捷微V3.3版本发布(支持微信公众号,微信企业号,支付窗)

    JeeWx捷微V3.3版本紧跟微信小程序更新,在原有多触点版本基础上,引入了更多的新亮点:支持微信公众号.微信企业号.支付宝服务窗等多触点开发:采用微服务框架实现,可插拔可集成,轻量级开发:对小程序的 ...

  7. CabloyJS的微信API对接模块:当前支持微信公众号和微信小程序

    Cabloy-微信是什么 Cabloy-微信是基于CabloyJS全栈业务开发框架开发的微信接口模块,当前整合了微信公众号和微信小程序的接口,达到开箱即用的使用效果.在Cabloy-微信的基础上,可以 ...

  8. 微信公众号开发(5)---使用开源组件开发公众号OAuth2.0网页授权授权登录

    搞清微信公众号授权登录的步骤步骤,我们的开发就完成了一大步 献上github 地址: https://github.com/Wechat-Group/weixin-java-tools/wiki/MP ...

  9. 14-网页,网站,微信公众号基础入门(网页版MQTT,小试牛刀)

    https://www.cnblogs.com/yangfengwu/p/11192639.html 抱歉哈...最近由于做板子,,教程的进度落下了... 这些天总共做了还几块板子 首先对当前这个教程 ...

  10. 微信公众号支付JSAPI网页,total_fee错误不正确,header重定向参数丢失,无法获取订单号和金额解决

    微信公众号支付官方demo错误, 公众号支付只能用在微信里,也就是微信内部浏览器. 1.到WxPayHubHelper.php文件 JsApi_pub()类下createOauthUrlForCode ...

随机推荐

  1. Tomcat shutdown执行后无法退出进程问题排查及解决

    问题定位及排查 上周无意中调试程序在Linux上ps -ef|grep tomcat发现有许多tomcat的进程,当时因为没有影响系统运行就没当回事.而且我内心总觉得这可能是tomcat像nginx一 ...

  2. Socket聊天程序——Common

    写在前面: 上一篇记录了Socket聊天程序的客户端设计,为了记录的完整性,这里还是将Socket聊天的最后一个模块--Common模块记录一下.Common的设计如下: 功能说明: Common模块 ...

  3. HTML5 progress和meter控件

    在HTML5中,新增了progress和meter控件.progress控件为进度条控件,可表示任务的进度,如Windows系统中软件的安装.文件的复制等场景的进度.meter控件为计量条控件,表示某 ...

  4. Xamarin+Prism小试牛刀:定制跨平台Outlook邮箱应用

    通过本文你将学会如下内容: 1,如何使用Xamarin开发跨平台(Windows,Android,iOS)应用. 2,如何使用微软的登录界面登入Microsoft账号. 3,如何使用Outlook邮箱 ...

  5. javascript动画系列第一篇——模拟拖拽

    × 目录 [1]原理介绍 [2]代码实现 [3]代码优化[4]拖拽冲突[5]IE兼容 前面的话 从本文开始,介绍javascript动画系列.javascript本身是具有原生拖放功能的,但是由于兼容 ...

  6. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  7. Linux命令【第一篇】

    1.创建一个目录/data 记忆方法:英文make directorys缩写后就是mkdir. 命令: mkdir /data 或 cd /;mkdir data #提示:使用分号可以在一行内分割两个 ...

  8. cmd窗口编码设置

    问题描述:不知道误操作了什么,导致cmd窗口的鼠标显示位置出现错位,如下: 现在要将鼠标位置调整回来. 使用工具:cmd. 操作步骤: 1.查看cmd属性可以看到 可以看到是UTF-8编码格式的,我们 ...

  9. 深入理解Spring MVC

    如何让一个普通类成为Controller? 方案一:实现接口Controller 解析:handleRequest(request,response) 方案二:继承AbstractController ...

  10. 学习笔记:Maven构造版本号的方法解决浏览器缓存问题

    需要解决的问题 在做WEB系统开发时,为了提高性能会利用浏览器的缓存功能,其实即使不显式的申明缓存,现代的浏览器都会对静态文件(js.css.图片之类)缓存.但也正因为这个问题导致一个问题,就是资源的 ...