I am working on this legacy system that needs to maintain its SOAP service, and I am currently trying to integrate it with codeigniter, keeps giving me an error XML error parsing SOAP payload on line 70: Reserved XML Name. I have tried the trim solution that someone mention and that did not work. It does not give me this error with normal arrays. Only multidimensional arrays. Any advice would be appreviated
<?php
class Employee_Trainings_Soap extends MY_Controller {
public function __construct() {
parent::__construct();
$this->load->library("Soap_lib");
$this->nusoap_server = new soap_server();
}
public function employee_detail() {
$namespace = 'http://localhost/employee_trainings_soap/employee_detail?wsdl';
$this->nusoap_server->debug_flag = true;
$this->nusoap_server->configureWSDL('EmployeeTrainings', $namespace);
$this->nusoap_server->wsdl->schemaTargetNamespace = $namespace;
$this->nusoap_server->wsdl->addComplexType('response', 'complexType', 'struct', 'all', '', array(
"validOPIN" => array(
"name" => "valid_OPIN",
"type" => "xsd:string"
),
"message" => array(
"name" => "message",
"type" => "xsd:string"
)
));
$this->nusoap_server->wsdl->addComplexType('responses', 'complexType', 'array', '', 'SOAP-ENC:Array', array(), array(
array(
"ref" => "SOAP-ENC:arrayType",
"wsdl:arrayType" => "tns:response[]"
)),
"tns:response"
);
$this->nusoap_server->register('getEmployeeTrainings', array("id" => "xsd:string"), array('test'=>'tns:responses'),
$namespace, $namespace."#getEmployeeTrainings", "rpc", "encoded",
'Use this service to list notaries connected to the signed-in title company.'
);
function getEmployeeTrainings($id) {
$data = array();
$data[] = array('valid_OPIN'=>'test','message'=>'test2');
$data[] = array('valid_OPIN'=>'test','message'=>'test2');
//$data = array('valid_OPIN'=>'test','message'=>'test2');
return array('test'=>$data);
}
$POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
$this->nusoap_server->service($POST_DATA);
}
function live_client_test() {
$this->soapclient = new nusoap_client('http://localhost/employee_trainings_soap/employee_detail');
$err = $this->soapclient->getError();
if ($err) {
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
}
$result = $this->soapclient->call('getEmployeeTrainings', array('id' => 'test'));
if ($this->soapclient->fault) {
echo '<h2>Fault</h2><pre>';
print_r($result);
echo '</pre>';
} else {
$err = $this->soapclient->getError();
if ($err) {
echo '<h2>Error</h2><pre>' . $err . '</pre>';
} else {
// Display the result
echo '<h2>Result</h2><pre>';
print_r($result);
echo '</pre>';
}
}
}
}
So I have found the issue, this may not be the only solution, it is the solution that we found that worked for us. We had to take the SOAP Service out of Code Igniter for it to work. The moment that we took the service outside of Code Igniter, it worked. This may be a bug with code igniter or it could have been with the way we were using it, but as a quick solution it worked. Additionally, we also found it worked better on a Linux dev box compared to an XAMPP dev box. I hope this helps anyone else that might have the same issue.
Related
I am trying to write an SSO plugin for my WordPress multisite and MemberSuite. I'm in the beginning steps, just trying to have the user sign in and get the MemberSuite sign-in token.
Here's the code I have so far:
define("MS_API_URL", "http://rest.membersuite.com/swagger/platform/v2/");
define("TENANT_ID", "00000");
define("USER_POOL", "placeholder");
define("CLIENT_ID", "placeholder");
function send_request() {
$username = $_POST[portalusername];
$password = $_POST[portalpassword];
return ms_sign_in($username, $password, USER_POOL, CLIENT_ID);
}
function ms_sign_in($un, $pw, $up, $cid) {
$url = MS_API_URL . 'storeJWTTokenForUser/' . TENANT_ID;
$data = array(
'username' => $un,
'password' => $pw,
'userPool' => $up,
'clientID' => $cid
);
$arguments = array(
'method' => 'POST',
'headers' => array(
'Content-Type' => 'application/json',
'Accept' => 'application/json'
),
'body' => json_encode($data)
);
echo "before post";
$response = wp_remote_post($url, $arguments);
echo "after post";
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
echo "Something went wrong: $error_message";
}
echo $response;
echo $response['body'];
return $response['body'];
}
?>
<html>
<body>
<p>body 1</p>
<?php echo send_request();?>
<p>body 2</p>
</body>
</html>
My form calls the send_request() function. As far as I can tell, I've implemented everything the way the MemberSuite documentation indicates it should be implemented. I've included all the necessary values for verification.
However, it appears execution just stops when I reach the line that says $response = wp_remote_post($url, $arguments);. The output displays:
body 1
before post
but nothing else. I'd like to know why this happening, if there is any way to fix it, and/or if there is a different way I should go about making the POST request.
I'm really stuck on this one. At the bottom of this post, I've attached the API documentation I'm working with. I want to catch the "message" when the response ("ask") isn't "Success". Seems reasonable enough, right? But when I do something like:
sfcSendError('Something went wrong. This is the message from the API: ' . $result->message);
I get a fatal error:
PHP Fatal error: Cannot access protected property SoapFault::$message
I found this seemingly related question on SO, so I tried changing "message" to "getMessage()" but (no surprise) that results in a different fatal error about calling an undefined function.
Here's my code snippet:
$client = mySoapClient(MODULE_SHIPPING_SFC_API_URL);
if (!$client) {
sfcSendError('could not make a SOAP connection. Halting until next CRON. [' . __FILE__ . ':' . __LINE__ . ']', 'SOAP Failure in cron job');
exit; //halt and wait for the next time cron runs
} else {
$HeaderRequest = array(
'customerId' => MODULE_SHIPPING_SFC_ACCOUNT,
'appToken' => MODULE_SHIPPING_SFC_TOKEN,
'appKey' => MODULE_SHIPPING_SFC_KEY
);
$reg = array(
'HeaderRequest' => $HeaderRequest,
'detailLevel' => 1,
'ordersCode' => $_query->fields['sfc_ordersCode']
);
$result = $client->getOrderByCode($reg);
if ($result->ask != "Success") {
sfcSendError('Something went wrong. This is the message from SFC: ' . $result->message, 'SOAP Failure in cron job');
$_query->MoveNext();
continue;
}
}
This is the referenced function:
function mySoapClient($url)
{
try {
$client = #new SoapClient($url, array(
'trace' => 1,
'exceptions' => 0,
'encoding' => 'UTF-8'
));
} catch (SoapFault $e) {
return 0;
}
return $client;
}
What am I doing wrong? Or is this a "bug" with the API where they really shouldn't be using "message" in their response?
I am developing a web service with NuSOAP in Laravel 4.
The class that I'm using is https://github.com/noiselabs/NoiselabsNuSOAPBundle.
Server
Route::any('ws/server', function()
{
$server = new \soap_server;
$server->configureWSDL('server.hello','urn:server.hello', Request::url());
$server->wsdl->schemaTargetNamespace = 'urn:server.hello';
$server->register('hello',
array('name' => 'xsd:string'),
array('return' => 'xsd:string'),
'urn:server.hello',
'urn:server.hello#hello',
'rpc',
'encoded',
'Retorna o nome'
);
function hello($name)
{
return 'Hello '.$name;
}
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
return Response::make($server->service($HTTP_RAW_POST_DATA), 200, array('Content-Type' => 'text/xml; charset=ISO-8859-1'));
});
Client
Route::get('ws/client/hello', function()
{
$client = new \nusoap_client('http://localhost/teste_laravel/public/ws/server?wsdl', true);
$err = $client->getError();
if ($err)
{
echo "Erro no construtor<pre>".$err."</pre>";
}
$result = $client->call('hello',array('Renato'));
if ($client->fault)
{
echo "Falha<pre>".print_r($result)."</pre>";
}
else
{
$err = $client->getError();
if ($err)
{
echo "Erro<pre>".print_r($err)."</pre>";
}
else
{
print_r($result);
}
}
});
This error is returned.
Array ( [faultcode] => SOAP-ENV:Client [faultactor] => [faultstring] => error in msg parsing: xml was empty, didn't parse! [detail] => ) Falha 1
When I do with pure PHP server and the client with the right Laravel.
$HTTP_RAW_POST_DATA is not always populated depending on your PHP config (http://www.php.net/manual/en/ini.core.php#ini.always-populate-raw-post-data). You could try this instead:
$rawPostData = file_get_contents("php://input");
I am new to the programming area and this is my first nusoap-0.9.5 client and server program. Although the the server looks correct the client keeps giving me this warning:
PHP Fatal error: SoapClient::SoapClient(): Invalid parameters in /var/www/client.php on line 5
PHP Fatal error: Uncaught SoapFault exception: [Client] SoapClient::SoapClient(): Invalid parameters in /var/www/client.php:5
Stack trace:
#0 /var/www/client.php(5): SoapClient->SoapClient('http://localhos...', true)
#1 {main}
thrown in /var/www/client.php on line 5
Anybody knows the reason? I am trying to find a solution over the net more than a week now and I can not understand what is wrong with my program why it is not working.
Client code:
Thanks again Davey, I have read all the tutorials that you recommend and I am still a bit confused but at least less confused than before. I have modified my code again, I hope it makes more sense now. So here it is:
<?php
include "conf_client.php";
require_once('nusoap.php');
$client = new soapclient('http://localhost:8048/server.php?wsdl',true);
class Data {
public $acro = acro;
public $note = note;
public $prio = prio;
public $date = date;
public function Delete() {
$create = array ($acro,
$date,
$note,
$prio);
return $create;
}// End of Function Delete
}// End of class Data
$data = new Data();
$delete = $data->Delete();
$response = $client->call('Lists.DeleteToDo',$delete);
var_dump($response);
?>
directory: {file:///var/www/server.php}
Any help is much appreciated.
'List.DeleteToDo'
Is the class: List and the Function: DeleteToDo on the side of the server that I am calling.
I manage to find more about my problem and I have solved it. I am posting my server code here maybe it can help also someone else.
As a beginner I have simplified the code as much as possible. I am not including to my answer the configuration file, but if anybody needs it please let me know and I will post it as well.
I would also like to say thank you to everyone who answered my query at this forum and help me understand my errors.
<?php
include "conf.php";
require_once('nusoap/lib/nusoap.php');
$server = new soap_server();
$server->configureWSDL('This is my First nuSoapServer', 'urn:nuSoapServer');
$server->wsdl->addComplexType('Data',
'compexType',
'struct',
'all',
'',
array('id' => array('name' => 'id', 'type' => 'xsd:int'),
'acro' => array('name' => 'acro', 'type' => 'xsd:string'),
'time' => array('name' => 'time', 'type' => 'xsd:string'),
'date' => array('name' => 'date', 'type' => 'xsd:string'),
'note' => array('name' => 'note', 'type' => 'xsd:string'),
'prio' => array('name' => 'prio', 'type' => 'xsd:int'),
'data' => array('name' => 'data', 'type' => 'xsd:string')
)
);
$server->wsdl->addComplexType(
'DataArray', // Name
'complexType', // Type Class
'array', // PHP Type
'', // Compositor
'SOAP-ENC:Array', // Restricted Base
array(), // Elements
array( // Atributes
array('ref' => 'SOAP-ENC:arrayType',
'wsdl:arrayType' => 'tns:Data[]')
),
'tns:Data'
);
$server->register('GetTodoList', // method name
array('acro' => 'xsd:string'), // input parameters
array('DataResult' => 'tns:DataArray'), // output parameters
'urn:nuSoapServer', // namespace($namespace)
'urn:nuSoapServer#GetTodoList', // soap action
'rpc', // style
'encoded', // use
'Return Get to do list'); // documentation
function GetMyConnection() {
global $InputArray;
$dbase_link = mysql_connect($InputArray['host'],$InputArray['mysql_user'],$InputArray['mysql_password']);
//check if connected
if (!$dbase_link) {
die("Can not connect: " . mysql_error());
}
//return $this->myconn;
//http://se1.php.net/manual/en/function.mysql-create-db.php
$dbase_select = mysql_select_db($InputArray['mysql_dbase']);
if (empty($dbase_select)) {
$sql = "CREATE DATABASE IF NOT EXISTS ".$InputArray['mysql_dbase']."\n";
if (mysql_query($sql)) {
echo "Database: " . $InputArray['mysql_dbase'] . " was created succesfully\n";
}
else {
echo "Error creating database: " . mysql_error() . "\n";
}
}
$dbase_select = mysql_select_db($InputArray['mysql_dbase']);
$sql = "CREATE TABLE IF NOT EXISTS ".$InputArray['mysql_dbase_table']." (
`id` int(11) NOT NULL AUTO_INCREMENT,
`acro` varchar(25) NOT NULL,
`time` varchar(25) NOT NULL,
`date` varchar(25) NOT NULL,
`note` varchar(1024) NOT NULL,
`prio` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1";
$create = mysql_query($sql);
if (!$create) {
echo "Error creating table: " . mysql_error() . "\n";
}
}// End of Function GetMyConnection
function closeConnection() {
$terminate = mysql_close();
if ($terminate) {
echo "Connection terminated\n";
}
else {
echo "Error terminating connection: " . mysql_error() . "\n";
}
}//End of function closeConnection
// create the function
function GetTodoList($acro) {
global $InputArray;
GetMyConnection();
if (!$acro) {
return new soap_fault('Client', '', 'No data received!');
}
else {
$dbase_select = mysql_select_db($InputArray['mysql_dbase']);
$get = mysql_query("SELECT * FROM " . $InputArray['mysql_dbase_table'] . " WHERE `acro` = '" . $acro . "'");
if($get === FALSE) {
echo "Could not retrieve data from: " . $InputArray['mysql_dbase_table'] . " due to: " . mysql_error() . "\n";
}
else {
while($total = mysql_fetch_array($get)) {
$Data[] = array('id' => $total['id'],
'acro' => $total['acro'],
'time' => $total['time'],
'date' => $total['date'],
'note' => $total['note'],
'prio' => $total['prio']);
}
}
}
return $Data;
closeConnection();
}
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
exit();
?>
Your URL for the SOAP is trying to access a local file path rather than a URL
If you open the URL you've specified in a browser you should get back a (possibly large) chunk of XML. I can almost guarantee that you would get nothing apart from a 404 error
For the SOAP connection you have to use the URL specified by the webserver rather than a local file path (unless you replace http:// with file:/// - that may work).
If your webserver exposes a URL (e.g., http://localmachine) and the WSDL is hosted in a subfolder (e.g., soapstuff) then the URL you would need to enter into the $client=new soapclient line would be something like http://localmachine/soapstuff?wsdl
I am going crazy starting off with Web Services. I am trying to call the following WSDL using PHP and keep getting nowhere:
http://webservices.sabre.com/wsdl/sabreXML1.0.00/usg/SessionCreateRQ.wsdl
I found the following piece of code on the net, from someone with similar problems, but I could not get it to work either:
$soap = new SoapClient('http://webservices.sabre.com/wsdl/sabreXML1.0.00/usg/SessionCreateRQ.wsdl',
array(
'trace' => true,
'soap_version' => SOAP_1_2,
"exceptions" => 0));
$eb = new EbXmlMessage();
$sec = new Security();
$scrq = new SessionCreateRQ();
try {
$omg = $soap->SessionCreateRQ($scrq, $sec,$eb);
}
catch (Exception $e)
{
print_r($e);
}
//debug
print "Request: \n".
htmlspecialchars($soap->__getLastRequestHeaders()) ."\n";
print "Request: \n".
htmlspecialchars($soap->__getLastRequest()) ."\n";
print "Response: \n".
$soap->__getLastResponseHeaders()."\n";
print "Response: \n".
$soap->__getLastResponse()."\n";
print_r($omg);
//the first envelope headers
class EbXmlMessage
{
public $From = array('PartyId' => 'mysite.com');
public $To = array('PartyId' => 'myprovider.com');
public $CPAId = 'ZZZZ';
public $ConversationId = 'myconv#id.com';
public $Service = 'Session';// or SessionCreate?
public $Action = 'SessionCreateRQ';
public $MessageData = array(
'MessageId' => 'messageid',
'Timestamp' => '2009-04-18T15:15:00Z');
}
//the security token
class Security {
public $Username = "xxxxx";
public $Password = "yyyyy";
public $Organization = "ZZZZ";
public $Domain = "DEFAULT";
}
//this is suppoused to be the payload, or the xml i need to send at the end
class SessionCreateRQ
{
public $POS = array(
'Source' => array(
'_'=>"",
'PseudoCityCode'=>'ZZZZ'
));
}
I keep getting the following error:
Response:
HTTP/1.1 500 Internal Server Error
SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Date: Sun, 19 Apr 2009 22:21:34 GMT
Connection: close
Server: SWS
Response:
soap-env:Client.InvalidEbXmlMessageUnable to internalize
messagejavax.xml.soap.SOAPException: Unable to internalize message at
com.sun.xml.messaging.saaj.soap.MessageImpl.(MessageImpl.java:135)
at
com.sun.xml.messaging.saaj.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:32)
at
com.sabre.universalservices.gateway.control.SoapProcessor.getRequest(SoapProcessor.java:263)
at
com.sabre.universalservices.gateway.control.WSGateway.handleRequest(WSGateway.java:380)
at
com.sabre.universalservices.gateway.control.WSGateway.doPost(WSGateway.java:306)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710) at
javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
at
org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:852)
at
org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:584)
at
org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1508)
at java.lang.Thread.run(Thread.java:595) Caused by:
javax.xml.soap.SOAPException: Invalid
Content-Type:application/soap+xml at
com.sun.xml.messaging.saaj.soap.MessageImpl.verify(MessageImpl.java:159)
at
com.sun.xml.messaging.saaj.soap.MessageImpl.(MessageImpl.java:91)
... 19 more
SoapFault Object (
[message:protected] => Unable to internalize message
[string:private] => .....
This service should be validating me on the system and returning a security object to be used in later calls - a string(?) which I can then store in a session variable for the following calls.
Any help GREATLY appreciated!!!
One thing I noticed is that there is a faultcode value in the SoapFault Object:
[faultcode] => soap-env:Client.InvalidEbXmlMessage
So that may be a useful avenue to start debugging.
I tried comparing the structure of your EbXmlMessage to the XSD and the schema documentation, but I couldn't see any obvious reason that it was declared invalid.
Have you tried changing the Content-type header to text/xml?
Try using wsdl2php. It makes php classes out of the wsdl file. It uses php's SoapClient to send the data.
Here is a nice post explaining how to do it:
http://itworkarounds.blogspot.com/2011/10/simple-soap-client-with-wsdl2php-using.html
Just use nuSOAP. I don't like PHP native SoapClient. nuSoap generates for you a wsdl so you don't have to worry about how to make one.. Here's nuSOAP and here's a simple example code or you can download whole working code here :
Server :
<?php
// include the SOAP classes
require_once('nuSOAP/lib/nusoap.php');
function HelloWorld(){
return 'HelloWorld'; // Returns HelloWorld string
}
function Hello($name){
return 'Hello '.$name; // Returns Hello with name string parameter
}
// create the server object
$server = new nusoap_server();
// Initialize WSDL support
$server->configureWSDL('webservicenamespace', 'urn:webservicenamespace');
$server->register('HelloWorld', array(), array('result' => 'xsd:string')); //xsd:string; xsd:boolean; xsd:integer and so on..
$server->register('Hello', array('name' => 'xsd:string'), array('result' => 'xsd:string')); // array('parametername' => 'parametertype'),array('result' => 'returntype');
if (isset($error))
{
$fault =
$server->fault('soap:Server','',$error);
}
// send the result as a SOAP response over HTTP $HTTP_RAW_POST_DATA
$post = file_get_contents('php://input');
$server->service($post);
?>
Client :
<?php
// Pull in the NuSOAP code
require_once('nuSOAP/lib/nusoap.php');
// Create the client instance
$client = new nusoap_client('http://pathtourl/sample_webservice.php?wsdl', true);
// Check for an error
$err = $client->getError();
if ($err) {
// Display the error
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
// At this point, you know the call that follows will fail
}
// Call the SOAP method
$result = $client->call('Hello', array('name' => 'Scott')); // Call function name, parameters;
// Check for a fault
if ($client->fault) {
echo '<h2>Fault</h2><pre>';
print_r($result);
echo '</pre>';
} else {
// Check for errors
$err = $client->getError();
if ($err) {
// Display the error
echo '<h2>Error</h2><pre>' . $err . '</pre>';
} else {
// Display the result
echo '<h2>Result</h2><pre>';
print_r($result);
echo '</pre>';
}
}
// Display the request and response
echo '<h2>Request</h2>';
echo '<pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2>';
echo '<pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
// Display the debug messages
echo '<h2>Debug</h2>';
echo '<pre>' . htmlspecialchars($client->debug_str, ENT_QUOTES) . '</pre>';
?>
Now when you want to make a client you need your wsdl you can simply get it by adding ?wsdl on your link i.e( webservice.php?wsdl )
Hope this helps :) Good luck with your web service.