How to create soap wsdl request template using php - php

this my xml request which i want to create for service.
<soapenv:Header>
<aut:AuthenticationHeader>
<aut:LoginName>John</aut:LoginName>
<aut:Password>Johnpass</aut:Password>
<aut:Culture>en_US</aut:Culture>
<aut:Version>8</aut:Version>
</aut:AuthenticationHeader>
</soapenv:Header>
<soapenv:Body>
<hot:GetCancellationPolicies>
<hot:hotelId>19752</hot:hotelId>
<hot:hotelRoomTypeId>20955</hot:hotelRoomTypeId>
<hot:dtCheckIn>2017-06-25</hot:dtCheckIn>
<hot:dtCheckOut>2017-06-28</hot:dtCheckOut>
</hot:GetCancellationPolicies>
and that is my php code
$p = new stdClass;
$p->request->HotelId = '19752';
$p->request->HotelRoomTypeId = '20955';
$p->request->dtCheckIn = '2017-06-25';
$p->request->dtCheckOut = '2017-06-28';
$quote = $client->GetCancellationPolicies($p);
actually i am getting error.which is mentioned below.
Error Details:
SOAP-ERROR: Encoding: object has no 'nResId' property
i'm new in web services it would be great if someone could help me out of it.

from the wsdl, you should generate the corresponding PHP sdk using a WSDL to php generator such as the PackageGenerator project as you won't wonder how to construct the request, in addition, it'll ease you handling the response as everything is OOP

Related

PHP API Soap Header Authentication

I have a small problem which I can't solve.
I'm trying to connect to a SOAP API (criteo) which works fine with SoapUI.
When I try to replicate the logic in e.g. php I get auth. errors.
I'm pretty sure that the header information are not passed correctly (I tried already several solutions which I found here without any result).
This is the request in SoapUI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v20="https://advertising.criteo.com/API/v201010">
<soapenv:Header>
<v20:apiHeader>
<v20:authToken>12345</v20:authToken>
<v20:appToken>123456</v20:appToken>
</v20:apiHeader>
</soapenv:Header>
<soapenv:Body>
<v20:getReportDownloadUrl>
<v20:jobID>12345</v20:jobID>
</v20:getReportDownloadUrl>
</soapenv:Body>
</soapenv:Envelope>
In php I created the header like that:
/*
* wsdl: https://advertising.criteo.com/API/v201010/AdvertiserService.asmx?WSDL
*/
$authTokens = new stdClass();
$authTokens->authToken = 12345;
$authTokens->appToken = '123456';
$header = new SoapHeader('https://advertising.criteo.com/API/v201010/AdvertiserService.asmx', "apiHeader", $authTokens, true);
$client->__setSoapHeaders(array($header));
print_r($client->getAccount());
When I run the script I'll get an error:
Uncaught SoapFault exception: [soap:Receiver] Server was unable to process request. ---> Unable to cast object of type 'System.Web.Services.Protocols.SoapUnknownHeader' to type 'Criteo.WebService.DataModel.apiHeader'
Can somebody give me a hint ?
Thanks for the help.
Got the same problem. Change namespace value to https://advertising.criteo.com/API/v201010 from https://advertising.criteo.com/API/v201010/AdvertiserService.asmx

wsdl service response once variables are sent, php

I am new to SOAP WSDL FUNCTIONS. I have a client who has been given a wsdl file from a company that deals in car testing. My client is a subcontractor for them. They have told us to upload the information about the car plate, category etc and once the details are sent through,There will be a response from server of either success or failure. Kindly assist in this.
Browsing through different information, I tried to do something like below but it is not working
<?php
$data = array('1'=>'value','2'=>'value','3'=>'value','4'='value','5'=>'value');
$wsdl ='http://181.24.80.32/ws/services/servicename';
$client = new SoapClient($wsdl);
$response = $client->servicenamerequest($data);
echo $response->servicenamereturn;
?>
First of all: Go get SoapUI if you are dealing with an unknown Soap service. SoapUI will read the WSDL file and allow you to look at nearly everything related to Soap methods, parameters, and return values (if you dare to make a call to the live service - hopefully there is a sandbox server that does nothing critical).
But SoapUI can help you there by creating a mock service that receives your request and responds with a canned request that you prepared. Here's how I got from your linked WSDL to a working code example without touching the real service.
Setting up SoapUI
Create a new project in SoapUI and give the location of the WSDL. You might name this project.
SoapUI then reads the contents of the WSDL and creates the project containing all described requests. After that you see what methods the service offers, and what kind of parameters have to go into it, as a tree. Opening this tree will get you to "Request 1" for every method detected, which displays some XML in the free version (paid version is slightly more comfortable with a form to fill) like this (from the vehiclePassedTest method):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tr="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
<soapenv:Header>
<tr:password>?</tr:password>
<tr:username>?</tr:username>
</soapenv:Header>
<soapenv:Body>
<tr:vehiclePassedTest>
<chassisNo>?</chassisNo>
<plateNo>?</plateNo>
<plateCode>?</plateCode>
<plateCategory>?</plateCategory>
<plcEmiCode>?</plcEmiCode>
<currentUserName>?</currentUserName>
</tr:vehiclePassedTest>
</soapenv:Body>
</soapenv:Envelope>
The questionmarks are where you have to provide data. This request structure has to be created by you using the SoapClient of PHP.
Let's mock this. Mocking means that SoapUI starts it's own Soap server that accepts requests. It usually runs on 127.0.0.1:8080. Right-click on the project "PassedVehicleTestService" and select "New MockService". Accept the name, press Ok.
Right-click on the method you want to mock. Select "Add to mock service" and select the created one from the previous step. Answer yes to open the mock response editor. There you see the XML structure of the answer, with question marks for the data that the service will fill out. All the responses from this service allow one answer as a string, so write something nice that will be returned. You can add the other methods to this service later if needed.
Right-click your "MockService 1" and select "Start minimized". This will start the Soap server, it will wait for an incoming request.
Setup PHP SoapClient for the mock.
You need to know two things. First the location of the WSDL. This file contains the address of the real server to be used for the requests, but PHP allows to override this. So the second info you need is the address of the running mock service.
SoapUI displays the address from the WSDL in the request editor. In your case it is http://181.24.80.32/ws/services/PassedVehicleTestService - the mock service runs on http://127.0.0.1:8080/ws/services/PassedVehicleTestService - IP and port is replaced, the path is kept.
This leads to the first lines of PHP code:
$options = array(
'location' => 'http://127.0.0.1:8080/ws/services/PassedVehicleTestService',
);
$client = new SoapClient("http://www.quickregistration.ae/temp/PassedVehicleTestService.xml", $options);
After that you have a configured SoapClient able to talk to your mock service. If later you want to use the real service, throw the line with "location" out of the array, and keep the other config parameters if you happen to add some.
Talk to the mock
With the client, you can do $client->nameOfSoapMethod(paramStructure). The parameter structure usually is a mixture of arrays or objects and scalar values like strings. So that's what I try first:
$result = $client->vehiclePassedTest(array());
var_dump($result);
Then I look at SoapUI to see what happens. Output from the php script:
Notice: Array to string conversion in [...]/soap.php on line 20
string(1) "?"
SoapUI says:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
<SOAP-ENV:Body>
<ns1:vehiclePassedTest>
<chassisNo>Array</chassisNo>
<plateNo/>
<plateCode/>
<plateCategory/>
<plcEmiCode/>
<currentUserName/>
</ns1:vehiclePassedTest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
That was not the right approach. The array got converted into a string "Array", and was placed as the first parameter. The rest is empty. Nice, because I know that soap calls may accept more that one parameter, and this is one of these services.
$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');
This shows up correctly in SoapUI, but the headers are still missing.
Adding SoapHeader to the request
The SoapClient offers a method named __setSoapHeaders(), and there is a class SoapHeader.
The description says that setSoapHeaders() accepts one SoapHeader object or an array of SoapHeader objects. Let's create one, pass it and see what happens:
$username = new SoapHeader();
$client->__setSoapHeaders($username);
$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');
var_dump($result);
PHP says: Warning: SoapHeader::SoapHeader() expects at least 2 parameters, 0 given
$username = new SoapHeader('namespace', 'username', 'MyUserName');
This works. SoapUI says:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService" xmlns:ns2="namespace">
<SOAP-ENV:Header>
<ns2:username>MyUserName</ns2:username>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:vehiclePassedTest><chassisNo>chassisNo</chassisNo><plateNo>plateNo</plateNo><plateCode>plateCode</plateCode><plateCategory>plateCategory</plateCategory><plcEmiCode>plcEmiCode</plcEmiCode><currentUserName>currentUserName</currentUserName></ns1:vehiclePassedTest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Note the TWO xmlns attributes in the SOAP-ENV:Envelope element. The original request requires the username be in the namespace "tr" - but "tr" is only a shortcut to the string that is defined as "xlmns:tr" - the string behind this is your namespace needed (although it might already work with the real service).
$username = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'username', 'myUser');
$password = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'password', 'yetAnotherPassword');
$client->__setSoapHeaders(array($username, $password));
This correctly defines the headers, as you can see:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
<SOAP-ENV:Header>
<ns1:username>myUser</ns1:username>
<ns1:password>yetAnotherPassword</ns1:password>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:vehiclePassedTest><chassisNo>chassisNo</chassisNo><plateNo>plateNo</plateNo><plateCode>plateCode</plateCode><plateCategory>plateCategory</plateCategory><plcEmiCode>plcEmiCode</plcEmiCode><currentUserName>currentUserName</currentUserName></ns1:vehiclePassedTest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
No two namespaces in the envelope element, and every element is of namespace "ns1". This should work.
Your final code:
$options = array(
'location' => 'http://127.0.0.1:8080/ws/services/PassedVehicleTestService',
);
$client = new SoapClient("http://www.quickregistration.ae/temp/PassedVehicleTestService.xml", $options);
$username = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'username', 'myUser');
$password = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'password', 'yetAnotherPassword');
$client->__setSoapHeaders(array($username, $password));
$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');
var_dump($result);
try something like this. Works for me.
try {
$client = new SoapClient("http://wsdl", array('trace' => 1));
$data = $client->someFunction(array('parma1' => 'value1', 'param2' => 'value2'));
print_r($data);
} catch (SoapFault $fault) {
trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_USER_ERROR);
exit();
}
And check is you have installed php-soap package in your server.
Greatings.

Using PHP soap service with Delphi without WSDL?

I'm quite familiar with using web services in Delphi when I have a WSDL. I simply use the wizard and in a few secs I'm up and running.
I now have a challenge where I'm given a soap interface written in PHP, without any WSDL schema.
The sample given to me for PHP is:
<?php
// The xml to be sent to the webService
$reqest_string = <<<XML
<test_api>
<request>1</request>
</test_api>
XML;
// create web service client
$client = new WSClient(array("to" => "http://api.infax.co.za/edge_api.php"));
// send request to the web service
$reply = $client->request($reqest_string);
// display the responce from the webservice
$xml_str = simplexml_load_string($reply->str);
// display response on screen
echo "Came from server = ".$xml_str->response."<br>";
?>
I've tried just post-ing the xml to the url, but I get a soap error back about a function that does not exist.
Any ideas??
For very simple SOAP web services, it could be easier to follow existing examples / documentation or (if neither is good enough) record the interaction using a HTTP proxy (fiddler2), and then code the communciation using a XML library of your choice.

PHP Soap - How to remove xsi:type= from XML tag

I'm sending a SOAP request that looks like:
<SOAP-ENV:Body>
<api:GetOrder xsi:type="SOAP-ENC:Struct">
<api_orderId xsi:type="xsd:int">1234</api_orderId>
</api:GetOrder>
</SOAP-ENV:Body>
But needs to look like this (SoapUI generated):
<soapenv:Body>
<api:GetOrder>
<api:orderId>1234</api:orderId>
</api:GetOrder>
</soapenv:Body>
My PHP Code:
$client = $this->getConnection();
$soap_options = array('soapaction' => $config->getValue('soapaction_url') . 'GetOrder');
$obj = new stdClass();
$obj->api_orderId = 59698;
$results = $client->__soapCall('GetOrder', array(new SoapParam($obj, "api:GetOrder")), $soap_options);
2 questions really:
1) How can I remove the "xsi:type" from the request? (If I add xsi:type in to my SoapUI request, I get back a "400 Bad Request"
2) Instead of "api_orderId" I need to send "api:orderId", but I can't name an object with a colon, so do I have to pass the name and value as an array somehow?
Appreciate any help, thank you.
EDIT:
I wasn't able to figure out any other way to send these requests and I essentially ended up doing as Mr.K suggested below.
I wrote a custom class to extend SoapClient. Then overrode the __doRequest method to send my own custom SOAP request.
The only downside is that SOAP no longer returns me an array of objects, so I also had to parse the XML of the SOAP response.
Also I suspect that the performance of doing it this way is a bit slower, but I didn't notice it.
Try with Simple XML parsing, and create the new request as you like.
Read the tag values from Original request, assign those values to a new XML object using parsing. You can create string of XML message and load it as an XML object in PHP.
Just like get it from there, put it inside this..and Send!..

Set attributes for parameters in SOAP request PHP

I'm trying to use a webservice which only allows SOAP request
as far as I know I must create a request that looks like this
<?xml version="1.0" encoding="utf-8"?>
<SessionCreateRQ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<POS>
<Source PseudoCityCode="SECRET_CODE" />
</POS>
</SessionCreateRQ>
however while adding the parameter to SessionCreateRQ method I don't know how to add the POS parameter called Source and have no clue on how to set the attribute for that parameter
im trying the following in php
$body = array(
'POS' => array('source' => 'PseudoCityCode:SECRET_CODE'));
try
{
$result = $c->SessionCreateRQ($body);
}
but no luck, does anyone has a clue on how should I construct this call properly ?
thanks !
Firstly you need WSDL definition for this service (online or in local file). Any not bad SOAP service provide WSDL to users.
Secondly you need translate WSDL service definition to PHP-code. Try wsdl2php generator. Its generate file with classes, that making calls to web-services.
Your example will be approximately as follows:
require_once 'GeneratedTypes.php';
$client = new SOAPService();
$res = $client->SessionCreateRQ(SECRET_CODE);
p.s. wsdl2php not ideal but it is working :)

Categories