How to execute a web service using php - php

I need to execute a web service from a php page
The web service is located in the following url
https://www.agemni.com/AgemniWebservices/service1.asmx
The Web Service uses a SOAP protocol to exchange messages.
The WSDL info can be located at https://www.agemni.com/AgemniWebservices/service1.asmx?WSDL
The function in that service that we need to use is ValidateEntity
//ValidateEntity("username", "password", "companyID", 2, keys, values)
So , how can i execute this web service and get result from my php page

A simple example, hope it helps...
$service1 = new SoapClient('https://www.agemni.com/AgemniWebservices/service1.asmx');
//here you instanciate your object with those properties
$entity = new Entity();
$entity->strUsername = 'José';
$entity->strPassword = '123';
$entity->strCompanyName = 'Somethin';
$entity->0 //because your type is int
$res = $service1->ValidateEntity($entity);//here you send the information to your service's method, if I'm not mistaken, it must be a object
$res->ValidateEntityResult;//this is the return of your service.
As I said, it is really simple but works.

See soap calls help from php.net:
http://www.php.net/manual/en/soapclient.soapcall.php

You need to use PHP's SOAP libraries...
http://www.php.net/manual/en/soapclient.soapcall.php

For https WebServices you need to enable openssl extension. The WS use .net it means that the class use type hinting so you need to create the ValidateEntity class, here's the code:
$ws = new soapclient('https://www.agemni.com/AgemniWebservices/service1.asmx?wsdl');
class ValidateEntity {
public $strUsername,
$strPassword,
$strCompanyName,
$objecttype;
}
$parameters = new ValidateEntity();
$parameters->strUsername = 'username';
$parameters->strPassword = 'password';
$parameters->strCompanyName = 'company';
$parameters->objecttype = 1;
echo '<pre>';
print_r($ws->ValidateEntity($parameters));
echo '</pre>';

Related

PHP Soap Client does not send all object properties in a webservice call

I try to implement a webservice Client using php and got stuck...
I'm using an existing webservice called metadataservice with a known wsdl.
I'll use wsdl2phpgenerator to create the php classes for the datatypes and the Service itself.
Using one of the Webservice Methods (addMetadataToObject), I have to send an Array of objects to the Server.
There is a base class:
class AssetInfo
{
public $dataFieldId = null;
public $dataFieldName = null;
public $dataFieldTagName = null;
public function __construct($dataFieldId, $dataFieldName, $dataFieldTagName)
{
$this->dataFieldId = $dataFieldId;
$this->dataFieldName = $dataFieldName;
$this->dataFieldTagName = $dataFieldTagName;
}
}
and a derived class Holding string values (there are also other derived classes for Longs etc.):
class StringAssetInfo extends AssetInfo
{
public $value = null;
public function __construct($dataFieldId, $dataFieldName,$dataFieldTagName, $value)
{
parent::__construct($dataFieldId, $dataFieldName, $dataFieldTagName);
$this->value = $value;
}
}
For the call of Metadataservice->addMetadataToObject there is also a addMetadataToObject defined:
class addMetadataToObject
{
public $objectId = null;
public $objectType = null;
public $assetInfos = null;
public function __construct($objectId, $objectType)
{
$this->objectId = $objectId;
$this->objectType = $objectType;
}
}
The property $assetInfos should hold an Array of AssetInfo objects. wdsl2phpgenerator creates a class for my MetadataService which is derived from SoapClient. This class provides all the avialable Methods for this Service. Here I only show the addMetadataToObject Method:
public function addMetadataToObject(addMetadataToObject $parameters)
{
return $this->__soapCall('addMetadataToObject', array($parameters));
}
My Code does:
// Define the Data
$ServiceOptions = [];
$AssetInfos = [];
$AssetInfo = new StringAssetInfo(2, "TitleName", "TitleName","New Title Name);
array_push($AssetInfos, $AssetInfo);
// Create the Service
$Service = new MetadataService($ServiceOptions, getServiceWSDL($Options, "MetadataService"));
$Service->__setSoapHeaders(getGalaxySoapHeader($Options));
$NewMetaData = new addMetadataToObject(61755, "ASSET");
$NewMetaData->assetInfos = $AssetInfos;
// Call the Service
$failedAssets = $Service->addMetadataToObject($NewMetaData);
The call throws a Soap Exception that a value could not be extracted. Which makes me wonder. I started to monitor the traffic to the Soap Server using wireshark and yes....there is no value anymore as defined in the StringAsset Info Class...Here is the Soap Body shown by wireshark:
<SOAP-ENV:Body>
<ns1:addMetadataToObject>
<objectId>61755</objectId>
<objectType>ASSET</objectType>
<assetInfos>
<dataFieldId>2</dataFieldId>
<dataFieldName>TitleName</dataFieldName>
<dataFieldTagName>TitleName</dataFieldTagName>
</assetInfos>
</ns1:addMetadataToObject>
Id</SOAP-ENV:Body>
I would expect a tag New Title Name. But ist gone. When I checked the $NewMetaData object in my Code or the $Parameter object in $Service->addMetadataToObject I can see that the property "Value" is defined and set.
For me it seems, that the call to
return $this->__soapCall('addMetadataToObject', array($parameters));
only accepts the properties of the base class AssetInfo but not the properties from the derived class StringAssetInfo.
I also changed the Code to use an Array (instead of an object) for $AssetInfo:
$AssetInfo = array("dataFieldId"=>2, "dataFieldName"=>"TitleName","dataFieldTagName"=>"TitleName, "value"=>"New Title Name");
But without any change. It seems that we have here some Kind of runtime type conversion or type alignment but I can't see the reason of this. I'm still new to webservices at all and also on php (however I have to use both for the Moment:-)
Can anybody comment or give me a hint what's happening here?
I was able to realize it by using Arrays and soapvars, Please note my comments in the code:
$ServiceOptions = [];
$AssetInfos = [];
// I have to use an Array because the Server depends on the order of the properties. I wasn't able to define expected order using the existing objects but with arrays
$AssetInfo = array("dataFieldId"=>2, "dataFieldName"=>"TitleName","dataFieldTagName"=>"TitleName, "value"=>"New Title Name");
// instead of pushing the Array directly, I create an instance of an SoapVar, pass the Array as data and set the Encoding, the expected type and the Namespace uri
array_push($AssetInfos, new SoapVar($AssetInfo, SOAP_ENC_OBJECT, "StringAssetInfo", "http://metadataservice.services.provider.com"));
array_push($AssetInfos, $AssetInfo);
// Create the Service
$Service = new MetadataService($ServiceOptions, getServiceWSDL($Options, "MetadataService"));
$Service->__setSoapHeaders(getGalaxySoapHeader($Options));
$NewMetaData = new addMetadataToObject(61755, "ASSET");
$NewMetaData->assetInfos = $AssetInfos;
// Call the Service
$failedAssets = $Service->addMetadataToObject($NewMetaData);
This produced the expected Output in the Soap Body (and also added some namespaces to the Soap envelope
<SOAP-ENV:Body>
<ns1:addMetadataToObject>
<objectId>61755</objectId>
<objectType>ASSET</objectType>
<assetInfos xsi:type="ns1:StringAssetInfo">
<dataFieldId>2</dataFieldId>
<dataFieldName>TitleName</dataFieldName>
<dataFieldTagName>TitleName</dataFieldTagName>
<value>New Titel Name 1146</value>
</assetInfos>
</ns1:addMetadataToObject>
</SOAP-ENV:Body>

Get method name from soap service call

I have a working soap service with several methods available. I am wondering if it is possible to get the name of the method that the user contacting the service is requesting; for example:
try{
$soapServer = new Zend_Soap_Server('http://path-to-service/wsdl');
$soapServer->setClass('My\Soap\Server\Class');
$soapServer->handle();
// is something like this available? :
// $callName = $soapServer->getLastRequestedMethod();
// or
// $callName = $soapServer->getMethod();
}catch(SoapFault $e){
echo $e->getMessage();
}
I didn't see anything like this in the docs # zend or php.net, but just thought I would check to see if anyone knows a way to do this; would be useful for logging purposes. Thanks!
Zend_Soap_Server supports a getLastRequest() method. Example usage would be:
$soapServer = new Zend_Soap_Server('http://path-to-service/wsdl');
$soapServer->setClass('My\Soap\Server\Class');
$soapServer->handle();
$lastRequestXML = $soapServer->getlastRequest()`;

Soap not getting sent correctly, need to get the request

I have this class to send a SOAP-request (the class also defines the header)
class Personinfo
{
function __construct() {
$this->soap = new SoapClient('mysource.wsdl',array('trace' => 1));
}
private function build_auth_header() {
$auth->BrukerID = 'userid';
$auth->Passord = 'pass';
$auth->SluttBruker = 'name';
$auth->Versjon = 'v1-1-0';
$authvalues = new SoapVar($auth, SOAP_ENC_OBJECT);
$header = new SoapHeader('http://www.example.com', "BrukerAutorisasjon", // Rename this to the tag you need
$authvalues, false);
$this->soap->__setSoapHeaders(array($header));
}
public function hentPersoninfo($params){
$this->build_auth_header();
$res = $this->soap->hentPersoninfo($params);
return $res;
}
}
The problem is that there's something wrong with my function and the response is an error. I'd like to find out what content I am sending with my request, but I can't figure out how.
I've tried a try/catch-block in the hentPersoninfo-function that calls $this->soap->__getLastRequest but it is always empty.
What am I doing wrong?
Before I ever start accessing a service programmatically, I use SoapUI to ensure that I know what needs sent to the service, and what I should expect back.
This way, you can ensure the issue isn't in the web service and/or in your understanding of how you should access the web service.
After you understand this, you can narrow your focus onto making the relevant SOAP framework do what you need it to do.

Does Ksoap2 require that a web service produce a wsdl?

I have successfully written an Android app which calls an asp.net web service using Ksoap2. I now want to migrate the app to use a PHP web service. I have successfully migrated the web service over to a native PHP web service (and tested it using a PHP client) but I'm having trouble calling it using KSOAP. One thought that struck me was that the native PHP web service was not generated using a wsdl, and is not able to automatically generate a wsdl.
Does ksoap2 require a wsdl to successfully call a web service method?
The asp.net web service is located at http://mycomputer/AlumLocateService/Service.asmx
For the succesful call to asp.net service:
private static final String NAMESPACE = "http://mycomputer/";
private static final String URL = "http://mycomputer/AlumLocateService/Service.asmx";
private static final String METHOD_NAME_3 = "FindCloseDetails";
private static final String SOAP_ACTION_3 = NAMESPACE + METHOD_NAME_3;
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME_3);
PropertyInfo pi = new PropertyInfo();
pi.setName("userid");
pi.setValue(userid);
pi.setType(string.class);
request.addProperty(pi);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.call(SOAP_ACTION_3, envelope);
//Parse Response
Object myResult = envelope.bodyIn;
SoapObject resultsRequestSOAP = (SoapObject) myResult;
String[] results = getStringArrayResponse(resultsRequestSOAP, null);
return results;
The PHP service is located at http://mycomputer/PHPTest/testserver.php and replicates the methods of the asp.net web service. I had hoped thta all I woudl need to do would be to change the following
private static final String URL = "http://mycomputer/PHPTest/testserver.php";
and remove the line
envelope.dotNet = true;
but when I do that i get "XmlPullParserException: unexpected type (position END_DOCUMENT null...." when the androidHttpTransport.call(SOAP_ACTION_3, envelope) call is made.
One I had changed to using a PHP Zend_Soap_Server I had to change the last part of my Android code to:
Object myResult = envelope.getResponse();
String[] results = null;
if (myResult instanceof Vector)
{
Vector<Object> myVector = (Vector<Object>) myResult;
results = new String[myVector.size()];
for (int i = 0; i< myVector.size();i++){
results[i] = myVector.elementAt(i).toString();
}
}
return results;

How do i remove a file from Rackspace's Cloudfiles with their api?

I was wondering how do i remove a file from Rackspace's Cloudfiles using their API?
Im using php.
Devan
Use the delete_object method of CF_Container.
Here is my code in C#. Just guessing the api is similar for php.
UserCredentials userCredientials = new UserCredentials("xxxxxx", "99999999999999");
cloudConnection = new Connection(userCredientials);
cloudConnection.DeleteStorageItem(ContainerName, fileName);
Make sure you set the container and define any sudo folder you are using.
$my_container = $this->conn->get_container($cf_container);
//delete file
$my_container->delete_object($cf_folder.$file_name);
I thought I would post here since there isn't an answer marked as the correct one, although I would accept Matthew Flaschen answer as the correct one. This would be all the code you need to delete your file
<?php
require '/path/to/php-cloudfiles/cloudfiles.php';
$username = 'my_username';
$api_key = 'my_api_key';
$full_object_name = 'this/is/the/full/file/name/in/the/container.png';
$auth = new CF_Authentication($username, $api_key);
$auth->ssl_use_cabundle();
$auth->authenticate();
if ( $auth->authenticated() )
{
$this->connection = new CF_Connection($auth);
// Get the container we want to use
$container = $this->connection->get_container($name);
$object = $container->delete_object($full_object_name);
echo 'object deleted';
}
else
{
throw new AuthenticationException("Authentication failed") ;
}
Note that the "$full_object_name" includes the "path" to the file in the container and the file name with no initial '/'. This is because containers use a Pseudo-Hierarchical folders/directories and what end ups being the name of the file in the container is the path + filename. for more info see http://docs.rackspace.com/files/api/v1/cf-devguide/content/Pseudo-Hierarchical_Folders_Directories-d1e1580.html
Use the method called DeleteObject from class CF_Container.
The method DeleteObject of CF_Container require only one string argument object_name.
This arguments should be the filename to be deleted.
See the example C# code bellow:
string username = "your-username";
string apiKey = "your-api-key";
CF_Client client = new CF_Client();
UserCredentials creds = new UserCredentials(username, apiKey);
Connection conn = new CF_Connection(creds, client);
conn.Authenticate();
var containerObj = new CF_Container(conn, client, container);
string file = "filename-to-delete";
containerObj.DeleteObject(file);
Note Don´t use the DeleteObject from class *CF_Client*

Categories