All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.taobao.api.DefaultTaobaoClient Maven / Gradle / Ivy

The newest version!
package com.taobao.api;

import java.io.IOException;
import java.net.Proxy;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.aliyun.api.internal.mapping.RequestBodyConverter;
import com.qimen.api.QimenRequest;
import com.taobao.api.internal.cluster.ClusterManager;
import com.taobao.api.internal.cluster.DnsConfig;
import com.taobao.api.internal.dto.RequestDTO;
import com.taobao.api.internal.parser.json.ObjectJsonParser;
import com.taobao.api.internal.parser.xml.ObjectXmlParser;
import com.taobao.api.internal.util.*;

/**
 * 基于REST的TOP客户端。
 * 
 * @author carver.gu
 * @since 1.0, Sep 13, 2009
 */
public class DefaultTaobaoClient implements TaobaoClient {

	protected String serverUrl;
	protected String appKey;
	protected String appSecret;
	protected String format = Constants.FORMAT_JSON;
	protected String signMethod = Constants.SIGN_METHOD_HMAC_SHA256;
	protected int connectTimeout = 15000; // 默认连接超时时间为15秒
	protected int readTimeout = 30000; // 默认响应超时时间为30秒
	protected boolean needCheckRequest = true; // 是否在客户端校验请求
	protected boolean needEnableParser = true; // 是否对响应结果进行解释
	protected boolean useSimplifyJson = false; // 是否采用精简化的JSON返回
	protected boolean useGzipEncoding = true; // 是否启用响应GZIP压缩
	private   boolean isHttpDnsEnabled = false; //是否启用了httpdns
    private   String  originalHttpHost = null;  //原始请求Host
	private String version = "2.0";

	private Proxy proxy; //代理类
    
    public DefaultTaobaoClient(String serverUrl, String appKey, String appSecret) {
		this.appKey = appKey;
		this.appSecret = appSecret;
		this.serverUrl = serverUrl;
	}

	public DefaultTaobaoClient(String serverUrl, String appKey, String appSecret, String format) {
		this(serverUrl, appKey, appSecret);
		this.format = format;
	}

	public DefaultTaobaoClient(String serverUrl, String appKey, String appSecret, String format, int connectTimeout, int readTimeout) {
		this(serverUrl, appKey, appSecret, format);
		this.connectTimeout = connectTimeout;
		this.readTimeout = readTimeout;
	}

	public DefaultTaobaoClient(String serverUrl, String appKey, String appSecret, String format, int connectTimeout, int readTimeout, String signMethod) {
		this(serverUrl, appKey, appSecret, format, connectTimeout, readTimeout);
		this.signMethod = signMethod;
	}

	public  T execute(TaobaoRequest request) throws ApiException {
		return execute(request, null);
	}

	public  T execute(TaobaoRequest request, String session) throws ApiException {
		return _execute(request, session);
	}

	private  T _execute(TaobaoRequest request, String session) throws ApiException {
		long start = System.currentTimeMillis();

		// 构建响应解释器
		TaobaoParser parser = buildParser(request);

		// 本地校验请求参数
		if (this.needCheckRequest) {
			try {
				request.check();
			} catch (ApiRuleException e) {
				T localResponse = null;
				try {
					localResponse = request.getResponseClass().newInstance();
				} catch (Exception xe) {
					throw new ApiException(xe);
				}
				localResponse.setErrorCode(e.getErrCode());
				localResponse.setMsg(e.getErrMsg());
				return localResponse;
			}
		}

		RequestParametersHolder requestHolder = invokeApi(request, session, start);

		T tRsp = parseBody(parser, request, requestHolder);

		tRsp.setParams(requestHolder.getApplicationParams());
		if (!tRsp.isSuccess()) {
			TaobaoLogger.logApiError(appKey, request.getApiMethodName(), serverUrl, requestHolder.getAllParams(), System.currentTimeMillis() - start, tRsp.getBody());
		}
		return tRsp;
	}

	public String getServerUrl(String serverUrl, String apiName, String session,TaobaoHashMap appParams) {
	    if(isHttpDnsEnabled){
	        DnsConfig dnsConfig = ClusterManager.GetDnsConfigFromCache();
	        if (dnsConfig == null) {
	            return serverUrl;
	        } else {
	            return dnsConfig.getVipUrl(serverUrl);
	        }
	    }
        return serverUrl;
	}

	public String getSdkVersion() {
	    if(isHttpDnsEnabled){
	        return Constants.SDK_VERSION_HTTPDNS;   
	    }
		return Constants.SDK_VERSION;
	}

	/**
	 * 是否在客户端校验请求参数。
	 */
	public void setNeedCheckRequest(boolean needCheckRequest) {
		this.needCheckRequest = needCheckRequest;
	}

	/**
	 * 是否把响应字符串解释为对象。
	 */
	public void setNeedEnableParser(boolean needEnableParser) {
		this.needEnableParser = needEnableParser;
	}

	/**
	 * 是否采用标准化的JSON格式返回。
	 */
	public void setUseSimplifyJson(boolean useSimplifyJson) {
		this.useSimplifyJson = useSimplifyJson;
	}

	/**
	 * 是否记录API请求错误日志。
	 */
	public void setNeedEnableLogger(boolean needEnableLogger) {
		TaobaoLogger.setNeedEnableLogger(needEnableLogger);
	}

	/**
	 * 是否忽略HTTPS证书校验。
	 */
	public void setIgnoreSSLCheck(boolean ignore) {
		WebUtils.setIgnoreSSLCheck(ignore);
	}

	/**
	 * 是否启用响应GZIP压缩
	 */
	public void setUseGzipEncoding(boolean useGzipEncoding) {
		this.useGzipEncoding = useGzipEncoding;
	}

	/**
	 * 设置API请求的连接超时时间,默认为15秒。
	 */
	public void setConnectTimeout(int connectTimeout) {
		this.connectTimeout = connectTimeout;
	}

	/**
	 * 设置API请求的读超时时间,默认为30秒。
	 */
	public void setReadTimeout(int readTimeout) {
		this.readTimeout = readTimeout;
	}
	
	public String getTopHttpDnsHost(){
	    if(isHttpDnsEnabled){
	        return originalHttpHost;
	    }
	    return null;
	}
	
	/**
	 * 启用http dns
	 */
	public void enableHttpDns(){
	    WebUtils.setIgnoreHostCheck(true);
	    setHttpDnsHost(serverUrl);
        ClusterManager.initRefreshThread(appKey, appSecret);
        isHttpDnsEnabled = true;
	}

	/**
	 * 沙箱环境启用http dns
	 * @param onlineAppKey 正式key
	 * @param onlineAppSecret 正式环境secret
	 */
    public void enableHttpDns(String onlineAppKey, String onlineAppSecret){
        WebUtils.setIgnoreHostCheck(true);
        setHttpDnsHost(serverUrl);
        ClusterManager.initRefreshThread(onlineAppKey, onlineAppSecret);
        isHttpDnsEnabled = true;
    }
    
    public void resetServerUrl(String serverUrl){
    	this.serverUrl = serverUrl;
    }
    
    public String getRequestUrl(){
    	return this.serverUrl;
    }
    
    public String getAppKey() {
        return appKey;
    }

	private void setHttpDnsHost(String serverUrl){
		if(serverUrl == null){
			return;
		}
		try {
			URL url = new URL(serverUrl);
			originalHttpHost = url.getHost();
		} catch (Exception e) {
			throw new RuntimeException("error serverUrl:" + serverUrl, e);
		}
	}

    private  TaobaoParser buildParser(TaobaoRequest request) {
		TaobaoParser parser = null;
		if (this.needEnableParser) {
			String realFormat = request.getTopApiFormat() != null ? request.getTopApiFormat() : format;
			String realResponseType = this.getRealResponseType(request.getTopApiFormat() != null ? request.getTopApiFormat() : format,
					request.getTopResponseType());
			if (Constants.FORMAT_XML.equals(realFormat)
					|| Constants.FORMAT_XML2.equals(realFormat)) {
				parser = new ObjectXmlParser(request.getResponseClass());
			} else {
				if(realResponseType != null && (realResponseType.equals(Constants.RESPONSE_TYPE_QIMEN)
						|| realResponseType.equals(Constants.RESPONSE_TYPE_QIMEN2))) {
					// 奇门云网关固定simplify=true
					parser = new ObjectJsonParser(request.getResponseClass(), true);
				} else {
					parser = new ObjectJsonParser(request.getResponseClass(), this.useSimplifyJson);
				}
			}
		}
		return parser;
	}

	private  T parseBody(TaobaoParser parser, TaobaoRequest request, RequestParametersHolder requestHolder) throws ApiException {
    	String body = requestHolder.getResponseBody();
    	T tRsp = null;
		if (this.needEnableParser) {
			tRsp = parser.parse(body, getRealResponseType(request.getTopApiFormat() != null ? request.getTopApiFormat() : format,
					request.getTopResponseType()));
			if(tRsp == null){
				try {
					tRsp = request.getResponseClass().newInstance();
				}catch (Exception e){
					throw new ApiException(e);
				}
			}
			tRsp.setBody(body);
			tRsp.setRequestUrl(requestHolder.getRequestUrl());
            tRsp.setHeaderContent(requestHolder.getResponseHeaders());
		} else {
			try {
				tRsp = request.getResponseClass().newInstance();
				tRsp.setBody(body);
				tRsp.setRequestUrl(requestHolder.getRequestUrl());
				tRsp.setHeaderContent(requestHolder.getResponseHeaders());
			} catch (Exception e) {
				throw new ApiException(e);
			}
		}
		return tRsp;
	}

	private  RequestParametersHolder invokeApi(TaobaoRequest request, String session, long start) throws ApiException {
		RequestDTO requestDTO = new RequestDTO();
		requestDTO.setRequestBase(request);
		requestDTO.setTargetAppKey(request.getTargetAppKey());
		requestDTO.setTimestamp(request.getTimestamp());
		requestDTO.setHeaderMap(request.getHeaderMap());
		requestDTO.setTextParams(request.getTextParams());
		requestDTO.setContentType(request.getTopContentType());
		requestDTO.setApiMethodName(request.getApiMethodName());
		requestDTO.setApiVersion(request.getTopApiVersion());
		requestDTO.setFormat(request.getTopApiFormat());
		requestDTO.setApiCallType(request.getTopApiCallType());
		if(StringUtils.isEmpty(requestDTO.getBody())){
			requestDTO.setBody(RequestBodyConverter.getRequestBody(request, request.getTopContentType()));
		}
		return invokeApi(requestDTO, session, start);
	}

	protected RequestParametersHolder invokeApi(RequestDTO request, String session, long start) throws ApiException {
		RequestParametersHolder requestHolder = new RequestParametersHolder();
		if(request.getTextParams() == null){
			request.setTextParams(new HashMap());
		}
		TaobaoHashMap appParams = new TaobaoHashMap(request.getTextParams());
		requestHolder.setApplicationParams(appParams);

		// 添加协议级请求参数
		TaobaoHashMap protocalMustParams = new TaobaoHashMap();
		protocalMustParams.put(Constants.METHOD, request.getApiMethodName());
		protocalMustParams.put(Constants.VERSION, request.getApiVersion() != null ? request.getApiVersion() : version);
		if(appKey != null) {
			protocalMustParams.put(Constants.APP_KEY, appKey);
		}
		Long timestamp = request.getTimestamp();
		if (timestamp == null) {
			timestamp = System.currentTimeMillis();
		}

		protocalMustParams.put(Constants.TIMESTAMP, new Date(timestamp));
		requestHolder.setProtocalMustParams(protocalMustParams);

		TaobaoHashMap protocalOptParams = new TaobaoHashMap();
		protocalOptParams.put(Constants.FORMAT, request.getFormat() != null ? request.getFormat() : format);
		protocalOptParams.put(Constants.SIGN_METHOD, signMethod);
		protocalOptParams.put(Constants.SESSION, session);
		protocalOptParams.put(Constants.PARTNER_ID, getSdkVersion());
		protocalOptParams.put(Constants.TARGET_APP_KEY, request.getTargetAppKey());

		if (this.useSimplifyJson) {
			protocalOptParams.put(Constants.SIMPLIFY, Boolean.TRUE.toString());
		}
		requestHolder.setProtocalOptParams(protocalOptParams);

		//目前不支持xml格式的传参,需要使用form形式的
		Boolean isXml = Constants.CONTENT_TYPE_XML.equals(request.getContentType());
		Boolean isJson = Constants.CONTENT_TYPE_JSON.equals(request.getContentType());
		String apiBody = request.getBody();
		if(isXml) {
			if (StringUtils.isEmpty(apiBody)) {
				XmlWriter writer = new XmlWriter(true, Constants.QM_ROOT_TAG, QimenRequest.class);
				apiBody = writer.write(request);
			}
		}


		String fullUrl;
		String traceRequestUrl;
		try {
			if(request.getApiCallType() == null) {
				// 添加签名参数
				if (isJson || isXml) {
					protocalMustParams.put(Constants.SIGN, TaobaoUtils.signTopRequestWithBody(requestHolder, apiBody, appSecret, signMethod));
				} else {
					protocalMustParams.put(Constants.SIGN, TaobaoUtils.signTopRequest(requestHolder, appSecret, signMethod));
				}
			}

			String realServerUrl = getServerUrl(this.serverUrl, request.getApiMethodName(), session,appParams);
			String sysMustQuery = WebUtils.buildQuery(requestHolder.getProtocalMustParams(), Constants.CHARSET_UTF8);
			String sysOptQuery = WebUtils.buildQuery(requestHolder.getProtocalOptParams(), Constants.CHARSET_UTF8);
			String appParamsQuery = WebUtils.buildQuery(appParams, Constants.CHARSET_UTF8);
			if(isJson || isXml) {
				fullUrl = WebUtils.buildRequestUrl(realServerUrl, appParamsQuery, sysMustQuery, sysOptQuery);
				traceRequestUrl = WebUtils.buildRequestUrl(realServerUrl, sysMustQuery, sysOptQuery);
			} else {
				fullUrl = WebUtils.buildRequestUrl(realServerUrl, sysMustQuery, sysOptQuery);
				traceRequestUrl = WebUtils.buildRequestUrl(realServerUrl, appParamsQuery, sysMustQuery, sysOptQuery);
			}
			requestHolder.setRequestUrl(traceRequestUrl);

			HttpResponseData data = null;
			// 是否需要压缩响应
			if (this.useGzipEncoding) {
				request.getHeaderMap().put(Constants.ACCEPT_ENCODING, Constants.CONTENT_ENCODING_GZIP);
			}
			if(getTopHttpDnsHost() != null){
				request.getHeaderMap().put(Constants.TOP_HTTP_DNS_HOST, getTopHttpDnsHost());
			}
			// 是否需要上传文件
			if (request.getRequestBase() != null && request.getRequestBase() instanceof TaobaoUploadRequest) {
				TaobaoUploadRequest uRequest = (TaobaoUploadRequest) request.getRequestBase();
				Map fileParams = TaobaoUtils.cleanupMap(uRequest.getFileParams());
                data = WebV2Utils.doPost(fullUrl, appParams, fileParams, Constants.CHARSET_UTF8, connectTimeout, readTimeout, request.getHeaderMap());
			} else {
				byte[] bodyByte = apiBody == null ? new byte[0] : apiBody.getBytes(Constants.CHARSET_UTF8);
				if(isJson){
					data = WebV2Utils.doPost(fullUrl, Constants.QM_CONTENT_TYPE_JSON, bodyByte, connectTimeout, readTimeout, request.getHeaderMap(), this.getProxy());
				} else if(isXml) {
					data = WebV2Utils.doPost(fullUrl, Constants.QM_CONTENT_TYPE, bodyByte, connectTimeout, readTimeout, request.getHeaderMap(), this.getProxy());
				} else {
                    data = WebV2Utils.doPost(fullUrl, appParams, Constants.CHARSET_UTF8, connectTimeout, readTimeout, request.getHeaderMap(), this.getProxy());
				}
			}
			requestHolder.setResponseBody(data.getBody());
            requestHolder.setResponseHeaders(data.getHeaders());
		} catch (IOException e) {
			TaobaoLogger.logApiError(appKey, request.getApiMethodName(), serverUrl, requestHolder.getAllParams(), System.currentTimeMillis() - start, e.toString());
			throw new ApiException(e);
		}

		return requestHolder;
	}

	protected void setRealFormat(String responseType) {
    	if(responseType == null) {
    		return;
		}
		if(Constants.RESPONSE_TYPE_QIMEN2.equals(responseType)) {

		}
	}

	protected String getRealResponseType(String format, String responseType) {
		return Constants.FORMAT_JSON2.equals(this.format)
				|| Constants.FORMAT_XML2.equals(this.format) ? Constants.RESPONSE_TYPE_QIMEN2 : responseType;
	}

	public Proxy getProxy() {
		return proxy;
	}

	public void setProxy(Proxy proxy) {
		this.proxy = proxy;
	}

	public String getAppSecret() {
		return appSecret;
	}

	public String getFormat() {
		return format;
	}

	public String getSignMethod() {
		return signMethod;
	}

	public int getConnectTimeout() {
		return connectTimeout;
	}

	public int getReadTimeout() {
		return readTimeout;
	}

	public boolean isNeedCheckRequest() {
		return needCheckRequest;
	}

	public boolean isUseSimplifyJson() {
		return useSimplifyJson;
	}

	public boolean isUseGzipEncoding() {
		return useGzipEncoding;
	}

	public boolean isNeedEnableParser() {
		return needEnableParser;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy