Реализовываю API запросы на биржу криптовалют BTC-Alpha. В частности вот такой запрос, который позволяет приобретать на бирже разные валюты.
Вот моя реализация:
Вызов метода.
public OrderCreationResponseDTO CreateOrder(OrderCreationDTO dto)
=> POST<OrderCreationResponseDTO>(dto,
"https://btc-alpha.com/api/v1/order",
GetAuthHeaders(JsonConvert.SerializeObject(dto)));
Как вы видите, вызывается метод POST
, который возвращает нам непонятную DTO-ху, а внутрь этого метода передаётся ещё и метод GetAuthHeaders
, который в свою очередь, принимает JSON строку.
POST<>
private protected T POST<T>(object jsonDTO, string url, string[] headers = null)
{
var req = WebRequest.Create(url);
req.Method = "POST";
if (headers != null)
for (int i = 0; i < headers.Length; i++)
req.Headers.Add(headers[i]);
using (var dataStream = new StreamWriter(req.GetRequestStream(), Encoding.UTF8))
dataStream.Write(JsonConvert.SerializeObject(jsonDTO));
var response = (HttpWebResponse)req.GetResponse(); //Вот тут всё падает
var responseStream = response.GetResponseStream();
return JsonConvert.DeserializeObject<T>(new StreamReader(responseStream).ReadToEnd());
}
GetAuthHeaders | Этот метод делает нам правильные заголовки для запроса. Реализовано согласно документации API.
public string ApiKey { get; set; }
public string UserSecret { get; set; } //Это я для наглядности добавил
private string[] GetAuthHeaders(string postData = null)
{
if (postData == null) postData = string.Empty;
else //На костыль ниже не обращайте внимания, он рабочий :)
{
postData = postData.Replace("{", "");
postData = postData.Replace("}", "");
postData = postData.Replace("\"", "");
postData = postData.Replace(":", "=");
var args = postData.Split(',');
Array.Sort(args, (x, y) => string.Compare(x, y));
postData = args[0];
for (int i = 1; i < args.Length; i++)
postData += "&" + args[i];
}
string sign = BitConverter.ToString(new HMACSHA256(Encoding.ASCII.GetBytes(UserSecret))
.ComputeHash(Encoding.ASCII.GetBytes(ApiKey + postData))).Replace("-", "").ToLower();
return new string[3]
{
"X-KEY:" + ApiKey,
"X-SIGN:" + sign,
"X-NONCE:" + new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds()
};
}
OrderCreationDTO | Собственно те данные которые я хочу отправить
public sealed class OrderCreationDTO
{
[JsonProperty("amount")]
public string Amount { get; set; }
[JsonProperty("pair")]
public string Pair { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("price")]
public string Price { get; set; }
}
OrderCreationResponseDTO
показывать нет смысла, только лишних букв добавлю, коих и так не мало. Проблема в том, что сервер возвращает мне ошибку №400 Bad Request
, почему он такой прямо Bad
- я так и не понял, хотя уже много пытался. Может вы подскажите?
Просто пробовал разные варианты и вот такой - рабочий:
private protected T POST<T>(object jsonDTO, string url, string[] headers = null)
{
byte[] data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(jsonDTO));
var request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = data.Length;
if (headers != null)
for (int i = 0; i < headers.Length; i++)
request.Headers.Add(headers[i]);
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(data, 0, data.Length);
return JsonConvert.DeserializeObject<T>(new StreamReader(((HttpWebResponse)request.GetResponse()).GetResponseStream()).ReadToEnd());
}
Я не стал в деталях изучать в чём разница, во всяком случае пока, но оставлю это здесь, может кому полезно будет.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Для тестирования написал небольшой клиент, идет бесконечное подключение(в streamRead)