Hola.
Estoy tratado de obtener información sobre mi cuenta en Binance, empleando la Api de dicha empresa.
De la Api voy a emplear la funcion:
Para ello escribí el siguiente programa en B4J
Dicho programa esta basado en esta función escrita en PHP, la cual funciona correctamente.
Entiendo que tengo que crear una url de la forma
La parte timestamp=1614749827929 debe ser firmada con (HMAC SHA256). Para ello empleo la siguiente función:
La función importante del programa es SendCommand, la cual se encarga de hacer las solicituder de información a Binance empleando su Api
La ejecutar el programa me aparece el error
La ApiKey y el ApiSecret incluidas en el programa son validas (en caso que ud desee ejecutar el programa).
Si Ud desea ayudarme solo debe bajar el proyecto que he adjuntado. El programa esta escrito en B4J, el cual, como ud puede ver es muy similar a B4A. Para ejecutarlo requiere B4J.
Nota: el programa lo estoy desarrollando en B4J para instalarlo en un VPS o un mini computador sin partes móviles. Por eso no lo he desarrollado en B4A para Android.
Estoy tratado de obtener información sobre mi cuenta en Binance, empleando la Api de dicha empresa.
De la Api voy a emplear la funcion:
Binance Api: Account information (USER_DATA)
GET /api/v3/account (HMAC SHA256)
Podrá encontrar mas información sobre la api de Binance en:
binance-spot-api-docs/rest-api.md at master · binance/binance-spot-api-docs
Official Documentation for the Binance Spot APIs and Streams - binance/binance-spot-api-docsgithub.com
Para ello escribí el siguiente programa en B4J
B4X:
#Region Project Attributes
#MainFormWidth: 600
#MainFormHeight: 600
#End Region
Sub Process_Globals
Private fx As JFX
Private MainForm As Form
Private TextAreaOut As TextArea
Private ButtonGet As Button
Private BinanceApiUrl As String
Private ApiSecret As String
Private ApiKey As String
End Sub
Sub AppStart (Form1 As Form, Args() As String)
MainForm = Form1
MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
MainForm.Show
BinanceApiUrl = "https://api.binance.com/api/"
ApiKey = "VmcKfcJ127jpeGUPAKXnHXJBTSF9iMfHUqptwEb1TCvSLwgNnCJ2BuWsdVwyhsbD"
ApiSecret = "xTFh2bqOydbMumZmWcV13ecPYFTHmZa5pg0Xp3rlay5Tyog2VBoEAJQToMURhU1E"
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
Return True
End Sub
'Funcion encargada de hacer las solicitudes a la Api de Binance
private Sub SendCommand(work As String, uri As String, Signature As Boolean)
Try
'Si se debe firmar
If (Signature == True)Then
Dim timestamp As Long
timestamp = DateTime.now 'Creamos el timestamp
Dim queryString As String
queryString = "timestamp=" & timestamp 'Creamos el Query string
Dim Sign() As Byte
Sign = HashHmac(queryString, ApiSecret) 'Firmamos el Query string
Dim API_Signed As String
Dim Byte_Conv As ByteConverter
API_Signed = Byte_Conv.HexFromBytes(Sign) 'convert to HEX
API_Signed = API_Signed.ToLowerCase
End If
Dim j As HttpJob
j.Initialize(work, Me)
Dim Url As String
Url = BinanceApiUrl & uri & "?" & queryString & "&signature=" & API_Signed 'Creamos la Url
j.Download(Url)
Log(Url)
'Si se debe firmar
If (Signature == True)Then
Try
'Defino el SetHeader basado función "signedRequest()" que encontrará en este post.
j.GetRequest.SetHeader("User-Agent", "Mozilla/4.0 (compatible; PHP Binance API)")
j.GetRequest.SetHeader("X-MBX-ApiKey", ApiKey)
j.GetRequest.SetHeader("Content-Type", "application/x-www-form-urlencoded")
Catch
Log(LastException)
End Try
End If
Wait For (j) JobDone(j As HttpJob)
If j.Success Then
TextAreaOut.Text = j.JobName & CRLF
TextAreaOut.Text = TextAreaOut.Text & j.GetString
Log(j.GetString)
Else
TextAreaOut.Text = j.ErrorMessage
End If
j.Release
Catch
MessageBox(LastException, "Error")
End Try
End Sub
Sub ButtonGet_Click
SendCommand("GetBalances", "v3/account", True)
End Sub
'Funcion encargada de Firmar el QueryString
Public Sub HashHmac(data As String, secret As String) As Byte()
Try
Dim m As Mac 'm As Message Authentication Code
Dim kg As KeyGenerator 'kg As KeyGenerator
kg.Initialize("HmacSHA512") 'initialize kg using HmacSHA512 algorithm
kg.KeyFromBytes(secret.GetBytes("UTF8")) 'encode string "secret" to an array of Bytes using UTF8
m.Initialise("HmacSHA512", kg.Key) 'initialize m using HmacSHA512 algorithm and the secret key
m.Update(data.GetBytes("UTF8")) 'encodes post data to an array of Bytes and loads it to be signed
Return m.Sign 'sign the loaded data using the secret key, return the calc signature data
Catch
MessageBox(LastException, "Error")
End Try
End Sub
Public Sub MessageBox(Message As String, Title As String )
Private jxui As XUI
jxui.MsgboxAsync(Message, Title)
End Sub
Dicho programa esta basado en esta función escrita en PHP, la cual funciona correctamente.
PHP:
private function signedRequest($url, $params = [], $method = "GET") {
$params['timestamp'] = number_format(microtime(true)*1000,0,'.','');
$query = http_build_query($params, '', '&'); // https://www.php.net/manual/es/function.http-build-query.php
$signature = hash_hmac('sha256', $query, $this->api_secret);
$opt = [
"http" => [
"method" => $method,
"ignore_errors" => true,
"header" => "User-Agent: Mozilla/4.0 (compatible; PHP Binance API)\r\nX-MBX-APIKEY: {$this->api_key}\r\nContent-type: application/x-www-form-urlencoded\r\n"
]
];
if ( $method == 'GET' ) {
// parameters encoded as query string in URL
$endpoint = "{$this->base}{$url}?{$query}&signature={$signature}";
} else {
// parameters encoded as POST data (in $context)
$endpoint = "{$this->base}{$url}";
$postdata = "{$query}&signature={$signature}";
$opt['http']['content'] = $postdata;
}
$context = stream_context_create($opt); // https://www.php.net/manual/es/function.stream-context-create.php
return json_decode(file_get_contents($endpoint, false, $context), true); // https://www.php.net/manual/es/function.json-decode.php
}
Entiendo que tengo que crear una url de la forma
B4X:
https://api.binance.com/api/v3/account?timestamp=1614749827929&signature=5022a05d3b51db60b5933976c09a53775f8d753129fca5ee59b63b882bd9a0a80f7e4c9ab38cd4aec00bd042b8a344fb5841335e2e70946af2ca529bdf5dabab
La parte timestamp=1614749827929 debe ser firmada con (HMAC SHA256). Para ello empleo la siguiente función:
B4X:
Public Sub HashHmac(data As String, secret As String) As Byte()
Try
Dim m As Mac 'm As Message Authentication Code
Dim kg As KeyGenerator 'kg As KeyGenerator
kg.Initialize("HmacSHA512") 'initialize kg using HmacSHA512 algorithm
kg.KeyFromBytes(secret.GetBytes("UTF8")) 'encode string "secret" to an array of Bytes using UTF8
m.Initialise("HmacSHA512", kg.Key) 'initialize m using HmacSHA512 algorithm and the secret key
m.Update(data.GetBytes("UTF8")) 'encodes post data to an array of Bytes and loads it to be signed
Return m.Sign 'sign the loaded data using the secret key, return the calc signature data
Catch
MessageBox(LastException, "Error")
End Try
End Sub
La función importante del programa es SendCommand, la cual se encarga de hacer las solicituder de información a Binance empleando su Api
B4X:
private Sub SendCommand(work As String, uri As String, Signature As Boolean)
Try
'Si se debe firmar
If (Signature == True)Then
Dim timestamp As Long
timestamp = DateTime.now 'Creamos el timestamp
Dim queryString As String
queryString = "timestamp=" & timestamp 'Creamos el Query string
Dim Sign() As Byte
Sign = HashHmac(queryString, ApiSecret) 'Firmamos el Query string
Dim API_Signed As String
Dim Byte_Conv As ByteConverter
API_Signed = Byte_Conv.HexFromBytes(Sign) 'convert to HEX
API_Signed = API_Signed.ToLowerCase
End If
Dim j As HttpJob
j.Initialize(work, Me)
Dim Url As String
Url = BinanceApiUrl & uri & "?" & queryString & "&signature=" & API_Signed 'Creamos la Url
j.Download(Url)
Log(Url)
'Si se debe firmar
If (Signature == True)Then
Try
'Defino el SetHeader basado en la línea 11 del código de la función [B]signedRequest() [/B]que encontrará mas abajo.
j.GetRequest.SetHeader("User-Agent", "Mozilla/4.0 (compatible; PHP Binance API)")
j.GetRequest.SetHeader("X-MBX-ApiKey", ApiKey)
j.GetRequest.SetHeader("Content-Type", "application/x-www-form-urlencoded")
Catch
Log(LastException)
End Try
End If
Wait For (j) JobDone(j As HttpJob)
If j.Success Then
TextAreaOut.Text = j.JobName & CRLF
TextAreaOut.Text = TextAreaOut.Text & j.GetString
Log(j.GetString)
Else
TextAreaOut.Text = j.ErrorMessage
End If
j.Release
Catch
MessageBox(LastException, "Error")
End Try
End Sub
La ejecutar el programa me aparece el error
ResponseError. Reason: , Response: {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."}
La ApiKey y el ApiSecret incluidas en el programa son validas (en caso que ud desee ejecutar el programa).
Si Ud desea ayudarme solo debe bajar el proyecto que he adjuntado. El programa esta escrito en B4J, el cual, como ud puede ver es muy similar a B4A. Para ejecutarlo requiere B4J.
Nota: el programa lo estoy desarrollando en B4J para instalarlo en un VPS o un mini computador sin partes móviles. Por eso no lo he desarrollado en B4A para Android.
Attachments
Last edited: