Sample code for 30+ languages & platforms
Unicode C++ 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 Unicode C++ Downloads

Unicode C++
#include <CkRestW.h>
#include <CkSocketW.h>
#include <CkPfxW.h>
#include <CkPrivateKeyW.h>
#include <CkOAuth1W.h>
#include <CkStringBuilderW.h>
#include <CkXmlW.h>

void ChilkatSample(void)
    {
    bool success = false;

    //  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.
    CkRestW rest;

    //  Connect to the Xero server through an HTTP proxy, and then tell the REST object
    //  to use the socket connection.
    CkSocketW socket;

    //  Set the SOCKS proxy domain or IP address, port, and SOCKS version number (4 or 5)
    socket.put_SocksHostname(L"192.168.1.100");
    socket.put_SocksPort(1080);
    socket.put_SocksVersion(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..
    bool bTls = true;
    int port = 443;
    int maxWaitMs = 5000;
    success = socket.Connect(L"api.xero.com",port,bTls,maxWaitMs);
    if (success != true) {
        wprintf(L"Connect Failure Error Code: %d\n",socket.get_ConnectFailReason());
        wprintf(L"%s\n",socket.lastErrorText());
        return;
    }

    //  Use the SOCKS proxied TLS connection:
    success = rest.UseConnection(socket,true);
    if (success == false) {
        wprintf(L"%s\n",rest.lastErrorText());
        return;
    }

    //  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..

    const wchar_t *consumerKey = L"XERO_PRIVATE_APP_KEY";
    const wchar_t *consumerSecret = L"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.
    CkPfxW pfx;
    success = pfx.LoadPfxFile(L"qa_data/certs/xero_private_app/public_privatekey.pfx",L"PFX_PASSWORD");
    if (success == false) {
        wprintf(L"%s\n",pfx.lastErrorText());
        return;
    }

    CkPrivateKeyW privKeyFromPfx;
    success = pfx.PrivateKeyAt(0,privKeyFromPfx);
    if (success == false) {
        wprintf(L"%s\n",pfx.lastErrorText());
        return;
    }

    //  Or we can load from a PEM..
    CkPrivateKeyW privKeyFromPem;
    success = privKeyFromPem.LoadPemFile(L"qa_data/certs/xero_private_app/privatekey.pem");
    if (success == false) {
        wprintf(L"%s\n",privKeyFromPem.lastErrorText());
        return;
    }

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

    CkOAuth1W oauth1;
    oauth1.put_ConsumerKey(consumerKey);
    oauth1.put_ConsumerSecret(consumerSecret);
    oauth1.put_Token(consumerKey);
    oauth1.put_TokenSecret(consumerSecret);
    oauth1.put_SignatureMethod(L"RSA-SHA1");
    oauth1.SetRsaKey(privKeyFromPfx);

    //  Install the OAuth1 authenticator.
    rest.SetAuthOAuth1(oauth1,false);

    wprintf(L"OK, the Xero OAuth1 is initialized and the REST object is ready to make REST API calls..\n");

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

    //  Get the full list of contacts.
    CkStringBuilderW sbXml;
    success = rest.FullRequestNoBodySb(L"GET",L"/api.xro/2.0/Contacts",sbXml);
    if (success == false) {
        wprintf(L"%s\n",rest.lastErrorText());
        return;
    }

    //  A 200 response is expected for actual success.
    if (rest.get_ResponseStatusCode() != 200) {
        wprintf(L"%s\n",sbXml.getAsString());
        return;
    }

    //  Iterate over the contacts..
    bool bAutoTrim = false;
    CkXmlW xml;
    xml.LoadSb(sbXml,bAutoTrim);
    xml.SaveXml(L"qa_cache/xero_contacts.xml");

    //  How many records exist?
    int recordCount = xml.NumChildrenAt(L"Contacts");
    wprintf(L"numRecords = %d\n",recordCount);

    int i = 0;
    while (i < recordCount) {
        xml.put_I(i);
        wprintf(L"ContactID: %s\n",xml.getChildContent(L"Contacts|Contact[i]|ContactID"));
        i = i + 1;
    }
    }