I'm using the following code to send an request to a SOAP service:
header('Content-type: application/xml');
function doXMLCurl($url,$postXML){
$CURL = curl_init();
curl_setopt($CURL, CURLOPT_URL, $url);
curl_setopt($CURL, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($CURL, CURLOPT_POST, 1);
curl_setopt($CURL, CURLOPT_POSTFIELDS, $postXML);
curl_setopt($CURL, CURLOPT_HEADER, false);
curl_setopt($CURL, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($CURL, CURLOPT_HTTPHEADER, array('Accept: text/xml','Content-Type: application/soap+xml'));
curl_setopt($CURL, CURLOPT_RETURNTRANSFER, true);
$xmlResponse = curl_exec($CURL);
return $xmlResponse;
}
$input_xml = '<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">.....</s:Envelope>';
echo doXMLCurl('webservice_url', $input_xml);
The responde is a XML too.
How can i parse this data or convert to an array or object? I tried with simplexml_load_string() but without success.
EDIT
XML 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">...</a:Action>
</s:Header>
<s:Body>
<ListStatesResponse xmlns="http://tempuri.org/">
<ListStatesResult xmlns:b="..." xmlns:i="...">
<b:Return>0</b:Return>
<b:Message i:nil="true"/>
<b:Status>00</b:Status>
<b:ListStates>
<b:States>
<b:Description>ACRE</b:Description>
<b:Code>AC</b:Code>
</b:States>
<b:States>
<b:Description>ALAGOAS</b:Description>
<b:Code>AL</b:Code>
</b:States>
<b:States>
<b:Description>AMAZONAS</b:Description>
<b:Code>AM</b:Code>
</b:States>
...
</b:ListStates>
</ListStatesResult>
</ListStatesResponse>
</s:Body>
</s:Envelope>
Assuming the xml is valid, you can use SimpleXMLElement, i.e.:
$xml = new SimpleXMLElement($xmlResponse);
echo $xml->node->otherNode['Id'];
To loop it, use:
foreach ($xml->node->otherNode as $el) {
foreach($el as $key => $val) {
echo "{$key}: {$val}";
}
}
I found the easiest way is to use json functions
$jsonObject = json_decode(json_encode($xmlString));
Then print_r($jsonObject) to find the structure. This allows attributes to be accessible to using $jsonObject->{'#attributes'}->id;
Related
I find a problem to convert <string xmlns="http://tempuri.org/"> to json in php, I try to look for an example but fail all.
This is my php script:
public function register() {
$url = 'https://example.com/register';
$post_data="Email=frank#email.com";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded; charset=utf-8'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
echo $result;
}
and this is the response :
Please anyone help me to solve this problem.
Thanks
It's a strange idea to send JSON in an XML document, but anyway. Simplest (sensible way) is to load it with SimpleXML and then the JSON is just the text of the root node...
$xml = simplexml_load_string($result);
echo (string)$xml;
should give
[
{
"CreateDate": "123"
}
]
I agree with Nigel's comment that it's strange to embed JSON in XML, but IMO his solution plays a bit fast and loose with the assumed simplicity of the input. Also, DOMDocument and family tend to be a lot easier to use as far as PHP's XML libs go.
$in = <<<_E_
<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.com/">[
{
"foo": "bar"
}
]</string>
_E_;
$doc = new DomDocument();
$doc->loadxML($in);
$json = $doc->getElementsByTagName('string')->item(0)->nodeValue;
$decoded = json_decode($json, true);
var_dump($json, $decoded);
Output:
string(24) "[
{
"foo": "bar"
}
]"
array(1) {
[0]=>
array(1) {
["foo"]=>
string(3) "bar"
}
}
https://www.php.net/manual/en/book.dom.php
Finally, I find a solution, like this :
public function register() {
$url = 'https://example.com/register';
$post_data="Email=frank#email.com";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded; charset=utf-8'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
$xml = simplexml_load_string($result,'SimpleXMLElement',LIBXML_NOCDATA);
header('Content-Type: application/json');
$temp = json_decode($xml);
$json = json_encode($temp[0]);
echo $json;
}
and it works;
$curl = curl_init();
$xml_data = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Auth uid=”999999990019” tid=”public” ac=”public” sa=”public” ver=”1.6”txn=”AuthDemoClient:public:20160616070338756” lk=”MBFWjkJHNFfLidl8oOHtUwgL5p1ZjDbWrqsMEVEJLVEDpnlNj_CZTg”>
<Uses pi=”y” pa=”n” pfa=”n” bio=”n” bt=”n” pin=”” otp=”n”/>
<Tkn type=”” value=””/>
<Meta udc=”” fdc=”” idc=”” pip=”” lot=”G|P” lov=””/>
<Skey ci=”” ki=””></Skey>
<Data type=”X|P”>encrypted PID block</Data>
<Hmac>SHA-256 Hash of Pid block, encrypted and then encoded</Hmac
<Signature>Digital signature of AUA</Signature>
</Auth>
</xml>';
curl_setopt($curl, CURLOPT_URL,"http://auth.uidai.gov.in/1.6/public/9/9/MH4hSkrev2h_Feu0lBRC8NI-iqzT299_qPSSstOFbNFTwWrie29ThDo");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml','Content-Length:length'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $xml_data);
$result = curl_exec($curl);
curl_close($curl);
print_r($result);
This is the sample code which I wrote.Needs test data for some of the left out attributes like udc,fdc,idc etc. When I try to fire this API gets 400-Bad Request.Help would be appriciated.
Hi Can anyone explain me in implementing below SOAP XML in PHP, I saw some questions they were handled using CURL but I want to use SoapClient library in PHP Can anyone help me.
I saw some people used below code in PHP get the simple SOAP , How can I implement the same way in my code
<?php
//Create the client object
$soapclient = new SoapClient('http://www.example.com:8080/test/services/test?wsdl');
//Use the functions of the client, the params of the function are in
//the associative array
$params = array(
'locationID' => '19087525238255',
'custFirstName' => 'Seure',
'custLastName' => 'Install',
'customerType' => 'RESI'
);
$response = $soapclient->octService($params);
var_dump($response);
?>
SOAP XML
<soapenv:Envelope xmlns:soapenv = "http://schemas.xmlsoap.org/soap/envelope/" xmlns:com = "http://test.com/">
<soapenv:Header/>
<soapenv:Body>
<com:OCTService>
<locationID>19087525238255</locationID>
<customer>
<custFirstName>JOHN</custFirstName>
<custLastName>ADAM</custLastName>
<customerType>RESI</customerType>
</customer>
<order>
<orderScheduleType>NoSchedule</orderScheduleType>
<orderScheduledate/>
<reasonCode>NT</reasonCode>
<salesRep>0001</salesRep>
</order>
<Equipments>
<equipment>
<serialNumber>*</serialNumber>
<type>N</type>
</equipment>
<equipment>
<serialNumber>*</serialNumber>
<type>NH</type>
</equipment>
<equipment>
<serialNumber>*</serialNumber>
<type>NH</type>
</equipment>
</Equipments>
<csgServiceCodes>
<CSGServiceCode>
<rateCode>SR002</rateCode>
<packageCode/>
</CSGServiceCode>
<CSGServiceCode>
<rateCode>BA</rateCode>
<packageCode/>
</CSGServiceCode>
</csgServiceCodes>
<voiceFeatures>
<nativeNumbersCount>0</nativeNumbersCount>
<portedNmbers>?</portedNmbers>
</voiceFeatures>
<HuntGroup>
<huntGroupType>?</huntGroupType>
</HuntGroup>
</com:OCTService>
</soapenv:Body>
</soapenv:Envelope>
I not able to achieve using CURL POST.
Here important thing is SOAPAction which you can use in the WSDL document
$headers = array(
"Accept-Encoding: gzip,deflate",
"Content-Type: text",
"Cache-Control: no-cache",
"Username: yourusername",
"Password: password",
"SOAPAction: urn:OCTService",
"Content-length: ".strlen($xml_post_string),
); //SOAPAction: your op URL
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
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); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
// converting
$response = curl_exec($ch);
echo $response;
curl_close($ch);
// converting
$response1 = str_replace("<soap:Body>","",$response);
$response2 = str_replace("</soap:Body>","",$response1);
// convertingc to XML
$parser = simplexml_load_string($response2);
When I try to POST this XML document to Blackboard Learn LIS using PHP cURL I get this error. I'm checking the XML with simplexml to ensure it is well formed, so that's not the issue. I have also checked the XML document to ensure there is no BOM data attached. I've opened it in a Hex editor to ensure this.
I'm completely stumped on this one and I don't have access to the Blackboard logs.
PHP:
include("xml/envelope.php");
//sanity check to see if xml is well formed
$sxml = simplexml_load_string($xml);
$xml = $sxml->asXML();
$xml_length = strlen($xml);
$url = $this->lis_outcome_service_url;
$bodyHash = base64_encode(sha1($xml, TRUE)); // build oauth_body_hash
$consumer = new OAuthConsumer($key, $secret);
$request = OAuthRequest::from_consumer_and_token($consumer, '', 'POST', $url, array('oauth_body_hash' => $bodyHash) );
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, '');
$header = $request->to_header() . "Content-Type: application/xml\r\nContent-Length: $xml_length\r\n"; // add content type header
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array($header));
//curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POST, 1);
//curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
//curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
$output .= "$url<br><br>$output<pre>$header\n\n".htmlspecialchars($xml)."</pre><p>ERRORS?: ".curl_error($ch);
curl_close($ch);// "<p>Saved grade: "+var_export($output)+"</p>";
return $output;
The XML in envelope.php:
<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<imsx_POXEnvelopeRequest xmlns="http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0">
<imsx_POXHeader>
<imsx_POXRequestHeaderInfo>
<imsx_version>V1.0</imsx_version>
<imsx_messageIdentifier>$id</imsx_messageIdentifier>
</imsx_POXRequestHeaderInfo>
</imsx_POXHeader>
<imsx_POXBody>
<replaceResultRequest>
<resultRecord>
<sourcedGUID>
<sourcedId>$this->lis_result_sourcedid</sourcedId>
</sourcedGUID>
<result>
<resultScore>
<language>en-us</language>
<textString>0.7</textString>
</resultScore>
</result>
</resultRecord>
</replaceResultRequest>
</imsx_POXBody>
</imsx_POXEnvelopeRequest>
XML;
?>
The XML output in browser after parsing (during cURL request):
<?xml version="1.0" encoding="UTF-8"?>
<imsx_POXEnvelopeRequest xmlns="http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0">
<imsx_POXHeader>
<imsx_POXRequestHeaderInfo>
<imsx_version>V1.0</imsx_version>
<imsx_messageIdentifier>53e4657ec1499</imsx_messageIdentifier>
</imsx_POXRequestHeaderInfo>
</imsx_POXHeader>
<imsx_POXBody>
<replaceResultRequest>
<resultRecord>
<sourcedGUID>
<sourcedId>bbgc15659375gi290156</sourcedId>
</sourcedGUID>
<result>
<resultScore>
<language>en-us</language>
<textString>0.7</textString>
</resultScore>
</result>
</resultRecord>
</replaceResultRequest>
</imsx_POXBody>
</imsx_POXEnvelopeRequest>
Since there is so little detailed information on how to do this in LTI, I've posted my solution below. This is a duplicate of my addition to Blackboard's EduGarage forums, but to get it into the public domain I've put it here. I hope it helps other people trying to implement LTI tools.
Here is how to pass back a grade using PHP cURL, the contents of the envelope.php file shouldfollow the XML found in the IMS Global Documentation found here. The cURL request constructs the header and then adds the XML body below it.
Note that the envelope.php file contains the $xml variable in the following format (you will obviously need to add your own $id and set a grade with a variable etc...):
PHP code for passing grade using cURL:
include("xml/envelope.php");
$xml_length = strlen($xml);
$url = $this->lis_outcome_service_url;
$bodyHash = base64_encode(sha1($xml, TRUE)); // build oauth_body_hash
$consumer = new OAuthConsumer($key, $secret);
$request = OAuthRequest::from_consumer_and_token($consumer, '', 'POST', $url, array('oauth_body_hash' => $bodyHash) );
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, '');
$header .= $request->to_header(); // add content type header
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("POST http://your-tools-url-here.edu.au HTTP/1.0",
"Content-Length: $xml_length", $header, "Content-Type: application/xml"));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
How would you build a soap request manually? I didn't bother looking for a soap client for php so I am trying to build the requests manually. Here is a sample of the request:
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>
<EWalletLoginCmd xmlns="xxxxxxx">
<ewalleTID>string</ewalleTID>
<PIN>string</PIN>
</EWalletLoginCmd>
</soap12:Body>
</soap12:Envelope>
I made a function for sending the request like:
private function send($url, $xml) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: application/soap+xml; charset=utf-8"));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array('xml' => $xml));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return $result;
}
But I am lost on how to actually build the XML, I started with:
$xml = new DOMDocument('1.0', 'UTF-8');
$body = $xml->createElement('body');
$xml->appendChild($body);
return $xml->saveXML();
But how do you specifiy <soap12:? I am new to soap and xml on php.
PHP has the SoapClient class built in for using SOAP.
if your SOAP server has a wsdl try
$wsdl= 'location of your servers wsdl';
$options = array('soap_version'=>SOAP_1_2, 'trace'=>true);
$client = new SoapClient($wsdl, $options);
then you can call any method on your client like
$results = $client->EWalletLoginCmd(array('ewalleTID'=>'...', 'PIN'=>'...'));