Posted by Joel on 27th May 2011
Integrating with Kashflow using PHP
Includes sample code and best practice recommendations
Kashflow is a leading provider of cloud-based accounting software - it completely replaces Sage or Quickbooks and is much easier and faster to use. In this blog post I'm going to explain how you can get your website to talk to Kashflow using PHP. If you read it all, you'll find out how to program your website to create a sales invoice on Kashflow when you sell something!
If you're a web developer, this is cool simply because it's cool. If you're a business owner or a financial type, this is cool because you can automate some of your boring finance stuff and spend more time on important things like Social Media and late lunches.
Our solution uses PHP 5's SoapClient class. If you are looking for a solution based on Curl and SimpleXml, head on over to Creospace instead.
Contents
- Configure your Kashflow account
- How the API works
- Making it generic
- Handling more parameters
- Handling errors
- Creating a sales invoice using the API
- Downloads
- Bonus tips
Step 1 - Configure your Kashflow account
Before you do any coding, you need to activate the Kashflow API on your account. The API is the means by which your software will talk to Kashflow.
I recommend that you create yourself a Kashflow account specifically for testing the API - luckily there's a two-month free trial so it won't cost you anything.
Activate the API:
- Login to your account
- Go to the "Settings" area
- Choose "API Settings"
- Tick the "Enable the API for my KashFlow account" box
- Optionally (but recommended), restrict access to particular IP addresses
- Press "update"
If you're not sure whether you've enabled API access successfully, you can use our Kashflow API test page. You'll need to allow connections from IP address 89.151.81.82.
We promise we won't steal your login details but we can't promise someone else won't - make sure you change your Kashflow password while using the tool.
Step 2 - How the API works
The Kashflow API is based on SOAP, which is a widely used standard for software to communicate. Kashflow will act as a SOAP server, and your code will be a SOAP client.
When you need to talk to Kashflow, your code will send a SOAP request and then receive a SOAP response. PHP 5 has a built-in class called SoapClient which makes this very easy:
$client = new SoapClient("https://securedwebapp.com/api/service.asmx?WSDL");
This one line of code looks up all the functionality that the Kashflow API offers, and makes a ready-to-use object which has all the same functions as the API. All of the complicated communication stuff happens automatically behind the scenes.
Each function created by SoapClient takes a single parameter which should be an array containing the information that the API requires. For example:
$parameters['UserName'] = "username"; $parameters['Password'] = "password"; $response = $client->GetAccountOverview($parameters);
Step 3 - Making it generic
Since all of the Kashflow API calls require your username and password, it makes sense to do some refactoring. What I'd really like is to do this:
$kashflow = new Kashflow("username","password");
$kashflow->getAccountOverview();
This is cool because I don't even have to think about any of the SOAP stuff - I can concentrate on what needs to happen rather than how. So I've created a class, as follows:
class Kashflow
{
private $m_client = NULL;
private $m_username = "";
private $m_password = "";
public function __construct($username,$password)
{
$this->m_client = new SoapClient("https://securedwebapp.com/api/service.asmx?WSDL");
$this->m_username = $username;
$this->m_password = $password;
}
public function getAccountOverview()
{
return $this->makeRequest("GetAccountOverview");
}
private function makeRequest($fn)
{
$parameters['UserName'] = $this->m_username;
$parameters['Password'] = $this->m_password;
return $this->m_client->$fn($parameters);
}
}
The constructor handles the setup of the SoapClient object and stores the username and password for subsequent requests. This saves having to specify it every time I want to make a call.
The magic happens in makeRequest. I pass the name of the API function to makeRequest, which then builds the parameters and calls into Kashflow.
Step 4 - I need more parameters
So what happens if you need to pass more parameters to the Kashflow API? You need an enhanced version of makeRequest:
private function makeRequest($fn,$extra = NULL)
{
$parameters['UserName'] = $this->m_username;
$parameters['Password'] = $this->m_password;
if(NULL != $extra)
$parameters = array_merge($parameters,$extra);
return $this->m_client->$fn($parameters);
}
This allows you to optionally pass additional parameters through to Kashflow, for example:
public function getSupplier($code)
{
$parameters['SupplierCode'] = $code;
return $this->makeRequest("GetSupplier",$parameters);
}
In the above example, the supplier code gets merged with the username and password before being passed on to Kashflow.
Step 5 - Handling errors
Errors happen all the time - you need to handle them! Let's update our class to throw an exception when the API call fails.
private static function handleResponse($response)
{
if("NO" == $response->Status)
throw(new Exception($response->StatusDetail));
return $response;
}
private function makeRequest($fn,$extra = NULL)
{
$parameters['UserName'] = $this->m_username;
$parameters['Password'] = $this->m_password;
if(NULL != $extra)
$parameters = array_merge($parameters,$extra);
return self::handleResponse($this->m_client->$fn($parameters));
}
makeRequest has been updated to delegate the error checking to handleResponse, which checks if Kashflow returned "NO", and either throws an exception or just returns the response.
Step 6 - Creating a sales invoice
Wouldn't it be cool if you could automatically create a sales invoice every time you sold something?
$kashflow = new Kashflow("username","password");
$i = new KashflowInvoice("customer id","invoice number","invoice date","due date");
$i->addLine("qty","net","vat","vat rate","nominal id","description","project id");
$kashflow->insertInvoice($i);
Don't worry about the KashflowInvoice class for now - the interesting bit is how the insertInvoice function prepares the data. At first glance, you would think that all you need to do is pass through $lines as part of the invoice data:
$lines[] = array
(
"LineID" => 0,
"Quantity" => "qty",
"Description" => "description",
"Rate" => "unit net",
"ChargeType" => "nominal id",
"VatAmount" => "line vat",
"VatRate" => "vat rate",
"Sort" => 1,
"ProductID" => 0,
"ProjID" => "project id"
);
$parameters['Inv'] = array
(
"InvoiceNumber" => "invoice number",
"InvoiceDate" => "invoice date",
"DueDate" => "due date",
"CustomerID" => "customer id",
"Lines" => $lines,
"NetAmount" => "net",
"VATAmount" => "tax"
);
$response = $this->makeRequest("InsertInvoice",$parameters);
But it's not that simple. The Kashflow API specification requires that the lines parameter is an array of InvoiceLine objects. SoapClient enforces this and will fail unless you obey!
The solution is to use PHP's SoapVar object to wrap the invoice lines, as follows:
$line = array
(
"LineID" => 0,
"Quantity" => "qty",
"Description" => "description",
"Rate" => "unit net",
"ChargeType" => "nominal id",
"VatAmount" => "line vat",
"VatRate" => "vat rate",
"Sort" => 1,
"ProductID" => 0,
"ProjID" => "project id"
);
$lines[] = new SoapVar($line,0,"InvoiceLine","KashFlow");
$parameters['Inv'] = array
(
"InvoiceNumber" => "invoice number",
"InvoiceDate" => "invoice date",
"DueDate" => "due date",
"CustomerID" => "customer id",
"Lines" => $lines,
"NetAmount" => "net",
"VATAmount" => "tax"
);
$response = $this->makeRequest("InsertInvoice",$parameters);
SoapClient knows that SoapVar means "an object". The SoapVar constructor's first parameter is the data, the second is encoding, the third is the name of the object, and the fourth is the namespace. The PHP documentation for SoapVar is a bit sketchy so I just pass 0 for encoding and it seems to work. If you know better, please comment!
Downloads
- This zip file contains the Kashflow and KashflowInvoice classes, and a test script which raises a sales invoice.
- You may use this code as you see fit, but at your own risk.
Bonus tips
The biggest concern with integration is enforcing synchronisation between the systems. For maximum integrity, use the following rules:
Run Kashflow automation on Cron - inevitably there will be times you cannot connect to Kashflow, such as scheduled maintenance or temporary connectivity problems. If you run the integration in the background, your users will never know if there's a problem and you can handle them transparently.
Do one thing at a time - what happens if one API call works and then there's an error with a second? You'll have lost the results of the successful API call. Try to do one thing at a time, save everything you need and then move on to the next action.
Do Kashflow work late and use database transactions - if Kashflow succeeds but your subsequent code fails, you'll be left with unsynchronised data. Your system will think that it hasn't sent information to Kashflow, but Kashflow will have been updated!
Handle this by assuming that your Kashflow call will work, and doing all your database updates first. Do the Kashflow call as late as possible, and then you can easily rollback. The last thing to do is to store the result of the call such as an invoice id.
Did you find this useful?
If you found this article useful, I'd appreciate any or all of the following!
- Follow @switchplane on Twitter or like our Facebook page
- Link to us
- Enter affiliate code SWITCHPLANE into your Kashflow account :D
- Leave a nice comment below
Joel says On 7th February 2012 at 11:07
Hi Neha - glad you like the blog. I can't really answer your question as I don't know what data you have.
However, if you are still learning how to integrate with external APIs, I would recommend that you start with something small and tackle one step at a time. Remember that you can use the technique in this article for any of the Kashflow API functions.
Kashflow have a two month free trial, so sign up and treat it as a test account - that way you're not messing around with real financial data.
The online manual has the details for all of the functionality in the API - see http://accountingapi.com/.
neha says On 7th February 2012 at 08:52
Gr8 blog....
Neha says On 7th February 2012 at 08:49
Hi I am neha.I am learning kashflow api, so need some help.
I want to import all my site data to kashflow.how can i do this.
Thanks in advance
Joel says On 23rd January 2012 at 17:13
Hi Amer - take a look at the Kashflow API for the GetCustomer(s) and GetInvoice(s) families of methods. One of those is sure to help - http://accountingapi.com/manual.asp
You'll need to hack your version of the Kashflow class I've published to support the additional functionality you need.
Have fun!
Amer says On 23rd January 2012 at 09:29
This is really helpful! thank you Joel, How do I check if a client exists? the task I want to accomplish is to check if a client exists and and if a certain invoices exists then either insert or update the client.
Joel says On 18th July 2011 at 13:21
Yes, that sounds like it would work. I'd still recommend keeping a local copy of the Kashflow customer ID though.
Good luck!
Al says On 18th July 2011 at 12:30
Hey Joel, thanks for getting back to me, especially as I'm such a noob in this field! No I wasn't 100% sure either! I must apologise for not being clear, it is simply my confusion showing through! :-)
So, kashflow_customer_id is the number assigned to my customer which can be seen in the URL when on the edit customer screen as you describe, nothing to do with my kashflow account id.
So I would create a wrapper function that checks for existing email, then InsertCustomer if necessary and then create the invoice? Thanks again. Just noticed you're PR7, awesome! :-)
Joel says On 18th July 2011 at 11:24
No - I've deliberately named it that way to make it clear that Kashflow are responsible for the ID. When you synchronise data between two systems, you will have two ids: your own id, and the foreign id. To avoid confusion, you should give these different names i.e. "my_customer_id", "kashflow_customer_id".
Every Kashflow account has a different set of customer IDs - there's no way for me to know what IDs are in your account so I assigned a value of 1 to indicate that it's an integer value and to make it valid PHP code.
The comment is referring to Kashflow's GetCustomer API function. You'll need to update the Kashflow class in the download to support that function before you can use it. See http://accountingapi.com/manual_methods_GetCustomer.asp for documentation.
You're not restricted to just that function though - you can use any of the GetCustomer(s) API functions to get Kashflow's customer ID.
I would recommend that you keep Kashflow's customer ID in your own database of customers so you have it to hand when required. This is what we do as it cuts down on the number of requests when batch processing invoices for a lot of customers.
To create a customer, use InsertCustomer from the API (see http://accountingapi.com/manual_methods_InsertCustomer.asp for documentation). Again, you'll need to update the Kashflow class from the download. Be warned, you need to make sure you pass values for all of the CheckBox parameters otherwise you'll get a SOAP error for missing parameters.
Hope that helps as I wasn't 100% sure what you were after!
Al says On 18th July 2011 at 10:49
In the sample script download, shouldn't kashflow_customer_id be customer_id and the same for GetKashflowCustomerID and GetCustomerID. It's thrown me because line 16 of the source code assigns 1 to kashflow_customer_id but the comment explains the function GetCustomer should be used. Also, can you give a hint how to deal with new customers? Would we use GetCustomerByEmail. Many thanks for a great article.
Add A Comment
Recent Blogs
Twitter Tools
Do you use Twitter as part of your business marketing strategy. Here are some useful tips and tools to help you succeed. Read More »
Gradient Meshes in Adobe Illustrator
There's more to Adobe Illustrator than basic shapes and blocks of colour, and there's more to gradients than linear or radial effects. Read More »
Web Design Trends 2011
Web designers are shying away from creating gimmicky tricks, but rather clean, accessible, bug-free coding - that works. Read More »
Let's Do Business - Eastbourne 2011
Find out what Switchplane did at Let's Do Business Eastbourne 2011. Read More »
Improving Search with Levenshtein Distance
Find out how we've made Honey Barrett's document management system search facility handle spelling mistakes. Read More »
The New Switchplane Website
Our new website is ready - read about what we've updated and why, and get ready for Project Awesome! Read More »
Website Accessibility
Have you ever considered the importance of accessibility on your website? Read More »
How Amazing Databases Are
A blog post about the usefulness of databases, using a person management system as an example. Read More »
Reasons to use Vector Graphics over Rasters
When should you use vectors or rasters, and does it even matter? Read More »
Some thoughts on writing for your business website...
Read some tips on preparing copy for your website. Read More »
Let's Do Business - Hastings 2010
Switchplane attended LDB Hastings in 2010 - read about our day. Read More »
Lets Do Business Eastbourne 2010
Switchplane's experience at Let's Do Business 2010 in Eastbourne. Read More »
Web Design Trends 2010 Part 1
A guide to web design trends 2010, including hand-drawn and painted layouts, typefaces, modern vectors and large headers and footers. Read More »
Common Printing Problems and how to avoid them
Even if it looks good on your screen, it isn't guaranteed to come out like that! I've selected a few of the most common print problems to watch out for. Read More »
Web design trends 2009 Part 2: Old and Torn Paper
Make your website a real piece of personal artwork by collecting and scanning-in torn and crumpled paper and using it for the design of your website (or just take a visit to istock photo!). Read More »
Web design trends 2009 Part 1: Badges
Subtle elements and new layout ideas for 2009. My guide on how to make your website look fashionable and unique, packed full of information and further resources. Read More »
The Joys of JQuery
JQuery is a light-weight, cross-browser and feature packed JavaScript library. To explain why JQuery is so good, first you need to know why not using it is so bad! Read More »
Lets Do Business Eastbourne 2009
Last Thursday (25th June) Switchplane attended their first Lets Do Business event at the Winter Gardens in Eastbourne. Read More »
Top 10 Sales Tips
Times are tough. Sales are down. Morale is low. Sound familiar? Well it needn't be. Below are a few tips which are sure to help you re evaluate and succeed in pushing your sales margins. Read More »
Create printable artwork in Indesign and Photoshop
A few useful steps to help you successfully prepare your artwork for print, using Adobe Photoshop and Adobe Indesign. Learn about colour modes, resolution, size and other helpful tips! Read More »
Search engine ranking more important than ever
Search engine optimisation is now an essential part of a successful website. And because of the way search engines now work, the focus of SEO is now about producing quality content and getting your name out there so you get incoming links. Read More »
Four Months at Switchplane
I've been at Switchplane for four months now - to celebrate the launch of our new website I'm sharing some thoughts on what it's like working here. Read More »
How to run a cron job on the first weekday of the month
Often it's useful to generate automatic reports or perform some other task at the start of the month. Find out how to schedule a cron job to run on the first weekday of each month. Read More »

neha says On 7th February 2012 at 11:59