Validating European VAT numbers with PHP
As time passes, accounting laws become more and more strict, making electronic invoicing applications even more complicated. Over the last years and especially in the European Union, the issue of phony invoices has been increased, forcing the countries-members to adopt new laws in order to fight that.
One handy tool for us developers is VIES (VAT Information Exchange Service). It's a free of charge service that is maintained by EU, and can be used to check the validity of every VAT number of European Union. Queries can be run either by using their web interface or programmatically with the use of a Simple Objects Access Protocol (SOAP) API.
The implementation is relatively easy, and it was one of the things that motivated us to include it during the development of AssetCRM. And because any form of knowledge should be spread, I thought to post a simple example of extracting information from VIES using PHP language. Luckily in VIES website there is a well documented technical information which will guide us through our first steps in creating a script:
We'll define constant VIES_URL with the actual VIES communication URL.
It will be quite handy to build the script inside a function, since this will facilitate it's later usage:
<?php
DEFINE ( 'VIES_URL', 'http://ec.europa.eu/taxation_customs/vies/services/checkVatService' );
function viesCheckVAT($countryCode, $vatNumber, $timeout = 30) {
$response = array ();
$pattern = '/<(%s).*?>([\s\S]*)<\/\1/';
$keys = array (
'countryCode',
'vatNumber',
'requestDate',
'valid',
'name',
'address'
);
$content = "<s11:Envelope xmlns:s11='http://schemas.xmlsoap.org/soap/envelope/'>
<s11:Body>
<tns1:checkVat xmlns:tns1='urn:ec.europa.eu:taxud:vies:services:checkVat:types'>
<tns1:countryCode>%s</tns1:countryCode>
<tns1:vatNumber>%s</tns1:vatNumber>
</tns1:checkVat>
</s11:Body>
</s11:Envelope>";
$opts = array (
'http' => array (
'method' => 'POST',
'header' => "Content-Type: text/xml; charset=utf-8; SOAPAction: checkVatService",
'content' => sprintf ( $content, $countryCode, $vatNumber ),
'timeout' => $timeout
)
);
$ctx = stream_context_create ( $opts );
$result = file_get_contents ( VIES_URL, false, $ctx );
if (preg_match ( sprintf ( $pattern, 'checkVatResponse' ), $result, $matches )) {
foreach ( $keys as $key )
preg_match ( sprintf ( $pattern, $key ), $matches [2], $value ) && $response [$key] = $value [2];
}
return $response;
}
?>
Now to use the above function.
Say we want to check a German (DE) VAT number (1234567890). We call the function like that:
viesCheckVAT("DE","1234567890"); // which of course it will return "1234567890" as an invalid VAT number ))
The way the above function works, is quite simple:
First we create the arrays and variables, and then we construct the "xml" file that we send to the defined VIES_URL using header and other options specified in array "opts". Finally return the response by looping over the response keys, with a good ol' "foreach" loop.
This function was originally published by Eugen Mihailescu.
You can see the above script in action by clicking VAT number validation