SOAP request in PHP in CURL - php

It's have been already several days since I'm trying to figure out SOAP but no success :( Any chance to know how can I create PHP(curl) SOAP request to look like this?
POST /WebServices/domain.asmx HTTP/1.1
Host: webservices.domain.ru
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.domain.ru/GetVariants"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<AuthentificationHeader xmlns="http://www.domain.ru/">
<Login>string</Login>
<Password>string</Password>
<PartnerId>string</PartnerId>
</AuthentificationHeader>
</soap:Header>
<soap:Body>
<GetVariants xmlns="http://www.domain.ru/">
<RequestParameters>xml</RequestParameters>
</GetVariants>
</soap:Body>
</soap:Envelope>
Also I have following data:
WSDL:
http://webservices.domain.ru/WebServices/domainXml.asmx?WSDL
Soap action:
http://webservices.domain.ru/WebServices/domainXml.asmx?op=GetVariants

Basically:
PHP's support for SOAP just sucks.
You need to use your WSDL to generate your PHP classes, so you can build a Request object.
You will get something like this:
class SomeClass
{
var $name; //NCName
}
class SomeOtherClass
{
var $value; //anonymous2
}
.
.
.
There are some WSDL to PHP scripts out there. (Google wsdl to php)
Then you do something like this.
$soapClient = new SoapClient($this->_wsdlUrl, array(
'trace' => true,
'exceptions' => true,
'uri' => $this->_endPoint,
'location' => $this->_endPoint,
'local_cert' => $this->certificatePath,
'allow_self_signed' => true,
'soap_version' => SOAP_1_2,
));
// Build the SOAP client object, with your properties.
//After that, you have to call:
$yourContainerObject = new YourContainerObject(); // The top SOAP XML node
$yourContainerObject->SomeChildNode = new SomeChildNode();
$yourContainerObject->SomeChildNode->Name = 'John';
.
.
.
$soapResponse = $soapClient->GetVariants($yourContainerObject);
print_r(soapResponse); // to see what you get
The "GetVariants" method doesn't need to be implemented, so you don't get confused and ask yourself where do I get that from.It is described in WSLD and PHP's SOAP client knows that it is just a SOAP action.
This should be an more advanced example of creating SOAP requests via PHP.
I hope you get the basic flow of this.

Related

PHP To Call a SOAP Webservice

i would like some help please.
I am trying to call a webservice using PHP and i am having problems with different kind of messages.
The WSDL is "http://195.144.16.7/ElastrakEDI/ElastrakEDI.asmx?WSDL" and the Web Service is Called GetPartMaster. The username and password at first are both TESTUID and TESTPWD ( for testing purposes ).
The XML Below is the Request
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:edi="http://elastrak.gr/edi/">
<soap:Header>
<edi:AuthHeader>
<!--Optional:-->
<edi:Username>TESTUID</edi:Username>
<!--Optional:-->
<edi:Password>TESTPWD</edi:Password>
</edi:AuthHeader>
</soap:Header>
<soap:Body>
<edi:GetPartMaster/>
</soap:Body>
</soap:Envelope>
This XML is the response
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<AuthHeader xmlns="http://elastrak.gr/edi/">
<Username>TESTUID</Username>
<Password>TESTPWD</Password>
</AuthHeader>
</soap:Header>
<soap:Body>
<GetPartMasterResponse xmlns="http://elastrak.gr/edi/">
<GetPartMasterResult>
<elastrakPartMasterFile xmlns="">
<PartMasterURL>http://195.144.16.7/elastrakEDI/Temp/Parts/OTWKOJL4.txt</PartMasterURL>
<ErrorCode/>
<ErrorDescription/>
</elastrakPartMasterFile>
</GetPartMasterResult>
</GetPartMasterResponse>
</soap:Body>
</soap:Envelope>
I have tried the php code below but still cant get it to work
<?php
$wsdl = 'http://195.144.16.7/ElastrakEDI/ElastrakEDI.asmx?WSDL';
$trace = true;
$exceptions = true;
$xml_array['Username'] = 'TESTUID';
$xml_array['Password'] = 'TESTPWD';
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$client = new SoapClient($wsdl);
$response = $client->GetPartMaster($xml_array);
try
{
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$response = $client->GetPartMaster($xml_array);
}
catch (Exception $e)
{
echo "Error!";
echo $e -> getMessage ();
echo 'Last response: '. $client->__getLastResponse();
}
$response = $response->GetPartMaster->PartMasterURL;
var_dump($response);
?>
Thank you again for your time and Help.
Your request is currently wrongly constructed as you must take into account that therse is actually thow parts in the request:
the SOAP header, containing the username and password
the SOAP body, containing the GetPartMaster element
Take a look to the SoapClient class and the __setSoapHeaders method.
This is why I strongly advise you to use a WSDL to PHP generator to send SOAP Request as it will allow you to easily construct the request and then handle the response while using the OOP approach and not wondering how to send the parameters. Using the generated PHP SDK and a good IDE such as PhpStorm or any Eclipse based IDE with autocompletion, it'll be easy to find your way. Try the PackageGenerator project.

Create Soap Auth request in PHP

I'm new with SOAP and trying to connect it with PHP but without positive results. Maybe you can give me a hand
SOAP 1.2 Request
POST /XXXservice.asmx HTTP/1.1
Host: XXX.prueba.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetAcData xmlns="https://prueba.com/">
<Userid>string</Userid>
<Password>string</Password>
</GetAcData>
</soap12:Body>
</soap12:Envelope>
SOAP 1.2 Response
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetAcDataResponse xmlns="https://prueba.com/">
<XX>xml</GetAcDataResult>
</GetAcDataResponse>
</soap12:Body>
</soap12:Envelope>
I used the following code but I'm getting this message:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://XXX.YYYY.com/XXXservice.asmx' : Premature end of data in tag html line 3
<?php
$options = array(
'Userid' => 'xx',
'Password' => 'xx',
);
$client = new SoapClient("https://XXX.YYYY.com/XXXservice.asmx", $options);
$result = $client('GetAcData');
?>
First of all you need an endpoint url of your webservice, that provides you the wsdl content. As #camelsWrittenInCamelCase has written in his comment, you should try https://XXX.YYYY.com/XXXservice.asmx?wsdl instead of https://XXX.YYYY.com/XXXservice.asmx.
Next you should wrap all your soap client stuff in a try/catch block, to get all possible exceptions and the most informations in case of an error.
try {
$client = new \SoapClient(
'https://XXX.YYYY.com/XXXservice.asmx?wsdl',
[
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'soap_version' => SOAP_1_2,
'trace' => true,
]
);
} catch (\SoapFault $fault) {
echo "<pre>";
var_dump($fault);
echo "</pre>";
echo "<pre>";
var_dump($client->__getLastRequest());
echo "</pre>";
echo "<pre>";
var_dump($client->__getLastResponse());
echo "</pre>";
}
As shown in the example above the soap client is initialized with an options array. We use the trace option, to enable tracing for getting the last send request and response. Additionally wie use the exception option, to force the client to throw exceptions in case of any error. Further more we disable caching the wsdl settings as long as you are developing. If you are going into production, this option should be set to WSDL_CACHE_DISK or WSDL_CACHE_MEMORY.
Now you need to know, which functions and types (complex types) your webservice provides. For this purpose you can do the following.
// getting the functions of your webservice
echo "<pre>";
var_dump( $client->__getFunctions() );
echo "</pre>";
// getting the types of your webservice
echo "<pre>";
var_dump( $client->__getTypes() );
echo "</pre>";
Since I do not know the exact scope of your web service, I'll just assume that the webservice delivers a method called DetAcData with two parameters Userid and Password. With this informations I can only guess, how the right call could look like. For detailed informations I 'd need the output of __getFunctions() and __getTypes().
An examplary call could look like this.
try {
$client = new \SoapClient(
'https://XXX.YYYY.com/XXXservice.asmx?wsdl',
[
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'soap_version' => SOAP_1_2,
'trace' => true,
]
);
$data = new \stdClass();
$data->Userid = 'YourUserId';
$data->Username = 'YourUsername';
$result = $client->GetAcData($data);
// $result will be an object
echo "<pre>";
var_dump($result);
echo "</pre>";
} catch (\SoapFault $fault) {
// error handling
}
Further more you can write data objects for every complex type mentioned in the functions and types output from your webservice. You can add a classmap to the options array when instantiating your soap client, so that every response and request will automatically be parsed in the corresponding data object. How soap client classmaps work is explained in the php documentation.
Just have a try. I 'm sure you will get it on your own. ;)

How to make PHP SOAP Header like this xml snippet?

I'm trying to make a soap header that would look like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<a-user xmlns="a">testName</a-user>
<a-pass xmlns="a">testPassword</a-pass>
</s:Header>
<s:Body>
...
</s:Body>
</s:Envelope>
I'm pretty new to soap so I'm pretty sure I just don't understand what I'm supposed to put in for the parameters of the SoapHeader constructor, this is what I'm currently trying and it keeps failing to authenticate:
$authHeader = new SoapHeader("http://schemas.xmlsoap.org/soap/envelope/", "Envelope", array("Header" => array("a-user" => "testName", "a-pass" => "testPassword")));
Can someone explain how I'm supposed to translate that header from the xml into a php soapheader please?
Edit: Yes, agunn, I'm using a real user name and pass, I get a SoapFault exceptions saying "Vendor not authorized!" when I make my soapCall.
Here's the soap call part included:
$this->client->__setSoapHeaders($authHeader);
$response = $this->client->__soapCall("Foo", $params);
$authHeader = new SoapHeader("http://schemas.xmlsoap.org/soap/envelope/", "Envelope", array("Header" => array("a-user" => "testName", "a-pass" => "testPassword")));
By the SoapClient spec you should try like this
$this->client->__setSoapHeaders(array($authHeader));
$response = $this->client->__soapCall("Foo", $params);

Constructing and sending a Soap XML Request in PHP

I would like to use the ELOIS web service
Webservice interface:
To request pricing (see XML request):
For authentication:
The broker reference
The broker code
The broker password encrypted
The product code to which you wish Pricing
Action (new, update, quote, ...)
For pricing:
The information of the insured
The product-specific information
The reference quote if needed
Syntax Call :
To use the web service via SOAP, the parameters to use is :
Url: http://wsdev.elois.fr/Elois_Call.php
SOAPAction: getTarifs
example of an XML request
:
<auth>
<reference_courtier>ELOIS</reference_courtier>
<code_courtier>001234567</code_courtier>
<mot_de_passe_courtier>5d7a98bddsfg465qdfs0cb1ab4887eae8
</mot_de_passe_courtier>
<action>devispdf</action>
<code_produit>ACCEOPLUS</code_produit>
</auth>
<datas>
<reference_devis>123321</reference_devis>
<civilite1>Madame</civilite1>
<nom1>DUPONT</nom1>
<prenom1>Rosie</prenom1>
<date_naissance1>1970-02-01</date_naissance1>
<adresse1>25, rue Buffon</adresse1>
<code_postal1>75017</code_postal1>
<ville1>Paris</ville1>
<telephone1>06 06 06 06 06</telephone1>
<email1>mail#mail.fr</email1>
<perte_emploi1>non</perte_emploi1>
<dos_psy1>non</dos_psy1>
<chargement1>T30</chargement1>
<profession1>assureur</profession1>
<caution1>emprunteur</caution1>
<franchise1>90</franchise1>
<projet>travaux</projet>
<pret1Montant>100000</pret1Montant>
<pret1Quotite1>100</pret1Quotite1>
<pret1Garantie1>dcptia66</pret1Garantie1>
<pret1Duree>240</pret1Duree>
<pret1DiffAmor>0</pret1DiffAmor>
<pret1Taux>4</pret1Taux>
<pret1TypeTaux>fixe</pret1TypeTaux>
<date_effet>2014-09-25</date_effet>
<typePret1>Amort</typePret1>
</datas>
response returned by the web service
<DEVIS>
<IDENTIF>
<code_courtier>00123456</code_courtier>
<code_produit>ACCEOPLUS</code_produit>
<reference_devis>1234567</reference_devis>
</IDENTIF>
<ERROR>
</ERROR>
<TARIFS>
<pret1>
<montant>500000</montant>
<quotite>100</quotite>
<duree>160</duree>
<DCPTIA>4422.79</DCPTIA>
<ITTIPTIPP>3184.44</ITTIPTIPP>
<PE>0</PE>
<fraisAdhesion>176</fraisAdhesion>
<mensualite>47.5451875</mensualite>
<coutTotal>7607.23</coutTotal>
<tauxAnnuelMoyen>0.1141</tauxAnnuelMoyen>
</pret1>
<pret2>
<montant>120000</montant>
<quotite>100</quotite>
<duree>240</duree>
<DCPTIA>1920</DCPTIA>
<ITTIPTIPP>1280</ITTIPTIPP>
<PE>0</PE>
<fraisAdhesion>176</fraisAdhesion>
<mensualite>14.295833333333</mensualite>
<coutTotal>3431</coutTotal>
<tauxAnnuelMoyen>0.143</tauxAnnuelMoyen>
</pret2>
</TARIFS>
<PDF>
<libelle>DevisACCEOPLUS</libelle>
<url>http://www.elois.fr/modules/acceoplus/tmpdevis/WS145464549475.pdf
</url>
</PDF>
I would like to create a php script that sends a SOAP XML request to web service and receive the response
I tried this script :
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('display_startup_errors', true);
$test = 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd="http://www.w3.org/2001/XMLSchema” xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<auth>
<reference_courtier>ELOIS</reference_courtier>
<code_courtier>001234567</code_courtier>
...
<date_effet>2014-09-25</date_effet>
<typePret1>Amort</typePret1>
</datas>
</soap:Body>
</soap:Envelope>';
//Change this variables.
//$location_URL = 'http://write_your_location_url.asmx';
//$action_URL = 'http://write_your_action_to_perform_url.asmx&#8221';
$location_URL = 'http://wsdev.elois.fr/Elois_Call.php';
$action_URL = 'getTarifs';
$client = new SoapClient(null, array(
'location' => $location_URL,
'uri' => '',
'trace' => 1,
));
try{
$order_return = $client->__doRequest($test,$location_URL,$action_URL,1);
//Get response from here
print_r($order_return);
}catch (SoapFault $exception){
var_dump(get_class($exception));
var_dump($exception);
}
?>
The web service returns me this error :
SOAP-ENV:ClientBad Request

PHP SoapClient: Action mismatch

I am trying to use the PHP SoapClient extension to communicate with an external SOAP server.
This is my code:
$this->_client = new SoapClient(SOAP_TAGGING_URL, array(
'trace' => 1,
'soap_version' => SOAP_1_2,
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'uri' => SOAP_URI,
));
try {
$actionHdr = array();
$actionHdr[] = new SoapHeader(SOAP_TAGGING_URL, 'Action', 'GetMessagesByTagsByGroup');
$this->_client->__setSoapHeaders($actionHdr);
$info = $this->_client->GetMessagesByTagsByGroup(
new SoapParam($this->params['mPID'], 'ParentMessageID'),
new SoapParam($gid, 'GroupId'),
new SoapParam(REQUEST_TOKEN, 'RequestToken'),
new SoapParam(ACCESS_TOKEN, 'AccessToken'),
new SoapParam(ACCESS_TOKEN_SECRET, 'AccessTokenSecret')
);
} catch (SoapFault $fault) {
print("\n<br/>SOAP server returned the following ERROR: ".$fault->faultcode."-".$fault->faultstring);
}
echo "\n<br/>SOAP request: ". htmlentities($this->_client->__getLastRequest());
echo "\n<br/>SOAP response: ". htmlentities($this->_client->__getLastResponse());
This is the response I get (formatting added):
SOAP server returned the following ERROR: s:Sender-The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/ITagging/GetMessagesByTagsByGroup'.
SOAP request:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://tempuri.org/" xmlns:ns2="https://mywebserver.com/myWSDL.svc/ws?wsdl">
<env:Header>
<ns2:Action>GetMessagesByTagsByGroup</ns2:Action>
</env:Header>
<env:Body>
<ns1:GetMessagesByTagsByGroup/>
<GroupId>2178</GroupId>
<RequestToken>odwedwo09i0jACqbbjsw6KnlCA=</RequestToken>
<AccessToken>OlVbHurPJrNrEFR54Y0hV9kI/TZs=</AccessToken>
<AccessTokenSecret>js1kerfe453FLuaXpL 892DY o=</AccessTokenSecret>
</env:Body>
</env:Envelope>
SOAP response:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/fault</a:Action>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Sender</s:Value>
<s:Subcode>
<s:Value>a:ActionMismatch</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/ITagging/GetMessagesByTagsByGroup'. </s:Text>
</s:Reason>
<s:Detail>
<a:ProblemHeaderQName>a:Action</a:ProblemHeaderQName>
</s:Detail>
</s:Fault>
</s:Body>
</s:Envelope>
I thought I added the 'Action' parameter in the header, but clearly that is not the place to put it. Or am I doing something else wrong?
Unfortunately I cannot try NuSoap because I have no control over the server.
Thank you,
gm
It means meant that not only you must specify the HTTP header SOAPAction: "http://www.bla.com:MyAction"
but you need to specify also in the SOAP Envelope the header:
Check these links for some ref:
SOAP ACTION
You're passing it as SoapHeader, but actually it is HTTP header.
The way I found to do it is: http://lt.php.net/manual/en/soapclient.dorequest.php by setting $action parameter.
You'll probably need to extend SoapClient class to do it using less lines of code.

Categories