You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GDAX API请求签名失败返回400错误,求排查修正方案

Fixing GDAX API 400 Bad Request (Invalid Signature)

Let's walk through the issues in your code that are triggering the 400 Bad Request error. These are the critical fixes you need to implement:

Key Issues & Fixes

1. Mismatched Timestamps

You're generating two different timestamps: one for the signature, and a separate one for the CB-ACCESS-TIMESTAMP header. GDAX requires these values to be identical—if they don't match, the signature validation fails immediately.

2. Wrong Timestamp Precision

GDAX expects timestamps in seconds since epoch, but System.currentTimeMillis() returns milliseconds. Using a millisecond timestamp will cause the API to reject your request outright.

3. Base64 Encoding Includes Newlines

The Base64.DEFAULT flag adds newline characters to the encoded string, which breaks the signature format GDAX expects. Use Base64.NO_WRAP to produce a clean, single-line Base64 string.

4. Unsafe Shared Mac Instance

If GDAXConstants.SHARED_MAC is a global, reused Mac object, it's not thread-safe. AsyncTask runs in a background thread, and sharing Mac instances across threads can cause corrupted signatures. Always create a new Mac instance for each signature generation.

Modified Code

Updated doInBackground Method

protected Void doInBackground(String... params) {
    try {
        URL url = new URL(baseUrl + params[0]);
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        
        // Generate a single, second-precision timestamp (critical for GDAX)
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
        
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(true);
        urlConnection.setRequestMethod("GET"); // Set method first (good practice for HttpURLConnection)
        urlConnection.setRequestProperty("Content-Type", "application/json");
        urlConnection.setRequestProperty("CB-ACCESS-KEY", key);
        // Use the SAME timestamp for both signature generation and request header
        urlConnection.setRequestProperty("CB-ACCESS-SIGN", generate(params[0], "GET", "", timestamp));
        urlConnection.setRequestProperty("CB-ACCESS-TIMESTAMP", timestamp);
        urlConnection.setRequestProperty("CB-ACCESS-PASSPHRASE", passphrase);
        
        int statusCode = urlConnection.getResponseCode();
        if (statusCode == 200) {
            InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream());
            String response = convertInputStreamToString(inputStream);
            Log.d("TAG", response);
        } else {
            Log.d("TAG", "Status code: " + statusCode);
        }
    } catch (Exception e) {
        Log.d("TAG", "Error: " + e.getLocalizedMessage());
        e.printStackTrace();
    }
    return null;
}

Updated generate Method

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");
        
        // Create a new Mac instance each time to avoid thread-safety issues
        Mac sha256 = Mac.getInstance("HmacSHA256");
        sha256.init(keyspec);
        
        // Use NO_WRAP to ensure no newlines in the Base64 output
        String shadone = Base64.encodeToString(sha256.doFinal(prehash.getBytes()), Base64.NO_WRAP);
        return shadone;
    } catch (InvalidKeyException | NoSuchAlgorithmException e) {
        e.printStackTrace();
        throw new RuntimeException("Cannot set up authentication headers.", e);
    }
}

Additional Notes

  • Double-check that your requestPath exactly matches GDAX's expected format (e.g., /accounts without extra slashes or unencoded query parameters unless required).
  • For POST requests, the body parameter must be the exact JSON payload sent in the request—using an empty string is correct for GET requests as you have here.

内容的提问来源于stack exchange,提问作者someone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:34:47