I can't get this to work. I've read a bunch on it on the forum already but I just can't seem to find the solution to this.
I've created a SOAP call and it's working etc., but when I try to pass the same parameters multiple times it just overwrites itself which is logical.
The code has to be done with objects only so I've used stdClass()
Example of the code below:
$relationCreate = new stdClass();
$relationCreate->credentials = new stdClass();
$relationCreate->credentials->ApiKey = ''; //Removed for security reasons.
$relationCreate->credentials->DatabaseId = ''; //Removed for security reasons.;
$relationCreate->credentials->UserId = ''; //Removed for security reasons.;
$relationCreate->parentRelationId = $company;
$relationCreate->relationEntityTypeId = "84a15869-5b88-49df-ad47-7b6f9648ae07";
//surname
$relationCreate->relationFieldValues = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData->Id = "9d549512-dc8a-4774-84d1-27a349e8a8c7";
$relationCreate->relationFieldValues->PvFieldValueData->Value = $name;
// This one has to repeat which does not work. Which is logical
$relationCreate->relationFieldValues = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData = new stdClass();
$relationCreate->relationFieldValues->PvFieldValueData->Id = "9d549512-dc8a-4774-84d1-27a349e8a8c7";
$relationCreate->relationFieldValues->PvFieldValueData->Value = $name;
The soap should look as followed I tested this using SoapUI:
<api:fieldValues>
<!--Zero or more repetitions:-->
<api:PvFieldValueData>
<api:Id>c2fcb464-92e6-4227-8672-56f88e219279</api:Id>
<!--Optional:-->
<api:Value>Test</api:Value>
</api:PvFieldValueData>
</api:fieldValues>
<api:fieldValues>
<!--Zero or more repetitions:-->
<api:PvFieldValueData>
<api:Id>d900fe23-8549-451c-82f4-c5918cb3abbb</api:Id>
<!--Optional:-->
<api:Value>Test</api:Value>
</api:PvFieldValueData>
</api:fieldValues>
WSDL file for reference: https://api.perfectview.nl/V1/perfectview.asmx?WSDL
References:
PHP SoapClient - Multiple attributes with the same key
SoapClient: how to pass multiple elements with same name?
You can try to put the items into an array.
Example:
$relationCreate->relationFieldValues = [];
// repeat this in a foreach loop:
$item = new stdClass();
$item->PvFieldValueData = new stdClass();
$item->PvFieldValueData->Id = $uuid;
$item->PvFieldValueData->Value = $name;
// Add item to values
$relationCreate->relationFieldValues[] = $item;
Related
I'm trying to make a web-service request (WSDL).
$s = new soapclient("http://www.wb-service-address.com",array('wsdl'));
$HotelInfo = new stdClass;
<HotelInfo softwareID="123" SessionId="153">
<Hotel ID="103" />
</HotelInfo>
$HotelInfo->xmlRequest = $paramsStr;
$result = $s->__call("SubmitXmlString",array($HotelInfo));
$obj_pros = get_object_vars($result);
$hotel_full_xml = $obj_pros['SubmitXmlStringResult'];
$hotel_full_xml = simplexml_load_string($hotel_full_xml);
How the request will look like if i want to wrap the XML with a header?
I need to generate the following XML
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<SOAP-ENV:Body>
<ns1:submitGetHistoryRequest>
<ns1:headers>
<ns1:daterange>
<ns1:period>
<ns1:start>2018-05-08</ns1:start>
<ns1:end>2018-05-08</ns1:end>
</ns1:period>
</ns1:daterange>
</ns1:headers>
<ns1:fields>
<ns1:field>PX_LAST</ns1:field>
</ns1:fields>
<ns1:instruments>
<ns1:instrument>
<ns1:id>US0000000002</ns1:id>
<ns1:yellowkey>Equity</ns1:yellowkey>
<ns1:type>ISIN</ns1:type>
</ns1:instrument>
<ns1:instrument>
<ns1:id>US0000000001</ns1:id>
<ns1:yellowkey>Equity</ns1:yellowkey>
<ns1:type>ISIN</ns1:type>
</ns1:instrument>
</ns1:instruments>
</ns1:submitGetHistoryRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I use PHP 7.1.17 and SoapClient.
I can not pass options to SoapClient, as the instrument key is repeated and PHP's associated array can not have same key twice. I tried constructing object and setting instrument properties as SoapVar, but it generates incorrect XML. Here is code and result:
$options = new \stdClass();
$options->headers = new \stdClass();
$options->headers->daterange = new \stdClass();
$options->headers->daterange->period = new \stdClass();
$options->headers->daterange->period->start = '2018-05-08';
$options->headers->daterange->period->end = '2018-05-08';
$options->fields = new \stdClass();
$options->fields->field = 'PX_LAST';
//first instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000002';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments[] = new \SoapVar(
$instrument,
SOAP_ENC_OBJECT,
'stdClass',
"http://soapinterop.org/xsd",
"instrument"
);
//second instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000001';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments[] = new \SoapVar(
$instrument,
SOAP_ENC_OBJECT,
'stdClass',
"http://soapinterop.org/xsd",
"instrument"
);
<ns1:instruments/> remains empty in resulting XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://services.bloomberg.com/datalicense/dlws/ps/20071001">
<SOAP-ENV:Body>
<ns1:submitGetHistoryRequest>
<ns1:headers>
<ns1:daterange>
<ns1:period>
<ns1:start>2018-05-08</ns1:start>
<ns1:end>2018-05-08</ns1:end>
</ns1:period>
</ns1:daterange>
</ns1:headers>
<ns1:fields>
<ns1:field>PX_LAST</ns1:field>
</ns1:fields>
<ns1:instruments/>
</ns1:submitGetHistoryRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
How can I pass options to SoapClient, to generate XML with repeated instrument keys?
I solved this. Turns out when you pass an ordered array (not associative one) as object's property, as many XML nodes are generated using that property's name, as number of elements in the array. So instead of building SoapVar objects and putting them into instruments[] array, I just assigned array of instruments to instruments as instrument property:
$options->instruments = new \stdClass();
//first instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000002';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments->instrument[] = $instrument;
//second instrument
$instrument = new \stdClass();
$instrument->id = 'US0000000001';
$instrument->type = 'ISIN';
$instrument->yellowkey = 'Equity';
$options->instruments->instrument[] = $instrument;
I build instruments in a foreach loop. Btw converting array to object instead of building stdClass also works fine:
$options->instruments->instrument[] = (object)[
'id' => 'US0000000001',
'type' => 'ISIN',
'yellowkey' => 'Equity'
]
I am trying to consume a PHP Soap service however I seem to have having trouble with a complex/abstract type.
This is the SOAP call generated using SOAP UI :-
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lin="http://llu.webservices.opalonline.co.uk/LineCharacteristicsWS">
<soapenv:Header/>
<soapenv:Body>
<lin:GetLineCharacteristics>
<lin:request>
<!--Optional:-->
<lin:UserCredentials>
<!--Optional:-->
<!--Optional:-->
<lin:Username>testUser</lin:Username>
<lin:Password>testPass</lin:Password><lin:AgentID>1234</lin:AgentID>
</lin:UserCredentials>
<lin:RequestDetails xsi:type="lin:TelephoneNumberRequest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lin:TelephoneNumber>123456789</lin:TelephoneNumber>
</lin:RequestDetails>
<lin:UserConsent>Yes</lin:UserConsent>
<lin:ServiceType>MPF</lin:ServiceType>
</lin:request>
</lin:GetLineCharacteristics>
</soapenv:Body>
</soapenv:Envelope>
Here is my PHP code :-
$call = new StdClass();
$call->request = new StdClass();
$call->request->UserConsent = "Yes";
$call->request->ServiceType = "MPF";
$call->request->UserCredentials = new StdClass();
$call->request->UserCredentials->Username="testUser";
$call->request->UserCredentials->Password="testPass";
$call->request->UserCredentials->AgentID=1234;
$call->request->RequestDetails = new StdClass();
$call->request->RequestDetails->TelephoneNumber = "123456789";
$url = "https://llu.webservices.opalonline.co.uk/LineCharacteristicsWSV6/LineCharacteristicsWS.asmx?wsdl";
$client = new SoapClient($url, array('trace' => 1, exceptions=> 1,'soap_version' => SOAP_1_1));
$result = $client->GetLineCharacteristics($call);
echo $client->__getLastRequest();
echo $client->__getLastResponse();
When I run the code, the following error is generated :-
Fatal error: Uncaught SoapFault exception: [soap:Client] Server was unable to read request. ---> There is an error in XML document (2, 382). ---> The specified type is abstract: name='RequestType', namespace='http://llu.webservices.opalonline.co.uk/LineCharacteristicsWS', at http://llu.webservices.opalonline.co.uk/LineCharacteristicsWS'>. in /Users/jamesormerod/NetBeansProjects/fpdfDev/TestClass.php:23
Can anyone help?
To be able to send the request well formed with correct type and namespace, you must use both classes named as the required elements and a classmap that maps the elements to the classes.
The WsdlToPhp project can help you generate the classes and the classmap. You can use the project at wsdltophp.com.
Then if for example you generate the package with the name LineCharacteristics, you'll be able to send the request using this sample code:
$lineCharacteristicsServiceGet = new LineCharacteristicsServiceGet();
// sample call for LineCharacteristicsServiceGet::GetLineCharacteristics()
$details = new LineCharacteristicsStructTelephoneNumberRequest('+3363136363636');
$request = new LineCharacteristicsStructGetLineCharacteristicsRequest($details, LineCharacteristicsEnumUserConsentEnum::VALUE_YES, LineCharacteristicsEnumServiceTypeEnum::VALUE_MPF);
$userCredentials = new LineCharacteristicsStructCredentials(11111,'********','********');
$request->setUserCredentials($userCredentials);
$characteristics = new LineCharacteristicsStructGetLineCharacteristics($request);
$r = $lineCharacteristicsServiceGet->GetLineCharacteristics($characteristics);
echo implode("\r\n", array($lineCharacteristicsServiceGet->getLastRequestHeaders(),$lineCharacteristicsServiceGet->getLastRequest(),$lineCharacteristicsServiceGet->getLastResponseHeaders(),$lineCharacteristicsServiceGet->getLastResponse()));
if($r)
print_r($lineCharacteristicsServiceGet->getResult());
else
print_r($lineCharacteristicsServiceGet->getLastError());
The problem is that I cannot succeed to send an array of class through SOAP to a specific web service that I cannot change his structure.
Here below you'll see the schema of the Soap function:
http://www.elyotech.com/share/yoni/forum/developpeznet-soap.jpg
Here you'll find the code I'm corresponding to it:
$s = new soapclient($URL_WEBSERVICE,array('wsdl'=>true,"trace"=>true));
$params = new stdClass();
$params->loginInfo = new stdClass();
$params->loginInfo->UserName = 'username';
$params->loginInfo->Password = 'password';
$params->loginInfo->LanguageCode = 'en';
$params->reservation = new stdClass();
$params->reservation->EmailRecipient2 = 'yonia#yopmail.com';
$params->reservation->EmailRecipient3 = 'yonia2#yopmail.com';
$params->reservation->FirstName = 'Yoni'
foreach($extras as $id=>$extra)
{
$params->Extras[$id]= new stdClass();
$params->Extras[$id]->SelectedExtra = new stdClass();
$params->Extras[$id]->ExtensionData = new stdClass();
$params->Extras[$id]->SelectedExtra->Amount = 1;
$params->Extras[$id]->SelectedExtra->ID = $extra;
}
Here is the SOAP request that is sent:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/">
<SOAP-ENV:Body>
<ns1:CreateReservation>
<ns1:loginInfo>
<ns1:UserName>monusername</ns1:UserName>
<ns1:Password>monpass</ns1:Password>
<ns1:LanguageCode>en</ns1:LanguageCode>
</ns1:loginInfo>
<ns1:reservation>
<ns1:EmailRecipient2>yonia#yopmail.com</ns1:EmailRecipient2>
<ns1:EmailRecipient3>yonia2#yopmail.com</ns1:EmailRecipient3>
<ns1:FirstName>Yoni</ns1:FirstName>
</ns1:reservation>
</ns1:CreateReservation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In this Soap request, I cannot find the Extras array of objects.
Do you have any idea of how I should create my object in order to send it correctly?
A web service return Xml of format
<string>
<NewDataSet>
<DealBlotter>
<CustomerReference>161403239</CustomerReference>
<Symbol>EUR/USD</Symbol>
<BuySell>S</BuySell>
<ContractValue>-100000</ContractValue>
<Price>1.35070</Price>
<CounterValue>-135070</CounterValue>
<TradeDate>2011-01-20 22:05:21.690</TradeDate>
<ConfirmationNumber>78967117</ConfirmationNumber>
<Status>C</Status>
<lTID>111913820</lTID>
</DealBlotter>
</NewDataSet>
</string>
Now i am using curl to access this and then -
$xml = simplexml_load_string($result);
$dom = new DOMDOcument();
// Load your XML as a string
$dom->loadXML($xml);
// Create new XPath object
$xpath = new DOMXpath($dom);
$res = $xpath->query("/NewDataSet/DealBlotter");
foreach($res as $node)
{
print "i went inside foreach";
$custref = ($node->getElementsByTagName("CustomerReference")->item(0)->nodeValue);
print $custref;
$ccy = ($node->getElementsByTagName("Symbol")->item(0)->nodeValue);
print $ccy;
$type = ($node->getElementsByTagName("BuySell")->item(0)->nodeValue);
$lots = ($node->getElementsByTagName("ContractValue")->item(0)->nodeValue);
$price = ($node->getElementsByTagName("Price")->item(0)->nodeValue);
$confnumber = ($node->getElementsByTagName("ConfirmationNumber")->item(0)->nodeValue);
$status = ($node->getElementsByTagName("Status")->item(0)->nodeValue);
$ltid = ($node->getElementsByTagName("lTID")->item(0)->nodeValue);
$time = ($node->getElementsByTagName("TradeDate")->item(0)->nodeValue);
}
But nothing is getting printed. except the dummy statement.
using $res = $xpath->query("/string/NewDataSet/DealBlotter"); did not help. Also a print_r($res); gives output as DOMNodeList obect.
Doing this also does not print anything
$objDOM = new DOMDocument();
$objDOM->load($result);
$note = $objDOM->getElementsByTagName("DealBlotter");
foreach( $note as $value )
{
print "hello";
$tasks = $value->getElementsByTagName("Symbol");
$task = (string)$tasks->item(0)->nodeValue;
$details = $value->getElementsByTagName("Status");
$detail = (string)$details->item(0)->nodeValue;
print "$task :: $detail <br>";
}
There are a few problems.
With how you're loading the xml. Get rid of the simplexml line. It's not needed, and is messing things up. Instead just do $dom->loadXml($result);. There's no reason to load SimpleXML first if you're going to pass it directly into DomDocument.
With your query, the / operator is the direct decendent operator. So it means directly next to. So your first tag should be the root. So either add the root onto it:
$res = $xpath->query("/string/NewDataSet/DealBlotter");
Or make the leading slash into // which selects any matching decendent:
$res = $xpath->query("//NewDataSet/DealBlotter");
And finally, doing a var_dump on $res isn't going to tell you much. Instead, I like to do var_dump($res->length) since it'll tell you how many matches it has rather than that it's a domnodelist (which you already know)...