Anyone know how can I post a SOAP Request from PHP?
In my experience, it's not quite that simple. The built-in PHP SOAP client didn't work with the .NET-based SOAP server we had to use. It complained about an invalid schema definition. Even though .NET client worked with that server just fine. By the way, let me claim that SOAP interoperability is a myth.
The next step was NuSOAP. This worked for quite a while. By the way, for God's sake, don't forget to cache WSDL! But even with WSDL cached users complained the damn thing is slow.
Then, we decided to go bare HTTP, assembling the requests and reading the responses with SimpleXMLElemnt, like this:
$request_info = array();
$full_response = #http_post_data(
'http://example.com/OTA_WS.asmx',
$REQUEST_BODY,
array(
'headers' => array(
'Content-Type' => 'text/xml; charset=UTF-8',
'SOAPAction' => 'HotelAvail',
),
'timeout' => 60,
),
$request_info
);
$response_xml = new SimpleXMLElement(strstr($full_response, '<?xml'));
foreach ($response_xml->xpath('//#HotelName') as $HotelName) {
echo strval($HotelName) . "\n";
}
Note that in PHP 5.2 you'll need pecl_http, as far as (surprise-surpise!) there's no HTTP client built in.
Going to bare HTTP gained us over 30% in SOAP request times. And from then on we redirect all the performance complains to the server guys.
In the end, I'd recommend this latter approach, and not because of the performance. I think that, in general, in a dynamic language like PHP there's no benefit from all that WSDL/type-control. You don't need a fancy library to read and write XML, with all that stubs generation and dynamic proxies. Your language is already dynamic, and SimpleXMLElement works just fine, and is so easy to use. Also, you'll have less code, which is always good.
PHP has SOAP support.
Just call
$client = new SoapClient($url);
to connect to the SoapServer and then you can get list of functions and call functions simply by doing...
$client->__getTypes();
$client->__getFunctions();
$result = $client->functionName();
for more http://www.php.net/manual/en/soapclient.soapclient.php
I needed to do many very simple XML requests and after reading #Ivan Krechetov's comment about the speed hit of SOAP, I tried his code and discovered http_post_data() is not built into PHP 5.2. Not really wanting to install it, I tried cURL which is on all my servers. Although I do not know how fast cURL is compared to SOAP, it sure was easy to do what I needed. Below is a sample with cURL for anyone needing it.
$xml_data = '<?xml version="1.0" encoding="UTF-8" ?>
<priceRequest><customerNo>123</customerNo><password>abc</password><skuList><SKU>99999</SKU><lineNumber>1</lineNumber></skuList></priceRequest>';
$URL = "https://test.testserver.com/PriceAvailability";
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml_data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
print_r($output);
We can use the PHP cURL library to generate simple HTTP POST request. The following example shows you how to create a simple SOAP request using cURL.
Create the soap-server.php which write the SOAP request into soap-request.xml in web folder.
We can use the PHP cURL library to generate simple HTTP POST request. The following example shows you how to create a simple SOAP request using cURL.
Create the soap-server.php which write the SOAP request into soap-request.xml in web folder.
<?php
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$f = fopen("./soap-request.xml", "w");
fwrite($f, $HTTP_RAW_POST_DATA);
fclose($f);
?>
The next step is creating the soap-client.php which generate the SOAP request using the cURL library and send it to the soap-server.php URL.
<?php
$soap_request = "<?xml version=\"1.0\"?>\n";
$soap_request .= "<soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">\n";
$soap_request .= " <soap:Body xmlns:m=\"http://www.example.org/stock\">\n";
$soap_request .= " <m:GetStockPrice>\n";
$soap_request .= " <m:StockName>IBM</m:StockName>\n";
$soap_request .= " </m:GetStockPrice>\n";
$soap_request .= " </soap:Body>\n";
$soap_request .= "</soap:Envelope>";
$header = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: \"run\"",
"Content-length: ".strlen($soap_request),
);
$soap_do = curl_init();
curl_setopt($soap_do, CURLOPT_URL, "http://localhost/php-soap-curl/soap-server.php" );
curl_setopt($soap_do, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($soap_do, CURLOPT_TIMEOUT, 10);
curl_setopt($soap_do, CURLOPT_RETURNTRANSFER, true );
curl_setopt($soap_do, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($soap_do, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($soap_do, CURLOPT_POST, true );
curl_setopt($soap_do, CURLOPT_POSTFIELDS, $soap_request);
curl_setopt($soap_do, CURLOPT_HTTPHEADER, $header);
if(curl_exec($soap_do) === false) {
$err = 'Curl error: ' . curl_error($soap_do);
curl_close($soap_do);
print $err;
} else {
curl_close($soap_do);
print 'Operation completed without any errors';
}
?>
Enter the soap-client.php URL in browser to send the SOAP message. If success, Operation completed without any errors will be shown and the soap-request.xml will be created.
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<m:GetStockPrice>
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
Original - http://eureka.ykyuen.info/2011/05/05/php-send-a-soap-request-by-curl/
You might want to look here and here.
A Little code example from the first link:
<?php
// include the SOAP classes
require_once('nusoap.php');
// define parameter array (ISBN number)
$param = array('isbn'=>'0385503954');
// define path to server application
$serverpath ='http://services.xmethods.net:80/soap/servlet/rpcrouter';
//define method namespace
$namespace="urn:xmethods-BNPriceCheck";
// create client object
$client = new soapclient($serverpath);
// make the call
$price = $client->call('getPrice',$param,$namespace);
// if a fault occurred, output error info
if (isset($fault)) {
print "Error: ". $fault;
}
else if ($price == -1) {
print "The book is not in the database.";
} else {
// otherwise output the result
print "The price of book number ". $param[isbn] ." is $". $price;
}
// kill object
unset($client);
?>
Below is a quick example of how to do this (which best explained the matter to me) that I essentially found at this website. That website link also explains WSDL, which is important for working with SOAP services.
However, I don't think the API address they were using in the example below still works, so just switch in one of your own choosing.
$wsdl = 'http://terraservice.net/TerraService.asmx?WSDL';
$trace = true;
$exceptions = false;
$xml_array['placeName'] = 'Pomona';
$xml_array['MaxItems'] = 3;
$xml_array['imagePresence'] = true;
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$response = $client->GetPlaceList($xml_array);
var_dump($response);
If the XML have identities with same name in different levels there is a solution. You don´t have to ever submit a raw XML (this PHP SOAP object don´t allows send a RAW XML), so you have to always translate your XML to a array, like the example below:
$originalXML = "
<xml>
<firstClient>
<name>someone</name>
<adress>R. 1001</adress>
</firstClient>
<secondClient>
<name>another one</name>
<adress></adress>
</secondClient>
</xml>"
//Translate the XML above in a array, like PHP SOAP function requires
$myParams = array('firstClient' => array('name' => 'someone',
'adress' => 'R. 1001'),
'secondClient' => array('name' => 'another one',
'adress' => ''));
$webService = new SoapClient($someURL);
$result = $webService->someWebServiceFunction($myParams);
or
$soapUrl = "http://privpakservices.schenker.nu/package/package_1.3/packageservices.asmx?op=SearchCollectionPoint";
$xml_post_string = '<?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><SearchCollectionPoint xmlns="http://privpakservices.schenker.nu/"><customerID>XXX</customerID><key>XXXXXX-XXXXXX</key><serviceID></serviceID><paramID>0</paramID><address>RiksvŠgen 5</address><postcode>59018</postcode><city>Mantorp</city><maxhits>10</maxhits></SearchCollectionPoint></soap12:Body></soap12:Envelope>';
$headers = array(
"POST /package/package_1.3/packageservices.asmx HTTP/1.1",
"Host: privpakservices.schenker.nu",
"Content-Type: application/soap+xml; charset=utf-8",
"Content-Length: ".strlen($xml_post_string)
);
$url = $soapUrl;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
$response1 = str_replace("<soap:Body>","",$response);
$response2 = str_replace("</soap:Body>","",$response1);
$parser = simplexml_load_string($response2);
Related
I have been trying to figure out how to make a soap request using php/laravel. But from all the research on internet since two days now the only things that I can find are old rusty php codes to make soap requests non of them even worked:
Here is a snipped that I am trying to make it work so I have a general view of those soap requests but I only get errors not able to make a soapclient:
<?php
$aHTTP['http']['header'] = "User-Agent: PHP-SOAP/5.5.11\r\n";
$aHTTP['http']['header'].= "username: XXXXXXXXXXX\r\n"."password: XXXXX\r\n";
$context = stream_context_create($aHTTP);
$client=new SoapClient("http://www.thomas-bayer.com/axis2/services/BLZService?wsdl",array('trace' => 1,"stream_context" => $context));
$result = $client::__getFunctions();
var_dump($result);
since it looks super hard to me to find any info about the soap with php any idea ?
This is a sample of a soap request I currently make to a payment provider via php using curl statements. Basically map the xml request you want to make in a string. The string will be sent in the curl post fields and the response returned.
$soapdata="<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:tns='tns:ns'>
<soapenv:Header>
<tns:CheckOutHeader>
<MERCHANT_ID>$merchantid</MERCHANT_ID>
<PASSWORD>$password</PASSWORD>
<TIMESTAMP>$timestamp</TIMESTAMP>
</tns:CheckOutHeader>
</soapenv:Header>
<soapenv:Body>
<tns:processCheckOutRequest>
<MERCHANT_TRANSACTION_ID>$merchanttransactionid</MERCHANT_TRANSACTION_ID>
<REFERENCE_ID>$referenceid</REFERENCE_ID>
<AMOUNT>$amount</AMOUNT>
<MSISDN>$mobileno</MSISDN>
<!--Optional:-->
<ENC_PARAMS></ENC_PARAMS>
<CALL_BACK_URL>$callbackurl</CALL_BACK_URL>
<CALL_BACK_METHOD>$callbackmethod</CALL_BACK_METHOD>
<TIMESTAMP>$timestamp</TIMESTAMP>
</tns:processCheckOutRequest>
</soapenv:Body>
</soapenv:Envelope>";
//End Soap data
//We call the server for the first time
//end calling function
function makesoaprequest($url, $soapdata)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Authorization: Basic'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "$soapdata");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//Begin SSL
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
//End SSL
$response = curl_exec($ch);
return $response;
curl_close($ch);
}
I'm at a slight loss, havent touched a soap script in forever and looking around stackoverflow and google just confuses the matter more. PHP.net examples seem outdated as well.
The SOAP Request is supposed to POST to a non-WSDL url.
https://some.soapurl.com/provided
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:cam="http://kamp.gw.com/kamp">
<soapenv:Header/>
<soapenv:Body>
<cam:setRolesUpdatedRequest>
<cam:orgCode>username</cam:orgCode>
<cam:password>password</cam:password>
<cam:emails>
<cam:email>abc#dom.com</cam:email>
<cam:email>def#dom.com</cam:email>
<cam:email>ghi#dom.com</cam:email>
</cam:emails>
<cam:updateAllUsers>false</cam:updateAllUsers>
</cam:setRolesUpdatedRequest>
</soapenv:Body>
</soapenv:Envelope>
Just running this snippet returns a 200 OK header, which is good.
try {
$client = new SoapClient("https://abc.kamp.group.com/axis/services/KampService/setRolesUpdated");
}
catch(Exception $e)
{
$e->getMessage();
}
The Response i'm looking to get is supposed to look like
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns1:returnStatus xmlns:ns1="http://kamp.gw.com/kamp">
<ns1:type>S</ns1:type>
<ns1:desc>Successful</ns1:desc>
</ns1:returnStatus>
</soapenv:Body>
</soapenv:Envelope>
EDIT:
I attempted a curl version to post the xml string directly.
$post_string = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cam="http://kamp.gw.com/kamp">
<soapenv:Header/>
<soapenv:Body>
<cam:setRolesUpdatedRequest>
<cam:orgCode>username</cam:orgCode>
<cam:password>password</cam:password>
<cam:emails>
<cam:email>abc#dom.com</cam:email>
<cam:email>def#dom.com</cam:email>
<cam:email>ghi#dom.com</cam:email>
</cam:emails>
<cam:updateAllUsers>false</cam:updateAllUsers>
</cam:setRolesUpdatedRequest>
</soapenv:Body>
</soapenv:Envelope>';
$user = "username";
$password = "password";
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: \"run\"",
"Content-length: ".strlen($xml),
);
$soap_do = curl_init();
curl_setopt($soap_do, CURLOPT_URL, "https://abc.kamp.group.com/axis/services/KampService/setRolesUpdated" );
curl_setopt($soap_do, CURLOPT_CONNECTTIMEOUT, 100000);
curl_setopt($soap_do, CURLOPT_TIMEOUT, 100000);
curl_setopt($soap_do, CURLOPT_RETURNTRANSFER, true );
curl_setopt($soap_do, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($soap_do, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($soap_do, CURLOPT_POST, true );
curl_setopt($soap_do, CURLOPT_POSTFIELDS, $post_string);
curl_setopt($soap_do, CURLOPT_HTTPHEADER, $headers); //array('Content-Type: text/xml; charset=utf-8', 'Content-Length: '.strlen($post_string) )
curl_setopt($soap_do, CURLOPT_USERPWD, $user . ":" . $password);
$result = curl_exec($soap_do);
$err = curl_error($soap_do);
var_dump($result);
echo "<br /><br />";
var_dump($err);
But unfortunately the result is
bool(false)
string(74) "Failed connect to abc.kamp.group.com:443; Connection timed out"
And i'm not certain if that's my fault or the web service's fault. Even though i get connection timed out, the header returned is still 200 Ok.
First check that the SOAP service url and access credentials are working. Use SoapUI or a similar tool to make a request independent of your PHP SoapClient code.
Also check if there are any IP address restrictions in place when making calls and, if so, create / ask for an exception for the IP address you are making requests from.
If everything checks, use php.net SoapClient examples to make simple calls and build your script logic.
<?php
$client = new SoapClient('http://soap.amazon.com/schemas3/AmazonWebServices.wsdl');
var_dump($client->__getFunctions());
?>
Forgot i was behind a proxy, once i pointed curl to the proxy server everything worked out just fine.
I need to send this XML
<?xml version="1.0" encoding="UTF-8"?>
<gate>
<country>NO</country>
<accessNumber>1900</accessNumber>
<senderNumber>1900</senderNumber>
<targetNumber>4792267523</targetNumber>
<price>0</price>
<sms>
<content><![CDATA[This is a test æøå ÆØÅ]]></content>
</sms>
</gate>
to a SMS gateway service. The service listens for HTTP POST requests. The XML must be embedded in the BODY of the POST request.
I'm using PHP and the CodeIgniter framework, but I'm a total PHP n00b, so ideally I'd need a thorough guide, but any pointers in the right direction would be appreciated.
you can use cURL library for posting data:
http://www.php.net/curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_URL, "http://websiteURL");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "XML=".$xmlcontent."&password=".$password."&etc=etc");
$content=curl_exec($ch);
where postfield contains XML you need to send - you will need to name the postfield the API service (Clickatell I guess) expects
Another option would be file_get_contents():
// $xml_str = your xml
// $url = target url
$post_data = array('xml' => $xml_str);
$stream_options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded' . "\r\n",
'content' => http_build_query($post_data)));
$context = stream_context_create($stream_options);
$response = file_get_contents($url, null, $context);
I'm trying to set up a server status for the MMORPG Champions Online. I got some basic information from the web master and this is all he told me:
XML-RPC call to server: http://www.champions-online.com/xmlrpc.php
function name: wgsLauncher.getServerStatus
Parameter (language): en-US
Now, I found a nice example to start with here, and I ended up with this code:
<?php
ini_set('display_errors', 1);
error_reporting(E_ALL);
# Using the XML-RPC extension to format the XML package
$request = xmlrpc_encode_request("wgsLauncher.getServerStatus", "<param><value><string>en-US</string></value></param>", null );
# Using the cURL extension to send it off,
# first creating a custom header block
$header[] = "Host: http://www.champions-online.com:80/";
$header[] = "Content-type: text/xml";
$header[] = "Content-length: ".strlen($request) . "\r\n";
$header[] = $request;
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, "http://www.champions-online.com/xmlrpc.php"); # URL to post to
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); # return into a variable
curl_setopt( $ch, CURLOPT_HTTPHEADER, $header ); # custom headers, see above
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'POST' ); # This POST is special, and uses its specified Content-type
$result = curl_exec( $ch ); # run!
curl_close($ch);
echo $result;
?>
But I'm getting a "400 Bad Request" error. I'm new to XML RPC and I barely know php, so I'm at a loss. The examples from the php site show how to use an array as a parameter, but nothing else.
I obtained the parameter string <param><value><string>en-US</string></value></param> from this XMLRPC Debugger (very nice btw). I entered the parameter I needed in the "payload" box and this was the output.
So, I would appreciate any help on how to pass this parameter to the header.
Note: My host supports xmlrpc but it seems the function "xmlrpc_client" doesn't exist.
Update: The web master replied with this information, but it's still not working... it's getting to the point I may just scrape the status off the page.
$request = xmlrpc_encode_request("wgsLauncher.getServerStatus", "en-US" );
Ok, I finally figured out my answer... It seemed to be a problem in the header, because it worked when I changed the cURL code to match the code I found it on this site. The post is about how to remotely post to wordpress using XMLRPC in php.
This is the code I ended up with:
<?php
// ini_set('display_errors', 1);
// error_reporting(E_ALL);
# Using the XML-RPC extension to format the XML package
$request = xmlrpc_encode_request( "wgsLauncher.getServerStatus", "en-US" );
$ch = curl_init();
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_URL, "http://www.champions-online.com/xmlrpc.php");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
$result = curl_exec($ch);
curl_close($ch);
$method = null;
$params = xmlrpc_decode_request($result, &$method);
# server status result = true (up) or false (down)
$status = ($params['status']) ? 'up' : 'down';
$notice = ($params['notice'] == "") ? "" : "Notice: " + $params['notice'];
echo "Server Status: " . $status . "<br>";
echo $notice;
?>
I need some help with this problem, please.
For days I have been trying now.
The retrieving off feeds and parsing them is not really a problem, but
Uploading data in the form off xml is?
The code below is partially from the google docs samplecode also, but obviously it's not working.
I hope someone else is more into the google api workings, because I have no idea.
Currently, I am only attempting to add a tag to a photo in an album.
Once that works, I can probably do the rest also.
public function postTag() {
$query='smarty';
$this->updateOptie('tag', $query);
$feedUrl = $this->creeerFeedUrl('myalbum', false);
$picasa = $this->parseFeed( $feedUrl );
$gphoto = $picasa['gphoto'][0];
$gphotoid = $gphoto['id'];
//return $gphotoid;
////////////////////sofar no problem//////////////////
$tag = "mytag";
$data = "<entry xmlns='http://www.w3.org/2005/Atom'>
<title>$tag</title>
<category scheme=\"http://schemas.google.com/g/2005#kind\" term=\"http://schemas.google.com/photos/2007#tag\"/>
</entry>";
$albumid = 'myalbum';
$itemsFeedURL = $this->krijgPicasaBasisUrl(). "/albumid/$albumid/photoid/$gphotoid";
$len=strlen($data);
$headers = array(
"Authorization: GoogleLogin auth=" . $this->auth,
"GData-Version: 2",
'Content-Type: application/atom+xml',
"Content-Length: $len",
);
$ch = curl_init(); /* Create a CURL handle. */
/* Set cURL options. */
curl_setopt($ch, CURLOPT_URL, $itemsFeedURL);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt($ch, CURLOPT_POSTFIELDS,$data);
$result = curl_exec($ch); /* Execute the HTTP request. */
$info = curl_getinfo($ch);
curl_close($ch); /* Close the cURL handle. */
return $info;
thanks, rich
Your quoting is broken. The code as you posted in your quesion can't work, because $data contains unescaped double quotes ". You need to escape them all like so: \". If this is that way in the code, that may already be the problem.
Use echo curl_error() after the curl_exec() call to see whether something went wrong during the upload.