Reputation: 1344
I need to post to a client's URL (in case it matters the client is on a .Net platform) using SOAP and XML. The request needs to look something like this:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:XXX="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX" xmlns:XXX1="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.Admin"> <soap:Header/> <soap:Body>
<tem:SaveXXXStatus>
<!--Optional:-->
<tem:req>
<!--Optional:-->
<XXX:AWBNumber>69184678146</XXX:AWBNumber>
<!--Optional:-->
… etc. …
<!--Optional:-->
<XXX:pincode></XXX:pincode>
</tem:req>
<!--Optional:-->
<tem:profile>
<!--Optional:-->
<XXX1:Api_type>S</XXX1:Api_type>
<!--Optional:-->
<XXX1:Area></XXX1:Area>
<!--Optional:-->
<XXX1:LicenceKey>xxxxxxxxxxxxxxxxxxx</XXX1:LicenceKey>
<!--Optional:-->
<XXX1:LoginID>XXXYYY</XXX1:LoginID>
<!--Optional:-->
<XXX1:Version>1</XXX1:Version>
</tem:profile>
</tem:SaveXXXStatus> </soap:Body> </soap:Envelope>
I am using the following code:
$ch = curl_init();
//var_dump($ch);
curl_setopt($ch, CURLOPT_URL,"https://example.com?wsdl");
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'tem:"http://tempuri.org/"',
'Content-Type: text/xml',
'XXX:"http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX"'
'XXX1:"http://schemas.datacontract.org/2004/07/XXXAPI.Entities.Admin"'
));
//curl_setopt($ch, CURLOPT_USERPWD, "XXXYYY:xxxxxxxxxxxxx"); //Probably not needed
curl_setopt($ch, CURLOPT_POST, 1);
$strRequest = "";
$strRequest .= "AWBNumber=69184678161";
… etc….
$strRequest .= "&pincode=";
$strRequest .= "&Api_type=S";
$strRequest .= "&Area=";
$strRequest .= "&LicenceKey=xxxxxxxx";
$strRequest .= "&LoginID=XXXYYY";
$strRequest .= "&Version=1";
curl_setopt($ch, CURLOPT_POSTFIELDS,$strRequest);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
var_dump($server_output);
This post shows that the header (envelope etc.) can simply be added to the POSTFIELDS string but I tried that and it didn't work. Besides it seems like such a hack!
Anyway, no combination is working - I am getting a zero length string as a result ($server_output). What is the right way to pass the headers and what else needs to be fixed here?
Upvotes: 0
Views: 383
Reputation: 5119
As I mentioned in the comments already, it would be much easier using the build in PHP SoapClient
class and objects as entities. Here 's a little example, how you could solve your issue.
The PHP Soap Client
PHP got its own build in SoapClient
which works pretty fine. Have a look how to initialize the client for development.
try {
$client = new \SoapClient('https://example.com?wsdl', [
'cache_wsdl' )> WSDL_CACHE_NONE,
'exceptions' => true,
'trace' => true,
]);
} catch (\SoapFault $fault) {
echo "<pre>";
var_dump($fault->getMessage());
echo "</pre>";
if ($client) {
echo "<pre>";
var_dump($client->__getLastRequest(), $client->__getLastResponse());
echo "</pre>";
}
}
This is a simple init of the SoapClient
class with development options. Setting the trace
option to true enables the use of the clients internal functions __getLastRequest()
and __getLastResponse()
. So you can see, what the client has sent and what the response looks like, if there 's any. I 'm using this for checking the xml that the client has sent.
Simple entities as objects that can be used by soap
SOAP defines itself as complex and simple type definitions. You can see this, if you call the clients own __getTypes()
function. There will be displayed a lot of structs and simple type definitions, which are stored in the given wsdl file or in xsd files mentioned in the wsdl file. With this informations we are able to build our own object. In this example I 'm using simple stdClass
objects. In production manner, you should use computed own objects.
$req = new \stdClass();
$req->AWBNumber = new \SoapVar(
69184678146,
XSD_INT,
null,
null,
'AWBNumber',
'http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX'
);
$encodedReq = new \SoapVar($req, SOAP_ENC_OBJECT, null, null, 'req', 'http://tempuri.org/');
$saveXXXStatus = new \stdClass();
$saveXXXStatus->req = $encodedReq;
$encodedSaveXXXStatus = new \SoapVar($saveXXXStatus, SOAP_ENC_OBJECT, null, null, 'SaveXXXStatus, 'http://tempuri.org/');
// send the content with the soap client
$result = $client->SaveXXXStatus($encodedSaveXXXStatus);
Please keep in mind, that this is a short example which is incomplete and will lead to a soap fault. But what I 've done here? The req node in your xml is an object. You 'll find the definition of this object in the above metioned __getTypes()
function output. In this example I 've compiled this object as a stdClass
with the property AWBNumber
. The AWBNumber
itself is a SoapVar
object. We use a soap var because of the namespaces, which are used by the soap client. After defining a property we encode the req
object as a soap object, which is also a SoapVar
instance.
After all we call the webservice method SaveXXXStatus
with the encoded parameter.
The Last Request
If you send this example, the last request should look like:
<ns1:envelope xmlns:ns1="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns2="http://tempuri.org/"
xmlns:ns3="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX">
<ns1:body>
<ns2:SaveXXXStatus>
<ns2:req>
<ns3:AWBNumber>69184678146</ns3:AWBNumber>
</ns2:req>
</ns2:SaveXXXStatus>
</ns1:body>
</ns1:envelope>
As I said before, this is just an example. You have to code all the nodes as SoapVar
objects and append it to parents and finally call the webservice method with the complete encoded data.
Simple as pie, hm?
Upvotes: 0
Reputation: 440
i also stuck in this few days ago... but tried this way and got results
$xml_post_string ='<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:XXX="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX" xmlns:XXX1="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.Admin"> <soap:Header/> <soap:Body>
<tem:SaveXXXStatus>
<!--Optional:-->
<tem:req>
<!--Optional:-->
<XXX:AWBNumber>69184678146</XXX:AWBNumber>
<!--Optional:-->
… etc. …
<!--Optional:-->
<XXX:pincode></XXX:pincode>
</tem:req>
<!--Optional:-->
<tem:profile>
<!--Optional:-->
<XXX1:Api_type>S</XXX1:Api_type>
<!--Optional:-->
<XXX1:Area></XXX1:Area>
<!--Optional:-->
<XXX1:LicenceKey>xxxxxxxxxxxxxxxxxxx</XXX1:LicenceKey>
<!--Optional:-->
<XXX1:LoginID>XXXYYY</XXX1:LoginID>
<!--Optional:-->
<XXX1:Version>1</XXX1:Version>
</tem:profile>
</tem:SaveXXXStatus> </soap:Body> </soap:Envelope>';
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: url",
"Content-length: " . strlen($xml_post_string),
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_URL, 'yoururl');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
print_r($response);
Upvotes: 1