Sample code for 30+ languages & platforms
Tcl Requires Chilkat v11.0.0+

Xero API through an SOCKS Proxy

This example demonstrates connecting through a SOCKS proxy w/ 2-legged OAuth for a Xero private application.

Chilkat Tcl Downloads

Tcl

load ./chilkat.dll

set success 0

#  This sample code would typically be placed in a subroutine or function
#  where the rest object is passed by reference.
#  It does the OAuth1 setup and makes the initial connection.
set rest [new_CkRest]

#  Connect to the Xero server through an HTTP proxy, and then tell the REST object
#  to use the socket connection.
set socket [new_CkSocket]

#  Set the SOCKS proxy domain or IP address, port, and SOCKS version number (4 or 5)
CkSocket_put_SocksHostname $socket "192.168.1.100"
CkSocket_put_SocksPort $socket 1080
CkSocket_put_SocksVersion $socket 5
#  Other properties exist for specifying a SOCKS proxy login and password,
#  but these are not used in this example.

#  Connect through the SOCKS proxy..
set bTls 1
set port 443
set maxWaitMs 5000
set success [CkSocket_Connect $socket "api.xero.com" $port $bTls $maxWaitMs]
if {$success != 1} then {
    puts "Connect Failure Error Code: [CkSocket_get_ConnectFailReason $socket]"
    puts [CkSocket_lastErrorText $socket]
    delete_CkRest $rest
    delete_CkSocket $socket
    exit
}

#  Use the SOCKS proxied TLS connection:
set success [CkRest_UseConnection $rest $socket 1]
if {$success == 0} then {
    puts [CkRest_lastErrorText $rest]
    delete_CkRest $rest
    delete_CkSocket $socket
    exit
}

#  OK, we're connected.  
#  The UseConnection method has an internal reference to the underlying/internal socket.
#  The application can does not need to keep its socket object in existence.
#  -----------------------------------------------------------------
#  Now setup the OAuth1 authenticator..

set consumerKey "XERO_PRIVATE_APP_KEY"
set consumerSecret "XERO_PRIVATE_APP_SECRET"

#  Let's get our private key from our PFX (password protected), or the PEM (unprotected).
#  You can decide which to use.  Either is OK, although I would recommend keeping your
#  private keys in a PFX and not in an unprotected PEM.
set pfx [new_CkPfx]

set success [CkPfx_LoadPfxFile $pfx "qa_data/certs/xero_private_app/public_privatekey.pfx" "PFX_PASSWORD"]
if {$success == 0} then {
    puts [CkPfx_lastErrorText $pfx]
    delete_CkRest $rest
    delete_CkSocket $socket
    delete_CkPfx $pfx
    exit
}

set privKeyFromPfx [new_CkPrivateKey]

set success [CkPfx_PrivateKeyAt $pfx 0 $privKeyFromPfx]
if {$success == 0} then {
    puts [CkPfx_lastErrorText $pfx]
    delete_CkRest $rest
    delete_CkSocket $socket
    delete_CkPfx $pfx
    delete_CkPrivateKey $privKeyFromPfx
    exit
}

#  Or we can load from a PEM..
set privKeyFromPem [new_CkPrivateKey]

set success [CkPrivateKey_LoadPemFile $privKeyFromPem "qa_data/certs/xero_private_app/privatekey.pem"]
if {$success == 0} then {
    puts [CkPrivateKey_lastErrorText $privKeyFromPem]
    delete_CkRest $rest
    delete_CkSocket $socket
    delete_CkPfx $pfx
    delete_CkPrivateKey $privKeyFromPfx
    delete_CkPrivateKey $privKeyFromPem
    exit
}

#  Note: There are many other means for loading a private key, including
#  from other formats and directly from memory (i.e. not file-based).

set oauth1 [new_CkOAuth1]

CkOAuth1_put_ConsumerKey $oauth1 $consumerKey
CkOAuth1_put_ConsumerSecret $oauth1 $consumerSecret
CkOAuth1_put_Token $oauth1 $consumerKey
CkOAuth1_put_TokenSecret $oauth1 $consumerSecret
CkOAuth1_put_SignatureMethod $oauth1 "RSA-SHA1"
CkOAuth1_SetRsaKey $oauth1 $privKeyFromPfx

#  Install the OAuth1 authenticator.
CkRest_SetAuthOAuth1 $rest $oauth1 0

puts "OK, the Xero OAuth1 is initialized and the REST object is ready to make REST API calls.."

#  -----------------------------------------------------------------
#  Make a call to verify that OAuth1 through an HTTP proxy works..

#  Get the full list of contacts.
set sbXml [new_CkStringBuilder]

set success [CkRest_FullRequestNoBodySb $rest "GET" "/api.xro/2.0/Contacts" $sbXml]
if {$success == 0} then {
    puts [CkRest_lastErrorText $rest]
    delete_CkRest $rest
    delete_CkSocket $socket
    delete_CkPfx $pfx
    delete_CkPrivateKey $privKeyFromPfx
    delete_CkPrivateKey $privKeyFromPem
    delete_CkOAuth1 $oauth1
    delete_CkStringBuilder $sbXml
    exit
}

#  A 200 response is expected for actual success.
if {[CkRest_get_ResponseStatusCode $rest] != 200} then {
    puts [CkStringBuilder_getAsString $sbXml]
    delete_CkRest $rest
    delete_CkSocket $socket
    delete_CkPfx $pfx
    delete_CkPrivateKey $privKeyFromPfx
    delete_CkPrivateKey $privKeyFromPem
    delete_CkOAuth1 $oauth1
    delete_CkStringBuilder $sbXml
    exit
}

#  Iterate over the contacts..
set bAutoTrim 0
set xml [new_CkXml]

CkXml_LoadSb $xml $sbXml $bAutoTrim
CkXml_SaveXml $xml "qa_cache/xero_contacts.xml"

#  How many records exist?
set recordCount [CkXml_NumChildrenAt $xml "Contacts"]
puts "numRecords = $recordCount"

set i 0
while {$i < $recordCount} {
    CkXml_put_I $xml $i
    puts "ContactID: [CkXml_getChildContent $xml {Contacts|Contact[i]|ContactID}]"
    set i [expr $i + 1]
}

delete_CkRest $rest
delete_CkSocket $socket
delete_CkPfx $pfx
delete_CkPrivateKey $privKeyFromPfx
delete_CkPrivateKey $privKeyFromPem
delete_CkOAuth1 $oauth1
delete_CkStringBuilder $sbXml
delete_CkXml $xml