/**
* unionLoginCallbackPath
*/
@Value("${QQ_UNION_LOGIN_CALLBACK_PATH}")
private String qqUnionLoginCallbackPath;
/**
* appKey
*/
@Value("${QQ_CONSUMER_KEY}")
private String appKey;
/**
* appSecret
*/
@Value("${QQ_CONSUMER_SECRET}")
private String appSecret;
/**
* loginUrl
*/
@Value("${QQ_LOGIN_URL}")
private String loginUrl;
/**
* accessTokenUrl
*/
@Value("${QQ_ACCESS.TOKEN_URL}")
private String accessTokenUrl;
/**
* openIdUrl
*/
@Value("${QQ_OPEN_ID_URL}")
private String openIdUrl;
/**
* userInfoUrl
*/
@Value("${QQ_USER_INFO_URL}")
private String userInfoUrl;

public QQUnionLoginApi() {}

/**
* 获得QQ登录URL,第一步流程
* @param callBackPage
* @return
*/
public String getQQLoginUrl() {

// 获取QQ登录页面的url
StringBuilder qqLoginUrl = new StringBuilder();

// QQ登陆地址 用于获取Authorization Code
qqLoginUrl.append(this.loginUrl);

// 授权类型,此值固定为“code”
qqLoginUrl.append("?response_type=code");

// 申请QQ登录成功后,分配给应用的appid
qqLoginUrl.append("&client_id=" + this.appKey);

// 成功授权后的回调地址,建议设置为网站首页或网站的用户中心。
qqLoginUrl.append("&redirect_uri=" + qqUnionLoginCallbackPath);

// 请求用户授权时向用户显示的可进行授权的列表。如果要填写多个接口名称,请用逗号隔开。 不传则默认请求对接口get_user_info进行授权
qqLoginUrl.append("&scope=");

// client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。
qqLoginUrl.append("&state=javaSdk-code");

// 用于展示的样式。不传则默认展示为为PC下的样式。
// 如果传入“mobile”,则展示为mobile端下的样式。
qqLoginUrl.append("&display=");
LOG.info("build QQLoginUrl:" + qqLoginUrl.toString());
return qqLoginUrl.toString();
}

/**
* 获取请求access token 的URL第二步流程
* @param authorizationCode
* @param callBackPage
* @return
*/
public String getQQAccessTokenUrl(String authorizationCode) {

StringBuilder accessTokenUrl = new StringBuilder();

// 通过Authorization Code获取Access Token 的URl
accessTokenUrl.append(this.accessTokenUrl);

// QQ登陆地址 用于获取Authorization Code
accessTokenUrl.append("?grant_type=authorization_code");

// 申请QQ登录成功后,分配给应用的appid
accessTokenUrl.append("&client_id=" + this.appKey);

// 申请QQ登录成功后,分配给网站的appkey
accessTokenUrl.append("&client_secret=" + this.appSecret);

// 登陆成功后返回的authorization code
accessTokenUrl.append("&code=" + authorizationCode);

// client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。
accessTokenUrl.append("&state=javaSdk-token");

// 成功授权后的回调地址,建议设置为网站首页或网站的用户中心。
accessTokenUrl.append("&redirect_uri=" + qqUnionLoginCallbackPath);

return accessTokenUrl.toString();
}

/**
* 刷新access token 的URL
* @param authorizationCode
* @param callBackPage
* @return
*/
public String refreshQQAccessTokenUrl(String refresToken) {

StringBuilder refresTokenUrl = new StringBuilder();

//刷新access token 的URL
refresTokenUrl.append(this.accessTokenUrl);

// 刷新access token 的标志
refresTokenUrl.append("?grant_type=refresh_token");

// 申请QQ登录成功后,分配给应用的appid
refresTokenUrl.append("&client_id=" + this.appKey);

// 申请QQ登录成功后,分配给网站的appkey
refresTokenUrl.append("&client_secret=" + this.appSecret);

// 返回的refresToken
refresTokenUrl.append("&refresh_token=" + refresToken);

return refresTokenUrl.toString();
}

/**
* 获取请求open id的URL,open id就是QQ第3方用户ID,第3步流程
* @param accessToken
* @return
*/
public String getQQOpenIdUrl(String accessToken) {

// 换取OpenId的URL
StringBuilder openIdUrl = new StringBuilder();

// 使用Access Token来获取用户的OpenID 的URl
openIdUrl.append(this.openIdUrl);

// ACCESS_TOKEN
openIdUrl.append("?access_token=" + accessToken);

return openIdUrl.toString();
}

/**
* 动态拼接获取用户数据的url 第4部流程,获取用户的昵称
* @param accessToken
* @param openId
* @return
*/
public String getQQUserInfoUrl(String accessToken, String openId) {

// 动态拼接获取用户数据的url
StringBuilder userInfoUrl = new StringBuilder();

// 获取用户数据接口的URl
userInfoUrl.append(this.userInfoUrl);

// 应用的appid
userInfoUrl.append("?oauth_consumer_key=" + this.appKey);

// 应用的accessToken
userInfoUrl.append("&access_token=" + accessToken);

// 应用的OpenID
userInfoUrl.append("&openid=" + openId);

return userInfoUrl.toString();
}

/**
* 用 authorizationCode 换取 AccessToken
*
* @param authorizationCode 换取accessToken的code
* @return AccessToken
* @throws IOException
*/
public String getQQAccessToken(String code) throws IOException {

String accessTokenUrl = getQQAccessTokenUrl(code);
LOG.info("access_token init:" + accessTokenUrl);
String accessToken = "";
String expires_in = "";
String refresh_token = "";

// 接受返回的字符串 包含accessToken
String tempStr = "";

// 请求QQ接口,回去返回数据
tempStr = doGet(accessTokenUrl);

LOG.info("access_token response:" + tempStr);
// 获取accessToken失败的场合
if (tempStr.indexOf("access_token") >= 0) {
accessToken = tempStr.split("&")[0].split("=")[1];
expires_in = tempStr.split("&")[1].split("=")[1];
refresh_token = tempStr.split("&")[2].split("=")[1];

//token失效则重新获取
if(!StringUtil.isNumber(expires_in)){
accessToken = refreshQQAccessToken(refresh_token);
}
LOG.info("access_token:" + accessToken);
return accessToken;
} else {
LOG.info("access_token get fail return:" + tempStr);
return "";
}
}

/**
* 用 refreshToken 刷新 AccessToken
*
* @param refreshToken
* @return AccessToken
* @throws IOException
*/
public String refreshQQAccessToken(String refreshToken) throws IOException {

LOG.info("refresh_access_token init:" + refreshToken);
String refreshTokenUrl = refreshQQAccessTokenUrl(refreshToken);
String accessToken = "";
String expires_in = "";

// 接受返回的字符串 包含accessToken
String tempStr = "";

LOG.info("refresh_access_token url:" + refreshToken);
// 请求QQ接口,回去返回数据
tempStr = doGet(refreshTokenUrl);

LOG.info("refresh_access_token response:" + refreshToken);
// 获取accessToken失败的场合
if (tempStr.indexOf("access_token") >= 0) {
accessToken = tempStr.split("&")[0].split("=")[1];
expires_in = tempStr.split("&")[1].split("=")[1];

if(!StringUtil.isNumber(expires_in)){
accessToken = "";
}
LOG.info("refresh_access_token:" + accessToken);
return accessToken;
} else {
LOG.info("refresh_access_token get fail return:" + tempStr);
return "";
}
}

/**
* 根据AccessToken获取OpenId
*
* @param accessToken AccessToken
* @return OpenId
* @throws JsonMappingException
* @throws JsonParseException
* @throws IOException
* @throws JSONException
*/
@SuppressWarnings("unchecked")
public String getQQOpenId(String accessToken) throws IOException{

// 获取OpenId
String openId = "";
String getQQOpenIdUrl = getQQOpenIdUrl(accessToken);

LOG.info("refresh_access_token init:" + getQQOpenIdUrl);
// 请求QQ接口,回去返回数据
String interfaceData = doGet(getQQOpenIdUrl);
interfaceData = interfaceData.substring(interfaceData.indexOf("{"),interfaceData.indexOf("}") + 1);
LOG.info("get openid response:" + interfaceData);
try {
Map<String, String> map = JsonUtils.json2Object(interfaceData, HashMap.class);
LOG.info("get openid response to map:" + StringUtil.printParam(map));
if(map.get("openid")!=null){
openId = map.get("openid");
LOG.info("openid:" + openId);
}
} catch (Exception e) {
LOG.info("get QQ openid erro:" + e.getMessage());
}
return openId;
}

@SuppressWarnings("unchecked")
public String getUserNickName(String accessToken, String openId) throws IOException {

String getNickNameUrl = getQQUserInfoUrl(accessToken, openId);
LOG.info("get nickname init:" + getNickNameUrl);
// 获取接口返回的数据
String interfaceData = doGet(getNickNameUrl);
String nickName = "";
LOG.info("get nickname response:" + interfaceData);

try {
Map<String, String> map = JsonUtils.json2Object(interfaceData, HashMap.class);
if(map.get("nickname")!=null){
// 昵称
nickName = map.get("nickname");
LOG.info("get nickname:" + nickName);
}
} catch (Exception e) {
LOG.info("get QQ nickName erro:" + e.getMessage());
}
return nickName;
}

/**
* 链接QQ服务接口
*
* @param interfaceUrl
* 接口URL
*
* @return 接口返回的数据
* @throws IOException
*/
public String doGet(String interfaceUrl) throws IOException {
// 打印日志
LOG.info("QQ unionLogun doGet:" + interfaceUrl);

String interfaceData = "";
try
{
HttpResponseWrapper httpResponseWrapper = HttpsUtil.requestGetResponse(interfaceUrl);
int state = httpResponseWrapper.getStatusCode();

// 打印日志
LOG.info("QQ unionLogun doGet request Code:" + state);

// 是否请求正常
if (HttpsUtil.isCallOK(state)) {

// 获取返回的数据流
BufferedReader input = new BufferedReader(new InputStreamReader(httpResponseWrapper.getResponseStream(),"UTF-8"));
String tempStr = "";

// 获取返回的内容
while ((tempStr = input.readLine()) != null) {
interfaceData += tempStr.replace("\t", "");
}
}
// 关闭连接
httpResponseWrapper.close();
}
catch(Exception ex)
{
LOG.error(ex,ex);
}
// 打印日志
LOG.info("QQ unionLogun doGet return json:" + interfaceData);

return interfaceData;
}

腾讯OAuth授权联合登录的更多相关文章

  1. 联合登录 & OAuth 2.0 & OpenID

    联合登录 & OAuth 2.0 & OpenID 第三方联合登录一般可以降低网站的获客成本,所以一般的网站都会做一些联合登录,常用的就是QQ.微信.微博; https://www.z ...

  2. 微信订阅号里实现oauth授权登录,并获取用户信息 (完整篇)

    摘要 这段时间一直有人问我,订阅号实现的oauth授权登录的问题,之前写的比较简单,很多人不明白.众所周知,微信公众号分订阅号.服务号.企业号:每个号的用途不一样,接口开放程度也不一样.微信还有个扯淡 ...

  3. 第三方OAuth授权登录,QQ、微信(WeChat)、微博、GitHub、码云(Gitee)、淘宝(天猫)、微软(Microsoft )、钉钉、谷歌(Google)、支付宝(AliPay)、StackOverflow

    Netnr.Login 第三方OAuth授权登录 支持第三方登录 三方 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 安装 ( ...

  4. OAuth授权登录

    一.写在前面 日常生活中,我们经常看到到一个网站时,需要登录的时候,都提供了第三方的登录,也就是说你可以使用你的微信,QQ,微博等账号进行授权登录.那么这个认证登录的东西到底是什么呢? 微信授权登录页 ...

  5. OAuth2简易实战(四)-Github社交联合登录

    1. OAuth2简易实战(四)-Github社交联合登录 1.1. 用到的第三方插件 https://github.com/spring-projects/spring-social-github ...

  6. IOS第三天-新浪微博 - 版本新特性,OAuth授权认证

    *********版本新特性 #import "HWNewfeatureViewController.h" #import "HWTabBarViewController ...

  7. iOS之新浪微博的OAuth授权

    新浪微博的OAuth授权 之前通过新浪微博开发平台写过微博的的项目,现在就开始总结下各个方面的知识点,一个是为了加深印象.巩固知识,另一个记录自己学习过程,希望自己在开发这条路上有所积累,为以后的道路 ...

  8. OAuth授权过程

    什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准,所谓OAuth(即Open Authorization,开放授权),它是为用户资源授权提供了一种安全简单的标准, ...

  9. [iOS微博项目 - 2.0] - OAuth授权3步

    A.概念      OAUTH协议为用户资源的授权提供了一个安全的.开放而又简易的标准.与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用 ...

随机推荐

  1. DapperExtensions的基本用法

    介绍下使用Dapper-Extensions的基本语法 //实体类 DemoEntity entity = new DemoEntity(); //根据实体主键删除 this.Delete<De ...

  2. 26. linux查看端口占用情况

    linux系统下,查看端口占用情况的命令:lsof -i[root@www ~]# lsof -i

  3. 转:MyBean简介

                        (在开始之前,非常感谢 D10.天地弦) 1.1 概述 MyBean是一个用于Delphi应用程序开发的开源.轻量级.可配置插件框架.它通过巧妙的系统架构设计, ...

  4. 第六百一十八天 how can I 坚持

    此刻好烦,乱七八糟的,红米2死机也没弄好,哎. 下周三去长城,感觉还有很大提升空间啊,什么都不会.哎. 眼累的不行了,得抓紧睡觉了.ls他们来北京开年会了.. 明天,zjp来找我玩呢. 睡觉了.累.

  5. delphi数据类型及占用的字节数 C++ 对应数据类型

    delphi byte:1个字节. int/Integer: long: long long:8字节,64位 shortInt:2字节,16位 LongInt:4字节,32位 Int64:8字节,64 ...

  6. Data Transformation / Learning with Counts

    机器学习中离散特征的处理方法 Updated: August 25, 2016 Learning with counts is an efficient way to create a compact ...

  7. Redis中的简单事物以及消息订阅发布

    Redis支持简单的事物,但是没有mysql的Innodb支持的那么的完善 我们接下来看一下Redis和Mysql的事物的一个对比:   MySQL Redis 开启 start transactio ...

  8. Scala中的None,Nothing,Null,Nil

    在scala中这四个类型名称很类似,作用确实完全不同的. None是一个object,是Option的子类型,定义如下 case object None extends Option[Nothing] ...

  9. python学习心得第五章

    python学习心得第五章 1.冒泡排序: 冒泡是一种基础的算法,通过这算法可以将一堆值进行有效的排列,可以是从大到小,可以从小到大,条件是任意给出的. 冒泡的原理: 将需要比较的数(n个)有序的两个 ...

  10. Perl语言

    Perl是高级.通用.直译式.动态的程序语言家族.最初设计者拉里·沃尔(Larry Wall)为了让在UNIX上进行报表处理的工作变得更方便,决定开发一个通用的脚本语言,而在1987年12月18日发表 ...