Gdax API возвращает неверную подпись в запросах POST

Я пытаюсь интегрироваться с GDAX-API, и мне удалось выполнить вызовы GET и получить ответ, однако, когда я пытаюсь сделать вызов POST, я получаю следующий ответ {"сообщение": "недопустимая подпись"}

Я кое-что видел здесь: https://www.reddit.com/r/GDAX/comments/7twdfv/gdax_api_invalid_signature_problem/

но я не уверен, что это проблема...

Моя часть подписи основана на библиотеке Java, упомянутой Gdax https://github.com/irufus/gdax-java

вот интересная часть моего кода

public String purchaseOrder(String jsonOrder) throws ClientProtocolException, IOException {
        CloseableHttpClient client = HttpClientBuilder.create().build();
        HttpPost request = new HttpPost(BASE_URL + "/orders");
        String timestamp = Instant.now().getEpochSecond() + "";
        request.addHeader("accept", "application/json");
        request.addHeader("content-type", "application/json");
        request.addHeader("User-Agent", "gdax-java-client");
        request.addHeader(CB_ACCESS_KEY, API_KEY);
        request.addHeader(CB_ACCESS_SIGN, generateSignedHeader("/orders", "POST", jsonOrder, String.valueOf(timestamp)));
        request.addHeader(CB_ACCESS_TIMESTAMP, String.valueOf(timestamp));
        request.addHeader(CB_ACCESS_PASSPHRASE, PASSPHRASE);

        HttpResponse response = client.execute(request);
        String jsonResponse = EntityUtils.toString(response.getEntity(), "UTF-8");
        client.close();
        return jsonResponse;
    }

    private String generateSignedHeader(String requestPath, String method, String body, String timestamp) {
        try {
            String prehash = timestamp + method.toUpperCase() + requestPath + body;
            byte[] secretDecoded = Base64.getDecoder().decode(API_SECRET);
            SecretKeySpec keyspec = new SecretKeySpec(secretDecoded, Mac.getInstance("HmacSHA256").getAlgorithm());
            Mac sha256 = (Mac) Mac.getInstance("HmacSHA256").clone();
            sha256.init(keyspec);
            String response = Base64.getEncoder().encodeToString(sha256.doFinal(prehash.getBytes()));
            System.out.println(response);
            return response;
        } catch (CloneNotSupportedException | InvalidKeyException e) {
            System.out.println(e);
            throw new RuntimeErrorException(new Error("Cannot set up authentication headers."));
        } catch (NoSuchAlgorithmException e) {
            System.out.println(e);
            throw new RuntimeErrorException(new Error("Cannot set up authentication headers."));

        }
    }

и я напечатал json в тестовом запросе

{"side":"buy","type":"market","product_id":"BTC-USD","size":0.01000000000000000020816681711721685132943093776702880859375}

РЕДАКТИРОВАТЬ!!!!!!!

У меня была проблема с отметкой времени, по какой-то причине нет необходимости отбрасывать последние 3 цифры (мс), поэтому я передаю ее как есть, но теперь я получаю

{"message":"временная метка запроса истекла"}


person naoru    schedule 05.04.2018    source источник
comment
Просто наблюдение: если ваш timestamp объявлен как String, я не вижу необходимости использовать String.valueOf(...) ни при передаче его как String методу, ни при добавлении его в заголовок (который, вероятно, будет строковым значением) -   -  person blurfus    schedule 05.04.2018


Ответы (1)


Временная метка должна указываться в секундах с эпохи Unix (1 января 1970 г.).

Вы можете включить микросекунды, но у вас должна быть точка (например, 123.456).

Сообщение об ошибке, которое вы получаете, связано с тем, что время между вашим сервером и сервером GDAX отличается более чем на несколько секунд. Вполне вероятно, что вы не включаете период для мс, что он отключен примерно на 1000 раз...

person Alexis Wilke    schedule 10.04.2018