├── .gitignore ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | lib-cov 3 | *.seed 4 | *.log 5 | *.csv 6 | *.dat 7 | *.out 8 | *.pid 9 | *.gz 10 | 11 | pids 12 | logs 13 | results 14 | 15 | node_modules 16 | npm-debug.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xero 2 | A simple node library for Xero Private Applications 3 | 4 | ## Install 5 |
  6 |   npm install xero
  7 | 
8 | ## Usage 9 | ### Request 10 | ```javascript 11 | var express = require("express"); 12 | var Xero = require('xero'); 13 | var fs = require('fs'); 14 | 15 | var app = express(); 16 | 17 | var CONSUMER_KEY="my consumer key"; 18 | var CONSUMER_SECRET="my consumer secret"; 19 | var RSA_PRIVATE_KEY = fs.readFileSync(process.env.HOME + "/.ssh/id_rsa"); 20 | var xero = new Xero(CONSUMER_KEY, CONSUMER_SECRET, RSA_PRIVATE_KEY); 21 | 22 | app.get('/', function (req, res) { 23 | xero.call('GET', '/Users', null, function(err, json) { 24 | if (err) { 25 | res.status(err.statusCode); 26 | res.write(JSON.stringify(err)); 27 | res.end(); 28 | } else { 29 | res.status(200); 30 | res.write(JSON.stringify(json)); 31 | res.end(); 32 | } 33 | }); 34 | }); 35 | 36 | app.listen(3000, function () { 37 | console.log("Listening..."); 38 | }); 39 | ``` 40 | ### Response 41 | ```javascript 42 | { 43 | "Response":{ 44 | "Id":"37286998-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 45 | "Status":"OK", 46 | "ProviderName":"My Account", 47 | "DateTimeUTC":"2013-04-22T17:13:31.2755569Z", 48 | "Users":{ 49 | "User":{ 50 | "UserID":"613fbf01-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 51 | "FirstName":"Chadd", 52 | "LastName":"Sexington", 53 | "UpdatedDateUTC":"2013-04-12T05:54:50.477", 54 | "IsSubscriber":"true", 55 | "OrganisationRole":"STANDARD" 56 | } 57 | } 58 | } 59 | } 60 | ``` 61 | ### Example POST Request 62 | ```javascript 63 | ... 64 | // Adding contact(s) 65 | var request; 66 | // Single 67 | request = { 68 | Name: 'Name1' 69 | }; 70 | // Multiple 71 | request = [{ 72 | Name: 'Name1' 73 | }, { 74 | Name: 'Name2' 75 | }]; 76 | xero.call('POST', '/Contacts?SummarizeErrors=false', request, function(err, json) { 77 | ... 78 | }); 79 | ``` 80 | 81 | ### Download PDF 82 | ```javascript 83 | var Xero = require('xero'); 84 | var fs = require('fs'); 85 | 86 | var xero = new Xero(CONSUMER_KEY, CONSUMER_SECRET, RSA_PRIVATE_KEY); 87 | var invoiceId = 'invoice-identifier'; 88 | var req = xero.call('GET', '/Invoices/' + invoiceId); 89 | 90 | req.setHeader('Accept', 'application/pdf'); 91 | req.on('response', function(response) { 92 | var file = fs.createWriteStream(invoiceId + '.pdf'); 93 | response.pipe(file); 94 | }); 95 | req.end(); 96 | ``` 97 | 98 | ## Docs 99 | http://developer.xero.com/documentation/ 100 | 101 | Enjoy! - thallium205 102 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var crypto = require("crypto"); 2 | var oauth = require("oauth"); 3 | var EasyXml = require('easyxml'); 4 | var xml2js = require('xml2js'); 5 | var inflect = require('inflect'); 6 | 7 | var XERO_BASE_URL = 'https://api.xero.com'; 8 | var XERO_API_URL = XERO_BASE_URL + '/api.xro/2.0'; 9 | 10 | function Xero(key, secret, rsa_key, showXmlAttributes, customHeaders) { 11 | this.key = key; 12 | this.secret = secret; 13 | 14 | this.parser = new xml2js.Parser({explicitArray: false, ignoreAttrs: showXmlAttributes !== undefined ? (showXmlAttributes ? false : true) : true, async: true}); 15 | 16 | this.oa = new oauth.OAuth(null, null, key, secret, '1.0', null, "PLAINTEXT", null, customHeaders); 17 | this.oa._signatureMethod = "RSA-SHA1" 18 | this.oa._createSignature = function(signatureBase, tokenSecret) { 19 | return crypto.createSign("RSA-SHA1").update(signatureBase).sign(rsa_key, output_format = "base64"); 20 | } 21 | } 22 | 23 | Xero.prototype.call = function(method, path, body, callback) { 24 | var self = this; 25 | 26 | var post_body = null; 27 | var content_type = null; 28 | if (method && method !== 'GET' && body) { 29 | if (Buffer.isBuffer(body)) { 30 | post_body = body; 31 | } else { 32 | var root = path.match(/([^\/\?]+)/)[1]; 33 | post_body = new EasyXml({rootElement: inflect.singularize(root), rootArray: root, manifest: true}).render(body); 34 | content_type = 'application/xml'; 35 | } 36 | } 37 | var process = function(err, xml, res) { 38 | if (err) { 39 | return callback(err); 40 | } 41 | 42 | self.parser.parseString(xml, function(err, json) { 43 | if (err) return callback(err); 44 | if (json && json.Response && json.Response.Status !== 'OK') { 45 | return callback(json, res); 46 | } else { 47 | return callback(null, json, res); 48 | } 49 | }); 50 | }; 51 | return self.oa._performSecureRequest(self.key, self.secret, method, XERO_API_URL + path, null, post_body, content_type, callback ? process : null); 52 | } 53 | 54 | module.exports = Xero; 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xero", 3 | "version": "0.0.8", 4 | "dependencies": { 5 | "oauth": "0.9.12", 6 | "easyxml": "1.0.0", 7 | "xml2js": "0.4.4", 8 | "inflect": "0.3.0" 9 | }, 10 | "description": "Xero.com Node Library", 11 | "main": "index.js", 12 | "repository": { 13 | "type": "git", 14 | "url": "git@github.com:thallium205/xero.git" 15 | }, 16 | "keywords": [ 17 | "xero", 18 | "node", 19 | "nodejs" 20 | ], 21 | "author": "thallium205 ", 22 | "license": "MIT", 23 | "readmeFilename": "README.md", 24 | "devDependencies": {}, 25 | "scripts": { 26 | "test": "echo \"Error: no test specified\" && exit 1" 27 | }, 28 | "gitHead": "3ceec8036cd7bafb6949a709220aa6f4f367f710" 29 | } 30 | --------------------------------------------------------------------------------