EU VAT Validation


/ Published in: PHP
Save to your folder(s)

Look if the given input could be a legal VAT-number.
Accepts input with or without '.' between the numbers and must contain a County-code


Copy this code and paste it in your HTML
  1. /**
  2.  * http://www.pfz.nl/wiki/invoer-validatie/#Geldig_BTW.2FVAT_nummer
  3.  *
  4.  * Look if the given input could be a legal VAT-number.
  5.  * Accepts input with or without '.' between the numbers, must contain a County-code
  6.  *
  7.  * Note: This only checks the syntax, NOT IF THE VAT REALLY EXISTS OR IS ACTIVE!
  8.  *
  9.  * @author Sebastiaan Stok <[email protected]>
  10.  *
  11.  * @param string $psVatInput
  12.  * @return bool
  13.  */
  14. function isVAT($psVatInput) {
  15. $psVatInput = trim($psVatInput);
  16. $psVatInput = str_replace('.', '', $psVatInput);
  17. $aVatMatch = array();
  18.  
  19. // Common syntax
  20. if (!preg_match('/^([a-z]{2})[ ]*(.+)$/is', $psVatInput, $aVatMatch)) {
  21. return false;
  22. }
  23.  
  24. $aVatMatch[1] = strtoupper($aVatMatch[1]);
  25.  
  26. $functionName = 'isVAT_'. $aVatMatch[1];
  27. if (function_exists($functionName)) {
  28. return $functionName($psVatInput);
  29. }
  30.  
  31. $aVatRegexes = array(
  32. 'AT' => 'U[0-9]{8}',
  33. 'BE' => '0[0-9]{9}',
  34. 'BG' => '[0-9]{9,10}',
  35. 'CY' => '[0-9]{8}[A-Za-z]',
  36. 'CZ' => '[0-9]{8,10}',
  37. 'DE' => '[0-9]{9}',
  38. 'DK' => '[0-9]{2} ?[0-9]{2} ?[0-9]{2} ?[0-9]{2}',
  39. 'EE' => '[0-9]{9}',
  40. 'EL' => '[0-9]{9}',
  41. 'ES' => '([A-Za-z0-9][0-9]{7}[A-Za-z0-9])',
  42. 'FI' => '[0-9]{8}',
  43. 'FR' => '[A-Za-z0-9]{2} ?[0-9]{9}',
  44. 'GB' => '([0-9]{3} ?[0-9]{4} ?[0-9]{2}|[0-9]{3} ?[0-9]{4} ?[0-9]{2} ?[0-9]{3}|GD[0-9]{3}|HA[0-9]{3})',
  45. 'HU' => '[0-8]{8}',
  46. 'IE' => '[0-9][A-Za-z0-9+*][0-9]{5}[A-Za-z]',
  47. 'IT' => '[0-9]{11}',
  48. 'LT' => '([0-9]{9}|[0-9]{12})',
  49. 'LU' => '[0-9]{8}',
  50. 'LV' => '[0-9]{11}',
  51. 'MT' => '[0-9]{8}',
  52. 'NL' => '[0-9]{9}B[0-9]{2}',
  53. 'PL' => '[0-9]{10}',
  54. 'PT' => '[0-9]{9}',
  55. 'RO' => '[0-9]{2,10}',
  56. 'SE' => '[0-9]{12}',
  57. 'SI' => '[0-9]{8}',
  58. 'SK' => '[0-9]{10}',
  59. );
  60.  
  61. if (!isset($aVatRegexes[$aVatMatch[1]]) || !preg_match('/^([a-z]{2})[ ]*'.$aVatRegexes[$aVatMatch[1]].'$/is', $psVatInput)) {
  62. return false;
  63. }
  64.  
  65. return true;
  66. }
  67.  
  68. /**
  69.  * Checks whether or not the sofinummer provided passes the test of 11.
  70.  * @version 2.0
  71.  * @param $sofinummer The sofinummer to be checked.
  72.  * @return boolean
  73.  * @author Ivo Peters
  74.  * @author Berry Langerak, al had Ivo hem als eerste goed :)
  75.  **/
  76. function isVAT_NL( $psVatInput ) {
  77. // remove spaces and dots
  78. $sVatnr = str_replace(array(' ', '.'), '', ($psVatInput));
  79.  
  80. if (preg_match('#^NL([0-9]{9})B[0-9]{2}$#i', $sVatnr, $aMatch)) {
  81. $sVatnr = $aMatch[1];
  82.  
  83. // lijst met nummers die qua check kloppen, maar toch niet geldig zijn
  84. $aInvalid = array(
  85. '111111110',
  86. '999999990',
  87. '000000000',
  88. );
  89.  
  90. if (strlen($sVatnr) != 9 || !ctype_digit($sVatnr) || in_array($sVatnr, $aInvalid)) {
  91. return false;
  92. }
  93. for ($i = 9, $som = -$sVatnr % 10; $i > 1; $i--) {
  94. $som += $i * $sVatnr{(9 - $i)};
  95. }
  96.  
  97. return ($som % 11 == 0);
  98. }
  99.  
  100. return false;
  101. }
  102.  
  103. /**
  104.  * Check if the number might be a belgian VAT-number.
  105.  * Accepts input with or without '.' and spaces between the numbers,
  106.  * spaces at begin and end of string are ignored
  107.  * it must contain a County-code (BE) at the start (case insensitive)
  108.  * after the country code 9 or 10 digits follow.
  109.  * if 10 digits are given, the first must be zero
  110.  *
  111.  * Note: This only checks the syntax, NOT IF THE VAT REALLY EXITS OR IS ACTIVE!
  112.  *
  113.  * @author Ivo Peters
  114.  *
  115.  * @param string $psVatInput
  116.  * @return bool
  117.  */
  118. function isVAT_BE($psVatInput) {
  119. // remove spaces and dots
  120. $sVatnr = str_replace(array(' ', '.'), '', ($psVatInput));
  121.  
  122. if (preg_match('#^BE0?[0-9]{9}$#i', $sVatnr)) {
  123. $iVatnr = str_ireplace('BE','', $sVatnr);
  124. return (97 - (floor($iVatnr / 100) % 97) == $iVatnr % 100);
  125. }
  126.  
  127. return false;
  128. }
  129.  
  130. /**
  131.  * Check if the number might be a GB VAT-number.
  132.  * Accepts input with or without '.' and spaces between the numbers,
  133.  * spaces at begin and end of string are ignored
  134.  * it must contain a County-code (GB) at the start (case insensitive)
  135.  * after the country code 9 digits follow.
  136.  *
  137.  * Note: This only checks the syntax, NOT IF THE VAT REALLY EXITS OR IS ACTIVE!
  138.  *
  139.  * @author Ivo Peters
  140.  *
  141.  * @param string $psVatInput
  142.  * @return bool
  143.  */
  144. function isVAT_GB($psVatInput) {
  145. // remove spaces and dots
  146. $sVatnr = str_replace(array(' ', '.'), '', ($psVatInput));
  147.  
  148. if (preg_match('#^GB[0-9]{9}$#i', $sVatnr)) {
  149. $sVatnr = str_ireplace('GB', '', $sVatnr);
  150. $iSum = 0;
  151. for ($i = 0; $i < 7; $i++) {
  152. $iSum += substr($sVatnr, $i, 1) * (8 - $i);
  153. echo substr($sVatnr, $i, 1) .' * '. (8 - $i) .' = '. substr($sVatnr, $i, 1) * (8 - $i);
  154. echo PHP_EOL;
  155. }
  156.  
  157. return (97 - $iSum % 97 == $sVatnr % 100);
  158. }
  159.  
  160. return false;
  161. }

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.