Wechat login authorization(OAuth2.0)
一、前言
昨天小组开了个会,让我今天实现一个微信网页授权
的功能,可以让用户在授权之后无需再次登录既可进入用户授权界面。在这之前我也从没接触过微信公众号开发之类的,也不知道公众号后台是啥样子的,自己所在的小组也没有自己的认证公众号,就在这种情况下用一天的实现微信网页授权
的功能。
二、准备工作
1.一个怎样的项目
上面也说了我所在的小组没有自己的认证公众号(普通申请的公众号是不会开放高级接口的)也就说自己申请的公众号是无法实现这类功能的。还有一点是我们所要实现的这个微信网页授权
并不是针对某个公众号的,而是可以让任意公众号可以绑定我们的程序,自己的公众号并不需要实现微信网页授权
这个功能,就可以使用授权功能。
2.技术调研
了解了上面的需求,自然是针对所要用到的技术进行调研了,主要用到就是微信的一些接口,所以我们先到微信公众平台技术文档查找我们需要的资料。主要如下
1.回调域名
看来上面的示意图我们知道,这个回调域名是在给我们请求网页授权返回code的时候用的。所以开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。
请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头; 另外授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权
2.获取授权
在这里官方提供了两种授权方式"snsapi_base"和"snsapi_userinfo",他们都可以获取用户基本信息,但是既然提供两种方式肯定有不一样的地方。下面就介绍一下
- 相同点:都可以获取用户的基本信息
- 不同点:"snsapi_userinfo"发起的网页授权,需要用户手动同意才可以继续(如果用户已关注公众号则为静默模式,像snsapi_base一样不会弹出提示),而"snsapi_base"授权不需要,比前者少了①②两步;"snsapi_userinfo"授权获取用户基本信息不需要关注,而"snsapi_base"授权需要关注才可获取到
注意:上面有一个加粗标识的地方,因为我在这里在了一个跟头。下面为"snsapi_base"未关注公众号时返回的错误提示信息。
{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: Ftu8IA0999s106 ]"}
第一步:获取code
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_url | 是 | 授权后重定向的回调链接地址,请使用urlEncode对链接进行处理 |
response_type | 是 | 返回类型,请填写code |
scope | 是 | 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) |
state | 否 | 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 |
#wechat_redirect | 是 | 无论直接打开还是做页面302重定向时候,必须带此参数 |
下图为scope等于snsapi_userinfo时的授权页面:
如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。
code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
第二步:通过code换取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 公众号的唯一标识 |
secret | 是 | 公众号的appsecret |
code | 是 | 填写第一步获取的code参数 |
scope | 是 | 填写为authorization_code |
返回说明 - 正确时返回的JSON数据包如下:
{ "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE" }
参数 | 描述 |
---|---|
access_token | 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 |
expires_in | access_token接口调用凭证超时时间,单位(秒) |
refresh_token | 用户刷新access_token |
openid | 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID |
scope | 用户授权的作用域,使用逗号(,)分隔 |
错误时微信会返回JSON数据包如下(示例为Code无效错误):
{"errcode":40029,"errmsg":"invalid code"}
第三步:拉取用户信息
如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。如果网页授权作用域为snsapi_base需要关注后才能拉取用户信息
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
参数说明
参数 | 描述 |
---|---|
access_token | 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 |
openid | 用户的唯一标识 |
lang | 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语 |
返回说明 - 正确时返回的JSON数据包如下:
{
"openid":"OPENID",
"nickname":"NICKNAME",
"sex":"1",
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl":"http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46","privilege":[ "PRIVILEGE1" "PRIVILEGE2"],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
参数说明
参数 | 描述 |
---|---|
openid | 用户的唯一标识 |
nickname | 用户昵称 |
sex | 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知 |
province | 用户个人资料填写的省份 |
city | 普通用户个人资料填写的城市 |
country | 国家,如中国为CN |
headimgurl | 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。 |
privilege | 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom) |
unionid | 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 |
错误时微信会返回JSON数据包如下(示例为openid无效):
{"errcode":40003,"errmsg":" invalid openid "}
附录
另外还有"刷新access_token"、"检验授权凭证(access_token)"接口这里就不作说明了,需要了解的可以去查阅官方文档。
3.开发
上面我们已经了大概的流程了,自己有认证公众号的人自己就可以尝试开发了,我这边没有公众号所以是从隔壁组借来的一个“appid”然后从他们那儿代理再跳到我这边。什么意思呢?就是回调域名调用的是他们那边的接口,同时我也把自己这边写的一个接口(用来接收OpenId和access_token)带过去,等他那边获取到OpenId和access_token在通过刚才传的那个接口返回给我。这样我这边就得到OpenId和access_token了,我也在这边获取用户基本信息了。
三、常见问题
1.获取不到用户信息 答:你看你是用的是"snsapi_base"方式授权还是"snsapi_userinfo"方式授权,前者需要关注才能获取到用户信息,而后者无需关注也可以获取;也有可能是access_token过期导致获取失败,具体根据返回提示信息判断。
2.关于代理的问题 答:所谓的代理就是回调域名调用的是他们那边的接口,同时我也把自己这边写的一个接口(用来接收OpenId和access_token)带过去,等他那边获取到OpenId和access_token在通过刚才传的那个接口返回给我。这样我这边就得到OpenId和access_token了,我也在这边获取用户基本信息了。
3.微信有缓存怎么办 答:浏览器都有缓存,但是微信清理起来挺麻烦的,我们该怎么解决这类问题?这个和PC中处理的方式一样可以使用时间戳,或者加版本号,通过版本号判断文件是重新拉取还是从缓存中获取
4.两种授权方式有什么不同 答:"snsapi_userinfo"发起的网页授权,需要用户手动同意才可以继续(如果用户已关注公众号则为静默模式,像snsapi_base一样不会弹出提示),而"snsapi_base"授权不需要;"snsapi_userinfo"授权获取用户基本信息不需要关注,而"snsapi_base"授权需要关注才可获取到
上面大概就是我实现"微信网页授权"功能的大致流程,欢迎大家探讨指点。
参考:微信公众平台技术文档