微信授权的整体思路:
1 第一步:用户同意授权,获取code
2 第二步:通过code换取网页授权access_token
3 第三步:刷新access_token(如果需要)
4 第四步:拉取用户信息(需scope为 snsapi_userinfo)
5 附:检验授权凭证(access_token)是否有效
微信授权官方文档:
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
代码实现:
package com.woyaoce.TencentApi.controller;
import com.alibaba.fastjson.JSONObject;
import com.woyaoce.TencentApi.constant.WxConstants;
import com.woyaoce.TencentApi.utils.HttpClientUtil;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import java.util.Iterator;
import java.util.Map;
/**
* 微信授权操作入口操作公共方法控制层
*
* @author madong
*/
@RestController
@RequestMapping("/wx")
public class WxAuthorizeController {
private static final Logger logger = LoggerFactory.getLogger(WxAuthorizeController.class);
// 0000-失败
private final static String ERROR_CODE = "0000";
@ApiOperation(value = "扫描裂变海报二维进入海报报名会议首页", notes = "扫描裂变海报二维进入海报报名会议首页")
@RequestMapping(value = "/getCode")
public void getCode(@RequestParam(value = "code") String code, HttpServletResponse response) {
// 重定向地址 https://m.woyaoce.cn/special我的微信授权地址
String redirect_uri = "https://m.woyaoce.cn/special/wx/getWxUserInfo?code=" + code;
try {
redirect_uri = URLEncoder.encode(redirect_uri, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 微信授权接口
String getCodeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
"appid=" + WxConstants.APPID +
"&redirect_uri=" + redirect_uri +
"&response_type=code&" +
"scope=snsapi_userinfo&" +
"state=STATE&connect_redirect=1#wechat_redirect";
try {
response.sendRedirect(getCodeUrl);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 根据微信授权code拉取用户信息
*
* @param code 微信授权code
*/
@ApiOperation(value = "根据微信授权code拉取用户信息", notes = "根据微信授权code拉取用户信息")
@GetMapping(value = "/getWxUserInfo")
@ResponseBody
public String getWxUserInfo(@RequestParam @ApiParam(name = "code", value = "微信code", required = true) String code) {
logger.info("成功进入,开始根据微信授权code拉取用户信息,code:{}", code);
// 根据code调取微信获取用户信息的返回集
String wxResult;
String path = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + WxConstants.APPID + "&secret=" + WxConstants.APP_SECRET + "&code=" + code + "&grant_type=authorization_code";
// 重点:获取access_token,并判断返回值
JSONObject obj = JSONObject.parseObject(HttpClientUtil.doGet(path));
Iterator it =obj.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Object> entry = (Map.Entry<String, Object>) it.next();
if("errcode".equals(entry.getKey())){
return ERROR_CODE;
}
if("access_token".equals(entry.getKey())){
break;
}
}
//得到token
String accessToken = (String) obj.get("access_token");
logger.info("access_token:" + accessToken);
//得到openid
String openid = (String) obj.get("openid");
//根据code值和oppenid获取用户的基本信息
String path2 = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
wxResult = HttpClientUtil.doGet(path2);
logger.info("根据code调取微信获取用户信息的返回集wxResult:" + wxResult);
return wxResult;
}
}
代码真的不难,但是其中还是有很多坑的,比如在第二个方法getWxUserInfo()中获取access_token的时候,如果这块“JSONObject obj = JSONObject.parseObject(HttpClientUtil.doGet(path));”根据code调用实施失败或者获取不到access_token的话,他返回的是带有errcode的一个json数据;
{"errcode":"ox74s6K1jLNa3zlr4xvD0L0R5lA4",.....后面的json记不清了,错误返回肯定没有以access_token为key的数据}
但是如果正确返回,他返回的json数据是这样的:
{"access_token":"ox74s6K1jLNa3zlr4xvD0L0R5lA4",.....后面的json记不清了,大概是这个意思,反正是正确的返回没有以errcode为key的数据}
这时候为了程序的健壮性,你需要对结果集进行判断。如果返回结果集中包含errcode为主键的字符,那么说明调用失败,那么需要返回给其他调用服务一个错误代码(0000,这个错误代码随便定义),如果调用成功,那么返回的的肯定包含以access_token为key的数据,这样在继续调用微信获取用户信息的接口才能获取成功,最终调用获取用户信息接口成功返回的数据样例为:
{"openid":"ox74s6K1jLNa3zlr4xvD0L0R5lA4","nickname":"md","sex":1,"language":"zh_CN","city":"海淀","province":"北京","country":"中国","headimgurl":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/Q0j4TwGTfTLs8SZLLWjyib3HtL1ZPZ76jpVZYiaRk2fpBPBqwwVcE1ZwLBF5cVbDKRF4vZVfnMRmjEq84I7fibH6g\/132","privilege":[],"unionid":"o_mJ01oKG8BPQZZsHpowTSp6uavQ"}
写这个整体思路还是很重要的,要理解:获取code然后授权(弹出授权页面)这一块不需要你用代码实现,而是调用微信接口,微信给你做!!!!!