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
Related
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.
Having problems connecting with the Twitter API through ZendService/Twitter/Twitter.
Error: Fatal error: Call to a member function connect() on a non-object in somepath/vendor/zendframework/zendframework/library/Zend/Http/Client.php on line 1358
$config = array (
'access_token' => array (
'token' => 'dummy',
'secret' => 'dummy'
),
'oauth_options' => array (
'consumerKey' => 'dummy',
'consumerSecret' => 'dummy'
),
'http_client_options' => array (
'adapter' => 'Zend\Http\Client\Adapter\Curl',
'curloptions' => array (
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_SSL_VERIFYPEER => false
)
)
);
$twitter = new Twitter ( $config );
print_r ($twitter->account->verifyCredentials ());
Using curl 7.26.0 (x86_64-pc-linux-gnu) OpenSSL/1.0.1e
PHP 5.4.35 on ZF 2.3.3
Update 1: Removing the access_token section returns an "Bad Authentication data" message. Enabling it again, will throw the atal error: Call to a member function connect() on a non-object in somepath/vendor/zendframework/zendframework/library/Zend/Http/Client.php on line 1358
Twitter allows only SSL connections in Twitter API endpoints. This detail is documented here. So, you need to set your adapter options to meet the SSL protocol requirements.
Try this:
'http_client_options' => array (
'adapter' => 'Zend\Http\Client\Adapter\Curl',
'curloptions' => array (
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => '/path/to/certs/ca-bundle.pem'
)
),
When verifying a remote host, you need to provide one or more certificates of trusted CAs. The value 2 for VERIFYHOST option is required to checking the existence of a common name and also verifies that it matches the hostname provided. Use 1 for only check existence of name in the SSL peer certificate.
You may also want to read more about configuring SSL connections using Curl adapter in this nice tutorial.
I was working with older version of OpenSSL(OpenSSL 0.9.8o) and I was forced to use newer OpenSSL 1.0.1e-fips as the result I was unable to connect to WSDL:
Message: SoapClient::SoapClient(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
I need to disable SSL certification check, I tried:
$client = new SoapClient("https://IP:443/sdk/vimService?wsdl",
array(
"trace" => 1,
"location" => "https://IP:443/sdk/",
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true,
)
)
)
)
);
`
And it throw:
Message: SoapClient::SoapClient(): Peer certificate CN=localhost.localdom' did not match expected CN=SAME IP AS IN SoapClient()'
Then I added 'peer_name'=> 'localhost.localdom', in stream_context and then it says XML file is empty:
Fatal error: Uncaught SoapFault exception: [Client] looks like we got no XML document
PHP 5.5
Okey, I was able to found issue.
You can avoid this mess using stable PHP 5.5 version
Recently I learned that error: "looks like we got no XML document" is caused because of PHP version - PHP 5.6 in 5.5 working like a charm.
How to fix it in PHP 5.6
1) Remove SSL certificate check in PHP 5.6:
In 5.6 version SSL certification was enabled by default, so if you want to disabled it you must pass context stream:
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)
2) Deleted ?wsdl and added .wsdl instead (with ?wsdl, it didn't worke for me)
<?php
$client = new SoapClient("https://IP:443/sdk/vimService.wsdl",
array(
"trace" => 1,
"location" => "https://IP:443/sdk/",
'exceptions' => 1,
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)
)
);
$soapmsg["_this"] = array( "_" => "ServiceInstance", "type" => "ServiceInstance");
$result = $client->RetrieveServiceContent($soapmsg);
$ServiceContent = $result->returnval;
$soapmsg = NULL;
$soapmsg["_this"] = $ServiceContent->sessionManager;
$soapmsg["userName"] = "USERNAME";
$soapmsg["password"] = "PASSWORD";
$result = $client->Login($soapmsg);
$UserSession = $result->returnval;
echo "User, " . $UserSession->userName . ", successfully logged in!\n";
$soapmsg = NULL;
$soapmsg["_this"] = $ServiceContent->sessionManager;
$result = $client->Logout($soapmsg);
In my case stream_context_create didn't worked.
So I download this file here : https://curl.haxx.se/ca/cacert.pem
and placed it in my localhost as : F:\xampp\apache\cert.pem
and gave the same path for
openssl.cafile=F:\xampp\apache\cert.pem in my phpini
This made the localhost to acquire certificate and things worked great...!!
Posting this in case this may help some one going through my situation.
In my case was needed to add the crypt_method
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => true,
'verify_peer_name' => true,
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
)
)
)
In my case "stream_context" did the magic, i've just added the code :
`"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)`
i have a problem with running methods with SOAP. I'm using Apache and PHP.
this is the PHP code:
$opts = array(
'ssl' => array('ciphers'=>'RC4-SHA')
);
ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);
$client = new SoapClient('https://host?wsdl', array (
'stream_context' => stream_context_create($opts),
"trace" => 1,
"exceptions" => 0,
"connection_timeout"=>2000));
var_dump($client->__getFunctions());
$params = array ("key" => "value");
$result = $client->availabeFunction($params);
var_dump($result);
The __getFunctions() It returns me all of the available functions.
Then when i'm trying to call the the available function with parameters.
It returns me a strage error message:
public 'faultstring' => string 'Could not connect to host' (length=25)
public 'faultcode' => string 'HTTP' (length=4)
So i presume it is for some reasons are connecting to through the HTTP, but not through HTTPS.
I've looked up the web, and in some cases they are using a local_cert value with a .pem file.
It it neccecity to have it? Or i'm missing something else?
It's an openssl library bug.
At first try to disable SSL check by adding this params
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)
And next try to not use ?wsdl in location link, try use something like
.wsdl
The solution was much easier as i thoguht it will be:
ini_set('soap.wsdl_cache_enabled',0);
ini_set('soap.wsdl_cache_ttl',0);
$location = 'https://host';
$client = new SoapClient($location . '?wsdl', array (
"trace" => 1,
"exceptions" => 0,
"connection_timeout"=>2000,
"location"=>$location // <- this was the reqiured parameter
));
Everything else is same as before.
This beeing cause by WSDL file configuration, that instead of https URL, it has http.
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 );