View source
<?php
namespace Drupal\vat_number\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Component\Utility\Unicode;
use SoapClient;
use SoapFault;
class VatNumberController extends ControllerBase {
private $vatNumber;
private $vatInfo;
private $cleint = [
'message' => '',
];
private $valid = TRUE;
public function __construct($vatNumber) {
$this->vatNumber = $vatNumber;
$this->vatInfo = $this
->getComponents();
$this->cleint = $this
->connectDatabaseVies();
}
public function check() {
$this
->checkVatFormat();
if (!isset($this->vatInfo['message'])) {
if ($this
->validateVatNumber() === FALSE) {
$this->vatInfo['message'] = $this
->t('The VAT number could not be validated by the European VAT Database. Please go back and input a correct VAT number.');
}
else {
$this->vatInfo['message'] = NULL;
}
}
return [
'status' => $this->valid,
'message' => $this->vatInfo['message'],
];
}
private function validateVatNumber() {
if ($this->cleint) {
$params = [
'countryCode' => $this->vatInfo['country_code'],
'vatNumber' => $this->vatInfo['vatNumber'],
];
try {
$r = $this->cleint
->checkVat($params);
if ($r->valid != TRUE) {
$this->valid = FALSE;
return FALSE;
}
return TRUE;
} catch (SoapFault $e) {
\Drupal::logger('var_number')
->error($e->faultstring);
}
}
}
private function getComponents() {
$vatid = preg_replace('/[ .-]/', '', $this->vatNumber);
$vat_infos['country_code'] = Unicode::strtoupper(Unicode::substr($vatid, 0, 2));
$vat_infos['vatNumber'] = Unicode::strtoupper(Unicode::substr($vatid, 2));
return $vat_infos;
}
private function connectDatabaseVies() {
try {
return new SoapClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl", [
"exceptions" => 1,
]);
} catch (SoapFault $e) {
\Drupal::logger('vat_number')
->error($e->faultstring);
return FALSE;
}
}
private function checkVatFormat() {
switch ($this->vatInfo['country_code']) {
case 'AT':
$example['AT'] = $this
->t('@example, AT + 9 characters, the first position following the prefix is always an U', [
'@example' => 'ATU99999999',
]);
$regex = '/^(AT){0,1}U[0-9]{8}$/i';
break;
case 'BE':
$example['BE'] = $this
->t('@example, BE + 10 digits, the first digit following the prefix is always zero (0)', [
'@example' => 'BE0999999999',
]);
$regex = '/^(BE){0,1}[0]{1}[0-9]{9}$/i';
break;
case 'BG':
$example['BG'] = $this
->t('@example1 or @example2, BG + 9 or 10 digits', [
'@example1' => 'BG999999999',
'@example2' => 'BG9999999999',
]);
$regex = '/^(BG){0,1}[0-9]{9,10}$/i';
break;
case 'CY':
$example['CY'] = $this
->t('@example, CY + 9 characters', [
'@example' => 'CY99999999L',
]);
$regex = '/^(CY){0,1}[0-9]{8}[A-Z]{1}$/i';
break;
case 'CZ':
$example['CZ'] = $this
->t('@example1 or @example2 or @example3, CZ + 8, 9 or 10 digits', [
'@example1' => 'CZ99999999',
'@example2' => 'CZ999999999',
'@example3' => 'CZ9999999999',
]);
$regex = '/^(CZ){0,1}[0-9]{8,10}$/i';
break;
case 'DK':
$example['DK'] = $this
->t('@example, @block_count blocks of @digit_count digits', [
'@example' => 'DK99 99 99 99',
'@block_count' => 4,
'@digit_count' => 2,
]);
$regex = '/^(DK){0,1}([0-9]){8}$/i';
break;
case 'EE':
$example['EE'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'EE999999999',
'@digit_count' => 9,
]);
$regex = '/^(EE){0,1}[0-9]{9}$/i';
break;
case 'DE':
$example['DE'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'DE999999999',
'@digit_count' => 9,
]);
$regex = '/^(DE){0,1}[0-9]{9}$/i';
break;
case 'EL':
$example['EL'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'EL999999999',
'@digit_count' => 9,
]);
$regex = '/^(EL){0,1}[0-9]{9}$/i';
break;
case 'PT':
$example['PT'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'PT999999999',
'@digit_count' => 9,
]);
$regex = '/^(PT){0,1}[0-9]{9}$/i';
break;
case 'FR':
$example['FR'] = $this
->t('@example, 1 block of 2 characters, 1 block of 9 digits', [
'@example' => 'FRXX 999999999',
]);
$regex = '/^(FR){0,1}[0-9A-Z]{2}[0-9]{9}$/i';
break;
case 'FI':
$example['FI'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'FI99999999',
'@digit_count' => 8,
]);
$regex = '/^(FI){0,1}[0-9]{8}$/i';
break;
case 'HR':
$example['HU'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'HU12345678901',
'@digit_count' => 11,
]);
$regex = '/^(HR){0,1}[0-9]{11}$/i';
break;
case 'HU':
$example['HU'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'HU99999999',
'@digit_count' => 8,
]);
$regex = '/^(HU){0,1}[0-9]{8}$/i';
break;
case 'LU':
$example['LU'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'LU99999999',
'@digit_count' => 8,
]);
$regex = '/^(LU){0,1}[0-9]{8}$/i';
break;
case 'MT':
$example['MT'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'MT99999999',
'@digit_count' => 8,
]);
$regex = '/^(MT){0,1}[0-9]{8}$/i';
break;
case 'SI':
$example['SI'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'SI12345678',
'@digit_count' => 8,
]);
$regex = '/^(SI){0,1}[0-9]{8}$/i';
break;
case 'IE':
$example['IE'] = $this
->t('@example, 1 block of @char_count characters', [
'@example' => 'IE9S99999L',
'@char_count' => 8,
]);
$regex = '/^(IE){0,1}[0-9][0-9A-Z\\+\\*][0-9]{5}[A-Z]$/i';
break;
case 'IT':
$example['IT'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'IT99999999999',
'@digit_count' => 11,
]);
$regex = '/^(IT){0,1}[0-9]{11}$/i';
break;
case 'LV':
$example['LV'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'LV99999999999',
'@digit_count' => 11,
]);
$regex = '/^(LV){0,1}[0-9]{11}$/i';
break;
case 'LT':
$example['LT'] = $this
->t('@example1 or @example2, 1 block of 9 digits, or 1 block of 12 digits', [
'@example1' => 'LT999999999',
'@example2' => 'LT999999999999',
]);
$regex = '/^(LT){0,1}([0-9]{9}|[0-9]{12})$/i';
break;
case 'NL':
$example['NL'] = $this
->t('@example, 1 block of @char_count characters', [
'@example' => 'NL999999999B99',
'@char_count' => 12,
]);
$regex = '/^(NL){0,1}[0-9]{9}B[0-9]{2}$/i';
break;
case 'PL':
$example['PL'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'PL9999999999',
'@digit_count' => 10,
]);
$regex = '/^(PL){0,1}[0-9]{10}$/i';
break;
case 'SK':
$example['SK'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'SK9999999999',
'@digit_count' => 10,
]);
$regex = '/^(SK){0,1}[0-9]{10}$/i';
break;
case 'RO':
$example['RO'] = $this
->t('@example, 1 block of minimum 2 digits and maximum 10 digits', [
'@example' => 'RO999999999',
]);
$regex = '/^(RO){0,1}[0-9]{2,10}$/i';
break;
case 'SE':
$example['SE'] = $this
->t('@example, 1 block of @digit_count digits', [
'@example' => 'SE999999999999',
'@digit_count' => 12,
]);
$regex = '/^(SE){0,1}[0-9]{12}$/i';
break;
case 'ES':
$example['ES'] = $this
->t('@example, 1 block of @char_count characters', [
'@example' => 'ESX9999999X',
'@char_count' => 9,
]);
$regex = '/^(ES){0,1}([0-9A-Z][0-9]{7}[A-Z])|([A-Z][0-9]{7}[0-9A-Z])$/i';
break;
case 'GB':
$example['GB'] = $this
->t('@example, 9 digits (block of 3, block of 4, block of 2)', [
'@example' => 'GB999 9999 99',
]);
$regex = '/^(GB){0,1}(([0-9]{9})|([0-9]{12})|((GD|HA)[0-9]{3}))$/i';
break;
default:
$this->valid = FALSE;
$this->vatInfo['vat_format'] = FALSE;
$this->vatInfo['message'] = $this
->t('The country of the VAT number can not be detected. Please do not remove the language prefix. Example: DE123456789 (where DE is the country prefix).');
break;
}
if ($this->valid) {
$vatNumber = $this->vatInfo['country_code'] . $this->vatInfo['vatNumber'];
$this->vatInfo['vat_format'] = preg_match($regex, $vatNumber);
}
$eu_countries = $this
->euCountries();
$valid_eu = isset($eu_countries[$this->vatInfo['country_code']]);
if ($valid_eu && !$this->vatInfo['vat_format']) {
$this->valid = FALSE;
$this->vatInfo['message'] = $this
->t("Your VAT number does not match the '%country' VAT format.<br />It must have the following format: <strong>%format</strong>", [
'%country' => $eu_countries[$this->vatInfo['country_code']],
'%format' => $example[$this->vatInfo['country_code']],
]);
}
}
public function euCountries() {
$countries = \Drupal::service('country_manager')
->getList();
$eu_country_codes = [
"AT",
"BE",
"BG",
"CY",
"CZ",
"DE",
"DK",
"EE",
"ES",
"FI",
"FR",
"GB",
"GR",
"HR",
"HU",
"IE",
"IT",
"LT",
"LU",
"LV",
"MT",
"NL",
"PL",
"PT",
"RO",
"SE",
"SI",
"SK",
];
foreach ($eu_country_codes as $value) {
$eu_countries[$value] = $countries[$value];
}
return $eu_countries;
}
}