微信开放平台授权登录流程详解

原创 Dr Hydra 码农参上 2020-09-13 11:00

收录于合集

#微信开发技术3个

#java实战34个

最近在工作中用到了一些微信开放平台授权第三方登录,来获取用户基本信息的操作。看了一下微信给出的官方文档,写的已经很详细了,这里按照自己的步骤进行了一下总结,并附带了一些示例,方便大家理解。

微信公众号进行对第三方授权的流程可分为以下四步:

  1. 用户同意授权,获取code

  2. 通过code换取网页授权access_token

  3. 刷新access_token(非必须)

  4. 拉取用户信息(需scope为 snsapi_userinfo)

其中正常流程中,第3步为非必须步骤,仅使用在access_token失效的情况下,下面对每一个步骤进行详细介绍。

1.

获取code

官方api如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE&connect_redirect=1#wechat_redirect

当用户确认授权登录之后,会跳转到redirect_uri这个地址上,并带上微信后台生成的code参数,在前端可对code进行保存,用于后续获取access_token。

参数说明:

参数必须说明
appid公众号的唯一标识
redirect_uri授权后重定向的回调链接地址, 需使用 urlEncode 对链接进行处理
response_type返回类型,请填写code
scope应用授权作用域,snsapi_base 或 snsapi_userinfo
state重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect无论直接打开还是做页面302重定向时候,必须带此参数

后端代码示例:

@Controller@RequestMapping("wechat")public class WeChatContraller {    @GetMapping("authorization")    public String authorization() throws UnsupportedEncodingException {        return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?"                + "?appid=" + WeChatUtil.appid + "&redirect_uri="                + URLEncoder.encode(WeChatUtil.DomainName + "/index.html", "UTF-8")                + "&response_type=code&scope=snsapi_base&state=123#wechat_redirect";    }}

需要注意的是,由于授权操作安全等级较高,所以在发起授权请求时,微信会对授权链接做正则强匹配校验,如果链接的参数顺序不对,授权页面将无法正常访问。

并且应用授权作用域在为snsapi_base时,不弹出授权页面,直接跳转,只能获取用户openid;而在snsapi_userinfo时弹出授权页面,后续可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息。

2.

获取access_token

这里通过code换取一个特殊的网页授权access_token,官方api如下:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明:

参数必须说明
appid公众号的唯一标识
secret公众号的appsecret
code填写第一步获取的code参数
grant_type填写为authorization_code

后端代码示例:

@ResponseBody@GetMapping("getToken")public String getToken(@RequestParam(name = "code") String code) {    String url = "https://api.weixin.qq.com/sns/oauth2/access_token?"           + "?appid=" + WeChatUtil.appid + "&secret=" + WeChatUtil.appsecret           + "&code=" + code + "&grant_type=authorization_code";    String rs = HttpSendUtil.get(url, null);    JSONObject json = JSONObject.parseObject(rs);        if(null == json.get("errcode")){        return json.get("access_token").toString();            }else{        return "获取access_token出错";    }}

这里使用HttpClient发送get请求,从返回的JSON中取出access_token返回。正确返回的完整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用户唯一标识
scope

用户授权的作用域,使用逗号(,)分隔

错误时微信会返回JSON数据包如下(示例为code无效错误):

{  "errcode":40029,  "errmsg":"invalid code"}

需要注意code只能够使用一次,如果被消费后第二次仍然用相同code请求获取access_token则会失败。

3.

刷新access_token(非必须)

access_token拥有时效性,当超时失效后可以使用refresh_token进行刷新,需要用户重新授权。

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

参数说明:

参数必须说明
appid公众号的唯一标识
grant_type填写refresh_token
refresh_token填写通过access_token获取到的refresh_token参数

正确时返回的JSON数据包如下,与直接获取格式相同:

{   "access_token":"ACCESS_TOKEN",  "expires_in":7200,  "refresh_token":"REFRESH_TOKEN",  "openid":"OPENID",  "scope":"SCOPE" }

4.

拉取用户信息

如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。

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 英语

后端代码示例:

@ResponseBody@GetMapping("getUserInfo")public JSONObject getUserInfo(@RequestParam(name = "accessToken") String accessToken,                          @RequestParam(name = "openid") String openid) {    String url = "https://api.weixin.qq.com/sns/userinfo?"            + "?access_token=" + accessToken + "&openid=" +openid            + "&lang=zh_CN";
    String rs = HttpSendUtil.get(url, null);    JSONObject json = JSONObject.parseObject(rs);        return json;}

正确时返回的JSON数据包如下:

{     "openid":" OPENID",  "nickname": NICKNAME,  "sex":"1",  "province":"PROVINCE",  "city":"CITY",  "country":"COUNTRY",  "headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"],  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"}

返回参数说明:

参数说明
openid用户的唯一标识
nickname用户昵称
sex用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
province用户个人资料填写的省份
city

普通用户个人资料填写的城市

country国家,如中国为CN
headimgurl用户头像
privilege用户特权信息,json 数组
unionid只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段

错误时微信会返回JSON数据包如下(示例为openid无效):

{    "errcode":40003,  "errmsg":" invalid openid "}

需要注意的是,由于公众号的secret和获取到的access_token安全级别都非常高,只能保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值