As a software business owner you might want your software to communicate with other apps around the web for various reasons:
- Temporary extension before you bake third party functionality in your app.
- Extending your app functionality which is not your core business but some customers want it.
- Bringing customers from existing established apps to your app.
The list can be longer but the point is there are very good reasons why your app needs to communicate with third party software. One such service is very popular Australian (and global) accounting software https://www.xero.com. Xero is subscription based Software as a service mostly used by small businesses. They have a marketplace of partner apps which is a good way for your app to get more credibility and customers.
Recently we worked with HERO.WORK App - a popular job management app for tradies and small businesses. Some of their customers were using Xero and requested the feature to synchronize their contacts, invoices and payments between HERO.WORK and Xero. We have jumped on to the task and successfully connected Node.JS based app HERO.WORK with Xero. The rest of the blog post is about technical challenges we had to solve for that.
For those who don't want to read the whole post but want to jump straight into code, check following 2 Node Vision github repositories:
xero-client - npm module which:
- connects to xero rest api (you will need your own xero credentials)
- requests authentication token and stores it in session
- reads, creates and updates data in connected Xero organization
node-react-xero-app - full stack javascript application written with Node.JS, Express, React and MongoDB
- you can
git clone
it or see a hosted version on reactxeroapp.nodevision.com.au - application allows adding invoices and contacts and demonstrates synchronization with Xero
Research and implementation
HERO.WORK required 2 way synchronization for contacts, invoices and payments with easily extendible api for future upgrades to other entities. For that we needed to do 5 steps:
- Research - where to start?, how Xero Api works? what's already available in open source world?
- Xero client - ideally a library or custom service which connects to Xero and pulls and pushes data.
- Transformation service - pieces of code to translate xero data structure to internal one.
- Business logic - create or update? Does Xero or our app have the most recent version? When to trigger sync? How to handle errors?
- UI - for this post we created a short app with React.JS frontend to demonstrate xero synchronization.
Step 1. Research
Xero enables 3 different types of integrations:
- private apps - think web or desktop app which connects to single Xero organization.
- public apps - web or desktop app which can connect to many organizations but allows only short-term access enabled by user.
- partner apps - similar to public but without limitations. Read more on xero application types.
As we have written several apps and apis with Node.JS, we know that one of its biggest advantages is enormous community around the platform and heaps of useful npm modules. Therefore we started by searching for useful stuff on npm and github.
HERO.WORK is by definition a public app so we searched for npm modules which would help with the task:
- The most popular extension was https://www.npmjs.com/package/xero - it is recommended by Xero but unfortunately works only for private apps.
- Then there is a github repository with a sample code for connecting public apps: https://github.com/jeromyevans/xero-api-public-application-nodejs
- and of course we can't forget the official documentation at http://developer.xero.com/documentation/ which goes in to great details when we needed to check data structures of entities and other requirements for API endpoints.
Step 2. Creating a xero client.
As there was no magic bullet to plug into the app, we had to build xero-client from the beginning while getting inspired by above mentioned modules.
2.1 First step - authentication
To allow our app to connect to Xero, user needs to log in to her Xero account and authorize our app to have access to organization.
Xero supports Oauth protocol which facilitates authentication without necessity of a third party app having to know user name and password. It would take another post to explain how oauth works, you can read this post https://blog.varonis.com/introduction-to-oauth/ to get a good overview. In essence we need to request a Consumer Key
and Consumer Secret
from Xero developer api console and use it for oauth requests when communicating with Xero. Another essential part is to provide a callback url
- that's an address (or api endpoint) which is called by xero upon successful authentication. The code on this url receives access token and secret which is stored in the session and is used for any additional requests. (Xero Public apps limit a token validity for 30 minutes - this limitation can be avoided by upgrading to a partner app)
There is a great npm module which encapsulates oauth functionality - oauth and code to initialize oauth request and receive token and secret in response
var oauth = new OAuth.OAuth(
'https://api.xero.com/oauth/RequestToken',
'https://api.xero.com/oauth/AccessToken',
config.xeroConsumerKey,
config.xeroConsumerSecret,
'1.0A',
null,
'HMAC-SHA1',
null,
{
"Accept": "application/json",
"Connection": "close"
},
_authorize_callback: config.xeroCallbackUrl
);
oauth.getOAuthRequestToken(function (error, oauthtoken, oauthtokensecret, results) {
if (error) {
//handle error
}
// store the token in the session
req.session.xeroAuth = {
token: oauthtoken,
tokensecret: oauthtoken_secret
};
});
2.2 one or two way sync?
Synchronization algorithm can become pretty complex with multiple database operations, network calls, deciding wheter create, update or delete records, figuring out which data has the latest version and which needs to be updated. You can save a lot of trouble if you decide that you need to synchronize only one way - e.g. our sample app only sends created contacts and invoices to Xero but doesn't download invoices from there.
2.3 json or xml?
In a Node.JS and javascript world the obvious preference for the data transfer format is JSON. Xero Api request and response format is configurable by setting appropriate headers and can accept both JSON and XML in GET requests. But when we need to modify data with PUT or POST requests, we have to use XML format. Fortunately building xml from native js objects in Node.JS is quite simple. We can use npm module easyxml. Converting js object into a xml which is used to create/update invoices or contacts is as easy as:
var post_body = new EasyXml({rootElement: 'Invoices', rootArray: invoices, manifest: true}).render(data);
See xero-client for full implementation of a client code.
Step 3. Transforming data from and to Xero
If you build an app with a sole purpose to connect with Xero, I'd recommend using data model which is used by Xero. They have put a lot of time to make sure it's flexible enough. But chances are that you have your own model and therefore need a transformation service to translate data. There are also data types which need a special attention like Date and time fields. Xero accepts only strict formats which we need to translate before sending.
Contacts are straightforward - there is only one thing which can save few issues down the line and that is a
ContactNumber
field - it is designed to be populated with a custom id (can be string, not just number). It is handy to save there a unique identifier from a local app so later on it's easier to match local and xero contacts and resolve duplicates.Invoices - are more complex. One must be very careful with setting if invoice line items include GST or not. Our sample app always includes GST in prices so we need to set
LineAmountTypes
toInclusive
. We also have to make sure that line items actually include GST. It's not relevant in the sample app, but when integrating a real world public application, users usually have a choice to either include or exclude tax in their pricing. With invoices we can setInvoiceNumber
for the same purposes as in contacts. Invoices are more strict than contacts and require more mandatory fields (like link to a contact, line items, due date etc.) See official documentation and try api explorer to verify that everything is in place. See xeroTransforms service for more details.
Step 4. Business logic
Why do we integrate with Xero? For HERO.WORK we needed to synchronize contacts and invoices and download reconciled payments so users can see accurate reporting and use invoicing features flawlessly in both apps without worrying that they have to enter details twice. For our example app we only demonstrated how to send contacts and invoices to Xero. Whatever you need to do, this is the place where multiple network and database operations are performed and you will need a solid asynchronous flow control library to keep the code clean and well organized. We used well known npm module async which allows to stack multiple serial, parallel and batch calls without running into callback hell issues.
Step 5. UI
As the name of the sample node-react-xero-app suggests we have used React to build UI for the app. In Node Vision we have been developing client side code with Angular.js and Ionic a lot, but as React has some clear advantages over Angular.js 1.x as server side rendering and works generally faster in mobile browsers, we decided to create a demo app with React. There are a lot of tutorials how to start with React which are out of scope of this blog post. You can just clone the code on github and have a play.
One note for implementing Xero authentication flow in UI - we chose to open the login ui in a popup window - that's good when we don't want our single page app to leave to a xero login page and then fully reload after returning back. As a side effect we don't know exactly when user finishes authentication. Because of that we have set a 2 second interval which polls xero authentication status and if it changes, we change button and add more info about token expiry. The better approach would be to set up web sockets connection which would notify React client when sync is ready. But that's too heavy weight for this demo.
Final notes
The guide is quite short but should be sufficient enough to get an idea what's involved when integrating the Node.JS based web app with Xero. For more details check Node Vision github account and check our live demo
Do you need help with Xero integration or found something missing? Please leave a comment.