1

我在为 GDAX API 签名消息时遇到问题。GDAX API 文档指出状态 400 ~ “Bad Request – Invalid request format”。你能告诉我我需要改变什么吗?

谢谢!


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."));
    }
}
4

2 回答 2

2

我对 c# 代码有同样的问题。问题是我没有添加用户代理标头。当我这样做时,一切都很完美。我的工作代码是:

HttpClient gdaxClient = new HttpClient();
gdaxClient.DefaultRequestHeaders.Add("User-Agent", ".NET Framework Test Client");

您的 java 代码也将是:

urlConnection.setRequestProperty("User-Agent", "Java Test Client");
于 2018-04-16T07:26:43.627 回答
0

试试下面的代码,我检查过它是否适用于其他人。通常错误归结为“错误请求” - 本身并没有多大帮助。但是,此代码还将生成等效的 curl 请求,如果您将其复制/粘贴到命令提示符上,它将向您显示来自服务器的实际反馈。这通常会提供更多信息反馈,以帮助诊断您的请求失败的原因。

确保您的时间设置正确,因为请求对时间敏感。您的 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();
        }
    }
}
于 2018-01-22T13:18:52.320 回答