Android 改装-传递POST参数数据和标题

Android 改装-传递POST参数数据和标题,android,retrofit,retrofit2,android-async-http,kraken.com,Android,Retrofit,Retrofit2,Android Async Http,Kraken.com,我正在尝试使用改型调用。我有一个正在工作的AsyncHttpClient版本,我想转换成一个改进版本,我在传递POST参数时遇到了一些问题 如文件中所述,它需要: 2个HTTP头:API密钥和API符号 发布数据:nonce 我正在调用的端点的2个输入参数:start和ofs AsyncHttpClient版本(有效): 改装版本(EAPI:Invalid keyresponse): String start=String.valueOf(cal.getTimeInMillis()/1000

我正在尝试使用改型调用。我有一个正在工作的
AsyncHttpClient
版本,我想转换成一个改进版本,我在传递POST参数时遇到了一些问题

如文件中所述,它需要:

  • 2个HTTP头:
    API密钥
    API符号
  • 发布数据:
    nonce
  • 我正在调用的端点的2个输入参数:
    start
    ofs
AsyncHttpClient版本(有效):

改装版本(
EAPI:Invalid key
response):

String start=String.valueOf(cal.getTimeInMillis()/1000);
String key=properties.getProperty(“KRAKEN_API_PUBLIC_key”);
字符串nonce=String.valueOf(System.currentTimeMillis());
字符串路径=“/0/private/TradesHistory”;
RequestParams params=新的RequestParams();
参数添加(“nonce”,nonce);
参数添加(“开始”,开始);
参数add(“ofs”,字符串.valueOf(offset));
字符串符号=calculateSignature(路径、nonce、params.toString());
KrakenService-KrakenService=KrakenService.reformation.create(KrakenService.class);
Call Call=krakenService.getTradeHistory(key、sign、nonce、start、String.valueOf(offset));
call.enqueue(新回调(){
@凌驾
公共void onResponse(@Nullable调用,@Nullable响应){
//EAPI:无效密钥
}
});
服务:

public interface KrakenService {

    @FormUrlEncoded
    @POST("private/TradesHistory")
    Call<KrakenTrades> getTradeHistory(
        @Header("API-Key") String apiKey,
        @Header("API-Sign") String apiSign,
        @Field("nonce") String nonce,
        @Field("start") String start,
        @Field("ofs") String ofs);

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.kraken.com/0/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
}
公共接口服务{
@FormUrlEncoded
@邮政(“私人/贸易档案”)
调用getTradeHistory(
@标题(“API键”)字符串apiKey,
@标题(“API符号”)字符串apiSign,
@字段(“nonce”)字符串nonce,
@字段(“开始”)字符串开始,
@字段(“ofs”)字符串(ofs);
改装改装=新改装.Builder()
.baseUrl(“https://api.kraken.com/0/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
只是电话不同,我错过了什么吗?我尝试过使用
@query
@Body
@FieldMap
@HeaderMap
等,但无法成功


编辑:我刚刚尝试了其他API,但遇到了相同的问题(无效密钥),而它仍然可以与基本的HTTPClient一起使用。

如果您对其他API开放,我建议,它的使用要简单得多

mesibo.Http http = new mesibo.Http();

Bundle b = new Bundle();
b.putString("token", "some_token");
b.putLong("mid", mid);


http.url = “https://example.com”;
http.postBundle = b;
http.other = myObject; // callback data

http.onMainThread = true; // invoke listener in main thread
http.listener = new mesibo.HttpListener() {
    @Override
    public boolean mesibo_onHttpProgress(mesibo.Http http, int state, int percent) {
        if(100 == percent && mesibo.Http.STATE_DOWNLOAD == state) {
                // download complete
        }

        Return true; // return false to cancel
    }
};

if(http.execute()) {

}

如果您对其他API持开放态度,我建议您,它的使用要简单得多

mesibo.Http http = new mesibo.Http();

Bundle b = new Bundle();
b.putString("token", "some_token");
b.putLong("mid", mid);


http.url = “https://example.com”;
http.postBundle = b;
http.other = myObject; // callback data

http.onMainThread = true; // invoke listener in main thread
http.listener = new mesibo.HttpListener() {
    @Override
    public boolean mesibo_onHttpProgress(mesibo.Http http, int state, int percent) {
        if(100 == percent && mesibo.Http.STATE_DOWNLOAD == state) {
                // download complete
        }

        Return true; // return false to cancel
    }
};

if(http.execute()) {

}

我设法使它工作,但我不得不承认我不明白重点

我激活了
OkHttp
日志来查看请求。这是我首先得到的(这些是假钥匙,不要浪费你的时间-):

查看发送数据中的差异?不没有

但是它工作了,我再也没有得到
无效键
的响应了

另一件奇怪的事情是,更改参数的顺序会使其返回到
无效键
响应:

String parameters = "start=" + start + "&ofs=" + offset +"&nonce=" + nonce; //works
String parameters = "start=" + start + "&nonce=" + nonce + "&ofs=" + offset; //doesn't work
我无法解释这个。。。也许是编码问题

编辑:好的,收到了,参数似乎在请求正文中排序。虽然服务器不关心HTTP参数的顺序,但HMAC会关心(当然,
param1=value1¶m2=value2
将生成与
param2=value2¶m1=value1
不同的HMAC)


因此,我必须在用于计算HMAC的字符串中使用与在请求正文中完全相同的顺序(我硬编码了从OkHttp日志中获得的顺序值,但最好的方法可能是从请求正文中提取该值,或者更好地规范化请求正文).

我设法做到了,但我不得不承认我没有抓住重点

我激活了
OkHttp
日志来查看请求。这是我首先得到的(这些是假钥匙,不要浪费你的时间-):

查看发送数据中的差异?不没有

但是它工作了,我再也没有得到
无效键
的响应了

另一件奇怪的事情是,更改参数的顺序会使其返回到
无效键
响应:

String parameters = "start=" + start + "&ofs=" + offset +"&nonce=" + nonce; //works
String parameters = "start=" + start + "&nonce=" + nonce + "&ofs=" + offset; //doesn't work
我无法解释这个。。。也许是编码问题

编辑:好的,收到了,参数似乎在请求正文中排序。虽然服务器不关心HTTP参数的顺序,但HMAC会关心(当然,
param1=value1¶m2=value2
将生成与
param2=value2¶m1=value1
不同的HMAC)

因此,我必须在用于计算HMAC的字符串中使用与在请求体中完全相同的顺序(我硬编码了从OkHttp日志中获得的顺序值,但最好的方法可能是从请求体中提取该值,或者更好地规范化请求体)

D/OkHttp: --> POST https://api.kraken.com/0/private/TradesHistory http/1.1
D/OkHttp: Content-Type: application/x-www-form-urlencoded
D/OkHttp: Content-Length: 42
D/OkHttp: API-Sign: DuxyUuHbj4V9WrOpaoBM6Rx3mZluoqJdkg3xBLgc0A/lVotq3WL19VErctz+ugTxi0eRpCI6oBnl95+Lmh9WmQ==
D/OkHttp: API-Key: XnmS2gW2Sr1xR/vnB0ivJuHABdXUnW4bsMTOBMREOlz8xYDh00J+D9i4
D/OkHttp: start=1481587200&ofs=0&nonce=1511302135971
D/OkHttp: --> END POST (42-byte body)
D/OkHttp: <-- 200  https://api.kraken.com/0/private/TradesHistory (1340ms)
D/OkHttp: date: Tue, 21 Nov 2017 22:09:04 GMT
D/OkHttp: content-type: application/json; charset=utf-8
D/OkHttp: set-cookie: __cfduid=d7916fbb113ed6f83b9382ea0a57240731511302143; expires=Wed, 21-Nov-18 22:09:03 GMT; path=/; domain=.kraken.com; HttpOnly
D/OkHttp: vary: Accept-Encoding
D/OkHttp: server: cloudflare-nginx
D/OkHttp: cf-ray: 3c16f89b4e273e62-ZRH
D/OkHttp: {"error":[],"result":{"trades":{...}}}
D/OkHttp: <-- END HTTP (11944-byte body)
String parameters = "start=" + start + "&ofs=" + offset +"&nonce=" + nonce; //works
String parameters = "start=" + start + "&nonce=" + nonce + "&ofs=" + offset; //doesn't work