GDAX API Bad Request 400
У меня возникают проблемы при подписании сообщения для GDAX API. Документация GDAX API гласит, что статус 400 ~ "Неверный запрос - Неверный формат запроса". Подскажите, пожалуйста, что мне нужно изменить?
Спасибо!
protected Void doInBackground(String... params) {
try {
URL url = new URL(baseUrl+params[0]);
// Create the urlConnection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("CB-ACCESS-KEY", key);
urlConnection.setRequestProperty("CB-ACCESS-SIGN", generate(params[0], "GET", "", String
.valueOf(System.currentTimeMillis())));
String timestamp = String.valueOf(System.currentTimeMillis());
urlConnection.setRequestProperty("CB-ACCESS-TIMESTAMP", timestamp);
urlConnection.setRequestProperty("CB-ACCESS-PASSPHRASE", passphrase);
urlConnection.setRequestMethod("GET");
int statusCode = urlConnection.getResponseCode();
if (statusCode == 200) {
InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream());
String response = convertInputStreamToString(inputStream);
Log.d("TAG", String.valueOf(response));
} else {
Log.d("TAG", String.valueOf(statusCode));
}
} catch (Exception e) {
Log.d("TAG", e.getLocalizedMessage());
}
return null;
}
генерирует CB-ACCESS-SIGN
public String generate(String requestPath, String method, String body, String timestamp) {
try {
String prehash = timestamp + method.toUpperCase() + requestPath + body;
byte[] secretDecoded = Base64.decode(secretKey, Base64.DEFAULT);
SecretKeySpec keyspec = new SecretKeySpec(secretDecoded, "HmacSHA256");
Mac sha256 = GDAXConstants.SHARED_MAC;
sha256.init(keyspec);
String shadone = Base64.encodeToString(sha256.doFinal(prehash.getBytes()),Base64.DEFAULT);
return shadone;
} catch (InvalidKeyException e) {
e.printStackTrace();
throw new RuntimeException(new Error("Cannot set up authentication headers."));
}
}
2 ответа
У меня была такая же проблема для кода C#. Проблема была в том, что я не добавил заголовок User Agent. Когда я сделал, все работает отлично. Мой рабочий код:
HttpClient gdaxClient = new HttpClient();
gdaxClient.DefaultRequestHeaders.Add("User-Agent", ".NET Framework Test Client");
То же самое для вашего кода Java будет:
urlConnection.setRequestProperty("User-Agent", "Java Test Client");
Попробуйте код ниже, который я проверил, работает для кого-то еще. Обычно ошибка сводится к "плохому запросу" - не очень полезно само по себе. Однако этот код также сгенерирует эквивалентный запрос скручивания, который покажет вам фактическую обратную связь с сервера, если вы скопируете / вставите ее в командной строке. Как правило, это обеспечивает гораздо более информативную обратную связь, чтобы помочь определить причину сбоя вашего запроса.
Убедитесь, что ваше время установлено правильно, так как запросы зависят от времени. Ваш ключ API также должен быть правильным / действительным для запросов, которые вы делаете.
Импорт объекта Account из библиотеки gdax-java
import com.coinbase.exchange.api.accounts.Account;
import com.google.gson.Gson;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Base64;
public class Testing {
private final String publicKey;
private final String passphrase;
private final String baseUrl;
private final String secret;
public Testing(String publicKey,
String passphrase,
String secret,
String baseUrl)
throws IOException, NoSuchAlgorithmException, InvalidKeyException {
this.publicKey = publicKey;
this.passphrase = passphrase;
this.baseUrl = baseUrl;
this.secret = secret;
}
private Account[] getAccounts() throws IOException, InvalidKeyException, NoSuchAlgorithmException {
String timestamp = Instant.now().getEpochSecond() + "";
String path = "/accounts";
URL url = new URL(baseUrl + path);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("CB-ACCESS-KEY", publicKey);
con.setRequestProperty("CB-ACCESS-SIGN", signMessage(timestamp, "GET", path));
con.setRequestProperty("CB-ACCESS-TIMESTAMP", timestamp);
con.setRequestProperty("CB-ACCESS-PASSPHRASE", passphrase);
con.setRequestProperty("content-type", "application/json");
System.out.println("curl -H \"CB-ACCESS-KEY: " + publicKey+ "\" "
+ "-H \"CB-ACCESS-SIGN: " + signMessage(timestamp,"GET", path) + "\" "
+ "-H \"CB-ACCESS-TIMESTAMP: " + timestamp + "\" "
+ "-H \"CB-ACCESS-PASSPHRASE: " + passphrase + "\" " + baseUrl + path);
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
String status = con.getResponseMessage();
if (status.equals("OK")) {
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
con.disconnect();
Gson gson = new Gson();
Account[] accounts = gson.fromJson(content.toString(), Account[].class);
Arrays.stream(accounts).forEach(a -> {
System.out.println("Account: " + a.getCurrency() + ", "
+ "Balance: " + a.getBalance().toPlainString() + ", "
+ "Available balance: " + a.getAvailable().toPlainString() + ", "
+ "Held: " + a.getHold().toPlainString());
});
return accounts;
} else {
throw new RuntimeException("Something went wrong. Response from server: " + status);
}
}
private String signMessage(String timestamp, String method, String path) throws NoSuchAlgorithmException, InvalidKeyException {
String prehash = timestamp + method + path;
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
byte[] secretDecoded = Base64.getDecoder().decode(secret);
SecretKeySpec secret_key = new SecretKeySpec(secretDecoded, "HmacSHA256");
sha256_HMAC.init(secret_key);
return Base64.getEncoder().encodeToString(sha256_HMAC.doFinal(prehash.getBytes()));
}
public static void main(String[] args) {
Testing t = null;
try {
t = new Testing("publicKey",
"passPhrase",
"secret",
"https://api.gdax.com");
t.getAccounts();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}