здесь body строка json. Есть заголовок KC-API-SIGN, в котором зашифрована строка, body это часть этой строки.
Как сделать то же в C#? Чтобы послать строку HttpRequestMessage или в HttpClient ее надо преобразовать в new StringContent(body) или создать new FormUrlEncodedContent(new Dictionary<string, string>... Обратное преобразование меняет порядок пар в json, поэтому сервер сравнивая часть зашифрованной строки (body) c полученной строкой выдает ошибку, что неверна зашифрованная часть. Но эта часть точно такая же как в Python, я сравнивал. С другой стороны это стандартная вещь при посылке на сервер зашифрованного запроса. Как же его сделать в C#? Пытался упорядочивать пары по алфавиту, но это ничего не дало.
На всякий случай привожу 2 варианта запроса Post, который пробовал.
1:
string url = "https://openapi-sandbox.kucoin.com/api/v1/orders";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(url));
//...Тот же код, что в Питоне, проверял, только не добавляю заголовок, который тут быть не может request.Headers.Add("Content-Type", "application/json");
//пробовал и request.Content = new StringContent(body, Encoding.UTF8, "application/json");
request.Content = new StringContent(body);
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
string message = await response.Content.ReadAsStringAsync();
//Сервер возвращает "{\"code\":\"400005\",\"msg\":\"Invalid KC-API-SIGN\"}"
2:
var client = new HttpClient();
//...Тот же код, что в Питоне, проверял, только не добавляю заголовок, который тут быть не может request.Headers.Add("Content-Type", "application/json");var content = new FormUrlEncodedContent(new Dictionary<string, string>{{ "clientOid", clientOid.ToString() },{ "symbol","CRO-USDT" },{"price",34000.ToString() },
{ "side","buy" },{"size",0.001m.ToString(CultureInfo.InvariantCulture) },{ "timeInForce","GTC" },{"type","limit"}});
var result = await client.PostAsync("https://openapi-sandbox.kucoin.com/api/v1/orders", content);// string resultContent = await result.Content.ReadAsStringAsync();
Безрезультатно пробовал и устаревший WebRequest. Можно установить IronPython, но видел код, спрятанный в nuget, на C#.
An object is an unordered set of name/value pairs. An object begins with {left brace and ends with }right brace. Each name is followed by :colon and the name/value pairs are separated by ,comma.
удачи в походе по граблям.
PS:
An array is an ordered collection of values. An array begins with [left bracket and ends with ]right bracket. Values are separated by ,comma.
WBR, Igor Evgrafov
Re[2]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, Ночной Смотрящий, Вы писали:
Спасибо. Нашел в коде ошибку, сейчас работает
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
// var body = "{\"clientOid\":\"" + clientOid.ToString() + "\",\"price\":\"34000\",\"side\":\"buy\",\"size\":\"0.001\",\"symbol\":\"CRO-USDT\",\"timeInForce\":\"GTC\",\"type\":\"limit\"}";
Но почему-то возвращается ошибка "{\"code\":\"400005\",\"msg\":\"Invalid KC-API-SIGN\"}", т.е. неверен заголовок содержащий зашифрованный body, если эту строку заменить на
request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>{
new KeyValuePair<string, string>( "clientOid", clientOid.ToString() ),
new KeyValuePair<string, string> ("price","34000" ),
new KeyValuePair<string, string> ( "side","buy" ),
new KeyValuePair<string, string> ("size","0.001" ),
new KeyValuePair<string, string> ( "symbol","CRO-USDT" ),
new KeyValuePair<string, string> ( "timeInForce","GTC" ),
new KeyValuePair<string, string> ( "type","limit")
});
Весь остальной код один и тот же. Может и создание json из new FormUrlEncodedContent(new List<KeyValuePair<string, string>> тоже меняет пары в строке? Впрочем это уже не важно.
Здравствуйте, Passerby, Вы писали:
P>Весь остальной код один и тот же. Может и создание json из new FormUrlEncodedContent(new List<KeyValuePair<string, string>> тоже меняет пары в строке?
Здравствуйте, Passerby, Вы писали:
P>Весь остальной код один и тот же. Может и создание json из new FormUrlEncodedContent(new List<KeyValuePair<string, string>> тоже меняет пары в строке? Впрочем это уже не важно.
А заголовок ваш секретный вы как формируете и добавляете в запрос?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[4]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, Ночной Смотрящий, Вы писали:
Дело, вероятно, в том, что в первом случае формирования строки у метода три параметра body, Encoding.UTF8, "application/json", а во втором только один body. Может, это должно быть отражено в заголовках?
Re[4]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, varenikAA, Вы писали: AA>А заголовок ваш секретный вы как формируете и добавляете в запрос?
Я код не меняю. Один и тот же метод. Только request.Content либо по первому способу оставляю, а второй закомментировав, либо наоборот. Т.е. разные способы формирования request.Content должны еще как-то изменять код. Может, заголовок какой-нибудь добавляется.
Re[5]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, Passerby, Вы писали:
P>Дело, вероятно, в том, что в первом случае формирования строки у метода три параметра body, Encoding.UTF8, "application/json", а во втором только один body.
// iso-8859-1, Western European (ISO)internal static readonly Encoding DefaultHttpEncoding = Encoding.GetEncoding(28591);
Поскольку неанглийского текста у тебя нет, разницы быть не должно.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[5]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, Passerby, Вы писали:
P>Здравствуйте, varenikAA, Вы писали: AA>>А заголовок ваш секретный вы как формируете и добавляете в запрос? P>Я код не меняю. Один и тот же метод. Только request.Content либо по первому способу оставляю, а второй закомментировав, либо наоборот. Т.е. разные способы формирования request.Content должны еще как-то изменять код. Может, заголовок какой-нибудь добавляется.
Здравствуйте, Ночной Смотрящий, Вы писали: НС>Поскольку неанглийского текста у тебя нет, разницы быть не должно.
А она есть.
public async Task<string> OpenOrderExample()
{
string url = "https://openapi-sandbox.kucoin.com/api/v1/orders";
var nonce = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
var endpoint = "/api/v1/orders";
var clientOid = Guid.NewGuid();
var body = "{\"clientOid\":\"" + clientOid.ToString() + "\",\"price\":\"34000\",\"side\":\"buy\",\"size\":\"0.001\",\"symbol\":\"CRO-USDT\",\"timeInForce\":\"GTC\",\"type\":\"limit\"}";
var strForSign = nonce + "POST" + endpoint + body;
var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(strForSign)));
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, new Uri(url));
request.Headers.Add("KC-API-KEY", key);
request.Headers.Add("KC-API-SIGN", signature);
request.Headers.Add("KC-API-TIMESTAMP", nonce);
request.Headers.Add("KC-API-PASSPHRASE", passphrase);
//request.Content = new StringContent(body, Encoding.UTF8, "application/json");
request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>{
new KeyValuePair<string, string>( "clientOid", clientOid.ToString() ),
new KeyValuePair<string, string> ("price","34000" ),
new KeyValuePair<string, string> ( "side","buy" ),
new KeyValuePair<string, string> ("size","0.001" ),
new KeyValuePair<string, string> ( "symbol","CRO-USDT" ),
new KeyValuePair<string, string> ( "timeInForce","GTC" ),
new KeyValuePair<string, string> ( "type","limit")
});
HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false);
string message = await response.Content.ReadAsStringAsync();
return message;
}
В одном случае {"code":"900001","msg":"Symbol [CRO-USDT] Not Exists"}, т.к. пока не хочу выставлять ордера существующих пар, т.е. нормальный ответ, в другом неверный "KC-API-SIGN".
Ключи и адрес песочницы, т.е. там позволяется поиграть и деньги не реальные. Но все равно хотелось бы еще кое-что проверить, поэтому просьба ордера реальных пар не выставлять, чтобы эти игровые деньги не исчезли.
UPD
Ключи удалил
Здравствуйте, Passerby, Вы писали:
P>В одном случае {"code":"900001","msg":"Symbol [CRO-USDT] Not Exists"}, т.к. пока не хочу выставлять ордера существующих пар, т.е. нормальный ответ, в другом неверный "KC-API-SIGN". P>Ключи и адрес песочницы, т.е. там позволяется поиграть и деньги не реальные. Но все равно хотелось бы еще кое-что проверить, поэтому просьба ордера реальных пар не выставлять, чтобы эти игровые деньги не исчезли.
Ну так поставь уже себе Fiddler или WireShark и посмотри чем реквесты отличаются.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[8]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, Ночной Смотрящий, Вы писали: НС>Ну так поставь уже себе Fiddler или WireShark и посмотри чем реквесты отличаются.
Все же отличаются, а не: "Поскольку неанглийского текста у тебя нет, разницы быть не должно." Что касается Fiddler или WireShark, это можно сейчас если есть интерес посмотреть на работающем коде. А когда пишешь и получаешь ошибку, совсем непонятно что делать.
Код с ключами могу удалить? Желательно, чтобы и varenikAA ответил.
Здравствуйте, Passerby, Вы писали:
НС>>Ну так поставь уже себе Fiddler или WireShark и посмотри чем реквесты отличаются. P>Все же отличаются, а не: "Поскольку неанглийского текста у тебя нет, разницы быть не должно."
Это замечание касалось исключительно твоей идеи насчет кодировок.
Так в чем у тебя проблема сравнить запросы?
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[10]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, Ночной Смотрящий, Вы писали: НС>Так в чем у тебя проблема сравнить запросы?
Проблемы нет. Только что это даст? Увижу, что отличается, я это и так знаю. Интересовать может не отличие, а правильный код запроса Post, когда используется request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>. Сейчас, очевидно, он не должен быть таким же, как в случае request.Content = new StringContent(body, Encoding.UTF8, "application/json"); И разницу, вероятно, можно найти в сети, есть ли документация не знаю, но примеры можно найти. Спасибо.
Re[11]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, Passerby, Вы писали:
P>Здравствуйте, Ночной Смотрящий, Вы писали: НС>>Поскольку неанглийского текста у тебя нет, разницы быть не должно. P>А она есть. P>
P>public async Task<string> OpenOrderExample()
P> {
P> var body = "{\"clientOid\":\"" + clientOid.ToString() + "\",\"price\":\"34000\",\"side\":\"buy\",\"size\":\"0.001\",\"symbol\":\"CRO-USDT\",\"timeInForce\":\"GTC\",\"type\":\"limit\"}";
P> request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>{
P> }
P>
Вот же она.
Почему вы не хотите сделать так на гите?
1. Замените лист на SortedDictionary <string, object>
2. строку для ЭЦП через стандартный метод
var jsonedBody = body != null && body.Count > 0
? JsonConvert.SerializeObject(body)
: string.Empty;
и посмотрите что получится.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[8]: Сделать Post строки, часть которой в зашифрованном ви
Здравствуйте, varenikAA, Вы писали: AA>Почему вы не хотите сделать так на гите?
Потому что все работает.
Я показал код для демонстрации, что request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>... не эквивалентен request.Content = new StringContent(body, Encoding.UTF8, "application/json");
Вы продемонстрировали, что request.Content = new StringContent(body, Encoding.UTF8, "application/json"); эквивалентен new FormUrlEncodedContent(new SortedDictionary<string, string>>... и плюс к этому показали, что в таком случае не надо писать строку body, а можно создать ее из созданного SortedDictionary (body у вас и в моем коде имеют разный смысл).
Что касается request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>..., то такое тоже встречал, но тогда остальной код должен быть каким-то другим (искать не хочу).
Re[9]: Сделать Post строки, часть которой в зашифрованном ви
В свою очередь получение информации ведет к уменьшению неопределенности.
В данный момент мы знаем только то, что код на питоне работает, а на сишарпе нет.
Идея. вы могли бы попробовать выполнить код на IronPython сохранить сборку и изучить код с помощью ILSpy.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[10]: Сделать Post строки, часть которой в зашифрованном в
Здравствуйте, varenikAA, Вы писали: AA>В данный момент мы знаем только то, что код на питоне работает, а на сишарпе нет.
Работает и на питоне и на C#. Проблем никаких нет.