QQ开放平台代码示例
腾讯开放平台
http://open.qq.com/tools?act=openapi_debug
测试类:
TestOpenApiV3
package demo;
import java.util.*;
import com.qq.open.OpenApiV3;
import com.qq.open.ErrorCode;
import com.qq.open.OpensnsException;
/**
* OpenAPI V3 SDK 示例代码
*
* @version 3.0.0
* @since jdk1.5
* @author open.qq.com
* @copyright © 2012, Tencent Corporation. All rights reserved.
* @History:
* 3.0.0 | nemozhang | 2012-03-21 12:01:05 | initialization
*
*/
public class TestOpenApiV3
{
public static void main(String args[])
{
// 应用基本信息
String appid = "1101765412";
String appkey = "ed4GFNj3nqLjNJF8";
// 用户的OpenID/OpenKey
String openid = "9B754E88EBEA9E906D6F496FCEBB4F76";
String openkey = "40CA7FAA1DF69E87B28AB5798BFC45B6";
//oauth_consumer_key=100330589&access_token=F9F6F34B8C5763E82A018F0208139913&openid=D8A612468696091AFB5C17F494FE456E&format=json
// OpenAPI的服务器IP
// 最新的API服务器地址请参考wiki文档: http://wiki.open.qq.com/wiki/API3.0%E6%96%87%E6%A1%A3
String serverName = "119.147.19.43";
// 所要访问的平台, pf的其他取值参考wiki文档: http://wiki.open.qq.com/wiki/API3.0%E6%96%87%E6%A1%A3
String pf = "qzone";
OpenApiV3 sdk = new OpenApiV3(appid, appkey);
sdk.setServerName(serverName);
System.out.println("===========test GetUserInfo===========");
testGetUserInfo(sdk, openid, openkey, pf);
}
/**
* 测试调用UserInfo接口
*
*/
public static void testGetUserInfo(OpenApiV3 sdk, String openid, String openkey, String pf)
{
// 指定OpenApi Cgi名字
String scriptName = "/v3/user/get_info";
// 指定HTTP请求协议类型
String protocol = "http";
// 填充URL请求参数
HashMap<String,String> params = new HashMap<String, String>();
params.put("openid", openid);
params.put("openkey", openkey);
params.put("pf", pf);
try
{
String resp = sdk.api(scriptName, params, protocol);
System.out.println(resp);
}
catch (OpensnsException e)
{
System.out.printf("Request Failed. code:%d, msg:%s\n", e.getErrorCode(), e.getMessage());
e.printStackTrace();
}
}
}
OpenApiV3
package com.qq.open;
import java.util.*;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;
import java.net.*;
import com.qq.open.SnsNetwork;
import com.qq.open.SnsSigCheck;
import com.qq.open.SnsStat;
import org.json.JSONObject;
import org.json.JSONException;
import org.apache.commons.httpclient.methods.multipart.FilePart;
/**
* 提供访问腾讯开放平台 OpenApiV3 的接口
*
* @version 3.0.2
* @since jdk1.5
* @author open.qq.com
* @copyright © 2012, Tencent Corporation. All rights reserved.
* @History:
* 3.0.3 | coolinchen| 2012-11-07 11:20:12 | support POST request in "multipart/form-data" format
* 3.0.2 | coolinchen| 2012-10-08 11:20:12 | support printing request string and result
* 3.0.1 | nemozhang | 2012-08-28 16:40:20 | support cpay callback sig verifictaion
* 3.0.0 | nemozhang | 2012-03-21 12:01:05 | initialization
*
*/
public class OpenApiV3
{
/**
* 构造函数
*
* @param appid 应用的ID
* @param appkey 应用的密钥
*/
public OpenApiV3(String appid, String appkey)
{
this.appid = appid;
this.appkey = appkey;
}
/**
* 设置OpenApi服务器的地址
*
* @param serverName OpenApi服务器的地址
*/
public void setServerName(String serverName)
{
this.serverName = serverName;
}
/**
* 执行API调用
*
* @param scriptName OpenApi CGI名字 ,如/v3/user/get_info
* @param params OpenApi的参数列表
* @param protocol HTTP请求协议 "http" / "https"
* @return 返回服务器响应内容
*/
public String api(String scriptName, HashMap<String, String> params, String protocol) throws OpensnsException
{
// 检查openid openkey等参数
if (params.get("openid") == null)
{
throw new OpensnsException(ErrorCode.PARAMETER_EMPTY, "openid is empty");
}
if (!isOpenid(params.get("openid")))
{
throw new OpensnsException(ErrorCode.PARAMETER_INVALID, "openid is invalid");
}
// 无需传sig,会自动生成
params.remove("sig");
// 添加固定参数
params.put("appid", this.appid);
// 请求方法
String method = "post";
// 签名密钥
String secret = this.appkey + "&";
// 计算签名
String sig = SnsSigCheck.makeSig(method, scriptName, params, secret);
params.put("sig", sig);
StringBuilder sb = new StringBuilder(64);
sb.append(protocol).append("://").append(this.serverName).append(scriptName);
String url = sb.toString();
// cookie
HashMap<String, String> cookies = null;
long startTime = System.currentTimeMillis();
//通过调用以下方法,可以打印出最终发送到openapi服务器的请求参数以及url,默认注释
//printRequest(url,method,params);
// 发送请求
String resp = SnsNetwork.postRequest(url, params, cookies, protocol);
// 解码JSON
JSONObject jo = null;
try
{
jo = new JSONObject(resp);
}
catch (JSONException e)
{
throw new OpensnsException(ErrorCode.RESPONSE_DATA_INVALID, e);
}
// 检测ret值
int rc = jo.optInt("ret", 0);
// 统计上报
SnsStat.statReport(startTime, serverName, params, method, protocol, rc,scriptName);
//通过调用以下方法,可以打印出调用openapi请求的返回码以及错误信息,默认注释
//printRespond(resp);
return resp;
}
/**
* 执行API调用
*
* @param scriptName OpenApi CGI名字 ,如/v3/user/get_info
* @param params OpenApi的参数列表
* @param fp 上传的文件
* @param protocol HTTP请求协议 "http" / "https"
* @return 返回服务器响应内容
*/
public String apiUploadFile(String scriptName, HashMap<String, String> params, FilePart fp,String protocol) throws OpensnsException
{
// 检查openid openkey等参数
if (params.get("openid") == null)
{
throw new OpensnsException(ErrorCode.PARAMETER_EMPTY, "openid is empty");
}
if (!isOpenid(params.get("openid")))
{
throw new OpensnsException(ErrorCode.PARAMETER_INVALID, "openid is invalid");
}
// 无需传sig,会自动生成
params.remove("sig");
// 添加固定参数
params.put("appid", this.appid);
// 请求方法
String method = "post";
// 签名密钥
String secret = this.appkey + "&";
// 计算签名
String sig = SnsSigCheck.makeSig(method, scriptName, params, secret);
params.put("sig", sig);
StringBuilder sb = new StringBuilder(64);
sb.append(protocol).append("://").append(this.serverName).append(scriptName);
String url = sb.toString();
// cookie
HashMap<String, String> cookies = null;
long startTime = System.currentTimeMillis();
//通过调用以下方法,可以打印出最终发送到openapi服务器的请求参数以及url,默认注释
//printRequest(url,method,params);
// 发送请求
String resp = SnsNetwork.postRequestWithFile(url, params, cookies, fp,protocol);
// 解码JSON
JSONObject jo = null;
try
{
jo = new JSONObject(resp);
}
catch (JSONException e)
{
throw new OpensnsException(ErrorCode.RESPONSE_DATA_INVALID, e);
}
// 检测ret值
int rc = jo.optInt("ret", 0);
// 统计上报
SnsStat.statReport(startTime, serverName, params, method, protocol, rc,scriptName);
//通过调用以下方法,可以打印出调用openapi请求的返回码以及错误信息,默认注释
//printRespond(resp);
return resp;
}
/**
* 辅助函数,打印出完整的请求串内容
*
* @param url 请求cgi的url
* @param method 请求的方式 get/post
* @param params OpenApi的参数列表
*/
private void printRequest(String url,String method,HashMap<String, String> params) throws OpensnsException
{
System.out.println("==========Request Info==========\n");
System.out.println("method: " + method);
System.out.println("url: " + url);
System.out.println("params:");
System.out.println(params);
System.out.println("querystring:");
StringBuilder buffer = new StringBuilder(128);
Iterator iter = params.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
try
{
buffer.append(URLEncoder.encode((String)entry.getKey(), "UTF-8").replace("+", "%20").replace("*", "%2A")).append("=").append(URLEncoder.encode((String)entry.getValue(), "UTF-8").replace("+", "%20").replace("*", "%2A")).append("&");
}
catch(UnsupportedEncodingException e)
{
throw new OpensnsException(ErrorCode.MAKE_SIGNATURE_ERROR, e);
}
}
String tmp = buffer.toString();
tmp = tmp.substring(0,tmp.length()-1);
System.out.println(tmp);
System.out.println();
}
/**
* 辅助函数,打印出完整的执行的返回信息
*
* @return 返回服务器响应内容
*/
private void printRespond(String resp)
{
System.out.println("===========Respond Info============");
System.out.println(resp);
}
/**
* 验证openid是否合法
*/
private boolean isOpenid(String openid)
{
return (openid.length()==32) && openid.matches("^[0-9A-Fa-f]+$");
}
private String appid;;
private String appkey;
private String serverName;
}
SnsNetwork:发送HTTP网络请求类
package com.qq.open;
import java.util.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.MultipartPostMethod;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import com.qq.open.OpensnsException;
import com.qq.open.ErrorCode;
import com.qq.open.https.MySecureProtocolSocketFactory;
/**
* 发送HTTP网络请求类
*
* @version 3.0.0
* @since jdk1.5
* @author open.qq.com
* @copyright © 2012, Tencent Corporation. All rights reserved.
* @History:
* 3.0.1 | coolinchen| 2012-11-07 11:20:12 | support POST request in "multipart/form-data" format
* 3.0.0 | nemozhang | 2012-03-21 12:01:05 | initialization
*
*/
public class SnsNetwork
{
/**
* 发送POST请求
*
* @param url 请求URL地址
* @param params 请求参数
* @param protocol 请求协议 "http" / "https"
* @return 服务器响应的请求结果
* @throws OpensnsException 网络故障时抛出异常。
*/
public static String postRequest(
String url,
HashMap<String, String> params,
HashMap<String, String> cookies,
String protocol) throws OpensnsException
{
if (protocol.equalsIgnoreCase("https"))
{
Protocol httpsProtocol = new Protocol("https",
new MySecureProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", httpsProtocol);
}
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url);
// 设置请求参数
if (params != null && !params.isEmpty())
{
NameValuePair[] data = new NameValuePair[params.size()];
Iterator iter = params.entrySet().iterator();
int i=0;
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
data[i] = new NameValuePair((String)entry.getKey(), (String)entry.getValue());
++i;
}
postMethod.setRequestBody(data);
}
// 设置cookie
if (cookies !=null && !cookies.isEmpty())
{
Iterator iter = cookies.entrySet().iterator();
StringBuilder buffer = new StringBuilder(128);
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
buffer.append((String)entry.getKey()).append("=").append((String)entry.getValue()).append("; ");
}
// 设置cookie策略
postMethod.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
// 设置cookie内容
postMethod.setRequestHeader("Cookie", buffer.toString());
}
// 设置User-Agent
postMethod.setRequestHeader("User-Agent", "Java OpenApiV3 SDK Client");
// 设置建立连接超时时间
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECTION_TIMEOUT);
// 设置读数据超时时间
httpClient.getHttpConnectionManager().getParams().setSoTimeout(READ_DATA_TIMEOUT);
// 设置编码
postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,
CONTENT_CHARSET);
//使用系统提供的默认的恢复策略
postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
try
{
try
{
int statusCode = httpClient.executeMethod(postMethod);
if (statusCode != HttpStatus.SC_OK)
{
throw new OpensnsException(ErrorCode.NETWORK_ERROR, "Request [" + url + "] failed:" + postMethod.getStatusLine());
}
//读取内容
byte[] responseBody = postMethod.getResponseBody();
return new String(responseBody, CONTENT_CHARSET);
}
finally
{
//释放链接
postMethod.releaseConnection();
}
}
catch (HttpException e)
{
//发生致命的异常,可能是协议不对或者返回的内容有问题
throw new OpensnsException(ErrorCode.NETWORK_ERROR, "Request [" + url + "] failed:" + e.getMessage());
}
catch (IOException e)
{
//发生网络异常
throw new OpensnsException(ErrorCode.NETWORK_ERROR, "Request [" + url + "] failed:" + e.getMessage());
}
}
/**
* 发送POST请求
*
* @param url 请求URL地址
* @param params 请求参数
* @param protocol 请求协议 "http" / "https"
* @param fp 上传的文件
* @return 服务器响应的请求结果
* @throws OpensnsException 网络故障时抛出异常。
*/
public static String postRequestWithFile(
String url,
HashMap<String, String> params,
HashMap<String, String> cookies,
FilePart fp,
String protocol) throws OpensnsException
{
if (protocol.equalsIgnoreCase("https"))
{
Protocol httpsProtocol = new Protocol("https",
new MySecureProtocolSocketFactory(), 443);
Protocol.registerProtocol("https", httpsProtocol);
}
HttpClient httpClient = new HttpClient();
//上传文件要使用MultipartPostMethod类
MultipartPostMethod postMethod = new MultipartPostMethod(url);
//将FilePart类型的文件加到参数里
postMethod.addPart(fp);
// 设置请求参数
if (params != null && !params.isEmpty())
{
Iterator iter = params.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
//设置参数为UTF-8编码集,解决中文乱码问题,并且将参数加到post中
postMethod.addPart(new StringPart((String)entry.getKey(), (String)entry.getValue(), CONTENT_CHARSET));
}
}
// 设置cookie
if (cookies !=null && !cookies.isEmpty())
{
Iterator iter = cookies.entrySet().iterator();
StringBuilder buffer = new StringBuilder(128);
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
buffer.append((String)entry.getKey()).append("=").append((String)entry.getValue()).append("; ");
}
// 设置cookie策略
postMethod.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
// 设置cookie内容
postMethod.setRequestHeader("Cookie", buffer.toString());
}
// 设置User-Agent
postMethod.setRequestHeader("User-Agent", "Java OpenApiV3 SDK Client");
// 设置建立连接超时时间
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(CONNECTION_TIMEOUT);
// 设置读数据超时时间
httpClient.getHttpConnectionManager().getParams().setSoTimeout(READ_DATA_TIMEOUT);
//使用系统提供的默认的恢复策略
postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
//发送请求
try
{
try
{
postMethod.getParams().setContentCharset("UTF-8");
int statusCode = httpClient.executeMethod(postMethod);
if (statusCode != HttpStatus.SC_OK)
{
throw new OpensnsException(ErrorCode.NETWORK_ERROR, "Request [" + url + "] failed:" + postMethod.getStatusLine());
}
//读取内容
byte[] responseBody = postMethod.getResponseBody();
return new String(responseBody, CONTENT_CHARSET);
}
finally
{
//释放链接
postMethod.releaseConnection();
}
}
catch (HttpException e)
{
//发生致命的异常,可能是协议不对或者返回的内容有问题
throw new OpensnsException(ErrorCode.NETWORK_ERROR, "Request [" + url + "] failed:" + e.getMessage());
}
catch (IOException e)
{
//发生网络异常
throw new OpensnsException(ErrorCode.NETWORK_ERROR, "Request [" + url + "] failed:" + e.getMessage());
}
}
// 编码方式
private static final String CONTENT_CHARSET = "UTF-8";
// 连接超时时间
private static final int CONNECTION_TIMEOUT = 3000;
// 读数据超时时间
private static final int READ_DATA_TIMEOUT = 3000;
}
这里示例的是如下接口:
http://[域名]/v3/user/get_info
正式环境域名或测试环境IP详见:API3.0文档#请求URL说明。
json
GET, POST
TRUE
各个参数请进行URL 编码,编码时请遵守 RFC 1738
(1)公共参数
参数名称 | 是否必须 | 类型 | 描述 |
---|---|---|---|
openid | 必须 | string | 与APP通信的用户key。从平台跳转到应用时会调用应用的CanvasURL,平台会在CanvasURL后带上本参数。由平台直接传给应用,应用原样传给平台即可。 根据APPID以及QQ号码生成,即不同的appid下,同一个QQ号生成的OpenID是不一样的。 |
openkey | 必须 | string | session key。从平台跳转到应用时会调用应用的CanvasURL,平台会在CanvasURL后带上本参数。由平台直接传给应用,应用原样传给平台即可。 注: |
appid | 必须 | unsigned int | 应用的唯一ID。可以通过appid查找APP基本信息。 |
sig | 必须 | string | 请求串的签名,以appkey作为密钥,具体签名算法见腾讯开放平台第三方应用签名参数sig的说明。 |
pf | 必须 | string | 应用的来源平台。从平台跳转到应用时会调用应用的CanvasURL,平台会在CanvasURL后带上本参数。由平台直接传给应用,应用原样传给平台即可。 注: |
format | string | 定义API返回的数据格式。 取值说明:为xml时表示返回的格式是xml;为json时表示返回的格式是json。 | |
userip | string | 用户的IP。 应用服务器得到的remote_ip和x_forward_ip是10.x.x.x,由上一层腾讯路由转发。 |
(2)私有参数
参数名称 | 是否必须 | 类型 | 描述 |
---|---|---|---|
charset | string | 指定请求及响应的字符集,取值为gbk或utf-8(只有pf=qqgame或pf=3366时,可以输入该参数)。 默认值为utf-8,其他非法取值也认为是utf-8。 | |
flag | unsigned int | pf=qqgame时,必须输入该参数,指定需要获取QQGame中的哪些信息: 1:需要获取游戏昵称和性别; |
http://openapi.tencentyun.com/v3/user/get_info?
openid=B624064BA065E01CB73F835017FE96FA&
openkey=5F154D7D2751AEDC8527269006F290F70297B7E54667536C&
appid=2&
sig=VrN%2BTn5J%2Fg4IIo0egUdxq6%2B0otk%3D&
pf=qzone&
format=json&
userip=112.90.139.30
参数名称 | 描述 |
---|---|
ret | 返回码。详见公共返回码说明#OpenAPI V3.0 返回码。 |
msg | 如果错误,返回错误信息。 |
is_lost | 判断是否有数据丢失。如果应用不使用cache,不需要关心此参数。 0或者不返回:没有数据丢失,可以缓存。 |
nickname | 昵称。 |
gender | 性别。 |
country | 国家(当pf=qzone、pengyou或qplus时返回)。 |
province | 省(当pf=qzone、pengyou或qplus时返回)。 |
city | 市(当pf=qzone、pengyou或qplus时返回)。 |
figureurl | 头像URL。详见:前端页面规范#6. 关于用户头像的获取和尺寸说明。 |
openid | 用户QQ号码转化得到的ID(当pf=qplus时返回)。 |
qq_level | 用户QQ等级(当pf=qplus时返回)。 |
qq_vip_level | 用户QQ会员等级(当pf=qplus时返回)。 |
qplus_level | 用户Q+等级(当pf=qplus时返回)。 |
is_yellow_vip | 是否为黄钻用户(0:不是; 1:是)。 (当pf=qzone、pengyou或qplus时返回) |
is_yellow_year_vip | 是否为年费黄钻用户(0:不是; 1:是)。 (当pf=qzone、pengyou或qplus时返回) |
yellow_vip_level | 黄钻等级,目前最高级别为黄钻8级(如果是黄钻用户才返回此参数)。 (当pf=qzone、pengyou或qplus时返回) |
is_yellow_high_vip | 是否为豪华版黄钻用户(0:不是; 1:是)。 (当pf=qzone、pengyou或qplus时返回) |
is_blue_vip | 是否为蓝钻用户(0:不是; 1:是)。 (当pf=qqgame或3366时返回) |
is_blue_year_vip | 是否为年费蓝钻用户(0:不是; 1:是)。 (当pf=qqgame或3366时返回) |
blue_vip_level | 蓝钻等级(如果是蓝钻用户才返回此参数)。 (当pf=qqgame或3366时返回) |
3366_level | 3366用户的大等级。 (当pf=3366时返回) |
3366_level_name | 3366用户的等级名,如小游游、小游仙。 (当pf=3366时返回) |
3366_grow_level | 3366用户的成长等级。 (当pf=3366时返回) |
3366_grow_value | 3366用户的成长值。 (当pf=3366时返回) |
is_super_blue_vip | 是否是豪华蓝钻。 (当pf=qqgame或3366时返回) |
公共错误返回码:公共返回码说明#OpenAPI V3.0 返回码。
本接口私有错误返回码:暂无。
调用结果:
===========test GetUserInfo===========
{
"ret": 0,
"is_lost": 0,
"nickname": "點球踢勺子",
"gender": "男",
"country": "尼加拉瓜",
"province": "",
"city": "埃斯特利",
"figureurl": "http:\/\/thirdapp2.qlogo.cn\/qzopenapp\/f222d66b35733712e2fa2eba757a4520f1c85d1305ac0be31df25de8c74c46b4\/50",
"is_yellow_vip": 0,
"is_yellow_year_vip": 0,
"yellow_vip_level": 0,
"is_yellow_high_vip": 0
}