C# Coinigy V2 API上的授权问题

C# Coinigy V2 API上的授权问题,c#,http,bitcoin,cryptocurrency,C#,Http,Bitcoin,Cryptocurrency,我一直在从事一个项目,我曾经使用Conigy的v1API,并且喜欢这个api。现在的问题是新的v2api,我一直在尝试使用带有hmac_sha256签名的私有API。我最初联系coinigy支持部门,但由于运气不佳,无法使其完全工作(他们确实提供了帮助,但从未解决过问题,这很奇怪)。我用C#构建了一个简单的测试项目,用他们的api文档执行一个私有调用 program.cs: using Newtonsoft.Json.Linq; using System; using System.Collec

我一直在从事一个项目,我曾经使用Conigy的v1API,并且喜欢这个api。现在的问题是新的v2api,我一直在尝试使用带有hmac_sha256签名的私有API。我最初联系coinigy支持部门,但由于运气不佳,无法使其完全工作(他们确实提供了帮助,但从未解决过问题,这很奇怪)。我用C#构建了一个简单的测试项目,用他们的api文档执行一个私有调用

program.cs:

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace coinigy_example
{
class Program
{

    static void Main(string[] args)
    {
        string api_key = "API_KEY";
        string api_secret = "API_SECRET";
        CoinigyApiPrivateCall call = new CoinigyApiPrivateCall(api_key, api_decret);


        string data = call.HttpPostRequest("private/exchanges/" + "BINA" + "/markets/" + "BTC" + "/" + "LTC" + "/ticker", "", null, "GET");
        string body = null;
        call.xcoinApiCall("private/exchanges/" + "BINA" + "/markets/" + "BTC" + "/" + "LTC" + "/ticker", "", ref body);


        try
        {
            JObject j = JObject.Parse(data);

            TickerDataCoinigy tt = new TickerDataCoinigy();
            tt.volume = (string)j["volume"];
            tt.last = (string)j["last"];
            tt.high = (string)j["high"];
            tt.low = (string)j["low"];
            tt.ask = (string)j["ask"];
            tt.bid = (string)j["bid"];

            Console.WriteLine("Binance, BTC-LTC ticker data:");

            Console.WriteLine("Volume: " + tt.volume);
            Console.WriteLine("Last: " + tt.last);
            Console.WriteLine("High: " + tt.high);
            Console.WriteLine("Low: " + tt.low);
            Console.WriteLine("ask: " + tt.ask);
            Console.WriteLine("bid: " + tt.bid);
        }
        catch(Exception i)
        {
            Console.WriteLine("");
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(data);
            Console.ForegroundColor = ConsoleColor.White;

        }

        Console.ReadLine();
    }


}

public class TickerDataCoinigy
{
    public string volume;
    public string last;
    public string high;
    public string low;
    public string ask;
    public string bid;
}
}
还有几个版本的私有调用(看看调用api的不同方式是否有效)

coinigyapiravatecall.cs

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace coinigy_example
{
public class CoinigyApiPrivateCall
{
    private string api_key;
    private string api_secret;

    public CoinigyApiPrivateCall(string api_key, string api_secret)
    {
        this.api_key = api_key;
        this.api_secret = api_secret;
    }

    public static double ConvertToUnixTimestamp(DateTime date)
    {
        DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
        TimeSpan diff = date.ToUniversalTime() - origin;
        return Math.Floor(diff.TotalMilliseconds);
    }

    private string Hash_HMAC(string sKey, string sData)
    {
        byte[] rgbyKey = Encoding.ASCII.GetBytes(sKey);


        using (var hmacsha256 = new HMACSHA256(rgbyKey))
        {
            byte[] inf = hmacsha256.ComputeHash(Encoding.ASCII.GetBytes(sData));

            return (ByteToString(inf));
        }
    }

    private string ByteToString(byte[] rgbyBuff)
    {
        string sHexStr = "";


        for (int nCnt = 0; nCnt < rgbyBuff.Length; nCnt++)
        {
            sHexStr += rgbyBuff[nCnt].ToString("x2"); // Hex format
        }

        return (sHexStr);


    }

    private byte[] StringToByte(string sStr)
    {
        byte[] rgbyBuff = Encoding.ASCII.GetBytes(sStr);

        return (rgbyBuff);
    }



    public string HttpPostRequest(string url, string au, List<KeyValuePair<string, string>> postdata, string httpType)
    {
        var client = new HttpClient();

        //client.DefaultRequestHeaders.Add("User-Agent", ua);
        //client.DefaultRequestHeaders.Add("X-API-KEY", api_key);
        //client.DefaultRequestHeaders.Add("X-API-SECRET", api_secret);
        string time = Convert.ToString(ConvertToUnixTimestamp(DateTime.Now.ToUniversalTime()));
        FormUrlEncodedContent content = null;
        string data = null;
        if (postdata != null)
        {
            content = new FormUrlEncodedContent(postdata);
            var output = Newtonsoft.Json.JsonConvert.SerializeObject(postdata);
            data = api_key + time + httpType.ToUpper() + "/api/v2/" + url  + output;
        }
        else
        {
            data = api_key + time + httpType.ToUpper() + "/api/v2/" + url;
        }
        string sign = Hash_HMAC(api_secret, data);
        client.DefaultRequestHeaders.Add("X-API-SIGN", sign);
        client.DefaultRequestHeaders.Add("X-API-TIMESTAMP", time);

        HttpResponseMessage response = null;
        if (httpType.ToUpper() == "POST")
        {
            response = client.PostAsync("https://api.coinigy.com/api/v2/" + url, content).Result;
        }

        if (httpType.ToUpper() == "GET")
        {
            response = client.GetAsync("https://api.coinigy.com/api/v2/" + url).Result;
        }

        if (httpType.ToUpper() == "PUT")
        {
            response = client.PutAsync("https://api.coinigy.com/api/v2/" + url, content).Result;
        }

        if (httpType.ToUpper() == "DELETE")
        {
            response = client.DeleteAsync("https://api.coinigy.com/api/v2/" + url).Result;
        }



        return response.IsSuccessStatusCode
            ? response.Content.ReadAsStringAsync().Result
            : "ERROR:" + response.StatusCode + " " + response.ReasonPhrase + " | " + response.RequestMessage;
    }

    public JObject xcoinApiCall(string sEndPoint, string sParams, ref string sRespBodyData)
    {
        string sAPI_Sign = "";
        string sPostData = sParams;
        string sHMAC_Key = "";
        string sHMAC_Data = "";
        string sResult = "";
        double nNonce = 0;
        HttpStatusCode nCode = 0;


        sPostData += "&endpoint=" + Uri.EscapeDataString(sEndPoint);

        try
        {
            HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://api.coinigy.com/api/v2/" + sEndPoint);
            byte[] rgbyData = Encoding.ASCII.GetBytes(sPostData);


            nNonce = ConvertToUnixTimestamp(DateTime.Now.ToUniversalTime());

            sHMAC_Key = this.api_secret;
            sHMAC_Data = api_key + nNonce.ToString() + "GET" +  "/api/v2/"   + sEndPoint;
            //sHMAC_Data = sEndPoint + (char)0 + sPostData + (char)0 + nNonce.ToString();
            sResult = Hash_HMAC(sHMAC_Key, sHMAC_Data);
            //sAPI_Sign = Convert.ToBase64String(StringToByte(sResult));
            sAPI_Sign = sResult;

            Request.Headers.Add("X-API-SIGN", sAPI_Sign);
            Request.Headers.Add("X-API-TIMESTAMP", nNonce.ToString());

            Request.Method = "GET";
            Request.ContentType = "application/x-www-form-urlencoded";
            Request.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36";
            /*Request.ContentLength = rgbyData.Length;

            using (var stream = Request.GetRequestStream())
            {
                stream.Write(rgbyData, 0, rgbyData.Length);
            } */

            var Response = (HttpWebResponse)Request.GetResponse();

            sRespBodyData = new StreamReader(Response.GetResponseStream()).ReadToEnd();

            return (JObject.Parse(sRespBodyData));
        }
        catch (WebException webEx)
        {
            using (HttpWebResponse Response = (HttpWebResponse)webEx.Response)
            {
                nCode = Response.StatusCode;

                using (StreamReader reader = new StreamReader(Response.GetResponseStream()))
                {
                    sRespBodyData = reader.ReadToEnd();
                    try
                    {
                        return (JObject.Parse(sRespBodyData));
                    }
                    catch(Exception i)
                    {

                    }
                }
            }
        }

        return (null);
    }



}
}
我正在使用以下代码执行http调用:

   using System;
   using System.Collections.Generic;
   using System.Linq;
   using System.Text;
   using System.Threading.Tasks;
   using Coinigy_v2_api_2018.Functions;
   using System.Net.Http;

   namespace Coinigy_v2_api_test
   {
   class Program
   {
    static void Main(string[] args)
    {
        ApiRequest req = new ApiRequest();
        req.BaseUrl = "https://api.coinigy.com";
        req.Body = "";
        req.Method = "GET";
        req.Secret = "secret";
        req.Key = "key";
        req.Endpoint = "/api/v2/private/exchanges";

        string signature = req.Signature;
        HttpResponseMessage response = null;
        using (HttpClient client = new HttpClient())
        {
            client.DefaultRequestHeaders.Add("X-API-SIGN", signature);
            client.DefaultRequestHeaders.Add("X-API-TIMESTAMP", req.Timestamp);
            response = client.GetAsync(req.BaseUrl + req.Endpoint).Result;
        }
        string r = null;
        if (response.IsSuccessStatusCode)
        {
            r = response.Content.ReadAsStringAsync().Result;
        }

        Console.WriteLine(r);
        Console.ReadLine();


    }
}
}

再次提前感谢您

API文档可在此处找到:

2019-08-28:最新更新是端点在生成签名时必须要求查询参数未编码

首先要检查的是确保您使用的是v2api密钥/密码。旧的V1密钥不能与V2 api一起使用。如果升级订阅,则可能需要生成新密钥才能使其生效

下面是一个类,如果这不能解决问题,它应该会有所帮助:

public class ApiRequest
{
    public string BaseUrl { get; set; }
    public string Endpoint { get; set; }
    public string Key { get; set; }
    public string Secret { get; set; }
    public string Method { get; set; }
    public string Body { get; set; }
    public string Timestamp { get; set; } = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();


    /// <summary>
    /// Each API request needs to be signed so the sender can be identified.
    /// This property generates the signature based on the current request.
    /// </summary>
    public string Signature
    {
        get
        {
            var asciiEncoding = new ASCIIEncoding();
            var hmac = new HMACSHA256(asciiEncoding.GetBytes(Secret));
            string signature = Key + Timestamp + Method.ToUpper() + Endpoint + (Body ?? string.Empty);
            byte[] signatureBytes = asciiEncoding.GetBytes(signature);
            byte[] hashedSignatureBytes = hmac.ComputeHash(signatureBytes);
            string hexSignature = string.Join(string.Empty, Array.ConvertAll(hashedSignatureBytes, hb => hb.ToString("X2")));

            return hexSignature;
        }
    }
}

这里有一个额外的python3版本,它将执行整个过程:

嘿,乔,谢谢你帮助我!不幸的是,我仍然有同样的问题,没有得到授权。我要添加一个编辑代码,我有,这是使用您的代码给我。我得到这个结果:{StatusCode:401,ReasonPhrase:'Unauthorized',Version:1.1,Content:System.Net.Http.StreamContent,Headers:{Date:Sun,2018年7月29日19:19:36 GMT Content Length:0}}@parkerbidGare您应该有3个头,但我只看到两个。我想你缺少的是X-API-KEY(不确定它的确切名称)@ParkerBidigare我在那里工作,这就是我知道它的原因。目前还没有很好的记录。我们将更新文档,使其更加完善clear@ParkerBidigare我已经对文档进行了更改,这些文档将很快发布到生产环境中。他们可能星期五到那里。如果你想在那之前解决细节问题,请随时在这里提问,或者在推特或电子邮件上联系我。我很高兴accessible@ParkerBidigare请查看最新更新。我认为这些信息是解决问题的关键
public class ApiRequest
{
    public string BaseUrl { get; set; }
    public string Endpoint { get; set; }
    public string Key { get; set; }
    public string Secret { get; set; }
    public string Method { get; set; }
    public string Body { get; set; }
    public string Timestamp { get; set; } = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();


    /// <summary>
    /// Each API request needs to be signed so the sender can be identified.
    /// This property generates the signature based on the current request.
    /// </summary>
    public string Signature
    {
        get
        {
            var asciiEncoding = new ASCIIEncoding();
            var hmac = new HMACSHA256(asciiEncoding.GetBytes(Secret));
            string signature = Key + Timestamp + Method.ToUpper() + Endpoint + (Body ?? string.Empty);
            byte[] signatureBytes = asciiEncoding.GetBytes(signature);
            byte[] hashedSignatureBytes = hmac.ComputeHash(signatureBytes);
            string hexSignature = string.Join(string.Empty, Array.ConvertAll(hashedSignatureBytes, hb => hb.ToString("X2")));

            return hexSignature;
        }
    }
}
BaseUrl   : https://api.coinigy.com
Endpoint  : /api/v2/private/exchanges?pythagoreanTheorem=a%5E2%2Bb%5E2%3Dc%5E2
Key       : keykeykeykeykeykeykeykeykeykeyke
Secret    : secretsecretsecretsecretsecretse
Method    : GET
Timestamp : 1532718830 (which is 2018-07-27T19:13:50.6694555Z)
Body      : (empty string)

Signature : B618C0B3C92632C701D7CEFC00AC9C8A0771989B21E00D61D4945F79239D2F87