Firma una chiamata all'API Coinbase Pro con Google Apps Script

Aug 25 2020

Sto impazzendo cercando di inviare la mia prima chiamata API a Coinbase Pro utilizzando Google Apps Script. In node.js è abbastanza semplice (https://docs.pro.coinbase.com/#signing-a-message) ma fare lo stesso con gli script di Google significa semplicemente restituire ancora e ancora "Firma non valida".

Questo è il codice che sto usando:

function GetMyAccounts () {
  var globalvars_CB = {
   'apikey'     : 'f7d20a*******18c',
   'secret'     : '******pIIitRbWCv9N/mMWaR*****mGQMuI+m/vSbU1zuh5U6WFiFw==',
   'passphrase' : 'ceacdsewfcsa',
   'uri'        : 'https://api.pro.coinbase.com'
  }
  
  var requestPath = '/accounts';
  
  var timestamp = Math.floor(Date.now() / 1000);

  var options = {
    'method' : 'GET',
    'muteHttpExceptions' : true,     
    'headers' : {
      'Content-Type': 'application/json',
      'CB-ACCESS-KEY' : globalvars_CB.apikey,
      'CB-ACCESS-SIGN' : SignAPICall(globalvars_CB.secret, timestamp, 'GET', requestPath, ''),
      'CB-ACCESS-TIMESTAMP' : timestamp,
      'CB-ACCESS-PASSPHRASE' :  globalvars_CB.passphrase,
          }
  }  
    
  var responseJson = UrlFetchApp.fetch(globalvars_CB.uri+requestPath, options);
  
  Logger.log(responseJson);
 }
    

function SignAPICall(secret, timestamp, method, requestPath, body) {

  var what = (timestamp + method + requestPath + body);
  
  var decodedsecret = Utilities.base64Decode(secret).toString();
  
  var hmac = Utilities.computeHmacSha256Signature(what, decodedsecret);
 
  hmac = Utilities.base64Encode(hmac);
  
  return (hmac);    

}

Ho davvero bisogno di aiuto :-) - Grazie!

Risposte

1 Tanaike Aug 25 2020 at 22:26

Nello script, si suppone che le intestazioni della richiesta, ad eccezione del valore di CB-ACCESS-SIGNe dell'endpoint, siano corrette. Per favore, stai attento.

Punto di modifica:

  • Nel caso di Utilities.base64Decode(secret).toString(), l'array viene convertito nella stringa. Penso che questo potrebbe essere il motivo del tuo problema.

Quando il punto sopra viene riflesso, diventa il seguente.

Script modificato:

In questo caso, la funzione SignAPICallviene modificata.

function SignAPICall(secret, timestamp, method, requestPath, body) {
  var what = (timestamp + method + requestPath + body);
  var decodedsecret = Utilities.base64Decode(secret);  // Modified
  var res = Utilities.computeHmacSha256Signature(Utilities.newBlob(what).getBytes(), decodedsecret);  // Modified
  hmac = Utilities.base64Encode(res);
  return hmac;
}
  • In questo caso, valuee keyof computeHmacSha256Signature(value, key)sono l'array di byte.

Nota:

  • Quando ho controllato lo script modificato sopra confrontando gli script di esempio del documento ufficiale , ho potuto confermare che è possibile ottenere lo stesso risultato.
  • Sfortunatamente, non posso testare la richiesta all'API utilizzando lo script modificato sopra mentre posso confermare che la stessa firma dallo script di esempio nel documento ufficiale viene recuperata dallo script modificato sopra. Quindi prova la richiesta nel tuo ambiente. Quando hai richiesto all'API utilizzando lo script modificato sopra, quando si verifica un errore, controlla di nuovo le intestazioni della richiesta, l'endpoint e il segreto.

Riferimenti:

  • Firmare un messaggio
  • base64Decode (codificato)
  • computeHmacSha256Signature (valore, chiave)
AlbertSampietro Sep 06 2020 at 06:56

Finalmente ho trovato la soluzione. Era un problema con il tipo di dati che ho inviato a "Utilities.computeHmacSha256Signature". Nel codice puoi trovare la funzione che funziona bene.

function SignAndCallAPI(method, requestPath, body) {

  var timestamp = Math.floor(Date.now() / 1000).toString();
  
  var what = Utilities.base64Decode(Utilities.base64Encode(timestamp + method + requestPath + body));
  
  var decodedsecret = Utilities.base64Decode(globalvars_CB.secret);
  
  var hmac = Utilities.base64Encode(Utilities.computeHmacSha256Signature(what, decodedsecret));
     
  var options = {
    'method' : method,
    'muteHttpExceptions' : true,     
    'headers' : {
      'Content-Type': 'application/json',
      'CB-ACCESS-KEY' : globalvars_CB.apikey,
      'CB-ACCESS-SIGN' : hmac,
      'CB-ACCESS-TIMESTAMP' : timestamp,
      'CB-ACCESS-PASSPHRASE' :  globalvars_CB.passphrase,
     }
  }  
      
   var responseJson = UrlFetchApp.fetch(globalvars_CB.uri+requestPath, options);
  
  Logger.log(responseJson);
  return(responseJson);  

}