Помогите отправить строку в body HTTP запроса

Devillio
Дата: 24.06.2019 09:39:00
Добрый день!

Играюсь с биржей, получилось отправлять подписанные Get запросы
+ Вот описание API с биржи
#
# POST
#
verb = 'POST'
path = '/api/v1/order'
expires = 1518064238 # 2018-02-08T04:30:38Z
data = '{"symbol":"XBTM15","price":219.0,"clOrdID":"mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA","orderQty":98}'

# HEX(HMAC_SHA256(apiSecret, 'POST/api/v1/order1518064238{"symbol":"XBTM15","price":219.0,"clOrdID":"mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA","orderQty":98}'))
# Result is:
# '1749cd2ccae4aa49048ae09f0b95110cee706e0944e6a14ad0b3a8cb45bd336b'
signature = HEX(HMAC_SHA256(apiSecret, verb + path + str(expires) + data))
Get не прикрепляю, там все то же самое но без data
+ Вот моя "реализация" Post и Get к этой бирже
function TTraderThreadMain.API_PostGetSigned(AParams: TStringList; const AMethod, AData: String; const APath: String;
  var IsExcepted: Boolean): String;
var
  Param, URLParam, URLPath, Nonce, S: String;
  PostData: TStringList;
  MS: TStringStream;

  Sign: AnsiString;
  Http_req: TIdHTTP;
  SSL_req: TIdSSLIOHandlerSocketOpenSSL;
  i, N: Integer;
begin
  Result := '';
  IsExcepted := false;
  // if AParams.Count > 0 then
  try
    Param := '';
    N := TUniTrader(ATrader).Nonce;
    PostData := TStringList.Create;
    MS := TStringStream.Create;

    Http_req := TIdHTTP.Create(nil);
    SSL_req := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
    Http_req.IOHandler := SSL_req;
    Http_req.ReadTimeout := 10000;
    Http_req.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';

    if TUniTrader(ATrader).APIKind = akBitmex then
    begin
      // hex(HMAC_SHA256(apiSecret, глагол + путь + срок действия + данные))
      for i := 0 to AParams.Count - 1 do
        Param := Param + IfThen(i = 0, '', '&') + AParams.KeyNames[i] + '=' + AParams.ValueFromIndex[i];
      Nonce := IntToStr(N);

      URLPath := '/api/v1' + APath;
      URLParam := IfThen(Param = '', '', Copy(TIDURI.URLEncode('https://test.ru?' + Param), 16, 10000));
      PostData.Clear;
      if AData <> '' then
      begin
      PostData.add(AData);
      end;
      S := UpperCase(AMethod) + URLPath + URLParam + Nonce + AData; //тут вроде бы правильная строка, как по описанию api
//'POST/api/v1/position/leverage1561372499{"symbol": "XBTUSD", "leverage": 10}'
      Sign := SHA256DigestToHexW(CalcHMAC_SHA256(TUniTrader(ATrader).FAPISecret, S));
      Http_req.Request.CustomHeaders.AddValue('connection', 'Keep-Alive');
      Http_req.Request.CustomHeaders.AddValue('keep-alive', '90');
      Http_req.Request.CustomHeaders.AddValue('api-expires', Nonce);
      Http_req.Request.CustomHeaders.AddValue('api-key', TUniTrader(ATrader).FAPIID);
      Http_req.Request.CustomHeaders.AddValue('api-signature', Sign);
//      PostData.WriteBOM := False; //пробовал body передать как TStringList - тот же результат
//      PostData.TrailingLineBreak := false;
//      PostData.SaveToStream(MS);
//      MS.Position := 0;
    end;

    Http_req.AllowCookies := true;

    try
      // APIMutex.Enter;
      try
        if AMethod = 'post' then
          Result := Http_req.post(TUniTrader(ATrader).BaseURL + URLPath + URLParam, PostData); //на все post получаю 401 Unauth 
        if AMethod = 'get' then
          Result := Http_req.Get(TUniTrader(ATrader).BaseURL + URLPath + URLParam); //get запросы подписаны правильно, отрабатывают
      except
        on pe: EIdHTTPProtocolException do
        begin
          IsExcepted := true;
          Result := ' -> api error : ' + TimeToStr(Time) + ' ' + pe.Message;
        end;
        on e: exception do
        begin
          IsExcepted := true;
          Result := ' -> api error : ' + TimeToStr(Time) + ' ' + e.Message;
        end;
      end;
    finally
      // APIMutex.Leave;
    end;
  finally
    Http_req.Free;
    SSL_req.Free;
    FreeAndNil(PostData);
    FreeAndNil(MS);
  end;
end;

Явно что-то не так с отправкой body в post запросах у меня, подскажите, что не так делаю?
Спасибо!
Кроик Семён
Дата: 24.06.2019 11:14:50
я так понял из кода, вы хоть Get, хоть Post отправляете на один и тот же URL TUniTrader(ATrader).BaseURL + URLPath + URLParam

        if AMethod = 'post' then
          Result := Http_req.post(TUniTrader(ATrader).BaseURL + URLPath + URLParam, PostData); //на все post получаю 401 Unauth 
        if AMethod = 'get' then
          Result := Http_req.Get(TUniTrader(ATrader).BaseURL + URLPath + URLParam); //get запросы подписаны правильно, отрабатывают   


но ведь в вашем случае если Post, то должен быть другой URL, как то так

        if AMethod = 'post' then
          Result := Http_req.post(TUniTrader(ATrader).BaseURL + URLPath, PostData); //на все post получаю 401 Unauth