Сделать Post строки в json не меняя порядок пар
От: Passerby  
Дата: 21.06.21 17:19
Оценка: :))
Есть работающий метод Pyton:
response = requests.request('post', request_url, headers=headers, data=body)

здесь 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#.
Отредактировано 21.06.2021 17:25 Passerby . Предыдущая версия . Еще …
Отредактировано 21.06.2021 17:23 Passerby . Предыдущая версия .
Re: Сделать Post строки, часть которой в зашифрованном виде соде
От: Ночной Смотрящий Россия  
Дата: 21.06.21 17:28
Оценка: +1
Здравствуйте, Passerby, Вы писали:

P>Как же его сделать в C#? Пытался упорядочивать пары по алфавиту, но это ничего не дало.


Словарь не сохраняет порядок сортировки. Поэтому в ктор FormUrlEncodedContent надо запихивать не его, а List<KeyValuePair<string, string>>.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re: Сделать Post строки в json не меняя порядок пар
От: GarryIV  
Дата: 21.06.21 18:06
Оценка: 2 (1) +1
P>Безрезультатно пробовал и устаревший WebRequest. Можно установить IronPython, но видел код, спрятанный в nuget, на C#.

https://www.json.org/json-en.html

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 строки, часть которой в зашифрованном ви
От: Passerby  
Дата: 21.06.21 20:29
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:
Спасибо. Нашел в коде ошибку, сейчас работает
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>> тоже меняет пары в строке? Впрочем это уже не важно.
Отредактировано 21.06.2021 20:33 Passerby . Предыдущая версия .
Re[3]: Сделать Post строки, часть которой в зашифрованном ви
От: Ночной Смотрящий Россия  
Дата: 21.06.21 21:13
Оценка:
Здравствуйте, Passerby, Вы писали:

P>Весь остальной код один и тот же. Может и создание json из new FormUrlEncodedContent(new List<KeyValuePair<string, string>> тоже меняет пары в строке?


Нет.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: Сделать Post строки, часть которой в зашифрованном ви
От: varenikAA  
Дата: 22.06.21 04:31
Оценка:
Здравствуйте, Passerby, Вы писали:

P>Весь остальной код один и тот же. Может и создание json из new FormUrlEncodedContent(new List<KeyValuePair<string, string>> тоже меняет пары в строке? Впрочем это уже не важно.

А заголовок ваш секретный вы как формируете и добавляете в запрос?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[4]: Сделать Post строки, часть которой в зашифрованном ви
От: Passerby  
Дата: 22.06.21 06:21
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:
Дело, вероятно, в том, что в первом случае формирования строки у метода три параметра body, Encoding.UTF8, "application/json", а во втором только один body. Может, это должно быть отражено в заголовках?
Re[4]: Сделать Post строки, часть которой в зашифрованном ви
От: Passerby  
Дата: 22.06.21 06:30
Оценка:
Здравствуйте, varenikAA, Вы писали:
AA>А заголовок ваш секретный вы как формируете и добавляете в запрос?
Я код не меняю. Один и тот же метод. Только request.Content либо по первому способу оставляю, а второй закомментировав, либо наоборот. Т.е. разные способы формирования request.Content должны еще как-то изменять код. Может, заголовок какой-нибудь добавляется.
Re[5]: Сделать Post строки, часть которой в зашифрованном ви
От: Ночной Смотрящий Россия  
Дата: 22.06.21 07:27
Оценка:
Здравствуйте, 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 строки, часть которой в зашифрованном ви
От: varenikAA  
Дата: 22.06.21 08:05
Оценка: +1
Здравствуйте, Passerby, Вы писали:

P>Здравствуйте, varenikAA, Вы писали:

AA>>А заголовок ваш секретный вы как формируете и добавляете в запрос?
P>Я код не меняю. Один и тот же метод. Только request.Content либо по первому способу оставляю, а второй закомментировав, либо наоборот. Т.е. разные способы формирования request.Content должны еще как-то изменять код. Может, заголовок какой-нибудь добавляется.

Ничего непонятно. в питоне у вас задается какой-то headers
в сишарпе у вас ругается на KC-API-SIGN который как вы утверждается задается в заголовке.
вы его как задаете/вычисляете? не знаю что за апи, но видимо вычисляется хеш данных содержащийсяй в теле постзапроса и записывается в заголовок.
вообще на гите https://github.com/mscheetz/KuCoinApi.Net/blob/869334ac02446c30fe05a6e61115f0b48ee9bc98/KuCoinApi.Net/KuCoinApi.Net/Data/RepositoryBase.cs#L179
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[6]: Сделать Post строки, часть которой в зашифрованном ви
От: Passerby  
Дата: 22.06.21 09:20
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Поскольку неанглийского текста у тебя нет, разницы быть не должно.
А она есть.
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
Ключи удалил
Отредактировано 22.06.2021 13:23 Passerby . Предыдущая версия . Еще …
Отредактировано 22.06.2021 9:26 Passerby . Предыдущая версия .
Отредактировано 22.06.2021 9:24 Passerby . Предыдущая версия .
Re[7]: Сделать Post строки, часть которой в зашифрованном ви
От: Ночной Смотрящий Россия  
Дата: 22.06.21 09:34
Оценка:
Здравствуйте, 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 строки, часть которой в зашифрованном ви
От: Passerby  
Дата: 22.06.21 09:49
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Ну так поставь уже себе Fiddler или WireShark и посмотри чем реквесты отличаются.
Все же отличаются, а не: "Поскольку неанглийского текста у тебя нет, разницы быть не должно." Что касается Fiddler или WireShark, это можно сейчас если есть интерес посмотреть на работающем коде. А когда пишешь и получаешь ошибку, совсем непонятно что делать.
Код с ключами могу удалить? Желательно, чтобы и varenikAA ответил.
Отредактировано 22.06.2021 9:53 Passerby . Предыдущая версия .
Re[9]: Сделать Post строки, часть которой в зашифрованном ви
От: Ночной Смотрящий Россия  
Дата: 22.06.21 09:54
Оценка:
Здравствуйте, Passerby, Вы писали:

НС>>Ну так поставь уже себе Fiddler или WireShark и посмотри чем реквесты отличаются.

P>Все же отличаются, а не: "Поскольку неанглийского текста у тебя нет, разницы быть не должно."

Это замечание касалось исключительно твоей идеи насчет кодировок.
Так в чем у тебя проблема сравнить запросы?
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[10]: Сделать Post строки, часть которой в зашифрованном ви
От: Passerby  
Дата: 22.06.21 10:13
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Так в чем у тебя проблема сравнить запросы?
Проблемы нет. Только что это даст? Увижу, что отличается, я это и так знаю. Интересовать может не отличие, а правильный код запроса Post, когда используется request.Content = new FormUrlEncodedContent(new List<KeyValuePair<string, string>>. Сейчас, очевидно, он не должен быть таким же, как в случае request.Content = new StringContent(body, Encoding.UTF8, "application/json"); И разницу, вероятно, можно найти в сети, есть ли документация не знаю, но примеры можно найти. Спасибо.
Re[11]: Сделать Post строки, часть которой в зашифрованном ви
От: Ночной Смотрящий Россия  
Дата: 22.06.21 10:53
Оценка: +2
Здравствуйте, Passerby, Вы писали:

P>Проблемы нет. Только что это даст?


Поймешь в чем разница.

P>Увижу, что отличается, я это и так знаю.


Увидишь чем именно отличается.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[7]: Сделать Post строки, часть которой в зашифрованном ви
От: varenikAA  
Дата: 23.06.21 01:26
Оценка: 1 (1)
Здравствуйте, 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 строки, часть которой в зашифрованном ви
От: Passerby  
Дата: 23.06.21 09:10
Оценка:
Здравствуйте, 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 строки, часть которой в зашифрованном ви
От: varenikAA  
Дата: 24.06.21 01:43
Оценка:
Здравствуйте, Passerby, Вы писали:

P>Потому что все работает.


Думаю, чтобы решить вашу проблему нужно описание того для чего создается подпись.
Понимаете, для решения задачи не хватает информации.
Как гласит ДТИ:

Информация это запомненный выбор
одного из N возможных и равноправных вариантов.
© Кастлер

В свою очередь получение информации ведет к уменьшению неопределенности.
В данный момент мы знаем только то, что код на питоне работает, а на сишарпе нет.
Идея. вы могли бы попробовать выполнить код на IronPython сохранить сборку и изучить код с помощью ILSpy.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[10]: Сделать Post строки, часть которой в зашифрованном в
От: Passerby  
Дата: 24.06.21 17:04
Оценка: 6 (1)
Здравствуйте, varenikAA, Вы писали:
AA>В данный момент мы знаем только то, что код на питоне работает, а на сишарпе нет.
Работает и на питоне и на C#. Проблем никаких нет.
Отредактировано 24.06.2021 17:28 Passerby . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.