您的位置:首页 > 移动开发 > 微信开发

java微信第三方平台开发(二)

2016-11-15 18:29 561 查看
一、获取公众号的的授权

在申请的第三方平台下填写的开发者资料里有:授权测试公众号列表、授权事件接受的URL,首先要在测试列表里添加:公众号的原始ID,然后在URl地址里用java代码处理微信每10分钟推送过来xml啦,然后的步骤是解析xml,获取component_verify_ticket —> 调用接口获取component_access_token —>获取预授权码pre_auth_code(可存在数据库中) — >回复微信success — >引导用户进去授权页 —>获取authorization_code —>换取authorizer_access_token(它和普通公众号的基础token作用一样,也能获取用户的openId和用户信息)

第三方公众号获取微信推送的xml

/**
* 微信授权事件的接受
* @return
*/
@RequestMapping(value="/authorize",method={RequestMethod.GET,RequestMethod.POST})
public void acceptAuthorizeEvent(
HttpServletResponse response,HttpServletRequest request){
try {
//处理授权事件
weChatThridService.handleAuthorize(request,response);
PrintWriter pw = response.getWriter();
pw.write("success");
pw.flush();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}


handleAuthorize方法用来接受处理xml:

/**
* 处理微信授权事件
* @param request
* @param response
* @throws Exception
*/
public void handleAuthorize(Ht
4000
tpServletRequest request, HttpServletResponse response) throws Exception {
// TODO Auto-generated method stub
String timestamp=request.getParameter("timestamp");
String encrypt_type=request.getParameter("encrypt_type");
String nonce=request.getParameter("nonce");
String msg_signature=request.getParameter("msg_signature");
Log.logger.info("timestamp:"+timestamp);
Log.logger.info("encrypt_type:"+encrypt_type);
Log.logger.info("nonce:"+nonce);
Log.logger.info("msg_signature:"+msg_signature);
//验证通过后

StringBuilder sb = new StringBuilder();
BufferedReader in = request.getReader();
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
String xml = sb.toString();
Log.logger.info("微信推送的原生:"+xml);
String encodingAesKey =WeChatContants.encodingAesKey;// 第三方平台组件加密密钥
String appId=WeChatContants.THRID_APPID;//从xml中解析
WXBizMsgCrypt pc = new WXBizMsgCrypt(WeChatContants.token, encodingAesKey,appId);
xml = pc.decryptMsg(msg_signature, timestamp, nonce, xml);
Log.logger.info("解密后的:"+xml);


上述用到的加密解密工具类可以点击这里下载使用,这里的WeChatContants.token和encodingAesKey就是在开发者资料填写的token和key。

获取component_verify_ticket(第三方验证的票据)

解析上述解密后的xml文件,获取节点component_verify_ticket内容,后续用来调用微信接口获取第三方通行token.

接上述代码:

Map<String, String> parseXml = WeChatUtils.parseXml(xml);
String component_verify_ticket=parseXml.get("ComponentVerifyTicket");
Log.logger.info(component_verify_ticket);


调用微信接口获取component_access_token

url:https://api.weixin.qq.com/cgi-bin/component/api_component_token

method:post

type:json

params:

component_appid(第三方公众号appid,第三方公众号创建好后即可知道)、

component_appsecret(第三方公众号的appsecret,同上)、

component_verify_ticket(上步获取到component_verify_ticket)

接上述代码:

/************调用接口获取component_access_token***************/
WeChatThridGetTokenVo thridGetToken=new WeChatThridGetTokenVo();
thridGetToken.setComponent_appid(WeChatContants.THRID_APPID);
thridGetToken.setComponent_appsecret(WeChatContants.THRID_APPSECRET);
thridGetToken.setComponent_verify_ticket(component_verify_ticket);
String result = HttpNetUtils.getInstance().httpByJson(WeChatContants.THRID_COMPONENT_ACCESS_TOKEN, "POST",thridGetToken);
Log.logger.info(result);

if(result.contains("component_access_token")){
WeChatComponentAccessTokenVo componentAccessToken=JSON.parseObject(result,WeChatComponentAccessTokenVo.class);
component_access_token=componentAccessToken.getComponent_access_token();
}else{
Log.logger.info("获取component_access_token失败!");
}


第三方公众号获取预授权码pre_auth_code

url地址:

https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token={0}

method:post

type:json

params:

component_appid:第三方平台公众号appid

解析json,并将component_access_token存在数据库中,用来授权时使用。

接上述代码:

/*****************获取预授权码pre_auth_code*************************/
Object[]object={component_access_token};
String preUrl=MessageFormat.format(WeChatContants.THRID_PRE_AUTH_CODE,object);
WeChatGetPreAuthCodeVo getPreAuthCodeVo=new WeChatGetPreAuthCodeVo();
getPreAuthCodeVo.setComponent_appid(WeChatContants.THRID_APPID);
String result1 = HttpNetUtils.getInstance().httpByJson(preUrl,"POST",getPreAuthCodeVo);
Log.logger.info(result1);
String preAuthCode="";
if(result1.contains("pre_auth_code")){
WeChatPreAuthCodeVo preAuthCodeVo= JSON.parseObject(result1,WeChatPreAuthCodeVo.class);
preAuthCode=preAuthCodeVo.getPre_auth_code();
//将预授权码存在数据库中
Map<String, Object> where = new HashMap<String, Object>();
where.put("dic_type_id","THRID_WECHAT_PRE_CODE");
QueryResult<CsDictVo> page = csDictService.findByPage(where);
if(page.getList()!=null&&page.getList().size()>0){
CsDictVo csDictVo = page.getList().get(0);
CsDict csDict=new CsDict();
BeanCopyPropertyUtils.copyProperties(csDict,csDictVo);
csDict.setDicCode(preAuthCode);
csDict.setDicValue(new Date().toString());
csDictService.update(csDict);
}
}else{
Log.logger.info("获取pre_auth_code失败!");
}
}


引导普通公众号进入授权页面进行扫码授权

从数据库中获取上步存入的预授权码:pre_auth_code,用来访问微信提供的url地址,这是会跳转到微信的一个带二维码的页面,如下图:



用户扫码授权成功会跳转到你填写的转发地址(和公众号的授权的逻辑步骤是一样的,可以参考我前几篇写的微信开发)并且会带上一个auth_code。

url地址:https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid={0}&pre_auth_code={1}&redirect_uri={2}

method:get

params:component_appid、pre_auth_code、redirect_uri(转发的URL地址)

/**
* 引导用户进入授权页面
*/
@RequestMapping(value="/goAuthPage",method={RequestMethod.GET,RequestMethod.POST})
public String goAuthPage(
HttpServletResponse response,HttpServletRequest request){
String result="auth";
try {
request.getSession();
//查找预授权码
String preAuthCode = weChatThridService.getPreAuthCode();
if(preAuthCode.equals("")){
request.setAttribute("errorMsg","预授权码为空!");
return "error";
}
/**********************跳转到授权页面********************************/
Object[]object1={WeChatContants.THRID_APPID,preAuthCode,"http://自己的域名.com/a/weixin2/authInfo"};
String authorizationUrl=MessageFormat.format(WeChatContants.THRID_AUTHORIZATION_CODE,object1);
Log.logger.info("跳转的URL:"+authorizationUrl);
response.sendRedirect(authorizationUrl);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}


获取authorization_code

request.getParameter(“auth_code”)获取authorization_code,

getAuthAccessToken方法是获取authorizer_access_token

/**
* 处理微信授权事件完成跳转URL
* @return
*/
@RequestMapping(value="/authInfo",method={RequestMethod.GET,RequestMethod.POST})
public String successAuthorizeInfo(
HttpServletResponse response,HttpServletRequest request){
String result="error";
try {
//获取authorization_code
String authorization_code=request.getParameter("auth_code");
Log.logger.info("auth_code:"+authorization_code);
//换取authorizer_access_token
String authAccessToken = weChatThridService.getAuthAccessToken(authorization_code);
if(authAccessToken.equals("configError")){
request.getSession().setAttribute("errorMsg", "缺少配置,请联系管理员!");
return "error";
}else if(authAccessToken.equals("httpError")){
request.getSession().setAttribute("errorMsg", "微信返回信息失败!");
return "error";
}
}catch (Exception e) {
// TODO: handle exception
Log.logger.info(e.getMessage());
}
request.setAttribute("errorMsg","授权成功!");
return result;
}


获取authorizer_access_token(可用来代公众号授权登录,获取用户的openid和用户信息等)

url:https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token={0}

method:post

type:json

params:

component_appid:第三方平台的appid

authorization_code:上步获取到的code

注意:authorizer_access_token的有效期为2小时,所以需要存在数据库中。上述接口也会返回:authorizer_refresh_token刷新token,当时间超过2个小时后,开发者需要通过刷新token来更新authorizer_access_token,以此来确保token的长持久性。so,authorizer_refresh_token也需要存在数据库中。

/**
* 通过authorization_code换取可以调用api的accessToken
* @param authorization_code
* @throws Exception
*/
public String getAuthAccessToken(String authorization_code) throws Exception {
// TODO Auto-generated method stub
String data="";
Log.logger.info("component_access_token为:"+component_access_token);
Object[]objects={component_access_token};
String authAccessToken = MessageFormat.format(WeChatContants.THRID_AUTH_ACCESS_CODE, objects);
WeChatGetAuthAccessTokenVo getAuthAccessTokenVo =new WeChatGetAuthAccessTokenVo();
getAuthAccessTokenVo.setAuthorization_code(authorization_code);
getAuthAccessTokenVo.setComponent_appid(WeChatContants.THRID_APPID);

String result = HttpNetUtils.getInstance().httpByJson(authAccessToken, "POST", getAuthAccessTokenVo);
Log.logger.info(result);
String authorizer_access_token="";
String authorizer_refresh_token="";
if(result.contains("authorization_info")){
WeChatAuthorizationInfoDataVo authInfo= JSON.parseObject(result,WeChatAuthorizationInfoDataVo.class);
authorizer_access_token=authInfo.getAuthorization_info().getAuthorizer_access_token();
authorizer_refresh_token=authInfo.getAuthorization_info().getAuthorizer_refresh_token();
}else{
Log.logger.info("获取authorizer_access_token失败!");
data="httpError";
}
Log.logger.info(authorizer_access_token);
//将authorizer_access_token和authorizer_refresh_token存在字典表里
Map<String, Object> where = new HashMap<String, Object>();
where.put("dic_type_id","AUTHORIZER_ACCESS_TOKEN");
QueryResult<CsDictVo> page = csDictService.findByPage(where);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(page.getList()!=null&&page.getList().size()>0){
CsDictVo csDictVo = page.getList().get(0);
CsDict csDict=new CsDict();
BeanCopyPropertyUtils.copyProperties(csDict,csDictVo);
csDict.setDicCode(authorizer_access_token);
csDict.setDicValue(sdf.format(new Date()));
csDictService.update(csDict);
}else{
data="configError";
}
//将refresh_token存在字典表里
Map<String, Object> where1 = new HashMap<String, Object>();
where1.put("dic_type_id","THRID_REFRESH_TOKEN");
QueryResult<CsDictVo> page1 = csDictService.findByPage(where1);
if(page1.getList()!=null&&page1.getList().size()>0){
CsDictVo csDictVo = page.getList().get(0);
CsDict csDict=new CsDict();
BeanCopyPropertyUtils.copyProperties(csDict,csDictVo);
csDict.setDicCode(authorizer_refresh_token);
csDict.setDicValue(sdf.format(new Date()));
csDictService.update(csDict);
}else{
data="configError";
}
return data;
}


利用authorizer_refresh_token获取authorizer_access_token

authorizer_refresh_token需要妥善保管,当丢失后需要重新授权才能拿到。

url地址:

https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token={0}

method:post

type:json

params:

component_appid:第三方平台appid

authorizer_appid:授权方appid

authorizer_refresh_token:刷新token

//调用微信接口重新获取access_token
Object[]objects={component_access_token};
String refreshUrl=MessageFormat.format(WeChatContants.THRID_REFRESH_TOKEN, objects);
WeChatGetRefreshTokenVo refreshTokenVo=new WeChatGetRefreshTokenVo();
refreshTokenVo.setAuthorizer_appid(wechatConfig.getWxappid());
refreshTokenVo.setAuthorizer_refresh_token(csDictVo.getDicCode());
refreshTokenVo.setComponent_appid(WeChatContants.THRID_APPID);
Log.logger.info(refreshUrl);
String httpByJson = HttpNetUtils.getInstance().httpByJson(refreshUrl,"POST",refreshTokenVo);
Log.logger.info(httpByJson);
if(httpByJson.contains("authorizer_access_token")){
WeChatAuthorizerAccessTokenVo authorizerAccessTokenVo = JSON.parseObject(httpByJson, WeChatAuthorizerAccessTokenVo.class);
thridToken = authorizerAccessTokenVo.getAuthorizer_access_token();
//并将它存在数据字典里面
Map<String, Object> where1 = new HashMap<String, Object>();
where1.put("dic_type_id","AUTHORIZER_ACCESS_TOKEN");
QueryResult<CsDictVo> page1 = csDictService.findByPage(where1);
CsDictVo csDictVo2 = page1.getList().get(0);
CsDict csDict=new CsDict();
BeanCopyPropertyUtils.copyProperties(csDict,csDictVo2);
csDict.setDicCode(thridToken);
csDict.setDicValue(DateFromtUtils.getDataFormatYMDHMS24(new Date()));
csDictService.update(csDict);
}else{
thridToken="httpError";
}


二、代公众号发起网页授权,获取用户信息

当完成上述步骤后就可以代公众号发起网页授权了,获取用户openID,获取用户信息。

代公众号发起网页授权

url:https://open.weixin.qq.com/connect/oauth2/authorize

method:get

params:

appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}&component_appid={5}#wechat_redirect

//转发地址
String redUrl=URLEncoder.encode("http://自己的域名.com/b/weixin2/hongbao", "UTF-8");
String params=WeChatContants.THRID_WECHAT_OAUTH_PARAMS;
Object[]array={wechatConfig.getWxappid(),redUrl,"code","snsapi_base",1,WeChatContants.THRID_APPID};
String formatparams = MessageFormat.format(params, array);
Log.logger.info(WeChatContants.THRID_WECHAT_OAUTH_URL+"?"+formatparams);
//将转发地址存在session中,方便code失效时重新连接
request.getSession().setAttribute("oauthLink",WeChatContants.THRID_WECHAT_OAUTH_URL+"?"+formatparams);
//微信授权转发
response.sendRedirect(WeChatContants.THRID_WECHAT_OAUTH_URL+"?"+formatparams);


获取用户openID和用户基本信息

可参考前几篇写的获取用户信息

总结:微信官方文档里至始至终都没提到authorizer_access_token和公众号的token的作用是一样的,并且两者不冲突(即在获取某一个时不会导致另一个失效)。这是微信的一个大坑(吐槽一下…)。

未完待续。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐