Delphi + Binance Api +限价订单问题无效签名

9w11ddsr  于 2022-12-03  发布在  其他
关注(0)|答案(4)|浏览(189)
{"code":3702,"msg":"Invalid signature.","timestamp":1623848681308}

我使用的是trbinance.com api。我一直收到相同的错误

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;

总是问题:

{"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

问题出在哪里?
非常感谢你。

lp0sw83n

lp0sw83n1#

谢谢你的回答。我改进了代码。
有需要的朋友可以在 Delphi 中使用这个程序。(对于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;

此代码适用于Global Binance Api。

更改符号:BTTTRY -〉BTT_TRY和帖子URL:- -----
t不工作,结果:

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

此程序适用于“全局Binance Api”,但不适用于“事务Binance Api”

相同的过程在“trbinance api”中给出“无效签名”错误。:(

事务API示例:

HMAC SHA 256签名:

[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命令:

(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'
holgip5t

holgip5t2#

这段代码有很多问题,但我看到的最大的一个问题是,你不应该在你的TStringList字符串中包含尾随的&字符,例如:

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()将为您将这些&字符插入到请求正文中,因此传输的数据与您签名的数据不同。

yzuktlbb

yzuktlbb3#

根据Binance TR API文件:
使用secretKey作为HMAC操作的键,使用totalParams作为HMAC操作的值。totalParams定义为与请求正文连接的查询字符串。
来自API的文本为“签名无效”的错误。可能会给予您签名算法存在问题:

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

此处的代码仅对查询字符串进行签名,但根据API文档,您必须对与请求正文连接的查询字符串进行签名。
所以,你需要这样修改你的代码(“Post”变量必须在这一行之前初始化):

sign := THashSHA2.GetHMAC(queryString + Post.text, api_secret, SHA256);
pxyaymoc

pxyaymoc4#

谢谢您提供的各种解决方案,但我测试后还是有问题,无法正常执行,因为以前我是用B4 J写的系统正常连接Binance进行交易的,后来。我发现在 Delphi 中使用*TidHTTP*组件连接Binance有问题。我一直收到Http/1.1 400错误请求。我使用TNetHTTPClient而不是连接到Binance。非常高兴,我成功了。下面是我成功测试的程序,在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;

结束;

相关问题