签名 OK-ACCESS-SIGN的请求头是对timestamp + method + requestPath + body字符串(+表示字符串连接),以及secretKey,使用HMAC SHA256方法加密,通过BASE64编码输出而得到的。 例如:sign=CryptoJS.enc.Base64.Stringify(CryptoJS.HmacSHA256(timestamp + 'GET' + '/users/self/verify', secretKey)) 其中,timestamp的值与OK-ACCESS-TIMESTAMP请求头相同,必须是UTC时区Unix时间戳的十进制秒数格式或ISO8601标准的时间格式,精确到毫秒。。 method是请求方法,字母全部大写:GET/POST。 requestPath是请求接口路径。例如:/orders?before=2&limit=30 body是指请求主体的字符串,如果请求没有主体(通常为GET请求)则body可省略。例如:{"product_id":"BTC-USD-0309","order_id":"377454671037440"} secretKey为用户申请API Key时所生成。例如:22582BD*FF14C41EDBF1AB98506286D’ public enum ContentTypeEnum { APPLICATION_JSON("application/json"), APPLICATION_JSON_UTF8("application/json; charset=UTF-8"), // The server does not support types APPLICATION_FORM("application/x-www-form-urlencoded; charset=UTF-8"),; private String contentType; ContentTypeEnum(String contentType) { this.contentType = contentType; } public String contentType() { return contentType; }}public enum HttpHeadersEnum { OK_ACCESS_KEY("OK-ACCESS-KEY"), OK_ACCESS_SIGN("OK-ACCESS-SIGN"), OK_ACCESS_TIMESTAMP("OK-ACCESS-TIMESTAMP"), OK_ACCESS_PASSPHRASE("OK-ACCESS-PASSPHRASE"), OK_FROM("OK-FROM"), OK_TO("OK-TO"), OK_LIMIT("OK-LIMIT"),; private String header; HttpHeadersEnum(String header) { this.header = header; } public String header() { return header; }}import com.okcoin.commons.okex.open.api.config.APIConfiguration;import com.okcoin.commons.okex.open.api.constant.APIConstants;import com.okcoin.commons.okex.open.api.enums.ContentTypeEnum;import com.okcoin.commons.okex.open.api.enums.HttpHeadersEnum;import com.okcoin.commons.okex.open.api.exception.APIException;import com.okcoin.commons.okex.open.api.utils.DateUtils;import com.okcoin.commons.okex.open.api.utils.HmacSHA256Base64Utils;import okhttp3.*;import okio.Buffer;public class APIHttpClient { private APIConfiguration config; private APICredentials credentials; public APIHttpClient(APIConfiguration config, APICredentials credentials) { this.config = config; this.credentials = credentials; } public OkHttpClient client() { OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder(); clientBuilder.connectTimeout(this.config.getConnectTimeout(), TimeUnit.SECONDS); clientBuilder.readTimeout(this.config.getReadTimeout(), TimeUnit.SECONDS); clientBuilder.writeTimeout(this.config.getWriteTimeout(), TimeUnit.SECONDS); clientBuilder.retryOnConnectionFailure(this.config.isRetryOnConnectionFailure()); clientBuilder.addInterceptor((Interceptor.Chain chain) -> { Request.Builder requestBuilder = chain.request().newBuilder(); String timestamp = DateUtils.getUnixTime(); requestBuilder.headers(headers(chain.request(), timestamp)); Request request = requestBuilder.build(); if (this.config.isPrint()) { printRequest(request, timestamp); } return chain.proceed(request); }); return clientBuilder.build(); } private Headers headers(Request request, String timestamp) { Headers.Builder builder = new Headers.Builder(); builder.add(APIConstants.ACCEPT, ContentTypeEnum.APPLICATION_JSON.contentType()); builder.add(APIConstants.CONTENT_TYPE, ContentTypeEnum.APPLICATION_JSON_UTF8.contentType()); builder.add(APIConstants.COOKIE, getCookie()); if (StringUtils.isNotEmpty(this.credentials.getSecretKey())) { builder.add(HttpHeadersEnum.OK_ACCESS_KEY.header(), this.credentials.getApiKey()); builder.add(HttpHeadersEnum.OK_ACCESS_SIGN.header(), sign(request, timestamp)); builder.add(HttpHeadersEnum.OK_ACCESS_TIMESTAMP.header(), timestamp); builder.add(HttpHeadersEnum.OK_ACCESS_PASSPHRASE.header(), this.credentials.getPassphrase()); } return builder.build(); } private String getCookie() { StringBuilder cookie = new StringBuilder(); cookie.append(APIConstants.LOCALE).append(this.config.getI18n().i18n()); return cookie.toString(); } private String sign(Request request, String timestamp) { String sign; try { sign = HmacSHA256Base64Utils.sign(timestamp, method(request), requestPath(request), queryString(request), body(request), this.credentials.getSecretKey()); } catch (IOException e) { throw new APIException("Request get body io exception.", e); } catch (CloneNotSupportedException e) { throw new APIException("Hmac SHA256 Base64 Signature clone not supported exception.", e); } catch (InvalidKeyException e) { throw new APIException("Hmac SHA256 Base64 Signature invalid key exception.", e); } return sign; } private String url(Request request) { return request.url().toString(); } private String method(Request request) { return request.method().toUpperCase(); } private String requestPath(Request request) { String url = url(request); url = url.replace(this.config.getEndpoint(), APIConstants.EMPTY); String requestPath = url; if (requestPath.contains(APIConstants.QUESTION)) { requestPath = requestPath.subString(0, url.lastIndexOf(APIConstants.QUESTION)); } if(this.config.getEndpoint().endsWith(APIConstants.SLASH)){ requestPath = APIConstants.SLASH + requestPath; } return requestPath; } private String queryString(Request request) { String url = url(request); String queryString = APIConstants.EMPTY; if (url.contains(APIConstants.QUESTION)) { queryString = url.subString(url.lastIndexOf(APIConstants.QUESTION) + 1); } return queryString; } private String body(Request request) throws IOException { RequestBody requestBody = request.body(); String body = APIConstants.EMPTY; if (requestBody != null) { Buffer buffer = new Buffer(); requestBody.writeTo(buffer); body = buffer.readString(APIConstants.UTF_8); } return body; }}import retrofit2.Call;import retrofit2.http.GET;import retrofit2.http.Path;import retrofit2.http.Query;import java.util.List;interface FuturesMarketAPI { @GET("/api/futures/v3/products/{instrument_id}/candles") Call<JSONArray> getProductCandles(@Path("instrument_id") String productId, @Query("start") String start, @Query("end") String end, @Query("granularity") String granularity);}import com.alibaba.fastjson.JSONArray;import com.okcoin.commons.okex.open.api.bean.futures.result.*;import com.okcoin.commons.okex.open.api.client.APIClient;import com.okcoin.commons.okex.open.api.config.APIConfiguration;import com.okcoin.commons.okex.open.api.service.futures.FuturesMarketAPIService;public class FuturesMarketAPIServiceImpl implements FuturesMarketAPIService { private APIClient client; private FuturesMarketAPI api; public FuturesMarketAPIServiceImpl(APIConfiguration config) { this.client = new APIClient(config); this.api = client.createService(FuturesMarketAPI.class); } @Override public JSONArray getProductCandles(String productId, long start, long end, long granularity) { return this.client.executeSync(this.api.getProductCandles(productId, String.valueOf(start), String.valueOf(end), String.valueOf(granularity))); }}import okhttp3.Headers;import okhttp3.OkHttpClient;import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import retrofit2.Call;import retrofit2.Response;import retrofit2.Retrofit;import java.io.IOException;import java.util.List;import java.util.Optional;public class APIClient { /** * Synchronous send request */ public <T> T executeSync(Call<T> call) { try { Response<T> response = call.execute(); if (this.config.isPrint()) { printResponse(response); } int status = response.code(); String message = new StringBuilder().append(response.code()).append(" / ").append(response.message()).toString(); if (response.isSuccessful()) { return response.body(); } else if (APIConstants.resultStatusArray.contains(status)) { HttpResult result = JSON.parseObject(new String(response.errorBody().bytes()), HttpResult.class); result.setStatusCode(status); throw new APIException(result.message()); } else { throw new APIException(message); } } catch (IOException e) { throw new APIException("APIClient executeSync exception.", e); } }}public class FuturesAPIBaseTests extends BaseTests { public APIConfiguration config() { APIConfiguration config = new APIConfiguration(); config.setEndpoint("https://www.okex.com/"); config.setApiKey(""); config.setSecretKey(""); config.setPassphrase(""); config.setPrint(true); config.setI18n(I18nEnum.ENGLISH); return config; } String productId = "BTC-USD-180928";}import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.okcoin.commons.okex.open.api.bean.futures.result.*;import com.okcoin.commons.okex.open.api.service.futures.FuturesMarketAPIService;import com.okcoin.commons.okex.open.api.service.futures.impl.FuturesMarketAPIServiceImpl;import org.junit.Before;import org.junit.Test;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.List;public class FuturesMarketAPITests extends FuturesAPIBaseTests { private FuturesMarketAPIService marketAPIService; @Before public void before() { config = config(); marketAPIService = new FuturesMarketAPIServiceImpl(config); } @Test public void testGetProductCandles() { long start = System.currentTimeMillis(); long end = System.currentTimeMillis() + 2000L; JSONArray array = marketAPIService.getProductCandles(productId, 1530323640000L, 0, 180L); toResultString(LOG, "Product-Candles", array); }}帮我写个例程。怎么设置请求头啊?给我源码吧。
|