JavaScript AJAX到Coinbase API,获取"请求时间戳已过期"使用服务器时间错误

时间:2018-01-16 03:52:23

标签: javascript cryptojs coinbase-api

我一直在处理一些代码,这些代码会调用Coinbase API的List Accounts调用。我使用API Key进行身份验证,CryptoJSv3.1.2来处理加密。我相信我正确地签署了我的请求,但我还没有在JavaScript中进行过大量加密,所以请仔细检查我的工作。

我遇到的问题是我的帐户请求被拒绝了,而且我从Coinbase收到的消息是{"errors":[{"id":"authentication_error","message":"request timestamp expired"}]}

我知道请求的30秒限制,但是我使用的是Coinbase服务器时间,我从Get Current Time调用回来了。此外,两个呼叫的总运行时间<1秒,因此我的时间戳应该是当前时间。任何指导都会非常有帮助。提前谢谢。

这是我的代码:

var LOGIN_DATA = {
    Coinbase: {
        apiKey: "XXXXXXXXXXXXXXXX",
        apiSecret: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
        version: "2018-01-05"
    }
}
var Coinbase = new (function(){
    var cb = this;
    var baseURL = "https://api.coinbase.com/v2";

    this.listAccounts = function(){
        var start = new Date();
        var method = "GET";
        var url = baseURL + "/accounts";
        var header = buildRequestHeader(method, url);

        var accounts = connect(method, url, header);
        var finish = new Date();
        console.debug("time elapsed: ", (finish.getTime() - start.getTime()))
        return accounts;
    }

    function buildRequestHeader(method, url, data){
        var timeStamp = getServerTime();
        console.debug("timeStamp: ", timeStamp)
        var header = {
            "CB-ACCESS-KEY": LOGIN_DATA.Coinbase.apiKey,
            "CB-ACCESS-SIGN": buildSignature(timeStamp, method, url, data),
            "CB-ACCESS-TIMESTAMP": timeStamp
        }
        console.debug("header: ", header);
        return header;
    }

    function buildSignature(timeStamp, method, requestPath, data){
        var message = timeStamp + method.toUpperCase() + requestPath + (data == null ? "" : data)
        console.debug("signature message: ", message);
        var hash = CryptoJS.HmacSHA256(message, LOGIN_DATA.Coinbase.apiSecret);
        var hashInBase64 = CryptoJS.enc.Base64.stringify(hash);

        return hashInBase64
    }

    function getServerTime(){
        var method = "GET"
        var url = baseURL + "/time";
        var onSuccess = function(data){
            return (new Date(data.data.iso)).getTime();
        }

        return connect(method, url, null, null, onSuccess);
    }

    function connect(method, url, header, data, onSuccess, onError){
        var rtn = null;
        header = (header == null ? {} : header)
        data = (data === null ? {} : data)
        if(header["CB-VERSION"] === undefined){
            header["CB-VERSION"] = LOGIN_DATA.Coinbase.version
        }
        console.debug("final header: ", header);
        console.debug("final data: ", data);
        $.ajax({
            url: url,
            type: method,
            async: false,
            timeout: 5000,
            data: data,
            beforeSend: function(xhr) {
                for(var key in header){
                    xhr.setRequestHeader(key, header[key]);
                }
            },
            success: function(data, textStatus, jqXHR) {
                console.log("Coinbase connect successful: ", data);
                if(!onSuccess){
                    onSuccess = function(data){ return data; }
                }
                rtn = onSuccess(data, textStatus, jqXHR);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                console.error("Coinbase connect failed: ", textStatus, errorThrown, jqXHR);
                if(onError){
                    rtn = onError(jqXHR, textStatus, errorThrown);
                }
            }
        });

        return rtn;
    }
});

这里是我的控制台日志声明的屏幕截图,如果它们有帮助: Chrome Console

1 个答案:

答案 0 :(得分:1)

引用Coinbase API

  

CB-ACCESS-TIMESTAMP标头必须是自Unix Epoch以来的秒数。

您的时间戳以毫秒为单位,而不是秒。

如果我没弄错,签名应该用十六进制编码,而不是base64(source):

var hash = CryptoJS.HmacSHA256(message, LOGIN_DATA.Coinbase.apiSecret);
var hexDigest = hash.toString(CryptoJS.enc.Hex)