2

I am trying to validate EU VAT numbers using the script by Eugene Mihailescu that can be found here: https://stackoverflow.com/a/29955950 Although this script was working flawlessly up until a recently, now Apache comes up with the following error:

PHP Warning:  file_get_contents(http://ec.europa.eu/taxation_customs/vies/services/checkVatService): failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error

I searched and found a cUrl version of the same script by Professor Abronsius which can be found here:

https://stackoverflow.com/a/56035880

Unfortunately a similar error comes up in the console:

Object { response: false, info: {…}, errors: "The requested URL returned error: 500 Internal Server Error" } errors: "The requested URL returned error: 500 Internal Server Error" info: Object { url: "https://ec.europa.eu/taxation_customs/vies/services/checkVatService", http_code: 500, header_size: 0, … } …….

To my understanding the problem may rely in the "VIES" server itself, but there are no announcements in their website: https://ec.europa.eu/taxation_customs/vies/#/vat-validation

Any ideas/suggestions?

Theo Orphanos
  • 1,417
  • 1
  • 19
  • 27
  • well, the url : http://ec.europa.eu/taxation_customs/vies/services/checkVatService returns nothing at all. what is it even supposed to be? an api? – Mash tan Aug 22 '22 at 10:55
  • Have any of the relevant URLS from the first code changed to https in the seven years since the answer was posted? – droopsnoot Aug 22 '22 at 11:15
  • Oh, actually maybe not - the web site says you can use either http or https. Does it work better if you use https instead? – droopsnoot Aug 22 '22 at 11:19
  • @Mashtan it's a SOAP API... – Theo Orphanos Aug 22 '22 at 13:17
  • @droopsnoot It is supposed to work both with http and https. I have also tried https... the result is the same (( Up until a month ago -or less- was working fine... – Theo Orphanos Aug 22 '22 at 13:19

4 Answers4

2

Thanks to MexicanGuy for your solution, it was really useful in fixing the problem. In regard to the original question and the code used from :

https://github.com/lepoco/vies-api/blob/master/veis-api.php

by Eugene Mihailescu

It can be fixed by removing : "SOAPAction: checkVatService" from the end of the header line.

After this it returns XML content, however it is slightly different than before as it includes the XML namespace "NS2" on the relevant nodes. Adjusting the regex to the following can fix it.

$pattern = '/ns2:(%s).*?([\s\S]*)</ns2:\1/';

Then it started working again for us.

However we came to the conclusion that the solution isn't optimal in that it uses a regex to read XML data. There are bespoke XML readers and indeed SOAP extensions in PHP that can be used. There is also a potential library that seems perhaps more robust to future changes :

https://github.com/DragonBe/vies

Which we are thinking is a superior long term solution.

Kubla Ltd
  • 21
  • 1
1

Ran into the same problem, searched a little bit, and it seems that soap envelope as changed. Made some changes and included some functions to maintain previous workflow. Hope it helps

DEFINE ( 'VIES_URL', 'http://ec.europa.eu/taxation_customs/vies/services/checkVatService' );

/**
 * VIES VAT number validation
 *
 * @author Eugen Mihailescu
 *        
 * @param string $countryCode           
 * @param string $vatNumber         
 * @param int $timeout          
 */
function array_key_replace($item, $replace_with, array $array){
    $updated_array = [];
    foreach ($array as $key => $value) {
        if (!is_array($value) && $key == $item) {
            $updated_array = array_merge($updated_array, [$replace_with => $value]);
            continue;
        }
        $updated_array = array_merge($updated_array, [$key => $value]);
    }
    return $updated_array;
}

 function string_between_two_string($str, $starting_word, $ending_word)
{
    $subtring_start = strpos($str, $starting_word);
    //Adding the starting index of the starting word to
    //its length would give its ending index
    $subtring_start += strlen($starting_word); 
    //Length of our required sub string
    $size = strpos($str, $ending_word) - $subtring_start; 
    // Return the substring from the index substring_start of length size
    return substr($str, $subtring_start, $size); 
}
function viesCheckVAT($countryCode, $vatNumber, $timeout = 30) {
    $response = array ();
    $pattern = '/<(%s).*?>([\s\S]*)<\/\1/';
    $keys = array (
            'countryCode',
            'vatNumber',
            'requestDate',
            'valid',
            'name',
            'address' 
    );
    //Changed envelope
     $content = "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'
 xmlns:tns1='urn:ec.europa.eu:taxud:vies:services:checkVat:types'
 xmlns:impl='urn:ec.europa.eu:taxud:vies:services:checkVat'>
 <soap:Header>
 </soap:Header>
 <soap:Body>
    <tns1:checkVat xmlns:tns1='urn:ec.europa.eu:taxud:vies:services:checkVat:types'
    xmlns='urn:ec.europa.eu:taxud:vies:services:checkVat:types'>
    <tns1:countryCode>".$countryCode."</tns1:countryCode>
    <tns1:vatNumber>".$vatNumber."</tns1:vatNumber>
   </tns1:checkVat>
 </soap:Body>
</soap:Envelope>";


    $opts = array (
            'http' => array (
                    'method' => 'POST',
                    'header' => "Content-Type: text/xml; charset=utf-8;",
                    'content' => sprintf ( $content ),
                    'timeout' => $timeout 
            ) 
    );

    $ctx = stream_context_create ( $opts );
    $result = file_get_contents ( 'https://ec.europa.eu/taxation_customs/vies/services/checkVatService', false, $ctx );
    //extract necessary values from answer string
    $valid = string_between_two_string($result, '<ns2:valid>', '</ns2:valid>');
    $country = string_between_two_string($result, '<ns2:countryCode>', '</ns2:countryCode>');
    $vatnumber = string_between_two_string($result, '<ns2:vatNumber>', '</ns2:vatNumber>');
    $address = string_between_two_string($result, '<ns2:address>', '</ns2:address>');
    $name = string_between_two_string($result, '<ns2:name>', '</ns2:name>');
    $dater = string_between_two_string($result, '<ns2:requestDate>', '</ns2:requestDate>');

    //insert strings in array and replace index keys by name
    $vat = "$country$vatnumber";
    $vars = array($vat, $name, $address, $dater, $valid);
    $new_array = array_key_replace('0', 'vat', $vars);
    $new_array = array_key_replace('0', 'name', $new_array);
    $new_array = array_key_replace('0', 'address', $new_array);
    $new_array = array_key_replace('0', 'requestDate', $new_array);
    $new_array = array_key_replace('0', 'status', $new_array);



    return $new_array;
}

print_r (viesCheckVAT ( 'RO', '19386256' ));
Mexicanguy
  • 26
  • 1
0

Run into the same problem today. Try changing the Content-Type in the Header to text/xml. That's what solved the problem for us in Postman.

0

Run into the same problem today. Thanks to EmeseMora for the solution... I change the Content-Type in the Header to text/xml. In this way the problem is solved in Postman. But in my old C++ code I cannot solve. I try in this way:

    LPCWSTR header=L"Content-type: text/xml"; 
    SIZE_T len = lstrlenW(header);
    WinHttpAddRequestHeaders (hRequest,header,DWORD(len), WINHTTP_ADDREQ_FLAG_REPLACE);
ziomauri
  • 1
  • 1