Как правильно подписать запрос GDAX в Clojure
Некоторое время я боролся с подписанием запросов на частные конечные точки GDAX. Все, что я попробовал, приводит к 400 ответам с сообщением "неверная подпись". Я прочитал их документацию по этому вопросу несколько раз, которую можно найти здесь. Мой текущий код ниже. я использую clj-http
для подачи запросов. Я использую их /time
ответ конечной точки для временной метки, и я использую pandect для генерации HAMAC sha256. Я пытался преобразовать secret-decoded
к строке, используя String.
прежде чем передать его sha256-hmac
, Я также изучил запрос, используя clj-http
флаг отладки. Мне кажется, что я точно следую их указаниям, но что-то должно быть не так. Я сделал много онлайн-поиска, прежде чем размещать здесь. Любая помощь будет принята с благодарностью.
(defn get-time
[]
(-> (str (:api-base-url config) "/time")
(http/get {:as :json})
:body))
(defn- create-signature
([timestamp method path]
(create-signature timestamp method path ""))
([timestamp method path body]
(let [secret-decoded (b64/decode (.getBytes (:api-secret config)))
prehash-string (str timestamp (clojure.string/upper-case method) path body)
hmac (sha256-hmac prehash-string secret-decoded)]
(-> hmac
.getBytes
b64/encode
String.))))
(defn- send-signed-request
[method path & [opts]]
(let [url (str (:api-base-url config) path)
timestamp (long (:epoch (get-time)))
signature (create-signature timestamp method path (:body opts))]
(http/request
(merge {:method method
:url url
:as :json
:headers {"CB-ACCESS-KEY" (:api-key config)
"CB-ACCESS-SIGN" signature
"CB-ACCESS-TIMESTAMP" timestamp
"CB-ACCESS-PASSPHRASE" (:api-passphrase config)
"Content-Type" "application/json"}
:debug true}
opts))))
(defn get-accounts []
(send-signed-request "GET" "/accounts"))
(send-signed-request "GET" "/accounts")))
1 ответ
Я понял проблему. На случай, если у кого-то возникнет эта специфическая проблема, я выкладываю решение. Моя ошибка заключалась в том, что я использовал sha256-hmac
функция из pandect, которая возвращает строку hmac, затем я конвертировал ее в байтовый массив, кодировал в base64 и преобразовывал обратно в строку. Где-то в этих преобразованиях или, возможно, в преобразовании функции pandect, значение изменяется ошибочно.
Что работает с использованием sha256-hmac*
функция (обратите внимание на звездочку) из pandect, которая возвращает необработанный байтовый массив hmac, затем непосредственно кодирует base64 и возвращает его в строку. Ниже приведен исправленный рабочий фрагмент кода, с помощью которого я смог сделать запрос к частной конечной точке GDAX.
(defn create-signature
([timestamp method path]
(create-signature timestamp method path ""))
([timestamp method path body]
(let [secret-decoded (b64/decode (.getBytes (:api-secret config)))
prehash-string (str timestamp (clojure.string/upper-case method) path body)
hmac (sha256-hmac* prehash-string secret-decoded)]
(-> hmac
b64/encode
String.))))