微信開放平臺接入,官網:https://open.weixin.qq.com,在官網注冊并添加應用后即可獲得APP_ID和APP_SECRET。
步驟一:創建一個繼承AuthService的接口,WeChatAuthService,如下
1
2
3
|
public interface WeChatAuthService extends AuthService { public JSONObject getUserInfo(String accessToken, String openId); } |
步驟二:WeChatService的具體實現如下
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
@Service public class WeChatAuthServiceImpl extends DefaultAuthServiceImpl implements WeChatAuthService { private Logger logger = LoggerFactory.getLogger(WeChatAuthServiceImpl. class ); //請求此地址即跳轉到二維碼登錄界面 private static final String AUTHORIZATION_URL = "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect" ; // 獲取用戶 openid 和access——toke 的 URL private static final String ACCESSTOKE_OPENID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code" ; private static final String REFRESH_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s" ; private static final String USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN" ; private static final String APP_ID= "xxxxxx" ; private static final String APP_SECRET= "xxxxxx" ; private static final String SCOPE = "snsapi_login" ; private String callbackUrl = "https://www.xxx.cn/auth/wechat" ; //回調域名 @Override public String getAuthorizationUrl() throws UnsupportedEncodingException { callbackUrl = URLEncoder.encode(callbackUrl, "utf-8" ); String url = String.format(AUTHORIZATION_URL,APP_ID,callbackUrl,SCOPE,System.currentTimeMillis()); return url; } @Override public String getAccessToken(String code) { String url = String.format(ACCESSTOKE_OPENID_URL,APP_ID,APP_SECRET,code); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); URI uri = builder.build().encode().toUri(); String resp = getRestTemplate().getForObject(uri, String. class ); logger.error( "getAccessToken resp = " +resp); if (resp.contains( "openid" )){ JSONObject jsonObject = JSONObject.parseObject(resp); String access_token = jsonObject.getString( "access_token" ); String openId = jsonObject.getString( "openid" );; JSONObject res = new JSONObject(); res.put( "access_token" ,access_token); res.put( "openId" ,openId); res.put( "refresh_token" ,jsonObject.getString( "refresh_token" )); return res.toJSONString(); } else { throw new ServiceException( "獲取token失敗,msg = " +resp); } } //微信接口中,token和openId是一起返回,故此方法不需實現 @Override public String getOpenId(String accessToken) { return null ; } @Override public JSONObject getUserInfo(String accessToken, String openId){ String url = String.format(USER_INFO_URL, accessToken, openId); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); URI uri = builder.build().encode().toUri(); String resp = getRestTemplate().getForObject(uri, String. class ); logger.error( "getUserInfo resp = " +resp); if (resp.contains( "errcode" )){ throw new ServiceException( "獲取用戶信息錯誤,msg = " +resp); } else { JSONObject data =JSONObject.parseObject(resp); JSONObject result = new JSONObject(); result.put( "id" ,data.getString( "unionid" )); result.put( "nickName" ,data.getString( "nickname" )); result.put( "avatar" ,data.getString( "headimgurl" )); return result; } } //微信的token只有2小時的有效期,過時需要重新獲取,所以官方提供了 //根據refresh_token 刷新獲取token的方法,本項目僅僅是獲取用戶 //信息,并將信息存入庫,所以兩個小時也已經足夠了 @Override public String refreshToken(String refresh_token) { String url = String.format(REFRESH_TOKEN_URL,APP_ID,refresh_token); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url); URI uri = builder.build().encode().toUri(); ResponseEntity<JSONObject> resp = getRestTemplate().getForEntity(uri,JSONObject. class ); JSONObject jsonObject = resp.getBody(); String access_token = jsonObject.getString( "access_token" ); return access_token; } } |
步驟三:
在Controller中調用,代碼如下:
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
|
@RequestMapping (value = "/wxLoginPage" ,method = RequestMethod.GET) public JSONObject wxLoginPage() throws Exception { String uri = weChatAuthService.getAuthorizationUrl(); return loginPage(uri); } @RequestMapping (value = "/wechat" ) public void callback(String code,HttpServletRequest request,HttpServletResponse response) throws Exception { String result = weChatAuthService.getAccessToken(code); JSONObject jsonObject = JSONObject.parseObject(result); String access_token = jsonObject.getString( "access_token" ); String openId = jsonObject.getString( "openId" ); // String refresh_token = jsonObject.getString("refresh_token"); // 保存 access_token 到 cookie,兩小時過期 Cookie accessTokencookie = new Cookie( "accessToken" , access_token); accessTokencookie.setMaxAge( 60 * 2 ); response.addCookie(accessTokencookie); Cookie openIdCookie = new Cookie( "openId" , openId); openIdCookie.setMaxAge( 60 * 2 ); response.addCookie(openIdCookie); //根據openId判斷用戶是否已經登陸過 KmsUser user = userService.getUserByCondition(openId); if (user == null ) { response.sendRedirect(request.getContextPath() + "/student/html/index.min.html#/bind?type=" +Constants.LOGIN_TYPE_WECHAT); } else { //如果用戶已存在,則直接登錄 response.sendRedirect(request.getContextPath() + "/student/html/index.min.html#/app/home?open_id=" + openId); } } |
步驟四:
前臺js中,先請求auth/wxLoginPage,獲取授權地址,等用戶授權后會回調/auth/wechat,在此方法中進行邏輯處理即可。
遇到過的坑:
1.在微信官網中配置回調域名的時候,不需要些http或https協議,只需要寫上域即可,例如http://baidu.com,只需要填寫baidu.com即可,如果是想要跳轉到項目下面的某個Controller的某個方法中,如baidu.com/auth/wechat ,配置的時候也只需要配baidu.com,不需要指定后面的auth/wechat,后面的地址在代碼中配置回調的地址的時候寫上即可,代碼中應該配置為https://baidu.com/auth/wechat
2.在跳轉到授權二維碼界面的時候,會遇到有的時候二維碼出不來的狀況,這是因為代碼中的回調地址的問題,按照上面代碼中的方式配置應該是沒有問題的
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://blog.csdn.net/u010978008/article/details/73896306