Bad request while getting WSDL with SoapClient through proxy in PHP - php

I have two servers : one is used for development and can access to the WEB easily but another one for production which can access to the WEB only using a proxy.
I would like to call a SOAP WEB service from my production server.
So following is the code (the URLs are fake):
$url = 'https://www.webservice.com/soap.php';
$wsdl = 'https://www.webservice.com/soap.php?wsdl';
$client = new SoapClient
(
$wsdl,
array
(
'location' => $url,
'proxy_host' => 'www.myproxy.com',
'proxy_port' => 8080,
)
);
$namespace = 'urn:mynamespace';
$header = array
(
'header1' => 'H1',
'header2' => 'H2',
'header3' => 'H3',
);
$client->__setSoapHeaders(new SoapHeader($namespace, 'myHeader', $header));
$params = array
(
'param1' => 'val1',
'param2' => 'val2',
'param3' => 'val3',
);
$result = $client->method($params);
I run it from my development server and I get the expected result.
Now I run it from my production server and I get :
PHP Warning: SoapClient::SoapClient(https://www.webservice.com/soap.php?wsdl): failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request
PHP Warning: SoapClient::SoapClient(): I/O warning : failed to load external entity "https://www.webservice.com/soap.php?wsdl" in /home/benji/test.php on line 20
PHP Fatal error: SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://www.webservice.com/soap.php?wsdl' : failed to load external entity "https://www.webservice.com/soap.php?wsdl"
When I wget the wsdl from the production server, it's working:
$ https_proxy=www.myproxy.com wget https://www.webservice.com/soap.php?wsdl
--2013-02-22 10:57:40-- https://www.webservice.com/soap.php?wsdl
Resolving www.myproxy.com... 10.0.0.125
Connecting to www.myproxy.com|10.0.0.125|:8080... connected.
Proxy request sent, awaiting response... 200 OK
Length: unspecified [text/xml]
Saving to: `soap.php?wsdl'
[ <=> ] 9 010 --.-K/s in 0,009s
2013-02-22 10:57:40 (980 KB/s) - `soap.php?wsdl' saved [9010]

The following solution solved the described problem for me:
create a new stream context where you also specify your proxy information
for the stream context set option SNI_enabled to false
pass the stream context as new parameter in the options array to the soapclient
$context = stream_context_create(
array(
'ssl' => array(
'SNI_enabled' => false
),
'http' => array(
'proxy' => 'tcp://yourproxy.com:9999'
)
)
);
$soapOptions = array(
'stream_context' => $context
);
$soapClient = new SoapClient( 'wsdl.path', $soapOptions );

Related

"Uncaught SoapFault exception: [WSDL] SOAP-ERROR: WSDL parsing: Could not load" using ZEND SOAP client

I am having trouble accessing a SOAP service.
I'm using the Zend library, and did the following function:
public function boletoApiBB() {
//$token = $this->boletoApiBBOauth();
$client = new ZendSoapClient("https://cobranca.homologa.bb.com.br:7101/Processos/Ws/RegistroCobrancaService.serviceagent?wsdl");
echo " <br> testing <BR>";
echo("<PRE>");
print_r($client->getOptions());
echo " <br> client <BR>";
print_r($client);
echo " <br> functions <BR>";
print_r($client->getFunctions());
echo("</PRE>");
}
The request is returning me the following result
testing
Array
(
[encoding] => UTF-8
[soap_version] => 2
[wsdl] => https://cobranca.homologa.bb.com.br:7101/Processos/Ws/RegistroCobrancaService.serviceagent?wsdl
)
client!
Zend\Soap\Client Object
(
[classmap:protected] =>
[encoding:protected] => UTF-8
[faultExceptions:protected] => Array
(
)
[lastMethod:protected] =>
[permanentSoapInputHeaders:protected] => Array
(
)
[soapClient:protected] =>
[soapInputHeaders:protected] => Array
(
)
[soapOutputHeaders:protected] => Array
(
)
[soapVersion:protected] => 2
[typemap:protected] =>
[wsdl:protected] => https://cobranca.homologa.bb.com.br:7101/Processos/Ws/RegistroCobrancaService.serviceagent?wsdl
[keepAlive:protected] =>
[sslMethod:protected] =>
[connectionTimeout:protected] =>
[localCert:protected] =>
[location:protected] =>
[login:protected] =>
[passphrase:protected] =>
[password:protected] =>
[proxyHost:protected] =>
[proxyLogin:protected] =>
[proxyPassword:protected] =>
[proxyPort:protected] =>
[streamContext:protected] =>
[style:protected] =>
[uri:protected] =>
[use:protected] =>
[userAgent:protected] =>
[cacheWsdl:protected] =>
[compression:protected] =>
[features:protected] =>
)
functions
Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://cobranca.homologa.bb.com.br:7101/Processos/Ws/RegistroCobrancaService.serviceagent?wsdl' : failed to load external entity "https://cobranca.homologa.bb.com.br:7101/Processos/Ws/RegistroCobrancaService.serviceagent?wsdl"
in /var/www/html/vendor/zendframework/zend-soap/src/Client/Common.php:33
Stack trace:
#0 /var/www/html/vendor/zendframework/zend-soap/src/Client/Common.php(33): SoapClient->SoapClient('https://cobranc...', Array)
#1 /var/www/html/vendor/zendframework/zend-soap/src/Client.php(1070): Zend\Soap\Client\Common->__construct(Array, 'https://cobranc...', Array)
#2 /var/www/html/vendor/zendframework/zend-soap/src/Client.php(1245): Zend\Soap\Client->initSoapClientObject()
#3 /var/www/html/vendor/zendframework/zend-soap/src/Client.php(1202): Zend\Soap\Client->getSoapClient()
#4 /var/www/html/global/controllers/boletoControllerGlobal.php(1319): Zend\Soap\Client->getFunctions()
#5 /var/www/html/global/System.php(207 in /var/www/html/vendor/zendframework/zend-soap/src/Client/Common.php on line 33
By reading the SOAP service documentation, there is an OAUTH2 server for authentication. I did the authentication and it returns me a token.
The authentication function:
private function boletoApiBBOauth() {
$client_id = "eyJpZCI6Ijg...";
$secret_key = "eyJpZCI6IjBj...";
$authorization = "Basic ".base64_encode($client_id.":".$secret_key);
$client = new GuzzleHttp\Client();
$response = $client->request('POST', 'https://oauth.hm.bb.com.br/oauth/token',
[
'headers' => [
'authorization' => $authorization
],
'form_params' => [
'grant_type' => "client_credentials",
'scope' => "cobranca.registro-boletos",
]
]
);
$body = $response->getBody();
$resposta = json_decode($body, true);
$token = $resposta["access_token"];
return $token;
}
I send the authentication request to the URL
https://oauth.hm.bb.com.br/oauth/token.
With the token, I have to send the necessary information to the url
https://cobranca.homologa.bb.com.br:7101/registrarBoleto
Following this pattern:
Header
SOAPACTION: registrarBoleto
Authorization:Bearer
aO2TXKd5Mhsg4zpAs3H7ze0YEgk5TdAMeGgIazrsq5TI8EDdAiSryGz/fcGfhMeGgINeLotO+ndhgHVYOsJx87
g==.9iFwrWb9cxwz8i5Jj+YgB+asAn7jJMeGgIHEFtWj4ES503/BUR2fRHNKREAUT22ysR9sMyEoC2FGx/s7B+
wG/P+L6rHxQiMiXAVzUcOj2h0P30QRCWhZwRhp5EulgfnE3Sm5JYal7cXAG3zIP6NehU5Cx5baeiGEbyO2yR
gzyeAiHQ81TTUqOrCxCcRi6XbafVQJdKkwwbecwV5Wggg1cNHz7dZgPXLZdUPm5FDWRIX2+PrRVPrDdC2fgf
oZl2MHunUL6lkaQ9Cg+oPA0Nj9XSKhMeGgIVG3bR8TXgQNkzn02Rl2wJMybEYZXe9yeIjt3PtB9wR/eLNlxZW
OYu8bbDOEvXJ2hz218co3q1KXA7uLhazDgvI8HR9eVpfu7jM39mGLmmwLb15YXpeSg5TVnyE6sdlt5iHdQhI
snucU7qs9ZzsTBcnZk/GZoGqcSdyFoFRIts4+XdgrpRfs9rycZxNG2oNKSdTG0ZDfwo6puBqZeLMZ15MHzx/Zb
x4urjJnVbcsbHoi2iEjch/nHHdpRSDLJmnQni3Ya24rt3HFqnTFQY5TsEL95w0jxLImRxHjb/PK1b5o9+ST/Dfj8k
MsWzaVZGbVqNkpJ7TVkGtbwQgf/kVS4OLrFM6XDJZLNViGtTzKYBIyuUoJahwBcncwRXkwngdcu23qSjbLM
AXcQxYMloZ/jgA3jLGU7Yn
Content-Type: text/xml; charset=uft-8
Payload
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sch="http://www.tibco.com/schemas/bws_registro_cbr/Recursos/XSD/Schema.xsd">
<soapenv:Header/>
<soapenv:Body>
<sch:requisicao>
<sch:numeroConvenio>1014051</sch:numeroConvenio>
<sch:numeroCarteira>17</sch:numeroCarteira>
<sch:numeroVariacaoCarteira>19</sch:numeroVariacaoCarteira>
<sch:codigoModalidadeTitulo>1</sch:codigoModalidadeTitulo>
<sch:dataEmissaoTitulo>01.03.2017</sch:dataEmissaoTitulo>
<sch:dataVencimentoTitulo>21.11.2017</sch:dataVencimentoTitulo>
<sch:valorOriginalTitulo>30000</sch:valorOriginalTitulo>
<sch:codigoTipoDesconto>1</sch:codigoTipoDesconto>
<sch:dataDescontoTitulo>21.11.2016</sch:dataDescontoTitulo>
<sch:percentualDescontoTitulo/>
<sch:valorDescontoTitulo>10</sch:valorDescontoTitulo>
<sch:valorAbatimentoTitulo/>
<sch:quantidadeDiaProtesto>0</sch:quantidadeDiaProtesto>
<sch:codigoTipoJuroMora>0</sch:codigoTipoJuroMora>
<sch:percentualJuroMoraTitulo></sch:percentualJuroMoraTitulo>
<sch:valorJuroMoraTitulo></sch:valorJuroMoraTitulo>
<sch:codigoTipoMulta>2</sch:codigoTipoMulta>
<sch:dataMultaTitulo>22.11.2017</sch:dataMultaTitulo>
<sch:percentualMultaTitulo>10</sch:percentualMultaTitulo>
<sch:valorMultaTitulo></sch:valorMultaTitulo>
<sch:codigoAceiteTitulo>N</sch:codigoAceiteTitulo>
<sch:codigoTipoTitulo>2</sch:codigoTipoTitulo>
<sch:textoDescricaoTipoTitulo>DUPLICATA</sch:textoDescricaoTipoTitulo>
<sch:indicadorPermissaoRecebimentoParcial>N</sch:indicadorPermissaoRecebimentoParcial>
<sch:textoNumeroTituloBeneficiario>987654321987654</sch:textoNumeroTituloBeneficiario>
<sch:textoCampoUtilizacaoBeneficiario/>
<sch:codigoTipoContaCaucao>1</sch:codigoTipoContaCaucao>
<sch:textoNumeroTituloCliente>00010140510000000000</sch:textoNumeroTituloCliente>
<sch:textoMensagemBloquetoOcorrencia>Pagamento disponível até a data de vencimento
</sch:textoMensagemBloquetoOcorrencia>
<sch:codigoTipoInscricaoPagador>2</sch:codigoTipoInscricaoPagador>
<sch:numeroInscricaoPagador>73400584000166</sch:numeroInscricaoPagador>
<sch:nomePagador>MERCADO ANDREAZA DE MACEDO</sch:nomePagador>
<sch:textoEnderecoPagador>RUA SEM NOME</sch:textoEnderecoPagador>
<sch:numeroCepPagador>12345678</sch:numeroCepPagador>
<sch:nomeMunicipioPagador>BRASILIA</sch:nomeMunicipioPagador>
<sch:nomeBairroPagador>SIA</sch:nomeBairroPagador>
<sch:siglaUfPagador>DF</sch:siglaUfPagador>
<sch:textoNumeroTelefonePagador>45619988</sch:textoNumeroTelefonePagador>
<sch:codigoTipoInscricaoAvalista/>
<sch:numeroInscricaoAvalista/>
<sch:nomeAvalistaTitulo/>
<sch:codigoChaveUsuario>1</sch:codigoChaveUsuario>
<sch:codigoTipoCanalSolicitacao>5</sch:codigoTipoCanalSolicitacao>
</sch:requisicao>
</soapenv:Body>
</soapenv:Envelope>
I'm lost in how I should do it.
Could anyone work it out?
You are getting error in the first step of the process, that is fetching the WSDL resource. It's hard to debug this issue but most probable causes are:
the WSDL url is actually not reachable
the server uses not trusted HTTPS certificate
Try getting the WSDL with wget or curl on the same server, ex:
curl -vvv "https://cobranca.homologa.bb.com.br:7101/Processos/Ws/RegistroCobrancaService.serviceagent?wsdl"
For me it returns the error:
SSL certificate problem: self signed certificate in certificate chain
You can either add this self signed certificate to trusted certificates store on your system, or disable SSL verification by setting the proper stream context on the SOAP client with setStreamContext method (I don't know what version of Zend Soap client you are using, so maybe there is no such method in your client):
$client->setStreamContext(
stream_context_create(
[
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
],
]
)
);
Of course the solution with disabling SSL verification is not advised on production system. The service you are connecting to should use valid trusted certificate, nowadays it's free and easy to get one for example from Let's Encrypt.

Uncaught SoapFault exception: [HTTP] Unsupported Media Type when i use SoapClient

So i'm trying to get an appropriate response from the wsdl API but i keep getting the same error
"Unsupported Media type"
$opts = array(
'http' => array(
'user_agent' => 'PHPSoapClient',
'Content-Type' => 'application/soap+xml'
)
);
$ctx = stream_context_create($ctx_opts);
$options = array(
'soap_version'=>'SOAP_1_1',
'stream_context' => $ctx,
'keep_alive' => true
);
$params = array(
'UserId'=>'xxxx',
'Password'=>'xxxx',
'PassKey'=>'xxxxx'
);
$client = new SoapClient('http://bsestarmfdemo.bseindia.com/MFOrderEntry/MFOrder.svc?wsdl',$options);
$response = $client->getPassword($params);
I've tried changing the SOAP version to both SOAP 1.1 and SOAP 1.2 and even use text/xml as my Content-type but that does seem to work either throwing the same error. Any suggestions?
Found the error. it was because i set SOAP 1_2 in quotes when actually it's a predefined constant.

cURL error 58 while trying to access soap webserver

I'm trying to call (via PHP script) a remote (SOAP) webserver over https, it requires a password protected certificate.
I'm using nuSoap for making the call but I always get the following error
nusoap_client: got wsdl error: Getting https://ws-t.pitre.tn.it/wcfrouting/wsdl/Documents.wsdl - HTTP ERROR: cURL ERROR: 58: unable to use client certificate (no key found or wrong pass phrase?)
require_once("../nusoap/lib/nusoap.php");
$pitre_wsdl = "https://ws-t.pitre.tn.it/wcfrouting/wsdl/Documents.wsdl";
$client = new nusoap_client($pitre_wsdl, "wsdl");
$err = $client->getError();
if ($err) {
print("Error");
exit();
}
$client->setCredentials(
"",
"",
"certificate",
array (
"sslcertfile" => "../pitre/cert.p12",
"sslkeyfile" => "../pitre/cert.p12",
"certpassword" => "mypass",
"verifypeer" => FALSE,
"verifyhost" => FALSE
)
);
$result = $client->call(
"GetTemplatesDocuments",
array (
"CodeAdm" => "myCode"
)
);
With the browser I can access the wisdl without problems. I tried the following answer:
cURL with SSL certificates fails: error 58 unable to set private key file
I got the same result.
Am I missing something?
I found the answer, my solution is the following:
I wasn't able to make it work with nu_soap so I switched to SoapClient
Fist of all I had to convert my p12 certificate to pem format using openssl
openssl pkcs12 -in certificato.p12 -out certificato.pem -clcerts
Then I downloaded the CA certificates from here https://curl.haxx.se/docs/caextract.html
Here's my working code
$params->a = "a";
$params->b = "b";
$params->c = "c";
$params->d = "d";
$params->e = "e";
$context = stream_context_create(array (
"ssl" => array (
"verify_peer" => false,
"verify_peer_name" => true,
"local_cert" => getcwd()."\certificato.pem", //complete path is mandatory
"passphrase" => "mypassphrase",
"allow_self_signed" => true
),
"https" => array (
"curl_verify_ssl_peer" => false,
"curl_verify_ssl_host" => false
)
));
$pitre_client = new SoapClient($pitre_wsdl, array (
"trace" => 1,
"exceptions" => true,
"location" => "https://ws-t.pitre.tn.it/wcfrouting/servicerouter.svc",
"cafile" => getcwd()."\cacert.pem", //complete path is mandatory
"stream_context" => $context
));
// the call
$response = $pitre_client->GetTemplatesDocuments(
array (
'request' => $params //request key can be different
)
);
I hope this will help someone facing the same issue

php soapclient wsdl SOAP-ERROR: Parsing WSDL: Couldn't load from

I have googled and looked here in stackoverflow but I have not found a solution to my specific problem. I keep getting the error
SOAP-ERROR: Parsing WSDL: Couldnt load from "https://sampleurl.com/MerchantQueryService.asmx?WSDL" : failed to load external entity "https://sampleurl.com/MerchantQueryService.asmx?WSDL"
I am trying to use a SOAP API with a URL like
https://sampleurl.com/MerchantQueryService.asmx?WSDL
I am running MAMP on my localhost and using godaddy shared hosting, I have tried on both with the wsdl file can be found here
http://clemdemo.com/test.wsdl
In PHP I use the code below
error_reporting(-1);
ini_set('display_errors', 'On');
ini_set('soap.wsdl_cache_enabled', 0);
echo "<pre>";
try {
$url = "https://sampleurl.com/MerchantQueryService.asmx?WSDL ";
$headers = [
'Host: sampleurl.com',
'Connection: Keep-Alive',
'User-Agent: PHP-SOAP/5.3.29',
'Content-Type: text/xml; charset=utf-8',
'SOAPAction: "RequestTransaction"',
'Content-Length: 409'];
$rq = [
"userName" => "username_here",
"passWord" => "password_here",
"referenceId" => "3455566694",
"msisdn" => "346774313"];
try {
$cient = new SoapClient($url,
[
'soap_version' => SOAP_1_2,
'exceptions' => 1,
'cache_wsdl' => WSDL_CACHE_NONE,
'trace' => 1,
'stream_context' => stream_context_create(array('http' => array('header' => $headers)))
]);
print_r($cient);
} catch (SoapFault $e) {
echo "\nFault Code: ".$e->faultcode;
echo "\nFault String: ".$e->faultstring;
}
On my MAMP localhost i have SOAP,openssl and curl.
ALSO, I tried using (sending request) to the API with an online WSDL http://wsdlbrowser.com it WORKS but on code using PHP it fails
It often happens that providers neglect their SSL certificates and hence the sites and services end up having an invalid certificates - I suspect this is the case here.
Disabling the certificate validation as described by Kaii here or even better get your provider to fix their certificate.
Your code could/should then be something like:
$url = "https://sampleurl.com/MerchantQueryService.asmx?WSDL ";
$context = stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
));
$rq = ["userName" => "username_here",
"passWord" => "password_here",
"referenceId" => "3455566694",
"msisdn" => "346774313"];
$service = new SoapClient($url, array('stream_context' => $context));
$service->RequestTransaction($rq);
The error message appears to say that your app is not able to read our WSDL. Try opening a browser from the same machine on which your app is running and see if you can access the WSDL address at https://sampleurl.com/MerchantQueryService.asmx?WSDL.
If not - you have a network/firewall/Anti Virus problem. (in case)
If you can access this address from a browser - is your app still experiencing this problem? then check any app that could be hindering your firewall.(Anti virus are most probable cause)
If you use docker there is a chance you get error because of OpenSSL default security level. Even if you disable verify and allow self-signed in SoapClient options.
Try out to 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
By: 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
Better diagnostics can be performed with: libxml_get_last_error();
Could have cached a bad response, set 'cache_wsdl' => WSDL_CACHE_NONE when initating the object
if you skip cache, and get this in your libxml error:
LibXMLError Object
(
[level] => 1
[code] => 1549
[column] => 0
[message] => failed to load external entity "URL"
[file] =>
[line] => 0
)
With no description on Ubuntu, then its not pulling the file period. You just got hit with the Ubuntu update. Wave them the bronx salute and reboot.

Uncaught SoapFault exception: [HTTP] Proxy Authentication Required

Using the php Soapclient I got the exception:
Uncaught SoapFault exception: [HTTP] Proxy Authentication Required
But when using a web browser with the same proxy set up, without specifying any credentials for that proxy, I can connect getting a XML response.
The system department ensures that there is no need for authenticate. Also I'm using the SoapUI just configuring the proxy for testing porpouses, without credentials again, and I can call the methods in the WS.
Why is the php SoapClient throwing that exception? Here is the code I'm using...
$this->client = new SoapClient( null, array(
'location' => 'http://www.xxxxx.dev',
'uri' => self::URI,
'proxy_host' => self::PROXY_HOST,
'proxy_port' => self::PROXY_PORT,
) );
Following solve the exception
$this->client = SoapClient( self::URL , array(
'proxy_host' => self::PROXY_HOST,
'proxy_port' => self::PROXY_PORT,
'authentication' => SOAP_AUTHENTICATION_BASIC,
'stream_context' => stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => false
)
))
));
Misunderstood with the documentation, "URI of the WSDL file or NULL if working in non-WSDL mode" and I was expecting first parameter as a file, not an URL. In some of the attempts I already tried but forgetting to set up the stream context with the SSL parameter to skip peer verification. ( probably SOAP_AUTHENTICATION_BASIC isn't necessary )
Hope it helps someone

Categories