1、開發(fā)前準(zhǔn)備工作
1 進(jìn)入http://connect.qq.com進(jìn)行登陸,然后點擊網(wǎng)站接入(根據(jù)需求,如果需要移動利用接入點擊移動利用接入)。以下例子為網(wǎng)站接入。
2 創(chuàng)建利用頁面中,將鼠標(biāo)放在”驗證”按鈕上,會彈出1個小窗口,將要復(fù)制的內(nèi)容復(fù)制下來放在你網(wǎng)站的首頁對應(yīng)位置,然后點擊”開始驗證”按鈕
2、開發(fā)
1 將該代碼放入你網(wǎng)站登陸頁面
按鈕圖片下載官方地址:
http://wiki.connect.qq.com/%E7%BD%91%E7%AB%99%E5%89%8D%E7%AB%AF%E9%A1%B5%E9%9D%A2%E8%A7%84%E8%8C%83#1..E4.BD.BF.E7.94.A8.E8.85.BE.E8.AE.AF.E6.8F.90.E4.BE.9B.E7.9A.84.E6.A0.87.E5.87.86.E2.80.9CQQ.E7.99.BB.E5.BD.95.E2.80.9D.E6.A0.87.E8.AF.86
注意修改a標(biāo)簽中href里面client_id后面的值改成你利用的appid,status的值可以改成你想設(shè)置的值,可以用于驗證是不是來你利用的要求。redirect_uri是你的回調(diào)地址,該回調(diào)地址用于成功登陸后的操作。Scope的值還可以是其他值,scope不填時默許為get_user_info。具體請參考官方:http://wiki.connect.qq.com/api%E5%88%97%E8%A1%A8
2 進(jìn)入到你網(wǎng)址的QQ登陸頁面,點擊QQ登陸圖標(biāo),如果出現(xiàn)回調(diào)地址不合法的提示,請參考官方進(jìn)行回調(diào)地址修改,官方地址以下:
http://wiki.connect.qq.com/%E5%9B%9E%E8%B0%83%E5%9C%B0%E5%9D%80%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E5%8F%8A%E4%BF%AE%E6%94%B9%E6%96%B9%E6%B3%95
1切順暢出現(xiàn)以下頁面:
3 獲得access_token和openid方法我寫在回調(diào)action中,具體代碼以下:
package com.wingo.action.config;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.wingo.util.CommonUtil;
import com.wingo.util.ConfigUtil;
public class TencentLoginAction {
private static Logger log = LoggerFactory.getLogger(TencentLoginAction.class);
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
public String execute(){
String code = request.getParameter("code");
request.setAttribute("code", code);
/* 獲得access_token
* 成功后返回信息格式access_token=BA03E5Bxxxxxx950&expires_in=7776000&refresh_token=8972279xxxxxxF8752F
* 1般access_token有效期是3個月
*/
String parames = "grant_type=authorization_code&client_id="+ConfigUtil.CLIENT_ID+"&client_secret="+ConfigUtil.CLIENT_SECRET+"&code="+code+"&redirect_uri="+ConfigUtil.REDIRECT_URI;
String access_result = CommonUtil.httpsRequest(ConfigUtil.TOKEN_URL, "GET", parames);
if(access_result.contains("callback")){
/*當(dāng)返回的access_token是callback( {"error":100019,"error_description":"code to access token error"} )類似的數(shù)據(jù);
* 表示獲得access_token失敗,需要返回點擊QQ登陸頁面讓用戶重新登陸授權(quán)
*/
try {
response.sendRedirect("登陸頁面");
} catch (IOException e) {
e.printStackTrace();
}
}else {
String access_token = access_result.split("&")[0];
request.setAttribute("access_token", access_token);
/* 獲得openid
* 成功后返回信息格式:callback( {"client_id":"10xxxxx18","openid":"DDxxxxxxxxxxx587"} );
*/
String open_id = CommonUtil.httpsRequest(ConfigUtil.OPENID_URL, "GET", access_token);
request.setAttribute("openid", open_id);
if(open_id.contains("error")){
/*當(dāng)返回的open_id是callback( {"error":100007,"error_description":"param access token is wrong or lost "} );類似的數(shù)據(jù);
* 表示獲得open_id失敗,需要返回點擊QQ登陸頁面讓用戶重新登陸授權(quán)
*/
try {
response.sendRedirect("登陸頁面");
} catch (IOException e) {
e.printStackTrace();
}
}else {
String openId = open_id.substring(open_id.indexOf("openid")+9, open_id.lastIndexOf("""));
request.setAttribute("myOpenId", openId);
//TODO 我們可以將access_token與openid1起存入數(shù)據(jù)庫
/*發(fā)布1條不帶圖片的騰訊微博
*(注意:微博內(nèi)容140個漢子,即420字節(jié)。若在此處@好友,需要填寫好友的微博賬號而非昵稱)
* 默許返回json格式
* 如:{"data":{"id":"466544017145386","time":1421201332},"errcode":0,"msg":"ok","ret":0,"seqid":6104013246275818942}
* 其中ret為0表示成功
*/
parames = access_token+"&oauth_consumer_key="+ConfigUtil.CLIENT_ID+"&openid="+openId+"&content=LEO測試發(fā)布1條不帶圖片的騰訊微博";
String reslut = CommonUtil.httpsRequest(ConfigUtil.ADD_T_URL, "POST", parames);
request.setAttribute("reslut", reslut);
}
}
return "test";
}
}
上面相干的工具類代碼以下:
package com.wingo.util;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
CommonUtil工具類
/**
* 通用工具類
* @author 李欣樺
* @date 2014⑴1⑵1下午9:10:30
*/
public class CommonUtil {
private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
/**
* 發(fā)送https要求
*
* @param requestUrl 要求地址
* @param requestMethod 要求方式(GET、POST)
* @param outputStr 提交的數(shù)據(jù)
* @return 返回微佩服務(wù)器響應(yīng)的信息
*/
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
// 創(chuàng)建SSLContext對象,并使用我們指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 從上述SSLContext對象中得到SSLSocketFactory對象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 設(shè)置要求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 當(dāng)outputStr不為null時向輸出流寫數(shù)據(jù)
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意編碼格式
outputStream.write(outputStr.getBytes("UTF⑻"));
outputStream.close();
}
// 從輸入流讀取返回內(nèi)容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf⑻");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 釋放資源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
log.error("連接超時:{}", ce);
} catch (Exception e) {
log.error("https要求異常:{}", e);
}
return null;
}
public static String urlEncodeUTF8(String source){
String result = source;
try {
result = java.net.URLEncoder.encode(source,"utf⑻");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}
ConfigUtil工具類:
package com.wingo.util;
public class ConfigUtil {
//利用appid
public static final String CLIENT_ID= "101XXXXXX18";
//利用appsecret
public static final String CLIENT_SECRET = "21aXXXXXXXXXXXX86";
//授權(quán)成功后的回調(diào)地址
public static final String REDIRECT_URI = "http://loginXXXXXXXXte.action";
//獲得token的url(GET)獲得到access_token后有效期3個月
public static final String TOKEN_URL = "https://graph.qq.com/oauth2.0/token";
//獲得openid的url(GET)
public static final String OPENID_URL = "https://graph.qq.com/oauth2.0/me";
//發(fā)布1條不帶圖片的騰訊微博(POST)
public static final String ADD_T_URL = "https://graph.qq.com/t/add_t";
}
package com.wingo.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
MyX509TrustManager工具類:
/**
* 信任管理器
* @author 李欣樺
* @date 2014⑴1⑵1下午9:15:08
*/
public class MyX509TrustManager implements X509TrustManager {
// 檢查客戶端證書
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 檢查服務(wù)器端證書
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 返回受信任的X509證書數(shù)組
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
上面回調(diào)方法中獲得access_token,openid 時也能夠根據(jù)自己的需要傳其他參數(shù)。
官方地址:http://wiki.connect.qq.com/%E4%BD%BF%E7%94%A8authorization_code%E8%8E%B7%E5%8F%96access_token
除發(fā)布騰訊微博,還可以利用其他api獲得你想要的功能。api列表官方地址:http://wiki.connect.qq.com/api%E5%88%97%E8%A1%A8。具體使用方法可以參考上面回調(diào)地址中發(fā)布騰訊微博的代碼。
4 利用騰訊開發(fā)平臺組件可以分享內(nèi)容到QQ空間和朋友網(wǎng)(在彈出頁面,用戶也能夠選擇是不是分享到騰訊微博)。該組件不需要用戶授權(quán)也可以使用,當(dāng)沒有騰訊用戶是登錄狀態(tài)時(相對騰訊網(wǎng)),彈出的分享界面會讓分享用戶先登錄。官方網(wǎng)址:http://connect.qq.com/intro/share
例子以下: