viewpoint-particle

Author Topic: Sending an API-Key  (Read 220 times)

hdsouza

  • Full Member
  • ***
  • Posts: 117
Sending an API-Key
« on: November 18, 2017, 05:15:00 pm »
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
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

  • Pundit
  • *****
  • Posts: 668
Re: Sending an API-Key
« Reply #1 on: November 19, 2017, 07:16:21 am »
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

  • Full Member
  • ***
  • Posts: 117
Re: Sending an API-Key
« Reply #2 on: November 19, 2017, 05:11:15 pm »
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

  • Pundit
  • *****
  • Posts: 806
    • Data & Stuff Inc.
Re: Sending an API-Key
« Reply #3 on: November 19, 2017, 06:00:42 pm »
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

  • Tech Support
  • *****
  • Posts: 2223
    • WinBatch
Re: Sending an API-Key
« Reply #4 on: November 20, 2017, 06:51:31 am »
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.
"Success is a lousy teacher. It seduces smart people into thinking they can't lose."
  - Bill Gates


stanl

  • Pundit
  • *****
  • Posts: 668
Re: Sending an API-Key
« Reply #5 on: November 20, 2017, 10:15:04 am »
No harm in just trying

Code: Winbatch
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

  • Full Member
  • ***
  • Posts: 117
Re: Sending an API-Key
« Reply #6 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
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

  • Tech Support
  • *****
  • Posts: 2223
    • WinBatch
Re: Sending an API-Key
« Reply #7 on: November 20, 2017, 09:57:07 pm »
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
;; 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.
"Success is a lousy teacher. It seduces smart people into thinking they can't lose."
  - Bill Gates


stanl

  • Pundit
  • *****
  • Posts: 668
Re: Sending an API-Key
« Reply #8 on: November 21, 2017, 03:38:07 am »
Stanl, Did you mean like this....
I get an error on the last line "1298: COM: Error code not recognized"

Code: Winbatch
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

  • Full Member
  • ***
  • Posts: 117
Re: Sending an API-Key
« Reply #9 on: November 21, 2017, 04:29:24 pm »
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
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
<?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($ch, CURLOPT_URL, $url);
   curl_setopt ( $ch, CURLOPT_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_POST, 1);
     curl_setopt($ch,CURLOPT_POSTFIELDS, $post);
   }
   curl_setopt ( $ch, CURLOPT_AUTOREFERER, true );
   curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, true );
   $headers = array();
   $headers[] = "Authorization: $apikey";
   curl_setopt($ch, CURLOPT_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

  • Pundit
  • *****
  • Posts: 668
Re: Sending an API-Key
« Reply #10 on: November 22, 2017, 03:37:24 am »
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

  • Full Member
  • ***
  • Posts: 117
Re: Sending an API-Key
« Reply #11 on: November 22, 2017, 02:51:40 pm »
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)