由于后期需要在微信里跳转网页将用户的openid以及其他信息和学工号绑定,所以需要在通过网页授权来获取用户的基本信息.还有另一种获取用户信息的接口是直接获取的,就无法和业务进行对接了.
获取code
获取code的网址为
1
|
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
|
这里的redirect_uri的就是自己的业务页面.在用户主动同意授权后,页面将跳转至 redirect_uri/?code=CODE&state=STATE.这个state参数貌似有点意思,我曾经想过用这个参数来传递学工号来着,然后在跳转后的页面绑定.但是后来又改成了先用学工号登录自己的网站,把学工号存在cookie里,在跳转后读取cookie然后绑定.这样顺便也利用cookie实现了一下自动登录之类的功能.
好了,接下来新建一个OAuth2Servlet类,来处理网页的参数和跳转自己的页面.
1
2
3
4
5
6
7
8
|
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse respons(
throws ServletException,IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 用户同意授权后,能获取到code
String code = request.getParameter("code");
}
|
所以可以向而知了,这个OAuth2Servlet就是我们的redirect_uri,需要在测试号里设置一下网址(测试号可以用ip),以确保可以访问.
用code 获取access_token
这里也要用到之前写的doGet()方法,请求的Http地址为
1
|
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
|
这里将处理网页的实现,放在一个新的WebUtil类中继承WechatUtil,便可以直接用父类的doGet(),doPost()和一些字段了.具体代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public OAuth2AccessToken getOAuth2AccessToken(String code){
OAuth2AccessToken oAuth2AccessToken=new OAuth2AccessToken();
String url = WEB_ACCESS_TOKEN_URL.replace("APPID", getAPPID()).replace("SECRET", getAPPSECRET()).replace("CODE",code);
JSONObject jsonObject = doGet(url);
if (jsonObject != null) {
oAuth2AccessToken.setAccess_token(jsonObject.getString("access_token"));
oAuth2AccessToken.setExpires_in(jsonObject.getInt("expires_in"));
oAuth2AccessToken.setRefresh_token(jsonObject.getString("refresh_token"));
oAuth2AccessToken.setOpenid(jsonObject.getString("openid"));
oAuth2AccessToken.setScope(jsonObject.getString("scope"));
}
return oAuth2AccessToken;
}
|
这里有一个坑啊,因为此access_token,非彼access_token.这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同
.所以微信为了安全又在这里搞了另一个token,来增大在网页获取用户信息的难度?
用access_token和openid获取用户基本信息
新建一个UserInfo实体类来储存用户信息,代码就不贴了.接着继续在WebUtil类中添加代码,依旧是doGet()方法,请求的链接是https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public UserInfo getUserInfo(String webAccessToken, String openid){
UserInfo userInfo=new UserInfo();
String url=USER_INFO_URL.replace("ACCESS_TOKEN",webAccessToken).replace("OPENID",openid);
JSONObject jsonObject = doGet(url);
if (jsonObject!=null) {
userInfo.setOpenid(jsonObject.getString("openid"));
userInfo.setNickname(jsonObject.getString("nickname"));
userInfo.setSex(jsonObject.getString("sex"));
userInfo.setProvince(jsonObject.getString("province"));
userInfo.setCity(jsonObject.getString("city"));
userInfo.setCountry(jsonObject.getString("country"));
userInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
userInfo.setPrivilege(jsonObject.getString("privilege"));
}
return userInfo;
}
|
这样就已经实现了获取用户的基本信息,但是还没有结束,再在OAuth2Servlet()类中调用以上的方法,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 用户同意授权后,能获取到code
String code = request.getParameter("code");
if (code!=null&&!code.equals("")) {
WebUtil webUtil = new WebUtil();
//通过code换取网页授权的access_token
OAuth2AccessToken oAuth2AccessToken = webUtil.getOAuth2AccessToken(code);
//access_token
String access_token = oAuth2AccessToken.getAccess_token();
//openid
String openid = oAuth2AccessToken.getOpenid();
//获取用户信息
UserInfo userInfo = webUtil.getUserInfo(access_token, openid);
//todo 可以改成跳转到profile.jsp页面,通过参数()来显示是否已经绑定
request.setAttribute("UserInfo", userInfo);
request.getRequestDispatcher("message.jsp").forward(request,response);
}
}
|
可以看到在经过一系列操作之后得到了userInfo对象,并且将他传递到下一个页面.
实现自己的跳转页面
message.jsp代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="ObjectC.UserInfo"%>
<html>
<head>
<title>账号设置</title>
<meta name="viewport" content="width=device-width,user-scalable=0">
<link rel="shortcut icon" href="home/favicon.ico">
<style type="text/css">
*{margin:0; padding:0}
table{border:1px dashed #B9B9DD;font-size:12pt}
td{border:1px dashed #B9B9DD;word-break:break-all; word-wrap:break-word;}
#under{width: 200px;height: 20px;margin-top: 350px;}
</style>
</head>
<body>
<%
UserInfo user = (UserInfo)request.getAttribute("UserInfo");
if(null != user) {
String name=user.getName();
String openid=user.getOpenid();
String schoolid=user.getSchoolid();
String headImage=user.getHeadimgurl();
%>
<center>
<div id="users"><p>
<%=name %><br>
<%=schoolid%><br>
<%=openid%><br>
<%=headImage%><br>
绑定成功!<br>
<a href="profile.jsp">返回个人设置</a>
</center>
<center>
<div id="under">
<p>Copyright © 2016-2017 Yappy Doggie</p>
</div>
</center>
<%
}
else
out.print("用户不同意授权,未获取到用户信息!");
%>
</body>
</html>
|
主要是判断了一下用户是否授权,如果没有就显示"用户不同意授权,未获取到用户信息!"。这样基本的获取用户信息和跳转自己的页面就实现了。
最后
到现在终于写完了五篇,不能每个个细节都说的详细,但我也是看着开发文档和一些博客/视频,一步一步做出来的,虽然写的是垃圾代码,到目前为止也没有实现什么核心的业务逻辑,但是整个过程…..开心就好😂…..