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?
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.
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' ));
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.
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);
I have tried to fix this issue but unable to do so. Field 'card_nonce' is not found on the server although it is recently created. I have used npm and node to generate a card_nonce.
Code Used:
$billing_address = new Address();
$billing_address->setAddressLine1('500 Electric Ave');
$billing_address->setAddressLine2('Suite 600');
$billing_address->setLocality('New York');
$billing_address->setAdministrativeDistrictLevel1('NY');
$billing_address->setPostalCode('10003');
$billing_address->setCountry('AU');
// $body = new CreateCustomerCardRequest($_POST['nonce']);
$body = new CreateCustomerCardRequest('CBASECw9ri-7s1THlCWDoSVsVY8');
$body->setBillingAddress($billing_address);
$body->setCardholderName('Gaurav Gulati');
$api_response = $customersApi->createCustomerCard($customer_id, $body);
if ($api_response->isSuccess()) {
$result = $api_response->getResult();
$customer_card = $api_response->getCard();
$customer_card_id = $customer_card->getId();
} else {
$errors = $api_response->getErrors();
}
Response:
[0] => Square\Models\Error Object
(
[category:Square\Models\Error:private] => INVALID_REQUEST_ERROR
[code:Square\Models\Error:private] => NOT_FOUND
[detail:Square\Models\Error:private] => Resource not found.
[field:Square\Models\Error:private] => card_nonce
)
Anyone has idea how to resolve this error.
You've removed the "cnon:" from the parameter. "CBASECw9ri-7s1THlCWDoSVsVY8" should be cnon:CBASECw9ri-7s1THlCWDoSVsVY8.
I am trying to understand the new stdClass in terms of sending data to a function, I've created the following code and I'll get an error that's saying Warning: Creating default object from empty value, however, still I get the json data as well. How to fix the error and why I am getting it?
$send = new stdClass();
$send->user->id = '12121212121';
$send->message->attachment->type = 'file';
$send->message->attachment->image = 'png';
$res = process($send);
function process($send){
$data = json_encode($send);
print_r($data);
}
Result is looks like this and there is an error above below result as I mentioned it:
{"user":{"id":"12121212121"},"message":{"attachment":{"type":"file","image":"png"}}}
Create stdClass for each reference like this
$send = new stdClass();
$send->user=new stdClass();
$send->user->id = '12121212121';
$send->message=new stdClass();
$send->message->attachment=new stdClass();
$send->message->attachment->type = 'file';
$send->message->attachment->image = 'png';
$res = process($send);
function process($send){
$data = json_encode($send);
print_r($data);
}
I had this line of code which was working fine until I update the php version of my server from 5.3 to 5.6.
It re-writes a xml file.
I guess this line is not compactible with 5.6, but I don't know what is wrong exactly:
$newXml->asXml('my_xml.xml');
And this is the error message:
Fatal error: Call to a member function asXml() on boolean in /usr/home/example/www/sites/all/modules/custom/inmovilla_rewrite/inmovilla_rewrite.module on line 71
What changes should I do here?
UPDATE Complete function
<?php
/**
* Implemetns hook_cron()
*/
function inmovilla_rewrite_cron() {
$xml_external_path = 'http://ap.apinmo.com/portal/mls/jamp623433/my_xml.xml';
$xml = file_get_contents($xml_external_path);
$pattern = '/<unico>(.*?)<\/unico>/';
$response = preg_replace_callback($pattern,function($match){
$valueUnico = trim($match[1]);
$valueUnico = substr($valueUnico, 0, -4);
return '<unico>'.$valueUnico.'</unico>';
},$xml);
$searches = array();
$replacements = array();
for ($i = 1; $i <= 30; $i++) {
$searches[] = 'foto'.$i.'>';
$replacements[] = 'foto1>';
}
$response = str_replace( $searches, $replacements, $response ) ;
$newXml = $response;
$newXml = simplexml_load_string( $newXml );
$newXml->asXml('my_xml.xml');
}
You are calling the method: asXml() on a boolean data-type, not an instance of SimpleXMLElement - you are presumably not feeding in a "well-formed" XML string.
See here: http://php.net/manual/en/function.simplexml-load-string.php
Returns an object of class SimpleXMLElement with properties containing the data held within the xml document, or FALSE on failure.
You should firstly implement some error checking rather than assume that you have a SimpleXMLElement instance, e.g.
$newXml = simplexml_load_string($newXml);
if ($newXml instanceof SimpleXMLElement) {
$xml = $newXml->asXml('my_xml.xml');
}
However, you will need to do some further debugging on the values held in $newXml / $response to see what is wrong with the XML string. I cannot see the XML contents in your question to advise any further as to why the change of PHP version has affected this.
I am using SOAP to get data from some server (data coming in .xml) . But sometimes SOAP server is down and I need to display some error message instead of :
Warning: simplexml_load_string(): Entity: line 2: parser error : Start tag expected, '<' not found in /var/www/class/data2.php on line 619 Warning: simplexml_load_string(): in /var/www/class/data2.php on line 619 Warning: simplexml_load_string(): ^ in /var/www/class/data2.php
My code is:
$client = new SOAPClient ( 'link.wsdl' ); // initiate new SoapClient
$password ['_'] = 'PASSWORD'; // password for authenticate_user function in SoapHeader
$encoded = new SoapVar ( $password, SOAP_ENC_OBJECT ); // make SoapVariable out of $password
$header = new SoapHeader ( 'http://soapinterop.org/echoheader/', 'authenticate_user', $encoded ); // put authenticate_user method, and password in header
$client->__setSoapHeaders ( $header ); // set SoapHeader
$response = $client->get_details ($this->vin); // calling get_details with the vin given in the form field
$xml = simplexml_load_string ( $response ); // converting the response string to xml
$json = json_encode ( $xml ); // converting to an array in to easy steps (step 1)
$array = json_decode ( $json, TRUE ); // step 2
What I want:
Replace Warning message with something like: "This service is temporary unavaliable"
After
$xml = simplexml_load_string ( $response );
check if
$xml === false
and set the error message accordingly
http://php.net/manual/en/function.simplexml-load-string.php
As you can read in manual the simplexml_load_string function:
Returns an object of class SimpleXMLElement with properties containing the data held within the xml document, or FALSE on failure.
So simply check if it fails and if it does echo your This service is temporary unavaliable
To get rid of this warning consider to ini_set('display_errors', '0'); on production