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

Xero API through an SSH Tunnel

This example demonstrates connecting through an SSH Tunnel w/ 2-legged OAuth for a Xero private application.

Chilkat Swift Downloads

Swift

func chilkatTest() {
    var success: Bool = false

    //  This example requires the Chilkat API to have been previously unlocked.
    //  See Global Unlock Sample for sample code.

    let tunnel = CkoSocket()!

    var sshHostname: String? = "sftp.example.com"
    var sshPort: Int = 22

    //  Connect to an SSH server and establish the SSH tunnel:
    success = tunnel.sshOpenTunnel(sshHostname: sshHostname, sshPort: sshPort)
    if success == false {
        print("\(tunnel.lastErrorText!)")
        return
    }

    //  Authenticate with the SSH server via a login/password
    //  or with a public key.
    //  This example demonstrates SSH password authentication.
    success = tunnel.sshAuthenticatePw(sshLogin: "mySshLogin", sshPassword: "mySshPassword")
    if success == false {
        print("\(tunnel.lastErrorText!)")
        return
    }

    //   OK, the SSH tunnel is setup.  Now open a channel within the tunnel.
    //   (Any number of channels may be created from the same SSH tunnel.
    //   Multiple channels may coexist at the same time.)

    //  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.
    let rest = CkoRest()!

    var bTls: Bool = true
    var port: Int = 443
    var maxWaitMs: Int = 7000

    //  This returns a socket object that is a single channel within the SSH tunnel.
    let channel = CkoSocket()!
    success = tunnel.sshNewChannel(hostname: "api.xero.com", port: port, ssl: bTls, maxWaitMs: maxWaitMs, channel: channel)
    if success == false {
        print("\(tunnel.lastErrorText!)")
        return
    }

    //  Use the connection.  (This connection is a TLS running on an SSH channel through an SSH tunnel.
    //  In other words, TLS is wrapped within the SSH tunnel.)
    success = rest.useConnection(connection: channel, autoReconnect: true)
    if success == false {
        print("\(rest.lastErrorText!)")
        return
    }

    //  OK, we're connected.  
    //  -----------------------------------------------------------------
    //  Now setup the OAuth1 authenticator..

    var consumerKey: String? = "XERO_PRIVATE_APP_KEY"
    var consumerSecret: String? = "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.
    let pfx = CkoPfx()!
    success = pfx.loadFile(path: "qa_data/certs/xero_private_app/public_privatekey.pfx", password: "PFX_PASSWORD")
    if success == false {
        print("\(pfx.lastErrorText!)")
        return
    }

    let privKeyFromPfx = CkoPrivateKey()!
    success = pfx.privateKey(at: 0, privKey: privKeyFromPfx)
    if success == false {
        print("\(pfx.lastErrorText!)")
        return
    }

    //  Or we can load from a PEM..
    let privKeyFromPem = CkoPrivateKey()!
    success = privKeyFromPem.loadPemFile(path: "qa_data/certs/xero_private_app/privatekey.pem")
    if success == false {
        print("\(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).

    let oauth1 = CkoOAuth1()!
    oauth1.consumerKey = consumerKey
    oauth1.consumerSecret = consumerSecret
    oauth1.token = consumerKey
    oauth1.tokenSecret = consumerSecret
    oauth1.signatureMethod = "RSA-SHA1"
    oauth1.setRsaKey(privKey: privKeyFromPfx)

    //  Install the OAuth1 authenticator.
    rest.setAuthOAuth1(authProvider: oauth1, useQueryParams: false)

    print("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.
    let sbXml = CkoStringBuilder()!
    success = rest.fullRequestNoBodySb(httpVerb: "GET", uriPath: "/api.xro/2.0/Contacts", sb: sbXml)
    if success == false {
        print("\(rest.lastErrorText!)")
        return
    }

    //  A 200 response is expected for actual success.
    if rest.responseStatusCode.intValue != 200 {
        print("\(sbXml.getAsString()!)")
        return
    }

    //  Iterate over the contacts..
    var bAutoTrim: Bool = false
    let xml = CkoXml()!
    xml.loadSb(sb: sbXml, autoTrim: bAutoTrim)
    xml.save(path: "qa_cache/xero_contacts.xml")

    //  How many records exist?
    var recordCount: Int = xml.numChildren(at: "Contacts").intValue
    print("numRecords = \(recordCount)")

    var i: Int = 0
    while i < recordCount {
        xml.i = i
        print("ContactID: \(xml.getChildContent(tagPath: "Contacts|Contact[i]|ContactID")!)")
        i = i + 1
    }


}