PHP Soap Client and .NET Web Service - php

Hi everyone Im trying to consume a .NET with PHP using SoapClient but I got the following issue when my php client send the request, the .NET WS doesnt get the request xml on the right format heres my code i hope some one help me, thanks ind advice
class login {
public $User;
public $Password;
}
$logr = new login;
$logr->User = 'user';
$logr->Password = 'pass';
try {
$client = new soapclient ("http://..../Service.asmx?WSDL", array('classmap' => array('LoginRequest' => 'login'),));
print_r($logr);
$client -> Login ($logr);
}
catch (Exception $e) {
echo "Error!<br />";
echo $e -> getMessage ();
}
when i test my .net webserver on a .net application i send this, and it works well
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2011/XMLScheme">
<soap:Body>
<Login
xmlns="http://tempuri.org">
<LoginRequest>
<User>user</User>
<Password>pass</Password>
</LoginRequest>
</Login
</soap:Body>
</soap:Envelope>
but when i test it on php i get this, and this error Server was unable to process request. ---> Object reference not set to an instance of an object.
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope"
xmlns:ns1="http://tempuri.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<SOAP-ENV:Body>
<Login
xmlns="http://tempuri.com"
xso:type="ns1:LoginRequest">
<User>user</User>
<Password>pass</Password>
</Login>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

class LoginRequest {
public $User;
public $Password;
public function __construct($usr, $pwd) {
$this->User = $usr;
$this->Password = $pwd;
}
}
$login = new LoginRequest('user', 'password');
$client = new SoapClient('http://..../services.asmx?wsdl');
$client->login($login); // try 1
$client->login(array('LoginRequest' => $login)); //try 2

To use a .Net web service, using the NetBeans IDE, add a 'service' and point to the .net web service (make sure to put ?WSDL at the end), and then drag and drop from the 'service's ' toolbox to a php file and it writes the code for you :)
Works great too.
[I can't say what's wrong with your code though]

I recently ran into this issue as well when helping a customer consume our .Net web service so I thought I would share in case anyone else came across this in the future.
Thanks to adudly for providing guidance that helped shed light on the issue. You have to provide a name for the parameter in the array, and note that the name is case sensitive.
Working Code
try {
$wsdl_url = 'http://<mywebserver>/LeadWs.svc?wsdl';
$client = new SOAPClient($wsdl_url);
$params = array(
'lead' => ""
);
$return = $client->Insert2($params);
print_r($return);
} catch (Exception $e) {
echo "Exception occurred: " . $e;
}
My failed attempts used a capital 'L' for Lead. This is apparently the only thing in the WSDLs/XSDs that is lowercase by default. If you do a careful search through the WSDLs/XSDs you will see the exact names of any parameters your method expects. Once you get those right, SoapClient handles the rest of the XML encoding.
My final Code looked like this:
try {
$wsdl_url = 'http://<mywebserver>/LeadWs.svc?wsdl';
$client = new SOAPClient($wsdl_url);
$lead = new Lead(); // Could just be an array as well
// but I created a class to help the user
$lead->FirstName = "Tester";
$lead->LastName = "Test";
$lead->ZipCode = "00000";
$lead->NumberOfTVs = 2;
$params = array('lead' => $lead);
$return = $client->Insert2($params);
print_r($return);
} catch (Exception $e) {
echo "Exception occurred: " . $e;
}
Hope that helps someone in the future.

You can use SoapHeader and setSoapHeaders here

Related

how to call a soap webservice with struct input parameters?

I want to interact with SOAP (as a client) and am not able to get the right syntax for input parameters. I have a WSDL URL that I have tested it with SoapUI and it returns result properly. There are two functions defined in the WSDL, but I only need one ("FirstFunction" below). Here is the script I run to get information on the available functions and types:
$client = new SoapClient("http://example.com/webservices?wsdl");
var_dump($client->__getFunctions());
var_dump($client->__getTypes());
And here is the output it generates:
array(
[0] => "FirstFunction Function1(FirstFunction $parameters)",
[1] => "SecondFunction Function2(SecondFunction $parameters)",
);
struct Amount {
anyURI Identifier;
Information charge;
string referenceCode;
}
struct Information {
string description;
decimal amount;
string code;
}
According to above result I developed my client with nusoap and php as below:
class Information
{
public $description;
public $amount;
public $code;
}
class Amount {
public $Identifier;
public $charge;
public $referenceCode;
}
$charge = new Information();
$charge->description = "ROUTE=XXX|abc=".$code;
$charge->amount = "NULL";
$charge->code = $chargecode;
$params = new Amount();
$params->Identifier =$num;
$params->charge = $charge;
$params->referenceCode = $refcode;
$header = new SoapHeader('key', $key);
$client->__setSoapHeaders($header);
try
{
$res = $client->__call('charge',array('parametrs'=>$params));
print_r($res->return);
}
catch(PDOException $e)
{
print_r($e->getMessage());
}
I get the following error as result:
Uncaught SoapFault exception: [soapenv:Server] unknown
In my opinion the best way to achieve it is to use a WSDL to php generator such as the PackageGenerator project. It abstracts the whole process so you only deal with objects without really worrying about SOAP.

SAP and php SOAP COMMIT

I have created a Webservice from a BAPI in SAP to insert some AccountDocuments into SAP. The system in these cases needs a COMMIT-call after a successful insert call. Both of these functions must be called in "one context".
Now I'm facing the problem that I don't know how to do this in php or if there is any way to do this?
I have created the following example, but it doesn't work. The COMMIT function gets executed but it has no impact in SAP. I cannot see the data in the databases, although the first call returns "Data successfully booked". I know that you must confirm this with the COMMIT call in SAP. In SE37 there is a way to put 2 function calls into one Sequence. I'm searching the php-way to do this.
function insertAccntDoc($accntgl, $currAmount, $docHeader, $accntTax)
{
#Define Authentication
$SOAP_AUTH = array( 'login' => SAPUSER,
'password' => SAPPASSWORD);
$WSDL = "url_to_my_wsdl";
#Create Client Object, download and parse WSDL
$client = new SoapClient($WSDL, $SOAP_AUTH);
#Setup input parameters (SAP Likes to Capitalise the parameter names)
$params = array(
'AccountGl' => $accntgl,
'CurrencyAmount' => $currAmount,
'DocumentHeader' => $docHeader,
'AccountTax' => $accntTax
);
#Call Operation (Function). Catch and display any errors
try
{
$result = $client->AcctngDocumentPost($params);
$result = $client->BapiServiceTransactionCommit();
$result->Gebucht = 'Committed';
if(count($result->Return) > 1)
{
$client->BapiServiceTransactionRollback();
$result->Gebucht = 'Rollback';
}
else if($result->Return->item->Type == 'S')
{
try
{
$client->BapiServiceTransactionCommit();
$result->Gebucht = 'Committed';
}
catch(SoapFault $exception)
{
$client->BapiServiceTransactionRollback();
$result->Fehler = "***Caught Exception***<br>".$exception."<br>***END Exception***<br>";
$result->Gebucht = 'Fehler beim Committen';
}
}
}
catch (SoapFault $exception)
{
$client->BapiServiceTransactionRollback();
$result->Fehler = "***Caught Exception***<br>".$exception."<br>***END Exception***<br>";
$result->Gebucht = 'Fehler beim Anlegen';
}
#Output the results
$result->FlexRet = 'insertAccntDoc';
return $result;
}
Thanks!
This link gives details on how to use "stateful" web services. This is required to have a shared session.
http://scn.sap.com/thread/140909

SOAP Request from PHP is not working

I have a web service available # http://www.xxxxx/zzzzzzzz/service.asmx and I am trying to send a SOAP request for method - some_function with both the parameters but still not able to get the connection through.
This is my code:
<?php
$param = array('cedula'=>'XXXX','contrasena'=>'YYYYYY');
$client = new SoapClient("http://www.xxxxx/zzzzzzzz/service.asmx?wsdl");
$result = $client->__soapCall('some_function', $param);
print $result;
?>
Error that I'm getting is:
Fatal error: Uncaught SoapFault exception: [soap:Server] Server was unable to process request. ---> Object reference not set to an instance of an object. in /home/zzzz/XXXXXXXXXX.com/uni/index.php:6 Stack trace: #0 /home/zzzz/XXXXXXXXXX.com/uni/index.php(6): SoapClient->__soapCall('some_function' , Array) #1 {main} thrown in /home/zzzz/XXXXXXXXXX.com/uni/index.php on line 6
Please suggest the corrections. Many thanks in advance :)
Thanks #dootzky & #lulco. I have solved this. Code below works perfectly fine for me:
<?php
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache
$wsdl_path = "http://www.xxxxxxx/zzzzzzzzzz/service.asmx?WSDL";
$login_id = 'XXXX';
$password = 'YYYYYY';
$client = new SoapClient($wsdl_path, array('trace' => 1));
try {
echo "<pre>\n";
$result = $client->SOME_FUNCTION(array("request" => array("cedula" => $login_id, "contrasena" => $password)))
print_r($result);
echo "\n";
}
catch (SoapFault $exception) {
echo $exception;
}
?>
I think you are very close to getting this code to work. I would also give credit to this answer on StackOverflow, looks very similar to what you are asking:
"Object reference not set to an instance of an object" error connecting to SOAP server from PHP
So maybe you should just shoot the method directly, like so:
$client->SOME_FUNCTION(array("request" => array('cedula'=>'XXXX','contrasena'=>'YYYYYY'));
Hope that helps! :)
I think it could be problem in wsdl for service SOME_FUNCTION.
Here is the list of services:
http://www.xxxxxx/zzzzzzzzzz/service.asmx
All of them work, but SOME_FUNCTION doesn't. Go to url http://www.xxxxxx/zzzzzzzzzz/service.asmx?op=SOME_FUNCTION and try to set parameters and click Invoke. It will not work and throw exception "Object reference not set to an instance of an object.".
Then try another service, it will work and return some result.
Example for OTHER_FUNCTION service works:
$param = array('estatus'=>'XXXX');
$client = new SoapClient("http://www.xxxxxx/zzzzzzzzzz/service.asmx?wsdl");
$result = $client->__soapCall('OTHER_FUNCTION', $param);
print_r($result);

Soap is not working in PHP

I am using SoapClient but I am not able to get the result. I get this error:
The server was unable to process the request due to an internal error.
For more information about the error, either turn on
IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute
or from the configuration behavior) on the server in order to send the
exception information back to the client, or turn on tracing as per
the Microsoft .NET Framework 3.0 SDK documentation and inspect the
server trace logs.
<?php
$silverpop = new SoapClient($my_url, array('trace' => 1));
/*$client = new stdClass();
$client->LoginID = 'mylogin-id';
$client->LicenceKey = 'mylicense-key';*/
$clientobj = (object) array("LoginID" => "mylogin-id", "LicenceKey" => "mylicense-key");
try {
//$var = $silverpop->__soapCall("GetServicesforPincode",array('P_Pincode'=>'110014','P_ClientObject'=>$clientobj));
//$var = $silverpop->GetServicesforPincode('110014',$clientobj);
$var = $silverpop -> __soapCall("GetServicesforPincode", array('110014', $clientobj));
} catch (SoapFault $exception) {
echo $exception -> getMessage();
}
echo '<pre>';
print_r($var);
?>
What am I doing wrong?
Either you have send your data not according to the specifications or your SoapServer is not working. I think the first one as Soap isn't always as clear as it should. As it looks like the error message is actually generated by the SoapServer, I recommend checking the schema for allowed parameters/calls and their format. If that's all correct, check if you are missing headers etc.
If all of the above is correct, fix your SoapServer. If you haven't gotten access to it, poke the owner.
try{
$client = new SoapClient($my_url,array('trace' => 1));
$object = new stdClass();
$object->LoginID = 'mylogin-id';
$object->LicenceKey = 'mylicense-key';
$xml = simplexml_load_string($client->GetServicesforPincode($object));
$json = json_encode($xml);
print_r($json);
}
catch (SoapFault $exception) { echo $exception; }

Android using ksoap calling PHP SOAP webservice fails: 'procedure 'CheckLogin' not found

I'm trying to call a PHP SOAP webservice. I know my webservice functions correctly because I use it in a WPF project succesfully. I'm also building an app in android, using the same webservice.
The WSDL file can be found here: http://www.wegotcha.nl/servicehandler/service.wsdl
This is my code in the android app:
String SOAP_ACTION = "http://www.wegotcha.nl/servicehandler/CheckLogin";
String NAMESPACE = "http://www.wegotcha.nl/servicehandler";
String METHOD_NAME = "CheckLogin";
String URL = "http://www.wegotcha.nl/servicehandler/servicehandler.php";
String resultData = "";
SoapSerializationEnvelope soapEnv = new SoapSerializationEnvelope(SoapEnvelope.VER11);
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
SoapObject UserCredentials = new SoapObject("Types", "UserCredentials6");
UserCredentials.addProperty("mail", params[0]);
UserCredentials.addProperty("password", md5(params[1]));
request.addSoapObject(UserCredentials);
soapEnv.setOutputSoapObject(request);
HttpTransportSE http = new HttpTransportSE(URL);
http.setXmlVersionTag("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
http.debug = true;
try {
http.call(SOAP_ACTION, soapEnv);
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
SoapObject results = null;
results = (SoapObject)soapEnv.bodyOut;
if(results != null)
resultData = results.getProperty(0).toString();
return resultData;
Using fiddler I got the following:
Android request:
<?xml version="1.0" encoding="utf-8"?>
<v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/"><v:Header />
<v:Body>
<n0:CheckLogin id="o0" c:root="1" xmlns:n0="http://www.wegotcha.nl/servicehandler">
<n1:UserCredentials6 i:type="n1:UserCredentials6" xmlns:n1="Types">
<mail i:type="d:string">myemail</mail>
<password i:type="d:string">myhashedpass</password>
</n1:UserCredentials6>
</n0:CheckLogin>
</v:Body>
</v:Envelope>
Getting the following response:
Procedure 'CheckLogin' not present
My request produced by my WPF app looks completely different:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<UserCredentials6 xmlns="Types">
<mail>mymail</mail>
<password>mypassword</password>
</UserCredentials6>
</s:Body>
</s:Envelope>
After googling my ass off I was not able to solve this problem by myself. It may be possible there are some weird things in my Java code because I changed a lot since. I hope you guys will be able to help me, thanks.
EDIT:
My webservice is of document/literal encoding style, after doing some research I found I should be able to use SoepEnvelope Instead of SoapSerializationEnvelope Though when I replace this I get an error before the try cache block, causing my app to crash.
Error:
11-04 16:23:26.786: E/AndroidRuntime(26447): Caused by: java.lang.ClassCastException: org.ksoap2.serialization.SoapObject cannot be cast to org.kxml2.kdom.Node
Which is caused by these lines:
request.addSoapObject(UserCredentials);
soapEnv.setOutputSoapObject(request);
This may be a solution though, how do I go about this? I found nothing about using a SoapEnvelope instead of a SoapSerializationEnvelope except for this awesome tutorial:
http://ksoap.objectweb.org/project/mailingLists/ksoap/msg00849.html
Some weird stuff just happened. I simply removed the a line (which I did thousands of times) tweaked the rest a little bit since I got some new errors and I got the following code working:
String SOAP_ACTION = "http://www.wegotcha.nl/servicehandler/CheckLogin";
String NAMESPACE = "http://www.wegotcha.nl/servicehandler";
String METHOD_NAME = "CheckLogin";
String URL = "http://www.wegotcha.nl/servicehandler/servicehandler.php";
String resultData = "";
SoapSerializationEnvelope soapEnv = new SoapSerializationEnvelope(SoapEnvelope.VER11);
SoapObject UserCredentials = new SoapObject("Types", "UserCredentials6");
UserCredentials.addProperty("mail", params[0]);
UserCredentials.addProperty("password", md5(params[1]));
// changed these lines
// request.addSoapObject(UserCredentials);
// soapEnv.setOutputSoapObject(request);
// into:
soapEnv.setOutputSoapObject(UserCredentials);
HttpTransportSE http = new HttpTransportSE(URL);
http.debug = true;
// little tweak here
String results = null;
try {
http.call(SOAP_ACTION, soapEnv);
//another tweak here
results = soapEnv.bodyIn.toString();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
}
if(results != null)
resultData = results;
return resultData;
And now I am able to login correctly :) They are not very functional workarounds as this is the only place where I'll get back a yes or a no. Think array's of complextypes and the like. But that's another story.

Categories