1.準備工作
只是登錄無(wú)需申請新浪和騰迅的開(kāi)發(fā)者賬號,如果需要發(fā)送微博功能,需要申請一個(gè)新浪和騰迅的開(kāi)發(fā)者賬號,并添加一個(gè)測試應用。
過(guò)程請參考官方幫助文檔,申請地址:新浪:http://open.weibo.com 騰迅:http://dev.t.qq.com/
我們需要的是App Key和App Secre及redirect_URI,源代碼中已經(jīng)包含了我申請的測試key,但由于限制直接用我的key你們的賬號是無(wú)法登錄成功的。
2.注意事項
1)需要注意的是應用的App Key和App Secre及redirect_URI,對應項目根目錄下的config.properties配置文件中的
client_ID=1745656892client_SERCRET=66056719c1d8ca7bcaf36f411217cefaredirect_URI=www.baidu.com
redirect_URI由于只是測試用并沒(méi)有直接的回調頁(yè)面,所以這里隨便填寫(xiě)一個(gè)地址就行了,但要注意與應用-高級設置里的“回調頁(yè)面”一致。
2)代碼中的測試賬號需要要自己添加測試賬號,新浪的在“應用信息-測試賬號”;騰迅的在“權限控制-創(chuàng )建白名單”中。當然直接用
開(kāi)發(fā)者賬號也可以。
3)發(fā)送微博引用了新浪的 weibo4j-oauth2-beta2.1.1.zip,騰迅的 Java_SDK_v1.2.1.7z。核心類(lèi)在util包下。
3.關(guān)鍵代碼
1)新浪
package org.utils;import java.io.IOException;import java.util.ArrayList;import java.util.List;import org.apache.commons.httpclient.Header;import org.apache.commons.httpclient.HttpClient;import org.apache.commons.httpclient.methods.PostMethod;import org.apache.commons.httpclient.params.HttpMethodParams;import org.apache.http.HttpException;import org.core.weibo.sina.Oauth;import org.core.weibo.sina.Timeline;import org.core.weibo.sina.http.AccessToken;import org.core.weibo.sina.model.WeiboException;import org.core.weibo.sina.weibo4j.util.WeiboConfig;/*** * 模擬自動(dòng)登錄并發(fā)微博 * @author zdw * */public class Sina { /*** * 模擬登錄并得到登錄后的Token * @param username 用戶(hù)名 * @param password 密碼 * @return * @throws HttpException * @throws IOException */ public static AccessToken getToken(String username,String password) throws HttpException, IOException { String clientId = WeiboConfig.getValue("client_ID") ; String redirectURI = WeiboConfig.getValue("redirect_URI") ; String url = WeiboConfig.getValue("authorizeURL"); PostMethod postMethod = new PostMethod(url); //應用的App Key postMethod.addParameter("client_id",clientId); //應用的重定向頁(yè)面 postMethod.addParameter("redirect_uri",redirectURI); //模擬登錄參數 //開(kāi)發(fā)者或測試賬號的用戶(hù)名和密碼 postMethod.addParameter("userId", username); postMethod.addParameter("passwd", password); postMethod.addParameter("isLoginSina", "0"); postMethod.addParameter("action", "submit"); postMethod.addParameter("response_type","code"); HttpMethodParams param = postMethod.getParams(); param.setContentCharset("UTF-8"); //添加頭信息 List<Header> headers = new ArrayList<Header>(); headers.add(new Header("Referer", "https://api.weibo.com/oauth2/authorize?client_id="+clientId+"&redirect_uri="+redirectURI+"&from=sina&response_type=code")); headers.add(new Header("Host", "api.weibo.com")); headers.add(new Header("User-Agent","Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0")); HttpClient client = new HttpClient(); client.getHostConfiguration().getParams().setParameter("http.default-headers", headers); client.executeMethod(postMethod); int status = postMethod.getStatusCode(); System.out.println(status); if (status != 302) { System.out.println("token刷新失敗"); return null; } //解析Token Header location = postMethod.getResponseHeader("Location"); if (location != null) { String retUrl = location.getValue(); int begin = retUrl.indexOf("code="); if (begin != -1) { int end = retUrl.indexOf("&", begin); if (end == -1) end = retUrl.length(); String code = retUrl.substring(begin + 5, end); if (code != null) { Oauth oauth = new Oauth(); try{ AccessToken token = oauth.getAccessTokenByCode(code); return token; }catch(Exception e){ e.printStackTrace(); } } } } return null; } /** * 發(fā)微博 * @param token 認證Token * @param content 微博內容 * @return * @throws Exception */ public static boolean sinaSendWeibo(String token,String content) throws Exception { boolean flag = false ; Timeline timeline = new Timeline(); timeline.client.setToken(token); try { timeline.UpdateStatus(content); flag = true ; } catch (WeiboException e) { flag = false ; System.out.println(e.getErrorCode()); } return flag; } public static void main(String[] args) throws Exception { AccessToken at = getToken("xxxx","xxx"); sinaSendWeibo(at.getAccessToken(),"測試呢"); }} 騰迅:
package org.utils;import java.io.ByteArrayOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.util.Scanner;import net.sf.json.JSONObject;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.util.EntityUtils;import org.core.weibo.tencent.api.UserAPI;import org.core.weibo.tencent.oauthv2.OAuthV2;import org.core.weibo.tencent.oauthv2.OAuthV2Client;/*** * 騰迅自動(dòng)登錄并獲取個(gè)人信息 * @author zdw * */public class Tencent{ public static final String HEXSTRING = "0123456789ABCDEF"; public static OAuthV2 oAuth = new OAuthV2(); private static HttpClient client = new DefaultHttpClient(); // 初始oAuth應用信息 public static void init(OAuthV2 oAuth) { oAuth.setClientId("801216331"); oAuth.setClientSecret("ea71b26b0cbe5778cdd1c09ad17553a3"); oAuth.setRedirectUri("http://www.tencent.com/zh-cn/index.shtml"); } /** * * @param qq * http://check.ptlogin2.qq.com/check?uin={0}&appid=15000101&r={1 } * 返回的第三個(gè)值 * @param password * QQ密碼 * @param verifycode * 驗證碼 * @return 加密后的密碼 * @throws UnsupportedEncodingException * @throws Exception * */ public static String GetPassword(String qq, String password, String verifycode) throws Exception { String P = hexchar2bin(md5(password)); String U = md5(P + hexchar2bin(qq.replace("\\x", "").toUpperCase())); String V = md5(U + verifycode.toUpperCase()); return V; } public static String md5(String originalText) throws Exception { byte buf[] = originalText.getBytes("ISO-8859-1"); StringBuffer hexString = new StringBuffer(); String result = ""; String digit = ""; try { MessageDigest algorithm = MessageDigest.getInstance("MD5"); algorithm.reset(); algorithm.update(buf); byte[] digest = algorithm.digest(); for (int i = 0; i < digest.length; i++) { digit = Integer.toHexString(0xFF & digest[i]); if (digit.length() == 1) { digit = "0" + digit; } hexString.append(digit); } result = hexString.toString(); } catch (Exception ex) { result = ""; } return result.toUpperCase(); } public static String hexchar2bin(String md5str) throws UnsupportedEncodingException { ByteArrayOutputStream baos = new ByteArrayOutputStream(md5str.length() / 2); for (int i = 0; i < md5str.length(); i = i + 2) { baos.write((HEXSTRING.indexOf(md5str.charAt(i)) << 4 | HEXSTRING .indexOf(md5str.charAt(i + 1)))); } return new String(baos.toByteArray(), "ISO-8859-1"); } /*** * 模擬登錄 * @param qq QQ號碼 * @param password QQ密碼 * @throws Exception */ public static void login(String qq, String password) throws Exception { HttpGet get = new HttpGet("https://ssl.ptlogin2.qq.com/check?uin="+ qq + "&appid=46000101&ptlang=2052&js_type=2&js_ver=10009&r=0.7948186025712065"); HttpResponse response = client.execute(get); String entity = EntityUtils.toString(response.getEntity()); String[] checkNum = entity.substring(entity.indexOf("(") + 1,entity.lastIndexOf(")")).replace("'", "").split(","); String pass = ""; String responseData = ""; // 獲取驗證碼(如果有驗證碼輸出到C:/code.jpg,查看后輸入可繼續執行 if ("1".equals(checkNum[0])) { // uin為qq號或者微博用戶(hù)名 HttpGet getimg = new HttpGet("http://captcha.qq.com/getimage?aid=46000101&r=0.3478789969909082&uin=" + qq + "&vc_type=" + checkNum[1] + ""); HttpResponse response2 = client.execute(getimg); OutputStream os = new FileOutputStream("c:/code.jpg"); byte[] b = EntityUtils.toByteArray(response2.getEntity()); os.write(b, 0, b.length); os.close(); Scanner in = new Scanner(System.in); responseData = in.nextLine(); in.close(); } else { responseData = checkNum[1]; } /** *******************加密密碼 ************************** */ pass = GetPassword(checkNum[2], password, responseData); /** *********************** 登錄 *************************** */ HttpGet getimg = new HttpGet("https://ssl.ptlogin2.qq.com/login?ptlang=2052&u="+ qq+ "&p="+ pass+ "&verifycode="+ responseData+ "&aid=46000101&target=top&u1=https%3A%2F%2Fopen.t.qq.com%2Fcgi-bin%2Foauth2%2Fauthorize%3Fclient_id%3D" + oAuth.getClientId()+ "%26response_type%3Dcode%26redirect_uri="+ oAuth.getRedirectUri()+ "&ptredirect=1&h=1&from_ui=1&dumy=&qlogin_param=abbfew=ddd&wording=%E6%8E%88%E6%9D%83&fp=loginerroralert&action=8-13-240977&g=1&t=1&dummy=&js_type=2&js_ver=10009"); HttpResponse response2 = client.execute(getimg); HttpEntity httpentity = response2.getEntity(); String entityxc = EntityUtils.toString(httpentity); System.out.println(entityxc); } /** * * 請求微博開(kāi)放平臺應用 返回登錄授權頁(yè)面,但是如果沒(méi)有sessionKey的話(huà)永遠登錄不成功 sessionKey * 發(fā)現在返回的頁(yè)面中一個(gè)input標簽里放的url中有,所以要取到這個(gè)sessionKey 其實(shí)直接訪(fǎng)問(wèn)標簽中的url就可以跳轉 * */ public static String getUrl() throws ClientProtocolException, IOException { HttpGet getcode = new HttpGet("https://open.t.qq.com/cgi-bin/oauth2/authorize?client_id="+ oAuth.getClientId()+ "&response_type=code&redirect_uri=" + oAuth.getRedirectUri()+ "&checkStatus=yes&appfrom=&g_tk&checkType=showAuth&state="); HttpResponse response3 = client.execute(getcode); HttpEntity entityqqq = response3.getEntity(); String entityxcc = EntityUtils.toString(entityqqq); String form = entityxcc.substring(entityxcc.indexOf("<form"), entityxcc .indexOf("</form>")); String[] ss = form.split("/>"); String input = ""; for (int i = 0; i < ss.length; i++) { if (ss[i].indexOf("name=\"u1\"") > 0) { input = ss[i]; } ; } return input.substring(input.indexOf("value=\"") + 7, input.indexOf("\" type=\"")); } /** * 解析并設置Token * @param get * @throws Exception */ public static void setToken(HttpGet get) throws Exception { HttpResponse response4 = client.execute(get); HttpEntity entityqqq1 = response4.getEntity(); String getUrlcode = EntityUtils.toString(entityqqq1); // 返回了最終跳轉的頁(yè)面URL,也就是回調頁(yè)redirect_uri,頁(yè)面地址上包含code openid openkey // 需要將這三個(gè)值單獨取出來(lái)再拼接成 code=xxxxx&openid=xxxxx&openkey=xxxxxx的形式 String entity = getUrlcode.substring(getUrlcode.indexOf("url="),getUrlcode.indexOf("\">")); StringBuffer sb = new StringBuffer(); String[] arr = entity.split("\\?")[1].split("&"); for (int x = 0; x < arr.length; x++) { if (arr[x].indexOf("code") >= 0 || arr[x].indexOf("openid") >= 0 || arr[x].indexOf("openkey") >= 0) { sb.append(arr[x] + "&"); } ; } // 利用code獲取accessToken OAuthV2Client.parseAuthorization(sb.substring(0, sb.length() - 1), oAuth); oAuth.setGrantType("authorize_code"); OAuthV2Client.accessToken(oAuth); } /*** * 調用(騰迅開(kāi)放平臺賬戶(hù)接口)獲取一個(gè)人的信息 * @throws Exception */ public static void getInfo() throws Exception { //輸出Token,如果拿到了Token就代表登錄成功,并可以進(jìn)行下一步操作。 System.out.println("Token="+oAuth.getAccessToken()); UserAPI getuser = new UserAPI(oAuth.getOauthVersion()); String userJson = getuser.otherInfo(oAuth, "json", "", oAuth.getOpenid()); JSONObject userJsonObject = JSONObject.fromObject(userJson); Integer errcode = (Integer) userJsonObject.get("errcode"); if (errcode == 0) { JSONObject userdataJsonObject = (JSONObject) userJsonObject.get("data"); System.out.println(userdataJsonObject.toString()); } } public static void main(String[] args) throws Exception { init(oAuth); login("123145", "xxxx"); HttpGet get = new HttpGet(getUrl()); setToken(get); getInfo(); }} 4.發(fā)送成功都有對應的日志輸出
新浪(最后一行日志):
2078 DEBUG [2013-03-14 16:35:29] {"created_at":"Thu Mar 14 16:35:30 +0800 2013","id":3555791132949940,"mid":"3555791132949940","idstr":"3555791132949940","text":"測試呢","source":"... 登錄成功的日志標志:
ptuiCB('0','0','https://open.t.qq.com/cgi-bin/oauth2/authorize?client_id=801216331&response_type=code&redirect_uri=http:','1','登錄成功!', 'ㄗs:ヤ淡 啶');查看個(gè)人信息成功后的日志標志:
QHttpClient httpGet [3] Response = {"data":{"birth_day":26,"birth_month":8,"birth_year":2011,"city_code":"2","comp":null,"country_code":"1","edu":null,"email":"","exp":141,"fansnum":.. 聯(lián)系客服