Sometimes fail to call the web service.
This problem happens all the time.
What could be the problem?
Error:
SoapFault exception: [HTTP] Could not connect to host in
0 [internal function]: SoapClient->__doRequest('<?xml version="...', http://.', '', 1, 0)
The problem was solved.The problem is the cache
ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);
I am adding my comment for completeness, as the solutions listed here did not help me. On PHP 5.6, SoapClient makes the first call to the specified WSDL URL in SoapClient::SoapClient and after connecting to it and receiving the result, it tries to connect to the WSDL specified in the result in:
<soap:address location="http://"/>
And the call fails with error Could not connect to host if the WSDL is different than the one you specified in SoapClient::SoapClient and is unreachable (my case was SoapUI using http://host.local/).
The behaviour in PHP 5.4 is different and it always uses the WSDL in SoapClient::SoapClient.
The host is either down or very slow to respond. If it's slow to respond, you can try increasing the timeout via the connection_timeout option or via the default_socket_timeout setting and see if that reduces the failures.
http://www.php.net/manual/en/soapclient.soapclient.php
http://www.php.net/manual/en/filesystem.configuration.php#ini.default-socket-timeout
You can also include error handling as zanlok pointed out to retry a few times. If you have users actually waiting on these SOAP calls then you'll want to queue them up and process them in the background and notify the user when they're finished.
A misconfigured service leaves the default namespace with tempuri.org
This means the connection to the wsdl will work, but the function call will fail.
Stacktrace:
SoapClient->__doRequest('http://example.com...', 'http://tempuri.org....', 2, 0)
To remediate this, you must explicitly set the location using __setLocation()
$this->soapClient = new \SoapClient(WS_URL);
$this->soapClient->__setLocation(WS_URL);
This work for me
$opts = array(
'ssl' => array('verify_peer' => false, 'verify_peer_name' => false)
);
if (!isset($this->soap_client)) {
$this->soap_client = new SoapClient($this->WSDL, array(
'soap_version' => $this->soap_version,
'location' => $this->URL,
'trace' => 1,
'exceptions' => 0,
'stream_context' => stream_context_create($opts)
));
there is a soap config section in your php.ini file, which control the wsdl access cache, may be shown as:
[soap]
; Enables or disables WSDL caching feature.
soap.wsdl_cache_enabled=1 ;
Sets the directory name where SOAP extension will put cache files.
soap.wsdl_cache_dir="/tmp"
; (time to live) Sets the number of second while cached file will be used ; instead of original one.
soap.wsdl_cache_ttl=86400
if wsdl file cache is enabled, it may cause this problem when changing wsdl URI in php code.
in this example, you can just delete file start with wsdl- under /tmp directory.
or you just set soap.wsdl_cache_enabled=0; and soap.wsdl_cache_ttl=0;
PHP will fetch the wsdl file every-time you visit the page.
In our case, it was a Ciphers negotiation problem. We were getting this error randomly. We solved our problem by forcing a Cipher like this:
$soapClient = new SoapClient ('http://example.com/soap.asmx?wsdl',
array (
"stream_context" => stream_context_create (
array (
'ssl' => array (
'ciphers'=>'AES256-SHA'
)
)
)
)
);
Looks like PHP wasn't negotiating the same Ciphers at each service call.
In my case it worked after the connection to the wsdl, use the function __setLocation() to define the location again because the call fails with the error:
Could not connect to the host
This happens if the WSDL is different to the one specified in SoapClient::SoapClient.
I hit this issue myself and after much digging I eventually found this bug for ubuntu:
https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/965371
specifically
https://bugs.launchpad.net/ubuntu/+source/openssl/+bug/965371/comments/62
openssl s_client -connect site.tld:443 failed however openssl s_client -tls1 -connect site.tld:443 gave success. In my particular case part of the output included
New, TLSv1/SSLv3, Cipher is RC4-MD5 so I set the php context ssl/cipher value appropriately.
It seems the error SoapFault exception: Could not connect to host can be caused be several different things. In my cased it wasn't caused by proxy, firewall or DNS (I actually had a SOAP connection from the same machine working using nusoap without any special setup).
Finally I found that it was caused by an invalid pem file which I referenced in the local_cert option in my SoapClient contructor.
Solution:
When I removed the certificate chain from the pem file, so it only contained certificate and private key, the SOAP calls started going through.
For me it was a certificate problem. Following worked for me
$context = stream_context_create([
'ssl' => [
// set some SSL/TLS specific options
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]);
$client = new SoapClient(null, [
'location' => 'https://...',
'uri' => '...',
'stream_context' => $context
]);
In my case service address in wsdl is wrong.
My wsdl url is.
https://myweb.com:4460/xxx_webservices/services/ABC.ABC?wsdl
But service address in that xml result is.
<soap:address location="http://myweb.com:8080/xxx_webservices/services/ABC.ABC/"/>
I just save that xml to local file and change service address to.
<soap:address location="https://myweb.com:4460/xxx_webservices/services/ABC.ABC/"/>
Good luck.
I finally found the reason,its becuse of the library can't find a CA bundle on your system.
PHP >= v5.6 automatically sets verify_peer to true by default. However, not all systems have a known CA bundle on disk .
You can try one of these procedures:
1.If you have a CA file on your system, set openssl.cafile or curl.cainfo in your php.ini to the path of your CA file.
2.Manually specify your SSL CA file location
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($cHandler, CURLOPT_CAINFO, $path-of-your-ca-file);
3.disabled verify_peer
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
For those who struggled the same as me with laravel artisan console command that makes a lot of requests to same wsdl of external soap server and then after some time fails with Could not connect to host error.
The problem was because I was creating new SoapClient instance each time before request was made. Do not do that. Create it once and make each request from the same client.
Hope it helps.
For me it was a DNS issue. My VPS's nameservers crapped out, so I switched to Google's by editing my /etc/resolv.conf to be:
nameserver 8.8.8.8
nameserver 8.8.4.4
If you have a firewall on your server, make sure to open the port used by SOAP.
In my case, I had to open the port 1664.
iptables -t filter -A INPUT -p tcp --dport 1664 -j ACCEPT
iptables -t filter -A OUTPUT -p tcp --dport 1664 -j ACCEPT
if ujava's solution can't help you,you can try to use try/catch to catch this fatal,this works fine on me.
try{
$res = $client->__call('LineStopQueryJson',array('Parameters' => $params));
}catch(SoapFault $e){
print_r($client);
}
With me, this problem in base Address in app.config of WCF service:
When I've used:
<baseAddresses><add baseAddress="http://127.0.0.1:9022/Service/GatewayService"/> </baseAddresses>
it's ok if use .net to connect with public ip or domain.
But when use PHP's SoapClient to connect to "http://[online ip]:9022/Service/GatewayService", it's throw exception "Coulod not connect to host"
I've changed baseAddress to [online ip]:9022 and everything's ok.
Another possible reason for this error is when you are creating and keeping too many connections open.
SoapClient sends the HTTP Header Connection: Keep-Alive by default (through the constructor option keep_alive). But if you create a new SoapClient instance for every call in your queue, this will create and keep-open a new connection everytime. If the calls are executed fast enough, you will eventually run into a limit of 1000 open connections or so and this results in SoapFault: Could not connect to host.
So make sure you create the SoapClient once and reuse it for subsequent calls.
I had a bad php.ini configuration. Verify the path and the certificate validity...
[openssl]
openssl.cafile = "C:/good/phpath/ca-bundle.crt"
Because my new \SoapClient($wsdl) was https !
Just to help other people who encounter this error, the url in <soap:address location="https://some.url"/> had an invalid certificate and caused the error.
For me, this was a problem in the httpd service (Fedora 24). A simple restart did the trick:
sudo service httpd restart
If the connection is through SSL, could be a problem of server instead of client (it is my case).
In PHP versions greater than 5.6 and 7, is important to check the CipherSuite used in server certificate.
There is a full list of ciphers allowed by this versions and a full list of ciphers that do not in this web link: https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Ciphersuite
If the cipher used is not allowed (it is a deprecated algorithm), SoapClient receives "Could not connect to host" and there is no more trace about it.
The cipher used can be checked by clients like SoapUI in the section of "SSL Info", for example.
There is no thread forum treating about this in internet.
Check this out, too: http://php.net/manual/en/migration56.openssl.php
In my case the host requires TLS 1.2 so needed to enforce using the crypto_method ssl param.
$client = new SoapClient($wsdl,
array(
'location' => $location,
'keep_alive' => false,
"stream_context" => stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT,
]
]),
'trace' => 1, // used for debug
)
);
In my case, disabled SELINUX allow PHP to call my WebService.
I run PHP in FPM with Apache2
SELinux status :
# sestatus
Disable SELinux :
setenforce 0
Enable SELinux :
# setenforce 1
Permanent disable :
edit this file /etc/selinux/config
Version check helped me OpenSSL. OpenSSL_1_0_1f not supported TSLv.1_2 !
Check version and compatibility with TSLv.1_2 on github openssl/openssl
. And regenerate your certificate with new openssl
openssl pkcs12 -in path.p12 -out newfile.pem
P.S I don’t know what they were minus, but this solution will really help.
That most likely refers to a connection issue. It could be either that your internet connection was down, or the web service you are trying to use was down. I suggest using this service to see if the web service is online or not: http://downforeveryoneorjustme.com/
Related
I'm running the next script from my local host and the production server, and Im getting different outputs. Anyone knows why am I getting that false from my localhost?
<?php
$host = 'ssl://mail.companyname.org';
$port = 993;
$error = 0;
$errorString = "";
var_dump(fsockopen($host, $port, $error, $errorString, 30));
var_dump($errorString);
var_dump($error);
Local host output:
bool(false)
Production server output:
resource(4) of type (stream)
UPDATE: after the comments/answer I have modified the code and now Im getting this output on my local host:
PHP Warning: fsockopen(): SSL operation failed with code 1. OpenSSL
Error messages: error:1416F086:SSL
routines:tls_process_server_certificate:certificate verify failed in
/tmp/test.php on line 7 PHP Warning: fsockopen(): Failed to enable
crypto in /tmp/test.php on line 7 PHP Warning: fsockopen(): unable to
connect to ssl://mail.twmdata.org:993 (Unknown error) in /tmp/test.php
on line 7 bool(false) string(0) "" int(0)
it seems this is problem with server certificate :
first you can check if your server certificate and its chains are valid by this:
https://www.sslshopper.com/ssl-checker.htm
if somethings were wrong in ssl-checker?
you can try to correct SSL certificate configs in companyname.org
if you succeed and error was persists ?
you have to add Certificate files manually.
if you have a self-signed certificate:
you have to add Certificate files manually.
if you dont have certificate nor you dont care about man-in-the-middle attack,
you can still use SSL without Certificate.
turn off php fsock Certificate check (not recommended)
its recommended to have a certificate at least a self-signed. if you have a self-signed try 1 solution.
I have found the Problem
You have exposed your Domain name in your PHP Warning Log, so i have checked your domain SSL.
after i check your company`s domain certificate using this tool:
https://www.sslshopper.com/ssl-checker.html#hostname=twmdata.org
it had 2 errors with your certificates:
This certificate has expired (0 days ago). Renew now.
None of the common names in the certificate match the name that was entered (twmdata.org). You may receive an error when accessing this site in a web browser.
so it seems you have to renew your certificate first
Update:
i have found this answer maybe helpful
https://stackoverflow.com/a/40962061/9287628
it suggested to use
stream_context_create(['ssl' => [
'ciphers' => 'RC4-MD5'
]])
as #ChrisHaas suggested connecting with stream_context_create and stream_socket_client brings you a lot of option if you want to dictate the cert directory or you want to turn off certificate check.
Per the documentation for fsockopen
The function stream_socket_client() is similar but provides a richer set of options, including non-blocking connection and the ability to provide a stream context.
Basically, fsockopen is very low-level but without many options, or, arguably, "sane defaults".
Instead, you can switch to stream_socket_client which will allow you to specify a context as the last parameter, and that object has many options, including a dedicated one with over a dozen options specific to SSL. The object created from this function is compatible with fwrite and other functions, so it should do everything you are hoping for.
$context = stream_context_create([/*Options here*/]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
Now, what options should you use?
The worst option that might work is probably verify_peer. I say "worst" because you are throwing away the verifiability part of SSL/TLS and only using it for encryption, and doing this will make you susceptible to MitM attacks. However, there's a place and time for this, so you could try it if the other options are too complicated.
$context = stream_context_create(['ssl' => ['verify_peer' => false]]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
Instead, I'd recommend using either cafile or capath which do the same thing except the former is for a file while the latter is for a directory.
$context = stream_context_create(['ssl' => ['verify_peer' => true, 'cafile' => '/path/to/file']]);
$connection = stream_socket_client($host, $errno, $errorString, 30, null, $context);
What certs should you use? We use this library to pull in recent CA files on a periodic basis, very convenient. There's a little bit of setup that's per-project but once you get it it goes pretty fast. See this for pulling in a CA file at a well-known location.
One other last option is local_cert which you can use with a PEM file that holds the certificate and private key from the server, if you have access to that.
EDIT
The cert on mail.twmdata.org:993 is different than the web server's cert that other people are talking about, which is generally a best practice. You can inspect that cert using:
openssl s_client -connect mail.twmdata.org:993 -servername mail.twmdata.org
If you do that, you'll see that the server has a self-signed cert which you can get around by setting the verify_peer option to false.
Remove the # symbol. You are hiding error messages that might tell you what the problem is. You should also set a variable in the errorno argument to fsockopen() and echo it for debugging.
My guess would be that you haven't installed PHP with SSL support on your local server. See here.
Companyname.org might also block requests from your local server that are allowed from the production server.
I'm having problems connecting a Php client app to an Ssl enabled ActiveMq installation. I've looked at many sources and am getting more confused as I go.
My setup so far uses authentication via users/groups.properties and authorizationPlugin. This works fine on regular connections
For ActiveMq Ssl I followed a few articles and created the Jks store and certs and also configured with the following
<sslContext>
<sslContext keyStore="file:${activemq.base}/conf/server.ks"
keyStorePassword="$STORE_PASS"
trustStore="file:${activemq.base}/conf/server.ts"
trustStorePassword="$STORE_PASS" />
</sslContext>
<transportConnector
name="stomp+ssl" uri="stomp+ssl://0.0.0.0:61617?needClientAuth=true"/>
I also tried the ACTIVEMQ_SSL_OPTS approach. Both load fine when starting the server. Logs show Sll connector started. I also checked the php cli to make sure Sll is enabled on stomp installation
The problem I'm having is with the Php stomp client. First, these are the articles I read.
http://activemq.apache.org/how-do-i-use-ssl.html
http://php.net/manual/en/stomp.construct.php
https://github.com/stomp-php/stomp-php/wiki/Connectivity
From my understanding, there are two php stomp libs based on the documentation I can't figure out how to set all this up. The php site docs simply give an example of using the constructor with ssl protocol
$link = stomp_connect('ssl://localhost:61612', $user, $pass, $headers);
This doesn't work, I get a null cert error in the logs.
The other article that uses FuseSource stomp has options for including a client cert when establishing a connection but after getting further into the article it looks like it's just to authenticate via Sll cert and not with a user/pass.
https://github.com/rethab/php-stomp-cert-example/blob/master/README.md
So I went back to the previous stomp installation thinking there's a way to pass the client cert files but there doesn't seem to be an interface for it and no docs on the headers param which I'm assuming is not how to go about this.
Can someone shed some light on were in this complex mess I went wrong.
I don't know if you're still interested, but just in case someone stumbles upon this question hoping for an answer.
We're using https://github.com/stomp-php/stomp-php/ for our Stomp connection and this is roughly how we create the client:
function createClient($broker_url, $login, $password) {
$client = new \Stomp\Client($broker_url);
$sslContext = [
'ssl' => [
'cafile' => '/path/to/cert',
'verify_peer' => true,
'verify_peer_name' => false,
'ciphers' => 'HIGH',
],
];
$client->getConnection()->setContext($sslContext);
$client->setLogin($login, $password);
$client->connect();
return new \Stomp\StatefulStomp($client);
}
$broker_url should be in the format ssl://host:port.
I'm configuring a Magento 1.9.1 to use an external SMTP to send emails, using SMTP PRO (https://www.magentocommerce.com/magento-connect/smtp-pro-email-free-custom-smtp-email.html).
I've setup the configuration (hostname, port, username, password) but when I try to send a test email it fails with a 'Could not open socket' error message. If I dig into the code I see that the error is generated from this piece of code in lib/Zend/Mail/Protocol/Abstract.php:
$this->_socket = #stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);
if ($this->_socket === false) {
if ($errorNum == 0) {
$errorStr = $remote.' Could not open socket '.phpversion();
}
/**
* #see Zend_Mail_Protocol_Exception
*/
#require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($errorStr);
}
My PHP environment (5.6.30) has openssl support (see image and snippet below)
[root#ns3023903 httpdocs]# php -r 'print_r(stream_get_transports());'
Array
(
[0] => tcp
[1] => udp
[2] => unix
[3] => udg
[4] => ssl
[5] => sslv3
[6] => sslv2
[7] => tls
)
There are no firewall issues as i can both telnet on the port 465 to the target host or send an email using the same SMTP using phpmailer with the same user I use to run the site virtualhost.
I'm on a CentOS 7 64 bit server, with SELinux disabled and, if that matters, I'm using Plesk 12 to configure virtual hosts.
Name resolution is also working ok (I can ping the SMTP name correctly and the IP address is looked up just fine).
I'm obviously missing something here...but what?
It turned out it was something that changed in the PHP version 5.6.30, in terms of default options assumed by stream_socket_client().
First of all before getting rid of the stupid # in front of the stream_socket_client call in the Magento core code I wasn't actually able to understand what was going on. I'm not even close to a PHP developer so I keep forgotting what that stupid # prefix is for (to be honest I don't even know why it exists).
After removing the # I saw this:
Warning: stream_socket_client(): Peer certificate CN=`*.aruba.it' did not match expected CN=`mail.myclientreserveddomain.com'
I looked a bit into the PHP documentation and I came out with a two line diff to the core code (I know this is not right, I'll refactor it now, but I wanted to share the quick workaround first).
Basically I'm creating a context and using another version of the stream_socket_client call
$context = stream_context_create(['ssl' => [
'verify_peer' => false,
'verify_peer_name' => false
]]);
// open connection
$this->_socket = stream_socket_client($remote, $errorNum, $errorStr, 120, STREAM_CLIENT_CONNECT, $context);
Skipping peer name validation is the key. Not sure why/how/when it changed from php pre 5.6.30 to PHP 5.6.30 (have I said I'm not a PHP dev?) but it works. I also tried to run the original code under PHP 5.4.x and it worked without the workaround so it's definitely that.
This works fine on my WAMP server, but doesn't work on the linux master server!?
try{
$client = new SoapClient('http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', ['trace' => true]);
$result = $client->checkVat([
'countryCode' => 'DK',
'vatNumber' => '47458714'
]);
print_r($result);
}
catch(Exception $e){
echo $e->getMessage();
}
What am I missing here?! :(
SOAP is enabled
Error
SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl' : failed to load external entity "http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl"/taxation_customs/vies/checkVatService.wsdl"
Call the URL from PHP
Calling the URL from PHP returns error
$wsdl = file_get_contents('http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl');
echo $wsdl;
Error
Warning: file_get_contents(http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl): failed to open stream: HTTP request failed! HTTP/1.0 503 Service Unavailable
Call the URL from command line
Calling the URL from the linux command line HTTP 200 is returned with a XML response
curl http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
For some versions of php, the SoapClient does not send http user agent information. What php versions do you have on the server vs your local WAMP?
Try to set the user agent explicitly, using a context stream as follows:
try {
$opts = array(
'http' => array(
'user_agent' => 'PHPSoapClient'
)
);
$context = stream_context_create($opts);
$wsdlUrl = 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl';
$soapClientOptions = array(
'stream_context' => $context,
'cache_wsdl' => WSDL_CACHE_NONE
);
$client = new SoapClient($wsdlUrl, $soapClientOptions);
$checkVatParameters = array(
'countryCode' => 'DK',
'vatNumber' => '47458714'
);
$result = $client->checkVat($checkVatParameters);
print_r($result);
}
catch(Exception $e) {
echo $e->getMessage();
}
Edit
It actually seems to be some issues with the web service you are using. The combination of HTTP over IPv6, and missing HTTP User Agent string, seems to give the web service problems.
To verify this, try the following on your linux host:
curl -A '' -6 http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
this IPv6 request fails.
curl -A 'cURL User Agent' -6 http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
this IPv6 request succeeds.
curl -A '' -4 http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
curl -A 'cURL User Agent' -4 http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
both these IPv4 request succeeds.
Interesting case :) I guess your linux host resolves ec.europa.eu to its IPv6 address, and that your version of SoapClient did not add a user agent string by default.
Security issue: This answer disables security features and should not be used in production!
Try this. I hope it helps
$options = [
'cache_wsdl' => WSDL_CACHE_NONE,
'trace' => 1,
'stream_context' => stream_context_create(
[
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]
)
];
$client = new SoapClient($url, $options);
This issue can be caused by the libxml entity loader having been disabled.
Try running libxml_disable_entity_loader(false); before instantiating SoapClient.
It may be helpful for someone, although there is no precise answer to this question.
My soap url has a non-standard port(9087 for example), and firewall blocked that request and I took each time this error:
ERROR - 2017-12-19 20:44:11 --> Fatal Error - SOAP-ERROR: Parsing
WSDL: Couldn't load from 'http://soalurl.test:9087/orawsv?wsdl' :
failed to load external entity "http://soalurl.test:9087/orawsv?wsdl"
I allowed port in firewall and solved the error!
Try changing
$client = new SoapClient('http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', ['trace' => true]);
to
$client = new SoapClient('http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', ['trace' => true, 'cache_wsdl' => WSDL_CACHE_MEMORY]);
Also (whether that works or not), check to make sure that /tmp is writeable by your web server and that it isn't full.
Try enabling openssl extension in your php.ini if it is disabled.
This way I could access the web service without need of any extra arguments, i.e.,
$client = new SoapClient(url);
None of the above works for me, so after a lot of research, I ended up pre-downloading the wsdl file, saving it locally, and passing that file as the first parameter to SoapClient.
Worth mentioning is that file_get_contents($serviceUrl) returned empty response for me, while the url opened fine in my browser. That is probably why SoapClient also could not load the wsdl document. So I ended up downloading it with the php curl library. Here is an example
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $serviceUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$wsdl = curl_exec($ch);
curl_close($ch);
$wsdlFile = '/tmp/service.wsdl';
file_put_contents($wsdlFile, $wsdl);
$client = new SoapClient($wsdlFile);
You can of course implement your own caching policy for the wsdl file, so it won't be downloaded on each request.
503 means the functions are working and you're getting a response from the remote server denying you. If you ever tried to cURL google results the same thing happens, because they can detect the user-agent used by file_get_contents and cURL and as a result block those user agents. It's also possible that the server you're accessing from also has it's IP address blackballed for such practices.
Mainly three common reasons why the commands wouldn't work just like the browser in a remote situation.
1) The default USER-AGENT has been blocked.
2) Your server's IP block has been blocked.
3) Remote host has a proxy detection.
After hours of analysis reading tons of logs and internet, finally found problem.
If you use docker and php 7.4 (my case) you probably get error because default security level in OpenSSL it too high for wsdl cert. Even if you disable verify and allow self-signed in SoapClient options.
You need lower seclevel in /etc/ssl/openssl.cnf from DEFAULT#SECLEVEL=2 to
DEFAULT#SECLEVEL=1
Or just add into Dockerfile
RUN sed -i "s|DEFAULT#SECLEVEL=2|DEFAULT#SECLEVEL=1|g" /etc/ssl/openssl.cnf
Source: https://github.com/dotnet/runtime/issues/30667#issuecomment-566482876
You can verify it by run on container
curl -A 'cURL User Agent' -4 https://ewus.nfz.gov.pl/ws-broker-server-ewus/services/Auth?wsdl
Before that change I got error:
SSL routines:tls_process_ske_dhe:dh key too small
It was solved for me this way:
Every company from which you provide "Host" has a firewall.
This error occurs when your source IP is not defined in that firewall.
Contact the server administrator to add the IP.
Or the target IP must be defined in the server firewall whitelist.
I use the AdWords API, and sometimes I have the same problem.
My solution is to add
ini_set('default_socket_timeout', 900);
on the file
vendor\googleads\googleads-php-lib\src\Google\AdsApi\AdsSoapClient.php line 65
and in the
vendor\googleads-php-lib\src\Google\AdsApi\Adwords\Reporting\v201702\ReportDownloader.php line 126
ini_set('default_socket_timeout', 900);
$requestOptions['stream_context']['http']['timeout'] = "900";
Google package overwrite the default php.ini parameter.
Sometimes, the page could connect to 'https://adwords.google.com/ap
i/adwords/mcm/v201702/ManagedCustomerService?wsdl and sometimes no.
If the page connects once, The WSDL cache will contain the same page, and the program will be ok until the code refreshes the cache...
Adding ?wsdl at the end and calling the method:
$client->__setLocation('url?wsdl');
helped to me.
I might have read all questions about this for two days. None of the answers worked for me.
In my case I was lacking cURL module for PHP.
Be aware that, just because you can use cURL on terminal, it does not mean that you have PHP cURL module and it is active.
There was no error showing about it. Not even on /var/log/apache2/error.log
How to install module:
(replace version number for the apropiated one)
sudo apt install php7.2-curl
sudo service apache2 reload
I had the same problem
From local machines everything work (wamp + php5.5.38 or vagrant + php 7.4), but from prod linux server I had error
SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl' : failed to load external entity "http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl"
From redirect path plugin in chrome I discovered permanent redirect to https, but change url to https doesnt help.
Status Code URL IP Page Type Redirect Type Redirect URL
301 http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl 147.67.210.30 server_redirect permanent https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl
200 https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl 147.67.210.30 normal none none
After few attempts of different code solutions helped my our server provider. He discovered problem in IP forwarding with ipv6.
http://ec.europa.eu/
Pinging ec.europa.eu [147.67.34.30] with 32 bytes of data:
Request timed out.
Request timed out.
Request timed out.
Recommendation was user stream_context_create with socket and bind to 0:0. this forces ipv4
// https://www.php.net/manual/en/context.socket.php
$streamContextOptions = [
'socket' => [
'bindto' => '0:0'
],
];
$streamContext = stream_context_create($streamContextOptions);
$soapOptions = [
'stream_context' => $streamContext
];
$service = new SoapClient('https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl', $soapOptions);
I had similar error because I accidently removed attribute
[ServiceContract] from my contract, yet the service host was still opening successfully. Blunders happen
May try to see if the endpoint supports https as well
Below solution worked for me.
1- Go to php.ini in ubuntu with apache is /etc/php/7.4/apache2
( note: you should use your php version replace by 7.4 )
2- Remove ; from this line ;extension=openssl to make in uncommented.
3- Restart your web server sudo service apache2 restart
How can I force TLSv1.0 in a PHP stream context when trying to access an https URL?
I’m looking for something along the lines of this:
$context = stream_context_create(
array(
'ssl' => array(
'protocol_version' => 'tls1',
),
));
file_get_contents('https://example.com/test', false, $context);
Background
Actually I’m facing an issue in Ubuntu 12.04 when working with PHP’s SoapClient. Unfortunately, the server I’m trying to connect to does only support SSLv3.0/TLSv1.0 and fails on the default TLSv1.1 negotiation. Therefore I’d like to explicitly set the protocol of the ssl:// transport to TLSv1.0.
PHP 5.6+ Users
This is a new feature as documented on the PHP 5.6 OpenSSL Changes page.
At time of writing this, PHP5.6 is in Beta1 and thus this isn't overly useful. People of the future - lucky you!
The future is upon us. PHP 5.6 is a thing and its use should be encouraged. Be aware that it deprecates some fairly widely used things like mysql_* functions so care should be taken when upgrading.
Everyone else
#toubsen is correct in his answer - this isn't directly possible. To elaborate on his suggested workarounds... when working around a problem where a supplier's API server wasn't correctly negotiating TLSv1.2 down to its supported TLSv1.0, sending a small subset of ciphers seemed to allow negotiation to complete correctly. Stream context code is:
$context = stream_context_create(
[
'ssl' => [
'ciphers' => 'DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:KRB5-RC4-MD5:KRB5-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:KRB5-DES-CBC-MD5:KRB5-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-KRB5-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-RC4-MD5:EXP-RC4-MD5',
],
]
);
SOAP Users
PHP's SOAP client doesn't use curl, nor does it seem to use the default context set with stream_context_set_default. As such, the created context needs to be passed to the SOAPClient constructor in the 2nd parameter as such:
$soap_client = new SOAPClient('http://webservices.site.com/wsdlfile.wsdl', array('stream_context' => $context));
Why those Ciphers?
Running the command openssl ciphers on the server gives you a list of supported ciphers in the above format. Running openssl ciphers -v tells you those that are TLSv1.2 specific. The above list was compiled from all of the non-TLSv1.2 ciphers reported by OpenSSL.
openssl ciphers -v | grep -v 'TLSv1.2' | cut -d ' ' -f 1 | tr "\n" ':'
In case someone wants to know how to "disable" TLSv1.0 when making a SOAP request...
$parameters = array(
'trace' => true,
'exceptions' => true,
'cache_wsdl' => WSDL_CACHE_NONE,
'stream_context' => stream_context_create(array(
'ssl' => array(
'ciphers' => 'DEFAULT:!TLSv1.0:!SSLv3'
),
)),
'connection_timeout' => 15
);
$client = new SoapClient(YOUR_WSDL_URL_HERE, $parameters);
The key part here is that stream context ciphers line. This says use the default ciphers, but exclude TLSv1.0 ciphers (the 1.0 package also has TLSv1.1 ciphers). The : is the cipher package separator (what goes between packages) and the ! here is to tell it to exclude this package (it's a hard exclude so if it shows up later in the list it will still be excluded). Soft exclude is - character and add to the end of the list is + character. To add in order just add it without anything in front of it.
Cipher information here: https://www.openssl.org/docs/manmaster/man1/ciphers.html#CIPHER-LIST-FORMAT
Edit:
For whatever reason including the
'ssl_method' => SOAP_SSL_METHOD_TLS,
part from the options was really causing me headaches and wouldn't connect in certain contexts. After tons of troubleshooting and playing around with options I finally realized that removing this setting and letting it autoset this seems to have resolved the issue.
Base information
The field protocol_version is only valid for HTTP context (HTTP 1.0 vs 1.1), but does not affect the SSL context.
The following manual page lists all stream context options for PHP:
Context options and parameters
For all SSL based stream wrappers, only the follwing options are available:
SSL context options
Possible solutions / workarounds
First advice: Get the server admin to fix his server instead of working around this in your client ;-)
Maybe you can get it wo work with the ciphers option for SSL streams, to pass only one exact TLSv1.0 cipher suite (that is unique to TLSv1.0) in the list, that your target server supports.
Switching the implementaion to use cURL will most probaly also not help here, as according to an entry in their mailing list, there's no option to force a certain TLS version - the client will downgrade when needed automatically.
tl;dr
I currently know of no way to explicitly force TLSv1.0 for SSL connections from PHP.
I can confirm that above accepted answer does not work for Ubuntu 12.04 and PHP 5.4.33 combination. Also found out that I have to manually specify certificate when trying openssl and curl to access https endpoints. I ended up using RHEL 7 and PHP 5.5 to achieve a solid solution as I was developing integration for an enterprise application. Nothing against Ubuntu, but in my specific case it didn't work.