2
{"code":3702,"msg":"Invalid signature.","timestamp":1623848681308}

i use trbinance.com api. I keep getting the same error

procedure TForm1.Button1Click(Sender: TObject);
var
  url, sign, queryString, nonce: string;
  ST: SystemTime;
  DT: TDateTime;
  uTime: int64;
  sHour, sMin, sSec, sMili: Word;
 
  stream, s_url: string;
  Post: TStringList;
  IdHTTP10 : TIDhttp;
  api_key , api_secret : String;
begin
  api_key := '**';
  api_secret := '**';
 
  GetSystemTime(ST);
  DT := EncodeDate(ST.wYear, ST.wMonth, ST.wDay) +
        EncodeTime(ST.wHour, ST.wMinute, ST.wSecond, ST.wMilliseconds);
  uTime := DateUtils.MilliSecondsBetween(DT, UnixDateDelta);
  nonce:=inttostr(uTime);
 
  url :='https://trbinance.com/open/v1/orders';
  queryString := 'symbol=BTT_TRY&side=0&type=1&quantity=1&price=0.0022&recvWindow=5000&timestamp='+nonce;
  sign := THashSHA2.GetHMAC(queryString, api_secret, SHA256);
 
  IdHTTP10 := TidHTTP.Create(nil);
  IdHTTP10.HandleRedirects := True;
  IdHTTP10.Request.CustomHeaders.Add('X-MBX-APIKEY:'+api_key);
  IdHTTP10.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
 
  Post:=TStringList.Create;
  Post.Add('quantity=1&');
  Post.Add('price=0.0022&');
  Post.Add('recvWindow=5000&');
  Post.Add('timestamp='+nonce+'&');
  Post.Add('signature='+sign);
 
  s_url := url + '?symbol=BTT_TRY&side=0&type=1';
  try
    stream:=IdHTTP10.POST(s_url, Post);
    Memo1.Lines.Add(stream);
  except
    on E: Exception do
      Memo1.Lines.Add(TimeToStr(time)+' <---> [Order] error: '+E.Message);
  end;
  IdHTTP10.Free;
  Post.Free;
end;

Always problem :

{"code":3702,"msg":"Invalid signature.","timestamp":1623848681308}

Normaly Binance Symbol : BTTTRY  
Turkey Api : BTT_TRY
Normaly Binance Order Url :  httpps://api.binance.com/api/v3/order
Turkey Api Order Url : https://trbinance.com/open/v1/orders

Where is the Problem ?

Thank you so much.

4 Answers4

1

There are a number of issues with this code, but the biggest one I see is that you should NOT be including trailing & characters in your TStringList strings, eg:

Post:=TStringList.Create;
Post.Add('quantity=1');
Post.Add('price=0.0022');
Post.Add('recvWindow=5000');
Post.Add('timestamp='+nonce);
Post.Add('signature='+sign); 

TIdHTTP.Post() will insert those & characters into the request body for you, thus the data being transmitted is different than the data you signed.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

Thank you for your answers. I made improvements to the code.

Friends in need can use this procedure in delphi. ( for Global Binance Api )

procedure TForm1.Button1Click(Sender: TObject);
const
  Publickey= '***';
  Secretkey= '***';
var
  IdHTTP        : TIdHTTP;
  RBody         : TStringstream;
  QueryString   : String;
  Signature     : String;
  url           : String;
begin

  queryString :=
    'symbol=BTTTRY&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1000&price=0.024400&recvWindow=5000&timestamp='
    + ABDULLAH_GetTimestamp();

  Signature := THashSHA2.GetHMAC(queryString, Secretkey, SHA256);

  Try

    IdHTTP := TIdHTTP.Create();
    RBody := TStringStream.Create(queryString + '&signature=' + Signature);

    IdHTTP.Request.CustomHeaders.Add('X-MBX-APIKEY:' + Publickey);
    IdHTTP.Request.CustomHeaders.UnfoldLines := True;
    IdHTTP.Request.Accept := 'application/json';
    IdHTTP.Request.ContentType := 'application/json';
    IdHTTP.Request.ContentEncoding := 'utf-8';
    IdHTTP.Request.BasicAuthentication := True;
    IdHTTP.HandleRedirects := True;
    IdHTTP.HTTPOptions := [hoKeepOrigProtocol, hoForceEncodeParams,
      hoNoProtocolErrorException, hoWantProtocolErrorContent];

    IdHTTP.iohandler := IdSSLIOHandlerSocketOpenSSL1;

    url := 'https://api.binance.com/api/v3/order?';

    Try
      Memo1.Lines.Add(IdHTTP.Post(url, RBody));
    Except
      ON E: EXCEPTION DO
        Memo1.Lines.Add('Error Message:' + E.Message);
    End;

  Finally
    FreeAndNil(IdHTTP);
    FreeAndNil(RBody);
  End;
end;

This code works for Global Binance Api.

Change Symbol : BTTTRY -> BTT_TRY And Post Url : https://api.binance.com/api/v3/order -> https://trbinance.com/open/v1/orders

İt's not working and Result :

{"code":3702,"msg":"Invalid signature.","timestamp":1723648673412}

This Procedure works in 'Global Binance Api' but not working 'trbinance Api'

Same procedure gives 'invalid signature' error in 'trbinance api'. :(

trbinance api example :

HMAC SHA256 signature:

[linux]$ echo -n "symbol=BTC_USDT&side=0&type=1&quantity=0.16&price=7500&timestamp=1581720670624&recvWindow=5000" | openssl dgst -sha256 -hmac "cfDC92B191b9B3Ca3D842Ae0e01108CBKI6BqEW6xr4NrPus3hoZ9Ze9YrmWwPFV"
(stdin)= 33824b5160daefc34257ab9cd3c3db7a0158a446674f896c9fc3b122ae656bfa

curl command:

(HMAC SHA256)
[linux]$  curl -H "X-MBX-APIKEY: cfDC92B191b9B3Ca3D842Ae0e01108CBKI6BqEW6xr4NrPus3hoZ9Ze9YrmWwPFV" -X POST 'https://www.trbinance.com/open/v1/orders' -d 'symbol=BTC_USDT&side=0&type=1&quantity=0.16&price=7500&timestamp=1581720670624&recvWindow=5000&signature=33824b5160daefc34257ab9cd3c3db7a0158a446674f896c9fc3b122ae656bfa'
1

According to Binance TR API docs:

Use your secretKey as the key and totalParams as the value for the HMAC operation. totalParams is defined as the query string concatenated with the request body.

Error from API with the text "Invalid signature." could give you a clue that the problem is with your signature algo:

sign := THashSHA2.GetHMAC(queryString, api_secret, SHA256);

Your code here signs only your query string, but according to API docs you must sign query string concatenated with the request body.

So, you need to change your code like this ("Post" variable must be initialized before this line):

sign := THashSHA2.GetHMAC(queryString + Post.text, api_secret, SHA256);
Tavel
  • 73
  • 7
0

I found that using the TIdHTTP component in Delphi to connect to Binance has problems. I kept getting Http/1.1 400 Bad Request.

I switched to TNetHTTPClient instead to connect with Binance.

The following is the working program that can be used for placing an order on Binance:

uses
System.Net.HttpClient, System.Hash, DateUtils;

procedure TForm1.fapiorder(oSide: String; oCoin: String; oAmt: Integer);
var
  sOrderAmt: string;
  ClearEntryUrl: string;
  Params: string;
  Signature: string;
  URL: string;
  ResponseStream : TStringStream;
  postStream: TStringStream;
  uTime: int64;
  nowDateTime: string;
  ST: SystemTime;
  DT: TDateTime;
  HttpClient: THttpClient;
  HttpResponse: IHttpResponse;
  BaseURLUSDM, ApiKey, ApiSecret: string;
begin
  //https://binance-docs.github.io/apidocs/futures/cn/#trade-3
  BaseURLUSDM   := 'https://fapi.binance.com/';    //合約永續
  ClearEntryUrl := 'fapi/v1/order';
  ApiSecret     := 'YOUR API SECRET KEY';

  //timestamp 開始
  GetSystemTime(ST);
  DT := EncodeDate(ST.wYear, ST.wMonth, ST.wDay) + EncodeTime(ST.wHour, 
  ST.wMinute, ST.wSecond, ST.wMilliseconds);
  uTime := DateUtils.MilliSecondsBetween(DT, UnixDateDelta);
  nowDateTime := IntToStr(uTime);
  Writeln('DateTime = ' + nowDateTime);
  //timestamp 結束

  Params := 'recvWindow=3000&timestamp=' + nowDateTime;

  if (TDCoinMap.TryGetValue(oCoin, CoinMap) = True) then
      begin
        sOrderAmt := '0.07';
        if (StrToFloat(sOrderAmt) <> 0) then
            begin
                Params := Params + '&symbol='     + oCoin;
                Params := Params + '&side='       + oSide;
                Params := Params + '&type=MARKET';
                Params := Params + '&quantity='   + sOrderAmt;
                Signature := THashSHA2.GetHMAC(Params, ApiSecret, SHA256);
                
                URL := BaseURLUSDM + ClearEntryUrl + '?' + Params + '&signature=' + Signature;
                postStream := TStringStream.Create('');
                ResponseStream := TStringStream.Create('');
                try
                    HttpClient := THTTPClient.Create;
                    HttpClient.HandleRedirects := True;
                    HttpClient.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0';
                    HttpClient.ContentType := 'application/x-www-form-urlencoded';
                    HttpClient.CustomHeaders['X-MBX-APIKEY'] := 'Your Binance APIKEY';
                    HttpResponse := HttpClient.Post(URL, ResponseStream);
                    jResult := HttpResponse.ContentAsString();
                    Writeln('jResult = ' + jResult);
                finally
                    HttpClient.Free;
                end;
           end;
    end;
end;
Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159