Swift Requires Chilkat v11.0.0+
Swift
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
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
}
}