.Net user can not connect to php Webservice - php

I have a php Webservice With this code :
require_once('nusoap.php');
require_once('gw.interface.php');
$namespace = 'www.mydomain.com';
$server = new soap_server();
$server->soap_defencoding = 'UTF-8';
$server->decode_utf8 = false;
$server->encode_utf8 = true;
$server->configureWSDL('smsserver', 'urn:smsserver');
$server->wsdl->addComplexType(
'ListArray',
'complexType',
'array',
'',
'SOAP-ENC:Array',
array(),
array(
array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')
),
'xsd:string'
);
/**
* SendSMS
**/
$server->register('SendSMS',
array(
'fromNum' => 'xsd:string',
'toNum' => 'xsd:string',
'messageContent' => 'xsd:string',
'messageType' => 'xsd:string',
'user' => 'xsd:string',
'pass' => 'xsd:string'
), array('return' => 'xsd:string'),
$namespace, 'SendSMS', 'rpc', 'encoded', 'send your sms');
function SendSMS($fromNum, $toNum, $messageContent, $messageType, $user, $pass)
{
return gwi::sendsms($fromNum, $toNum, $messageContent, $messageType, $user, $pass);
}
/**
* GetCredit
**/
$server->register('GetCredit',
array(
'user' => 'xsd:string',
'pass' => 'xsd:string'
), array('return' => 'xsd:string'),
$namespace, 'GetCredit', 'rpc', 'encoded', 'check your credit');
function GetCredit($user, $pass)
{
return gwi::GetCredit($user, $pass);
}
/**
* GetStatus
**/
$server->register('GetStatus',
array(
'user' => 'xsd:string',
'pass' => 'xsd:string',
'batchid' => 'xsd:string',
'unique_ids' => 'tns:ListArray'
), array('return' => 'xsd:string'),
$namespace, 'GetStatus', 'rpc', 'encoded', 'get messages delivery status');
function GetStatus($user, $pass, $batchid, $uniqs)
{
return gwi::GetStatus($user, $pass, $batchid, $uniqs);
}
$server->service($HTTP_RAW_POST_DATA);
The Problem is this code worked before i change my webserver from apache to nginx.
i used this code on another server and was ok. the same Code same request.
So when a .Net client wants to connect to My webservice it can Detect My Webservice.
but When it wants to call of one of my methods
get this error in .net :
{"The remote server returned an error: (404) Not Found."}
and the client code For Example in Vb
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim x As ServiceReference2.
smsserverPortTypeClient = New ServiceReference2.smsserverPortTypeClient()
Dim result As String = "-"
result = x.GetCredit("test", "123456") + " ";
MsgBox(result)
End Sub

Have you tried adding the WS as a Web Reference on your .NET project, instead of a Service Reference? As far as I know, a PHP webservice has to be treated as a web service instead of a common one, as ASMX does.
To do so, follow these simple steps:
Right click on your project in the Solution Explorer.
Click on "Add Service Reference"
Click the "Advanced" button on the bottom-left of the dialog window (I'm sorry if the button has another name, I'm translating these steps from my spanish GUI)
Go again to the bottom-left corner and click the "Add web reference" button.
Add the webservice URL on the field on top, give it a name in the field to the right, and voilá!
The process, then, should be more simple: you use the methods of the WS using the name you gave to the service as a namespace.
I hope this suits you. Good luck!

Related

How to send multi response using nusoap with soapval?

I am stuck in a situation where I am unable to send multi-response not array type using soapval(nusoap). I looking for a solution to make struct which accepts multi-request and send multi-response in nusoap. I saw a lot of examples where I only saw the response as an array this is the main issue I think so.
Let me show you my code
$server->wsdl->addComplexType(
'InitiateHolidayDataTransferResult',
'complexType',
'struct',
'sequence',
'',
array( 'HOLIDAY_COMPLEX_TYPE_RES' => array(
'name' => 'HOLIDAY_COMPLEX_TYPE_RES', 'type' => 'tns:HOLIDAY_COMPLEX_TYPE_RES' ,'minOccurs' => '0', 'maxOccurs' => 'unbounded' )
)
);
$server->wsdl->addComplexType(
'HOLIDAY_COMPLEX_TYPE_RES',
'complexType',
'struct',
'all',
'',
array( 'STATUS' => array('name' => 'STATUS','type' => 'xsd:string'),
'STATUS_DESC' => array('name' => 'STATUS_DESC','type' => 'xsd:string')
));
// Register the method to expose
$server->register('HOLIDAY_INFORMATION_DATA', // method name
array('name' => 'tns:HOLIDAY_COMPLEX_TYPE_REQ'), // input parameters
array('return' => 'tns:HOLIDAY_COMPLEX_TYPE_RES'), // output parameters
'urn:HOLIDAY_SERVER1', // namespace
'urn:HOLIDAY_SERVER1#HOLIDAY_INFORMATION_DATA', // soapaction
'document', // style
'encoded', // use
'Holiday Information Get Method' // documentation
);
// Define the method as a PHP function
function HOLIDAY_INFORMATION_DATA($mycomplextype) {
$holiday_data_success='';
// trying to send multi reponse in many ways see below
foreach($mycomplextype as $key=>$val){
//one way
$parm = array();
$parm[] = array('STATUS'=>"Success", "STATUS_DESC"=>"-Holiday Added");
$parm[] = array('STATUS'=>"Success", "STATUS_DESC"=>"-Holiday Added");
$parm[] = array('STATUS'=>"Success", "STATUS_DESC"=>"-Holiday Added");
$holiday_data_success = new soapval('return', 'tns:HOLIDAYRES_COMPLEX_TYPE_RES', $parm);
//second way
$arr = array("STATUS"=>"12345", "STATUS_DESC"=>"Test heading",);
$arr2 = array("STATUS"=>"12346", "STATUS_DESC"=>"Test heading");
$holiday_data_success = array($arr, $arr2);
// third way
$holiday_data_success=[];
$holiday_data_success[] = new soapval('return', 'tns:InitiateHolidayRESTransferResult', array('STATUS'=>"Success", "STATUS_DESC"=>$successtr."-Holiday Added"));
} // end foreach
return $holiday_data_success;
}
// but nothing is working
I am unable to send multi-response for each record that I insert in db

How to debug a SOAP call?

I'm writing integration tests for a SOAP API (code example s. below).
Now I got an error and want to debug my server-side code (in PhpStorm). But the debugger considers only the breakpoints in the test and ignores the server-side code.
OK, I probably roughly understand why: The call of the $soapClient->doSomething(...); starts a new HTTP request. How to get this "sub-request" (from the point of view of PhpUnit) debugged?
Integration test's code:
class UserIntegrationTest extends TestCaseBase
{
const URL = "http://my-server.loc/soapapi/user/wsdl";
public static $classMap = [];
/** #var SoapClient */
private $soapClient;
/** #var ConfigurationServiceInterface */
private $config;
public function setUp()
{
parent::setUp();
$options = [
'exceptions' => true,
'login' => 'foo',
'password' => 'pwd',
'encoding' => 'utf-8',
// 'proxy_host' => '192.168.2.96',
// 'proxy_port' => '8080',
'classmap' => [],
'connection_timeout' => 5,
];
$this->soapClient = new SoapClient(self::URL, $options);
}
/**
* #test
* #group integration
*/
public function testDoSomething()
{
$options = array(
'exceptions' => true,
'login' => 'foo',
'password' => 'pwd',
'encoding' => 'utf-8',
// 'proxy_host' => '192.168.2.96',
// 'proxy_port' => '8080',
'classmap' => [],
'connection_timeout' => 5,
);
$soapClient = new SoapClient(self::URL, $options);
$message = new MyMessage();
$message->x = 1;
$message->y = 2;
$result = $soapClient->doSomething($message);
}
protected function getDataSet()
{
return new ArrayDataSet([
'users' => [
[
'id' => 1,
'username' => 'foo',
'password' => '...',
],
],
...
]);
}
}
The solution is to append ?XDEBUG_SESSION_START=ECLIPSE_DBGP to the URI called by the SOAP client. So in the port segment of the WSDL
<port name="UserPort" binding="tns:UserBinding">
<soap:address location="http://my-server.loc/soapapi/user"/>
</port>
the location needs to be extended by the Xdebug query and look like this:
http://my-server.loc/soapapi/user?XDEBUG_SESSION_START=ECLIPSE_DBGP
Sure, the productive WSDL should not contain such location. But WSDLs are usually generated (e.g. by Zend\Soap\AutoDiscover) and the URI can be easily made dynamically configurable.
You can do this by setting the XDEBUG_SESSION cookie in your client application.
I believe this is a better alternative than the accepted answer, as it does not require changing the server-side code (WSDL).
For example, using PHP SoapClient as per the OP's code sample
$soapClient = new SoapClient(self::URL, $options);
$soapClient->__setCookie('XDEBUG_SESSION', 'PHPSTORM');
Then in PhpStorm, Start listening for PHP Debug Connections and run your test script.

How to instantiate Nusoap's ComplexType using php in server side?

I am writing a simple web service methods using nusoap library in php.
I already create a complextype (struct) in server side but I want to instantiate that struct in a method so I can return it. I saw an example in here but using keyword "new" doesn't work. It doesn't see ComplexType.
So how can I create new ComplexLogin struct in my LoginTest function?
//ComplexLoginType
$server->wsdl->addComplexType('ComplexLogin','complexType','struct','all','',
array(
'EnterpriseId' => array('name' => 'EnterpriseId','type' => 'xsd:int'),
'FirstName' => array('name' => 'FirstName','type' => 'xsd:string'),
'Password' => array('name' => 'Password','type' => 'xsd:string'))
);
$server->register(
// method name:
'LoginTest',
// parameter list:
array('name'=>'tns:ComplexLogin'),
// return value(s):
array('return'=>'tns:ComplexLogin'),
// namespace:
$namespace,
// soapaction: (use default)
false,
// style: rpc or document
'rpc',
// use: encoded or literal
'encoded',
// description: documentation for the method
'Login Method'
);
I cannot instantiate ComplexType directly but if I use array instead, it works correctly.
However I wonder if there is another way to return ComplexType without using arrays?
My complete working function in server side;
function LoginTest($mycomplexlogin)
{
$conn=openConnection();
// Check connection
if ($conn->connect_error)
{
//return("Connection failed: " . $conn->connect_error);
return NULL;
}
$EnterpriseId=mysqli_real_escape_string($conn,$mycomplexlogin["EnterpriseId"]);
$FirstName=mysqli_real_escape_string($conn,$mycomplexlogin["FirstName"]);
$Password=mysqli_real_escape_string($conn,$mycomplexlogin["Password"]);
$result=array('EnterpriseId'=>$EnterpriseId, 'FirstName'=>$FirstName,'Password'=>$Password);
return $result;
}

NuSoap, XML was empty, couldn't parse

First, I have to say that I am totally new to WSDL-based Web Services using NuSOAP. I am trying to return an array of friends list from my soap server. Please find below my code listings as is:
Server:
//File includes omitted
function getFriendList($test = ''){
$results = array();
$results[] = array('name' => 'XXXXA1', 'surname' => 'XXXXA2');
$results[] = array('name' => 'XXXXXB1', 'surname' => 'XXXXB2');
$results[] = array('name' => 'XXXXXC1', 'surname' => 'XXXXC2');
return $results;
}
//Create server instance
$server = new soap_server();
//Configure our WSDL
$server->configureWSDL('server', 'urn:server');
//Add our Complex Type data type since we want to return an array
$server->wsdl->addComplexType(
'Friend',
'complexType',
'struct',
'all',
'',
array(
'name' => array('name' => 'name', 'type' => 'xsd:string'),
'surname' => array('name' => 'surname', 'type' => 'xsd:string')
)
);
//Register our array as a response
$server->wsdl->addComplexType(
'FriendArray',
'complexType',
'array',
'',
'SOAP-ENC:Array',
array(),
array(
array('ref' => 'SOAP-ENC:arrayType', 'wsdl:arrayType' => 'tns:Friend[]')
),
'tns:Friend'
);
//Register the actual function that retuns the array but in the
//return n field specify the complex type of array we added onto the wsdl
$server->register('getFriendList',
array('test' => 'xsd:string'),
array('return' => 'tns:FriendArray'),
'urn:server',
'urn:server#getFriendList',
'document',
'encoded',
'Fetch a list of friends as an array. If you\'re not here sorry.'
);
//Serve the service
$server->service($HTTP_RAW_POST_DATA = (!isset($HTTP_RAW_POST_DATA)) ? $HTTP_RAW_POST_DATA : '');
With this, I hoped that I did everything correctly. I followed the standard procedure to make it work but in vein.
On the client side, I used the soap address url in wsdl and appended it with "?wsdl", so that it give me wsdl file dynamically.
example:
//Client call
$client = new nusoap_client("http://soapserver.dev/webroot/part_three/server.php?wsdl", true);
I have also taken labour of adding some whistles and bells on my client object as shown below:
$client->soap_defencoding = 'UTF-8';
$client->decode_utf8 = false;
This doesn't seem to help at all. I had experienced an issue earlier since my function accepts no parameter, where my service died because I didnt pass any parameter that speaks of inputs in my $client->call($name, $in, $out). I ended up providing an empty array and I got this error.
Could this be related to the rpc/document parameter types of the register function?
Even using the wsdl file which I saved from my server url, I got the same error.
Can somebody please help me out here? Please!

PHP calling WCF service using WSHttpBinding

Currently I am working on WCF Service that is using WSHttpBinding. So far the service works great with .NET applications. However when it comes to using this service in PHP it throws me an error. The error is caused because PHP sends null as the parameter to the WCF services.
The service contract looks as follows:
[ServiceContract]
public interface IWebsite : IWcfSvc
{
[OperationContract]
[FaultContract(typeof(ServiceException))]
ResponseResult LostPassword(RequestLostPassword request);
}
The data contract that is used for the parameters looks like:
[DataContract]
public class RequestLostPassword
{
[DataMember(IsRequired = true)]
public string Email { get; set; }
[DataMember(IsRequired = true)]
public string NewPassword { get; set; }
[DataMember(IsRequired = true)]
public string CardNumber { get; set; }
[DataMember(IsRequired = true)]
public DateTime RequestStart { get; set; }
}
Since I am not an expert, it took me a while to get the PHP code working, but I end up writing a script like this:
$parameters = array(
'Email' => "user#test.com",
'NewPassword' => "test",
'CardNumber' => "1234567890",
'RequestStart' => date('c')
);
$svc = 'Website';
$port = '10007';
$func = 'LostPassword';
$url = 'http://xxx.xxx.xxx.xxx:'.$port.'/'.$svc;
$client = #new SoapClient(
$url."?wsdl",
array(
'soap_version' => SOAP_1_2,
'encoding'=>'ISO-8859-1',
'exceptions' => true,
'trace' => true,
'connection_timeout' => 120
)
);
$actionHeader[] = new SoapHeader(
'http://www.w3.org/2005/08/addressing',
'Action',
'http://tempuri.org/I'.$svc.'/'.$func,
true
);
$actionHeader[] = new SoapHeader(
'http://www.w3.org/2005/08/addressing',
'To',
$url,
true
);
$client->__setSoapHeaders($actionHeader);
$result = $client->__soapCall($func, array('parameters' => $parameters));
What I don't understand is why it is not passing the parameters to the WCF service. I have another service that works just fine although that does not require parameters. Can someone explain why this happens? I am a complete PHP noob and just want to get this to work as an example for the guy who is developing the website.
We found the answer!
The line of code below:
$result = $client->__soapCall($func, array('parameters' => $parameters));
Should be changed to:
$result = $client->__soapCall($func, array('parameters' => array('request' => $parameters)));
Apparently you need to tell PHP that your parameters are nested in an array called 'request', which is nested in an array called parameters, when you want to call a WCF service with a datacontract as a request object.

Categories