PHP SoapClient with Proxy: How to access schema over proxy? - php

When initializing the SoapClient class with proxy-options, the WSDL and its methods are accessed over proxy correctly:
$client = new SoapClient(
WSDL_URL,
array(
'proxy_host' => PROXY_HOST,
'proxy_port' => PROXY_PORT
)
);
Schemas (schemaLocation) however are not getting accessed over the specified proxy:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified">
<xs:import namespace="http://example.com/webservice/cisbase" schemaLocation="http://example.com/ws/cis_base.xsd"/>
<xs:import namespace="http://de.ws.example" schemaLocation="http://example.com/ws/is_base_de.xsd"/>
</xs:schema>
This leads to:
SOAP-ERROR: Parsing Schema: can't import schema from ...
So basically the SoapClient is trying to access the cis_base.xsd and is_base_de.xsd without proxy which is failing.
Is there a reason why the PHP SoapClient behaves like this and is there a workaround?

In my code i use those options and that works great with our proxy and https protocol. I hope that will work for you to :)
'proxy_host' => PROXY_HOST,
'proxy_port' => PROXY_PORT,
'stream_context' => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)
Regards.

Try:
$client = new SoapClient(
WSDL_URL,
array(
'proxy_host' => PROXY_HOST,
'proxy_port' => PROXY_PORT,
'stream_context' => stream_context_create(
array(
'proxy' => "tcp://$PROXY_HOST:$PROXY_PORT",
'request_fulluri' => true,
)
),
)
);
You might want to check other possible parameters in PHP documentation.

Related

SoapClient constructor works with 7.1, fails with 7.2

My SoapClient constructor works in 7.1 but fails in 7.2 returns an error
[message:protected] => SOAP-ERROR: Parsing WSDL:
Couldn't load from 'https://domain/url.svc?singleWsdl' : failed to load external entity
The WSDL URI appears to be legitimate. I can call it from a browser and get a WSDL document back. Any ideas for what to look at?
$opts = array(
'ssl' => array(
'ciphers' => 'RC4-SHA',
'verify_peer' => false,
'verify_peer_name' => false
)
);
$params = array(
'encoding' => 'UTF-8',
'verifypeer' => false,
'verifyhost' => false,
'soap_version' => SOAP_1_1,
'trace' => 1,
'exceptions' => 1,
'connection_timeout' => 180,
'stream_context' => stream_context_create($opts)
);
try {
$this->_client = new SoapClient($wsdl, $params);
The appropriate libraries are enabled in PHP 7.2
[PHP_OPENSSL]
extension=php_openssl.dll
[PHP_SOAP]
extension=php_soap.dll
In my case, the problem was caused because the certificate was not loaded.
[openssl]
openssl.cafile="/path/to/cacert.pem"
Check if the file is exists.

Soap request to https via proxy

I want to call a SOAP method via proxy on PHP. WSDL path is https://eaisto.gibdd.ru/common/ws/arm_expert.php?wsdl
I tried like this:
$url = 'https://eaisto.gibdd.ru/common/ws/arm_expert.php?wsdl';
$soap_params = array(
'stream_context' => stream_context_create(
array(
'ssl' => array(
'SNI_enabled' => false
),
'http' => array(
'proxy' => 'tcp://54.193.18.175:80'
),
)
),
'connection_timeout' => self::CONNECTION_TIMEOUT,
'proxy_host' => '54.193.18.175',
'proxy_port' => '80'
);
$gibdd_client = new SoapClient(self::GIBDD_URL, $soap_params);
$get_data_request = $gibdd_client->GetCardByVin(array());
But it doesn't work. Error:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://eaisto.gibdd.ru/common/ws/arm_expert.php?wsdl' : failed to load external entity "https://eaisto.gibdd.ru/common/ws/arm_expert.php?wsdl"
When I used http://eaisto.gibdd.ru/common/ws/arm_expert.php?wsdl instead of https://eaisto.gibdd.ru/common/ws/arm_expert.php?wsdl it works properly. How I can send a SOAP request to https via proxy?
I tried with
'ssl' => array(
'SNI_enabled' => false,
'verify_peer' => false,
'verify_peer_name' => false,
),
But this doesn't work too.
This should work:
$streamContext = stream_context_create([
'ssl' => [
'verify_peer' => true,
'cafile' => <path to the CA file>,
'local_cert' => <path to your PEM cert>,
'local_pk' => <path to your private key PEM file>
]
]);
$options = [
'proxy_host' => '<your proxy host>',
'proxy_port' => <your proxy port>
'proxy_login' => '<your proxy login>',
'proxy_password' => '<your proxy password>',
'stream_context' => $streamContext
]
$soapClient = new SoapClient($wsdl, $options);
I did this successfully on PHP5.4, but i wonder if it still works in modern versions of PHP: there use to be a bug that may be back : https://bugs.php.net/bug.php?id=50489
Also note that error messages won't be helpful.
E.g. I am getting error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol when the proxy rejects the authentication with HTTP/1.1 403 Forbidden... Weird and unhelpful...

PHP SOAP Credentials in Header securityContext

Im struggling with this 2 days and trying almost everything I found on internet. I have SOAP service with username and password in header securityContext but have no idea how to provide data in that form in PHP?
This is required header XML:
<soap:Header>
<SecurityContext xmlns="http://tempuri.org/">
<userName>string</userName>
<password>string</password>
</SecurityContext>
</soap:Header>
Huh, i managed it to work. Here is what is necessery if someone have similar problem.
Part for adding header values:
$soap = new SoapClient($wsdl, $options);
$auth = array(
'userName' => self::SOAP_USERNAME,
'password' => self::SOAP_PASSWORD,
);
$header = new SoapHeader(self::SOAP_NAMESPACE, 'SecurityContext', $auth);
$soap->__setSoapHeaders($header);
Also, because it's https request I needed to add some ssl options:
// set stream context opts
$opts = array(
"ssl" => array(
"verify_peer" => false,
"verify_peer_name" => false,
),
);
// set options
$options = array(
'encoding' => 'UTF-8',
'soap_version' => SOAP_1_2,
'cache_wsdl' => WSDL_CACHE_NONE,
'connection_timeout' => 15,
'login' => self::SOAP_USERNAME,
'password' => self::SOAP_PASSWORD,
'stream_context' => stream_context_create($opts),
);

SOAP Client over HTTPS with SSL certificates on both sides

I have to develop a SOAP Client, and the supplier send me this specifications:
Will be transmited using HTTPS through IP, and will be Packaged as XML documents that adjust to the diferent defnitions of XML scheme.
The Communications is synchronous, the third party should wait for response.
Each request and response will be signed.
I'm using the soapClient class from PHP, and all works fine, except when I try to use my private key to establish communication with the server:
Code: WSDL | Message: SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://remoteserver/CustomerManagementService?wsdl' : failed to load external entity "https://remoteserver/CustomerManagementService?wsdl
Then I tried creating a .pem file, it contains my private key concatenated with my certificate, as I've read in: how to send SOAP request with SSL certificate in PHP?
But it still returns an error:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://remoteserver:80/CustomerManager/proxy/CustomerManagementService?WSDL%2FGWTCommonResources%2Fwsdl%2FGWTCommonMessages' : failed to load external entity "http://remoteserver:80/CustomerManager/proxy/CustomerManagementService?WSDL%2FGWTCommonResources%2Fwsdl%2FGWTCommonMessages
I wonder if there is some way to get exactly the raw data that is being sent by the soapClient class of PHP. And where I must set the certificate of the supplier.
I've already tried with "$client->__getLastRequest()", but I'm getting a NULL. This is my code:
$client = new anotherSoapClient($service, array(
'local_cert' => $pem,
'style' => SOAP_RPC,
'use' => SOAP_ENCODED,
'soap_version' => SOAP_1_2,
'authentication'=> SOAP_AUTHENTICATION_DIGEST,
'ssl' => array(
'ciphers'=> "SHA1",
'verify_peer' => false,
'allow_self_signed' => true
),
'https' => array(
'curl_verify_ssl_peer' => false,
'curl_verify_ssl_host' => false
),
'cache_wsdl' => WSDL_CACHE_NONE,
'cache_ttl' => 86400,
'trace' => true,
'exceptions' => true,
));
// Test connection
echo BR.'Functions: <pre>';var_dump($client->__getFunctions());echo '</pre>';
$XMLrequest = $client->prepareRequest($email);
$response = $client->__anotherRequest('getCustomerInfo', $XMLrequest);
echo "REQUEST:\n" . $client->__getLastRequest() . "\n";
By the way, I'm using PHP 5.4.9 on my local machine and the server have PHP 5.3.10 and anotherSoapClient is a class who extend PHP soapClient class: PHP soapClient send custom XML
For debugging proposals your SOAP request you have to extend the SoapClient class.
class SoapClientDebug extends SoapClient
{
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
// Add code to inspect/dissect/debug/adjust the XML given in $request here
// Uncomment the following line, if you actually want to do the request
// return parent::__doRequest($request, $location, $action, $version, $one_way);
}
}
And next use it in your request:
$client = new SoapClientDebug("x.wsdl");
$response = $client->__soapCall($function);
echo $client->__getLastRequest();
Hope it helps to debug your code!
You probably need to specify following SoalClient options:
$defaultEndpoint = "https://remoteserver/CustomerManagementService";
$uri = "https://remoteserver";
$client = new anotherSoapClient($service, array(
'local_cert' => $pem,
'location' => $defaultEndpoint,
'uri' => $uri,
'style' => SOAP_RPC,
'use' => SOAP_ENCODED,
'soap_version' => SOAP_1_2,
'authentication'=> SOAP_AUTHENTICATION_DIGEST,
'ssl' => array(
'ciphers'=> "SHA1",
'verify_peer' => false,
'allow_self_signed' => true
),
'https' => array(
'curl_verify_ssl_peer' => false,
'curl_verify_ssl_host' => false
),
'cache_wsdl' => WSDL_CACHE_NONE,
'cache_ttl' => 86400,
'trace' => true,
'exceptions' => true,
));

PHP 5.3.6 SoapClient::__doRequest(): SSL: Connection reset by peer

I'm working on consuming a .net web service in php 5.3.6. I'm using SoapClient class to make the connection. It is keep on failing with "SoapClient::__doRequest(): SSL: Connection reset by peer" and "SoapFault Object ( [message:protected] => Error Fetching http headers ".
This is happening only for the Methods/Operations. If i use $response = $objClient->__getFunctions(); and it is working fine and I'm getting the responses with out issue.
$objClient = new SoapClient("http://sample.idws.syndication.kbb.com/3.0/VehicleInformationService.svc?wsdl", array('trace' => 1, 'username' => 'xxxxxxx', 'password' => 'xxxxxxx', 'soap_version' => SOAP_1_2, 'exceptions' => true ));
PHP: php 5.3.6 with ssl soap enabled.
OS: Ubuntu 11.10
i ve been facing a similar issue the past few months.
it turned out afterall that the problem was when i used non-wsdl mode
http://php.net/manual/en/soapclient.soapclient.php
occassionally the remote server wouldn't respond on the request of the location of the wsdl.
initial non-wsdl mode
$soapx = new SoapClient(null,
array(
"trace" => true,
'cache_wsdl' => WSDL_CACHE_NONE,
'location' => 'http://remote_wsdl_url',
'uri' => 'http://necessary_uri',
'use' => SOAP_LITERAL,
'style' => SOAP_DOCUMENT,));
turned to wsdl mode
$soapx = new SoapClient('http://remote_wsdl_url_turned_to_local',
array(
"trace" => true,
'cache_wsdl' => WSDL_CACHE_NONE,));
It seems like there is a problem on the SOAP Server end.
The best online client for debugging SOAP is soapclient
you might give it a try.
I recently came across this due to the same issue. For us the problem was with the SSL protocol being used. We had to force TLS 1.1 and everything started humming along. The key working component for us here is the 'crypto_method'.
$wsdl = 'PATH/TO/WSDL';
$url = 'http://URL_TO_SOAP_SERVICE';
$cert = 'PATH/TO/CLIENT/CERT';
$context = stream_context_create([
'ssl' => [
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT,
'verify_peer' => true,
'verify_peer_name' => true,
'allow_self_signed' => false,
'cafile' => '/path/to/cafile.selfsigned'
]
]);
$params = [
'location' => $url,
'local_cert' => $cert,
'trace' => true,
'exceptions' => true,
'verifypeer' => true,
'verifyhost' => true,
'allow_self_signed' => false,
'connection_timeout' => 180,
'keep_alive' => false,
'stream_context' => $context
];
$client = new SoapClient($wsdl, $params);

Categories