Sending an API-Key

Started by hdsouza, November 18, 2017, 05:15:00 PM

Previous topic - Next topic

hdsouza

Hi ,
I am trying to write a script that can pass  API credentials.
As an example i want to get the available cash  as in https://www.lendingclub.com/developers/available-cash
This is my first time writing calls to JSON, so I am a little lost.

Here is what I wrote so far , but it returns a bad response.
Any help would be appreciated.

Code (winbatch) Select

Invest_ID = "5166XXX"
cURL = 'https://api.lendingclub.com/api/investor/v1/accounts/%Invest_ID%/availablecash'
apikey = 'GVsZuDKATPRlsajFiBXXXXXXX'
GoSub UDFs

oHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
a = oHTTP.Open("GET", cURL, @FALSE)
;----------------------------------------------------------------------------
; Define Headers
;----------------------------------------------------------------------------
str_64=Base64StringFromClearString(B64GetCookie(),StrCat(":",apikey))
oHTTP.SetRequestHeader("Authorization",StrCat("Basic ", str_64))
oHTTP.SetRequestHeader("Content-Type", "application/json"); Content-Type

;----------------------------------------------------------------------------
; Send the request
;----------------------------------------------------------------------------
oHTTP.Send()
oHTTP.WaitForResponse()

If oHTTP.Status != 200
   If oHTTP.Status == 302
      Pause( "Server Attempted Redirect to: ", oHTTP.getResponseHeader("Location"))
   EndIf
   Status = oHTTP.Status
   StatusText = oHTTP.StatusText
   headers = oHTTP.GetAllResponseHeaders()
   Pause(oHTTP.Status, headers)
EndIf

;----------------------------------------------------------------------------
; Get Response
;----------------------------------------------------------------------------
JSON_Data = oHTTP.ResponseText
exit
;----------------------------------------------------------------------------
:UDFs
#DefineFunction B64GetCookie()
   B64Cookie=ArrDimension(256,2)  ; ,0 is to B64  ,1 if from B64
   ArrInitialize(B64Cookie,-1)
   AUPPER=Char2Num("A")
   alower=Char2Num("a")
   ZEROChr=Char2Num("0")

   For xx=0 To 25
      B64Cookie[xx,0]=Num2Char(AUPPER+xx)
      B64Cookie[xx+26,0]=Num2Char(alower+xx)
   Next

   For xx=52 To 61
      B64Cookie[xx,0]=Num2Char(ZEROChr+xx-52)
   Next

   B64Cookie[62,0]="+"
   B64Cookie[63,0]="/"

   For xx=0 To 63
       val=Char2Num(B64Cookie[xx,0])
       B64Cookie[val,1]=xx
   Next
   b64Cookie[Char2Num("="),1]=9999  ; flag the = sign

   Return(B64Cookie)
#EndFunction

#DefineFunction Base64StringFromClearString(B64Cookie,clearstring)
  s=StrLen(clearstring)
  bb=BinaryAlloc(s)
  BinaryPokeStr(bb,0,clearstring)
  b64bb=Base64BBFromClearBB(B64Cookie,bb)
  s=BinaryPeekStr(b64bb,0,BinaryEodGet(b64bb))
  BinaryFree(bb)
  BinaryFree(b64bb)
  Return(s)
#EndFunction

#DefineFunction Base64BBFromClearBB(B64Cookie,clearbb)
   ;clearbb contains bytes to be converted into base64 format
   ;how many triplets
   clearbytes=BinaryEodGet(clearbb)
   cleartriplets= clearbytes/3
   clearremnants= clearbytes mod 3
   ;if clearremnants !=0 then cleartriplets=cleartriplets+1
   b64quads=ClearTriplets
   If clearremnants!=0 Then b64quads=b64quads+1
   b64bytes= b64quads*4  + (b64quads/16)*2  + 6; 4bytes per quad + CRLF every 16 quads plus 6 in case I got the math wrong
   ;Only 16 quads per line allowed
   quadlinecount=0
   B64BB=BinaryAlloc(b64bytes)
   For xx= 1 To cleartriplets
      c1 = BinaryPeek(clearbb,(xx-1)*3+0)
      c2 = BinaryPeek(clearbb,(xx-1)*3+1)
      c3 = BinaryPeek(clearbb,(xx-1)*3+2)

      d1 =                      c1 >> 2
      d2 = ( (c1 &  3) << 4) | (c2 >> 4)
      d3 = ( (c2 & 15) << 2) | (c3 >> 6)
      d4 = ( (c3 & 63)     )
      quad=StrCat(B64Cookie[d1,0],B64Cookie[d2,0],B64Cookie[d3,0],B64Cookie[d4,0])
      BinaryPokeStr(b64BB,BinaryEodGet(b64bb),quad)
      quadlinecount=quadlinecount+1
      If (quadlinecount mod 16)==0 Then BinaryPokeStr(b64BB,BinaryEodGet(b64bb),@CRLF)
   Next xx
   Switch clearremnants
      Case 1
          c1=BinaryPeek(clearbb,(cleartriplets)*3+0)
          d1 =                      c1 >> 2
          d2 = ( (c1 &  3) << 4)
          quad=StrCat(B64Cookie[d1,0],B64Cookie[d2,0],"==")
          Continue
      Case 2
          c1=BinaryPeek(clearbb,(cleartriplets)*3+0)
          c2 = BinaryPeek(clearbb,(cleartriplets)*3+1)
          d1 =                      c1 >> 2
          d2 = ( (c1 &  3) << 4) | (c2 >> 4)
          d3 = ( (c2 & 15) << 2)
          quad=StrCat(B64Cookie[d1,0],B64Cookie[d2,0],B64Cookie[d3,0],"=")
          Continue
      Case 1
      Case 2
         BinaryPokeStr(b64BB,BinaryEodGet(b64bb),quad)
         quadlinecount=quadlinecount+1
         If (quadlinecount mod 16)==0 Then BinaryPokeStr(b64BB,BinaryEodGet(b64bb),@CRLF)
   EndSwitch
   Return(b64BB)
#EndFunction

Return

stanl

Having done several similar web queries with returned JSON, the code you posted looks like it should work, but you didn't post the error or return code that was invalid. I have never needed to use a base64 conversion: str_64=Base64StringFromClearString(B64GetCookie(),StrCat(":",apikey)) so I cannot be of any help there. Maybe if others and Tony pitch in things will become clearer. BTW: this is an SSL request and those get tricky./

hdsouza

Hi Stanl,

For :
"StatusText" I get "Bad Request"
"JSON_Data"  I get "{"status":400,"error_code":"LARGE_PARAMETER","message":"Request parameter too large: credential-key","id":0}"

I dont know If I need base64 either. Is there a way around it. I am in the blind here.
Thanks
Hil

JTaylor

Why are you converting the key to base64?   Did something indicate that should be done?   Have you tried it without the base64 encoding?

Jim

td

Concur with Jim and Stan.  Have never encountered a case where it was required to base-64 encode a web services app key.   The JSON response indicates that the request parameter is to large which is what happens to a string when it is base-64 encoded, i.e., it becomes longer.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

No harm in just trying

Code (WINBATCH) Select

oHTTP.SetRequestHeader("Authorization",apikey)


can't find 'Basic' in any of the samples for access in their doscs.
[EDIT]
Found it in the tech database, it was specific to a particular URL.

hdsouza

Stanl, Did you mean like this....
I get an error on the last line "1298: COM: Error code not recognized"

Code (winbatch) Select

Invest_ID = "5166xxxx"
cURL = 'https://api.lendingclub.com/api/investor/v1/accounts/%Invest_ID%/availablecash'
apikey = 'GVsZuDKATPRlsajFiBCxxxxx'

oHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
oHTTP.SetRequestHeader("Authorization",apikey)
exit

td

The exact requirements vary from vendor to vendor but here are a few lines from a working script used in a production environment.

Code (winbatch) Select
;; Error handling removed for readability.
objHttp=ObjectCreate("WinHttp.WinHttpRequest.5.1")
objHttp.SetTimeouts(50000, 50000, 50000, 50000);
objHttp.open("POST",strSquUrl,"False")
strAuth='Bearer ':strAccTok
objHttp.SetRequestHeader("Authorization", strAuth )
objHttp.SetRequestHeader("Accept", "application/json")
objHttp.SetRequestHeader("Content-Type", "application/json")
objHttp.Send(body)
if objHttp.Status != 200
   ;Blah blah blah error blah blah blah
endif
strResponse=objHttp.responseText


You would need to check your site's documentation carefully to determine what exactly it is expecting.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Quote from: hdsouza on November 20, 2017, 05:45:43 PM
Stanl, Did you mean like this....
I get an error on the last line "1298: COM: Error code not recognized"

Code (winbatch) Select

Invest_ID = "5166xxxx"
cURL = 'https://api.lendingclub.com/api/investor/v1/accounts/%Invest_ID%/availablecash'
apikey = 'GVsZuDKATPRlsajFiBCxxxxx'

oHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
oHTTP.SetRequestHeader("Authorization",apikey)
exit


I meant just re-write the line in your original script. What you posted [above] should fail. Since you received a Json return in the original script we were just suggesting you remove the base64 stuff.

hdsouza

Thanks TD.
I took your sample code and applied it to my script.
We may be a little closer. Now I get "StatusText" = "Unauthorized"
I believe strAuth has the incorrect format.
Verified that my api key is correct.
Any ideas?

Code (winbatch) Select

Invest_ID = "5166XXXX"
cURL = 'https://api.lendingclub.com/api/investor/v1/accounts/%Invest_ID%/availablecash'
apikey = 'GVsZuDKATPRlsaXXXXXXXXXXX'

oHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")
oHttp.SetTimeouts(50000, 50000, 50000, 50000);
oHttp.open("POST",cURL,"False")
strAuth='Bearer ':apikey
oHttp.SetRequestHeader("Authorization", strAuth )   
oHttp.SetRequestHeader("Accept", "application/json")
oHttp.SetRequestHeader("Content-Type", "application/json")
oHttp.Send()
if oHttp.Status != 200
   If oHTTP.Status == 302
      Pause( "Server Attempted Redirect to: ", oHTTP.getResponseHeader("Location"))
   EndIf
   Status = oHTTP.Status
   StatusText = oHTTP.StatusText
   headers = oHTTP.GetAllResponseHeaders()
   Pause(oHTTP.Status, headers)
endif
strResponse=oHttp.responseText
exit


Also if it will help here is the Equivalent WORKING PHP code:
Code (php) Select

<?php
  $Invest_ID 
"5166XXXX";
  
$apikey 'GVsZuDKATPRlsaXXXXXXXXXXX';
  
define("DEBUG_LENDING_API"false);
  
$balance get_balance($Invest_ID$apikey);
  echo 
$balance;

  function 
get_balance($Invest_ID$apikey){
    
$balance_url "https://api.lendingclub.com/api/investor/v1/accounts/$Invest_ID/availablecash";
    
// to get balance call this
     
return call_curl($balance_url$apikey);
  }
  function 
call_curl($url$apikey$post "0"){
   
$ch curl_init();
   
curl_setopt($chCURLOPT_URL$url);
   
curl_setopt $chCURLOPT_USERAGENT"Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.9) Gecko/2008052906 Firefox/3.0" );
   if(
$post != "0"){
     
curl_setopt($ch,CURLOPT_POST1);
     
curl_setopt($ch,CURLOPT_POSTFIELDS$post);
   }
   
curl_setopt $chCURLOPT_AUTOREFERERtrue );
   
curl_setopt $chCURLOPT_FOLLOWLOCATIONtrue );
   
$headers = array();
   
$headers[] = "Authorization: $apikey";
   
curl_setopt($chCURLOPT_HTTPHEADER$headers);
   
$server_output curl_exec ($ch);
   
$info curl_getinfo($ch);
   
curl_close ($ch);
   if(
DEBUG_LENDING_API == true){
     return array(
"data" => $server_output"response" => $info);
   }else{
     return 
json_decode($server_output);
   }
  }
?>


stanl

Just looking at your last post.  There is no 'Bearer' in the PHP code and I don't believe the concatenation is necessary. Also, you probably should be using a GET not a POST (as was Tony's example - and the PHP code appears to use GET)

hdsouza

You were right about the GET and not needing the concatenation.  That did the trick.
Thanks Stan and Tony !!!!
(This is just the first step and have several other things to do, so i may have a few more questions)