这张图是官方提供的扫码授权流程
Controller
/**
* 刷新公共授权码,由于component_access_token需要2个小时刷新一次,所以需要判断本地表中存在的第三方接口调用凭据updateTime和当前时间的差值
* 如果超过1小时50分就调用微信接口更新,否则不做任何操作
* componentVerifyTicket 根据最近可用的component_verify_ticket来获得componentAccessToken和preAuthCode
*/
@ApiOperation(value = "获取预授权码")
@RequestMapping(value = "/platform/getpreAuthCode",
method = { RequestMethod.GET, RequestMethod.POST })
public String getpreAuthCode() {
return weChatService.getpreAuthCode();
}
Service处理
public String getpreAuthCode() {
try{
String componentVerifyTicket = redisService.getCacheObject("component_verify_ticket");
if(StringUtils.isEmpty(componentVerifyTicket)) throw new ServiceException("第三方平台获取【验证票据Ticket】失败");
WeChatPlatFormAuth weChatPlatFormAuth = redisService.getCacheObject("component_access_token");
if (weChatPlatFormAuth!=null) { // component_access_token没有过期
//刷新component_access_token
//weChatPlatFormAuth = refreshComponentAccessToken(PLATFORM_APP_ID,PLATFORM_APP_SECRET,componentVerifyTicket);
//获取预授权码
WeChatPlatFormAuth preAuth = redisService.getCacheObject("pre_auth_code");
if(preAuth!=null){
return preAuth.getPre_auth_code();
}else{
//刷新预授权码
preAuth = refreshPreAuthCode(weChatPlatFormAuth.getComponentAccessToken(),PLATFORM_APP_ID);
return preAuth.getPre_auth_code();
}
} else { //首次接收ticket,需要走一遍整个流程,获取component_access_token和pre_auth_code,添加进本地数据库
// 首先获取component_access_token
JSONObject params = new JSONObject();
params.put("component_verify_ticket", componentVerifyTicket);
params.put("component_appsecret", PLATFORM_APP_SECRET);
params.put("component_appid", PLATFORM_APP_ID);
String result = HttpUtils.httpRequest("https://api.weixin.qq.com/cgi-bin/component/api_component_token", "POST", params.toString()).toString();
String componentAccessToken = com.alibaba.fastjson.JSONObject.parseObject(result).getString("component_access_token");
// 获取pre_auth_code
JSONObject preParams = new JSONObject();
preParams.put("component_appid", PLATFORM_APP_ID);
JSONObject preAuth = HttpUtils.httpRequest("https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=" + componentAccessToken, "POST", preParams.toString());
WeChatPlatFormAuth preAuthCodeInfo = (WeChatPlatFormAuth) JSONObject.toBean(preAuth,WeChatPlatFormAuth.class);
String preAuthCode = preAuthCodeInfo.getPre_auth_code();
// 封装参数,添加进本地数据库
if (!StringUtils.isEmpty(componentAccessToken) && !StringUtils.isEmpty(preAuthCode)) {
weChatPlatFormAuth = new WeChatPlatFormAuth();
weChatPlatFormAuth.setComponentVerifyTicket(componentVerifyTicket);
weChatPlatFormAuth.setComponentAccessToken(componentAccessToken);
redisService.setCacheObject("component_access_token", weChatPlatFormAuth, (long) 7100, TimeUnit.SECONDS);
redisService.setCacheObject("pre_auth_code", preAuthCodeInfo, (long) preAuthCodeInfo.getExpires_in(), TimeUnit.SECONDS);
} else {
throw new ServiceException("获取授权码失败,请联系管理员");
}
return preAuthCode;
}
}catch (Exception e){
throw new ServiceException("获取授权码失败,请联系管理员");
}
}
web接收preAuthCode
引导用户进入扫码画面
getPreAuthCode().then(res=>{
#component_appid :第三方平台id
#pre_auth_code : 后天返回的授权码字符串
#redirect_uri : 授权完成后需要跳转的地址
const url = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=" + this.component_appid + "&pre_auth_code=" +res+ '&redirect_uri='+this.basePath+'&auth_type=1'
// window.open(url)
location.href= url
}).catch(error=>{
this.msgError(error)
})
授权完成后跳转的地址会带有两个 参数分别是 auth_code 和 expires_in
这是公众号获取调用令牌所需要的code,带着auth_code去后台获取调用令牌并保存下来
let auth_code = that.$route.query.auth_code;
let expires_in = that.$route.query.expires_in;
if(auth_code&&expires_in){
getAuthorizerInfo({authCode:auth_code,expiresIn:expires_in}).then(res=>{
that.msgSuccess("保存成功!");
})
}
public void getAuthorizerInfo(String authCode, String expiresIn) {
try {
SysDept sysDept = tokenService.getLoginUser().getSysUser().getDept();
VtWechatAccount wechatAccount = new VtWechatAccount();
//获取授权公众号的刷新令牌
logger.error("准备获取公众号主体信息======PLATFORM_APP_ID:" + PLATFORM_APP_ID );
WeChatPlatFormAuth weChatPlatFormAuth = redisService.getCacheObject("component_access_token");
WeChatPlatFormAuth preAuth = redisService.getCacheObject("pre_auth_code");
if(weChatPlatFormAuth!=null&&preAuth!=null){
//String componentAccessToken = com.alibaba.fastjson.JSONObject.parseObject(redisService.getCacheObject("pre_auth_code")).getString("componentAccessToken");
JSONObject params = new JSONObject();
params.put("component_appid", PLATFORM_APP_ID);
params.put("authorization_code", authCode);
//-------获取授权公众号的刷新令牌
String authorizerRefreshToken = HttpUtils.httpRequest("https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=" + weChatPlatFormAuth.getComponentAccessToken(),"POST", params.toString()).toString();
com.alibaba.fastjson.JSONObject obj = com.alibaba.fastjson.JSONObject.parseObject(com.alibaba.fastjson.JSONObject.parseObject(authorizerRefreshToken).getString("authorization_info"));
String authorizer_appid = obj.getString("authorizer_appid");
logger.error("获取授权公众号的刷新令牌======" + obj.getString("authorizer_refresh_token"));
//-------获取授权账号调用令牌
JSONObject authorizationInfo = new JSONObject();
authorizationInfo.put("component_appid", PLATFORM_APP_ID);
authorizationInfo.put("authorizer_appid", authorizer_appid);
authorizationInfo.put("authorizer_refresh_token", obj.getString("authorizer_refresh_token"));
String authorizer_access_token_info = HttpUtils.httpRequest("https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token="+weChatPlatFormAuth.getComponentAccessToken(),"POST", authorizationInfo.toString()).toString();
com.alibaba.fastjson.JSONObject authInfo = com.alibaba.fastjson.JSONObject.parseObject(authorizer_access_token_info);
String authorizer_access_token = authInfo.getString("authorizer_access_token");
String authorizer_refresh_token = authInfo.getString("authorizer_refresh_token");
wechatAccount.setAuthorizerAccessToken(authorizer_access_token);
wechatAccount.setAuthorizerRefreshToken(authorizer_refresh_token);
long account_expires_in = Long.parseLong(authInfo.getString("expires_in"));
//将授权账号调用令牌写入redis缓存,避免API调用触发每日限额
redisService.setCacheObject(Constants.WE_CHAT.AUTH_ACCESS_TOKEN_PREFIX + authorizer_appid,wechatAccount,account_expires_in,TimeUnit.SECONDS);
logger.error("获取授权账号调用令牌======" + authorizer_access_token);
//拉取已授权的帐号信息
JSONObject user = new JSONObject();
user.put("component_appid",PLATFORM_APP_ID);
user.put("authorizer_appid",authorizer_appid);
String usersStr = HttpUtils.httpRequest("https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token="+ weChatPlatFormAuth.getComponentAccessToken() ,"POST", user.toString()).toString();
com.alibaba.fastjson.JSONObject backObj = com.alibaba.fastjson.JSONObject.parseObject(usersStr);
com.alibaba.fastjson.JSONObject authorizerInfo = (com.alibaba.fastjson.JSONObject) backObj.get("authorizer_info");
logger.error("拉取已授权的帐号信息,公众号名称======" + authorizerInfo.getString("nick_name"));
//将授权的公众号基本信息保存至数据库中
redisService.setCacheObject(authorizer_appid,wechatAccount,account_expires_in,TimeUnit.SECONDS);
// 初始化菜单
int menu = createMenu("菜单 json",authorizer_access_token);
// if(menu==0){
// throw new ServiceException("初始化菜单失败");
// }
}else{
//response.sendRedirect("/vip/weChat");
throw new ServiceException("令牌已失效");
}
} catch (Exception e) {
throw new ServiceException("公众号信息保存失败!");
}
}
初始化公众号菜单
public static final String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
public static int createMenu(String jsonMenu, String accessToken) {
int result = 0;
// 拼装创建菜单的url
String url = MENU_CREATE_URL.replace("ACCESS_TOKEN", accessToken);
// 调用接口创建菜单
JSONObject jsonObject = HttpUtils.httpRequest(url, "POST", jsonMenu);
if (null != jsonObject) {
if (0 != jsonObject.getInt("errcode")) {
result = jsonObject.getInt("errcode");
}
}
return result;
}
至此授权流程完结!