Xero App

Icon

<i class="fa fa-gbp"></i>

Account

To set-up a new trial account:

  1. https://go.xero.com/Dashboard/

  2. Click on your profile icon, then choose Account followed by Home. Click Add an organisation.

  3. To delete the old test account, click on your profile icon, then choose Account followed by Home. Find your Trial account and click Cancel.

Tip

(If you are testing), then don’t forget to remove all records from the UUID models.

API

From https://github.com/freakboy3742/pyxero#private-applications

From https://developer.xero.com/documentation/api-guides/create-publicprivate-key

➤ openssl genrsa -out privatekey.pem 1024
Generating RSA private key, 1024 bit long modulus

➤ openssl req -new -x509 -key privatekey.pem -out publickey.cer -days 1825
Country Name (2 letter code) [AU]:GB
State or Province Name (full name) [Some-State]:Devon
Locality Name (eg, city) []:Okehampton
Organization Name (eg, company) [Internet Widgits Pty Ltd]:KB Software Ltd
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:kbsoftware.co.uk
Email Address []:patrick@kbsoftware.co.uk

# just press enter for the password
➤ openssl pkcs12 -export -out public_privatekey.pfx -inkey privatekey.pem -in publickey.cer
Enter Export Password:
Verifying - Enter Export Password:

https://developer.xero.com/myapps

  1. New app

  2. Private app

  3. App name e.g. KB7

  4. Organisation e.g. KB7

  5. Upload Certificate File, upload publickey.cer (generated above)…

  6. Create App

_images/xero-add-new-app-1.png

Note

If you get Failed to Create App, then try logging out and back in again (or browse to some of the profile pages).

_images/xero-add-new-app-2.png

Copy the Consumer Key from OAuth 1.0a Credentials to the .private file in your project e.g:

set -x XERO_CONSUMER_KEY="1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"

Add the consumer key to base.py in your settings:

XERO_CONSUMER_KEY = get_env_variable("XERO_CONSUMER_KEY")

Click Generate URL to see how to set-up HOST_NAME in your settings file. The HOST_NAME is used to build a URL to link back from Xero to your project.

If you log into your Xero app, you can see the Connected App (not so easy to find) e.g:

_images/xero-add-new-app-3.png

Management Commands

To upload a single invoice to Xero, pass in the primary key of the invoice e.g:

django-admin.py sync_invoice_to_xero 1234

Requirements

pip install pyxero

Usage

For development, add the following to your .private file:

set -x XERO_CONSUMER_KEY "ABC123456123456"

To .env:

export XERO_KEY_FILE="privatekey.pem"

To .env.fish:

set -x XERO_KEY_FILE "privatekey.pem"

Add the following to settings/base.py:

XERO_CONSUMER_KEY = get_env_variable("XERO_CONSUMER_KEY")
XERO_KEY_FILE = get_env_variable("XERO_KEY_FILE")

For the live site, add the following to your Salt sites file:

env:
  xero_consumer_key: "ABC123456123456"
  xero_key_file: "/home/web/repo/files/www.hatherleigh.info/project/privatekey.pem"

Testing

Tip

The pyxero module has a _parse_api_response method which extracts the data using the resource_name. To properly construct mock data you need to know the resource_name. (_parse_api_response can be found in site-packages/xero/basemanager.py). In the example below, Contacts and Invoices are the resource_name.

Use the responses library for mocking Xero. A good example of this can be found in the mock Xero code e.g:

import responses

@pytest.mark.django_db
@responses.activate
def test_xero_sync_invoice():
    invoice = InvoiceFactory()
    XeroCurrencyFactory(currency=invoice.currency)
    XeroSettingsFactory(invoice_account=AccountFactory(code="010203"))
    contact_uuid = str(uuid.uuid4())
    invoice_uuid = str(uuid.uuid4())
    responses.add(
        responses.PUT,
        "https://api.xero.com/api.xro/2.0/Contacts",
        json={"Status": "OK", "Contacts": [{"ContactID": contact_uuid}]},
        status=HTTPStatus.OK,
    )
    responses.add(
        responses.PUT,
        "https://api.xero.com/api.xro/2.0/Invoices",
        json={"Status": "OK", "Invoices": [{"InvoiceID": invoice_uuid}]},
        status=HTTPStatus.OK,
    )
    assert invoice.pk == xero_sync_invoice(invoice.pk)