I have problem in creating web-service using cakephp .
this what i do to create this web-service .
I use NuSOAP - Web Services Toolkit for PHP for this.
I create a controller called WsController and import the library on it.
class WsController extends AppController{
var $uses = array();
function info() {
$this->layout= null;
$ns="http://www.techvoicellc.com/Tutorials//";
$server = new soap_server();
$server->configureWSDL('mostafa',$ns);
$server->wsdl->schemaTargetNamespace=$ns;
$server->wsdl->addComplexType('ArrayOfstring','complexType',
'array','','SOAP-ENC:Array',array()
,array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]')),
'xsd:string');
$server->register('sum',
array('x' => 'xsd:integer','y' => 'xsd:integer'),
array('z' => 'xsd:integer'),
$ns,
"$ns#sum",
'rpc',
'encoded',
'documentation' // documentation
);
$server->service($HTTP_RAW_POST_DATA);
}
function sum($x,$y){
$z=$x+$y;
return new soapval('return','xsd:integer',$z);
}
}
and i create the clint in controller action like this
function index() {
$wsdl = 'http://localhost/asd/ws/info?wsdl';
$client = new nusoap_client ( $wsdl, true );
$this->client = new nusoap_client($wsdl, true);
$param1 = array ('x' => 2, 'y' => 1 );
$a = $client->call ( 'sum', $param1 );
echo $a;
}
it don't do any thins although that i create this in non cake project and its work very well
hope some one tell me what is the best practise to create web-service in cake php
This is quite Easy to develop web services in CakePHP. I have done it several times. Check the below steps.
class MyWebServicesController extends AppController {
var $name = 'MyWebServices';
var $layout = "ajax";
function index() {
$server = new SoapServer(null);
$server->setObject($this);
$server->handle();
exit(0);
}
public function addNumbers($a,$b) {
return $a+$b
}
}
Now your web service is hosted at http://webroot/MyWebServices
Now you can call addNumbers like below.
$client = new SoapClient(null, array('location' => "http://webroot/MyWebServices");
$sum = $client->addNumbers(1+2);
It is best to create restful web service. CakePHP has everything built in for REST. All you have to do is enable it and create json/xml views.
Here is a link with your starting point: http://book.cakephp.org/2.0/en/development/rest.html
Is there a reason you want SOAP web service?
It will be so much harder to create and test SOAP web service
SOAP will require external libraries
It will be harder for users to use the SOAP web service
Related
I'm building a webapp in Laravel which consumes multiple external REST API's, in which I have to authenticate myself and retrieve an access token before I'm able to do perform requests. I have built that like so:
ExampleAPIServiceProvider.php
class ExampleAPIServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(ExampleClient::class, function () {
return new ExampleClient(
accessToken: $this->getAccessToken()
);
});
}
private function getAccessToken(): ?AccessToken
{
return $this->accessToken ?? $this->requestAccessToken($clientId, $clientSecret);
}
}
This enables me to perform requests like so:
ExampleController.php
class ExampleController extends Controller
{
public function __construct(protected ExampleClient $client) { ... }
public function index()
{
$response = $this->client->getExamles();
}
}
I'm trying to consume another service, but this is a SOAP service. I know I can use the SoapClient(). If I understand correctly, with soap I first have to provide the url I'm trying to fetch data from and then do authentication. This is the example that the Soap Server I'm trying to consume provides:
try {
$soap = new SoapClient($webservice_url);
$res = $soap->Authenticate(array('accessKey' => $key));
if (!isset($res->AuthenticateResult)) exit();
$sess_id = $res->AuthenticateResult;
$xmlvar = new SoapVar('<ns1:xmlDoc>'.$xml.'</ns1:xmlDoc>', XSD_ANYXML);
$res = $soap->ProcessJournal(array('sessionID' => $sess_id, 'administrationID' => $admin_id, 'xmlDoc' => $xmlvar));
} catch (SoapFault $e) {
// throw exception...
}
I'd like to build a small wrapper client for this SoapClient and register that to the service provider as well. However I'm not sure how, as it seems that authentication happens after providing the webservice url. With the example from the Soap Server, it would mean that I'd have to provide the $sess_id and $administrationId each time I want to consume the service.
I think the result I'd like to have is to be able to call this from example the controller:
$this->soapClient->url($url)->ProcessJournal(...);
How do I go about doing registering it to the service provider? Or is there any other solution which would allow me to provide the authentication credentials only once?
Thanks in advance.
I am trying to load a model to a webservice (Nusoap) as follows:
Controller:
class Addition extends CI_Controller{
public function Addition(){
parent::__construct();
$ns = base_url().'addition/';
$endpoint = base_url().'addition/';
$this->load->library("nusoap_library"); // load nusoap toolkit library in controller
$this->nusoap_server = new soap_server(); // create soap server object
$this->nusoap_server->configureWSDL("SMS SOAP", $ns, $endpoint); // wsdl cinfiguration
$this->nusoap_server->wsdl->schemaTargetNamespace = $ns; // server namespace
// REGISTER FUNCTIONS
$input_array = array ('var1' => "xsd:string", 'var2' => "xsd:string"); // "addnumbers" method parameters
$return_array = array ("var3" => "xsd:int", 'var4' => "xsd:string");
$this->nusoap_server->register('send', $input_array, $return_array, "urn:SOAPServerWSDL", "urn:".$ns."send", "rpc", "encoded", "My Addition WS");
}
function index(){
function send($var1, $var2){
$this->load->model('mymodel'); // THIS IS MY MODEL
$data['var1'] = $this->mymodel->addnumbers($var1, $var2);
$data['var2'] = "yes";
return $data;
}
$this->nusoap_server->service(file_get_contents("php://input"));
}
}
The problem is that if I take out the model and just add directly, it will work perfectly, but with the model it returns nothing.
Any help will be greatly appresiated.
I think I solved my own question.
Apparently you cannot invoke directly the model. A way to do it is the following:
class Addition extends CI_Controller{
public function Addition(){
parent::__construct();
$ns = base_url().'addition/';
$endpoint = base_url().'addition/';
$this->load->library("nusoap_library"); // load nusoap toolkit library in controller
$this->nusoap_server = new soap_server(); // create soap server object
$this->nusoap_server->configureWSDL("SMS SOAP", $ns, $endpoint); // wsdl cinfiguration
$this->nusoap_server->wsdl->schemaTargetNamespace = $ns; // server namespace
// REGISTER FUNCTIONS
$input_array = array ('var1' => "xsd:string", 'var2' => "xsd:string"); // "addnumbers" method parameters
$return_array = array ("var3" => "xsd:int", 'var4' => "xsd:string");
$this->nusoap_server->register('send', $input_array, $return_array, "urn:SOAPServerWSDL", "urn:".$ns."send", "rpc", "encoded", "My Addition WS");
}
function index(){
function send($var1, $var2){
$CI =& get_instance();
$CI->load->model('mymodel'); // THIS IS MY MODEL
$data['var1'] = $CI->mymodel->addnumbers($var1, $var2);
$data['var2'] = "yes";
return $data;
}
$this->nusoap_server->service(file_get_contents("php://input"));
}
I know this may not be the best solution but it works perfectly and you are able to load any model using Codeigniter Framework with Nusoap.
Hope this helps as future reference.
If anyone has a better way to load the model please let us know.
I have two cakePHP apps on 2 different servers. One app is required to get data from the first one; I have succeeded to put the Restful architecture in place but I failed to implement an authentication procedure to the requests the server sends. I need to authenticate to secure the data. I have looked around on the web but can't seem to get it working. Can anyone point me to a resource / tutorial that explains this in detail.
What I would ultimately need would be a way to authenticate my server every time it sends a request to the other server. Any help would be appreciated.
I finally got it to work after some research; indeed one of the solutions is OAuth. In case you are facing the same problem, I can advise you this Plugin made for CakePHP.
In details what I did was put the OAuth Plugin into my API Server and I used it like so for my restful controller:
class RestObjectController extends AppController {
public $components = array('RequestHandler', 'OAuth.OAuth');
public $layout = FALSE;
public function token() {
$this->autoRender = false;
try {
$this->OAuth->grantAccessToken();
} catch (OAuth2ServerException $e) {
$e->sendHttpResponse();
}
}
public function index() {
$objects = $this->Object->find('all');
$this->set(array(
'objects' => $objects,
'_serialize' => array('objects')
));
}
The function RestObject.token() is what I would call to get an Access token which will be used to give me access to the Resources in my controller. (Note that by declaring OAuth in my controller components, all the resources within my controller will need an access token to be accessible).
So on the client Server I would get an access token in the following way:
public function acquireAccessToken(){
$this->autoRender = FALSE;
App::uses('HttpSocket', 'Network/Http');
$link = API_SERVER."rest_objects/token";
$data = array(
'grant_type' => 'client_credentials',
'client_id' => 'xxxx',
'client_secret' => 'xxxx'
);
$response = $httpSocket->post($link, $data);
if($response->code == 200){
$data = json_decode($response->body, true);
return $data['access_token'];
}
return FALSE;
}
This assumes that you have clients already set up as explained in the Plugin Doc (replace xxxx by the real values for the client credentials). Once I have my access token, all I have to do is use it as follows:
public function test(){
$this->layout = FALSE;
App::uses('HttpSocket', 'Network/Http');
$httpSocket = new HttpSocket();
if($access_token = $this->acquireAccessToken()){
$link = API_SERVER."rest_objects.json"; //For the index as e.g.
$data = array('access_token' => $access_token);
$response = $httpSocket->get($link, $data);
}
}
And here you have it! So start by reading the Oauth Specification to understand the Protocol (in particular the Obtaining Authorization part), see which protocol (can be different from the one I used) applies and adapt to your case by using the Plugin
Tutorial Here
I am trying to login to my magento's web services from a server that does not have SoapClient enabled. So I figured I would install and use Pear's SOAP_Client but I can't figure out how to login.
With SoapClient I use:
$client = new SoapClient($WSDL);
$session = $client->login($user, $api_key);
$response = $client->call($session, $method, $arguments);
But I can't find an analog to the login method for SOAP_Client
I gather that I should be setting something in the $proxy_params of the constructor, but I can't find what the indexes should be.
$proxy_params = array();
$client = new SOAP_Client($wsdl, true, false, $proxy_params);
$client->call($method, $arguments)
So I figured this out, and there are a couple of factors here.
There isn't a login function for SoapClient, the login I was calling is a call as defined in the WSDL
The various magento API methods are not defined in the WSDL, you provide an argument resource method to method defined as call by the WSDL. This created a bit of confusion because using $client->call() seems to invoke call as defined by the SOAP_Client class, so I need to use $client->call('call') to invoke the SOAP method call
The final code ended up being:
$method = 'catalog_product.info';
$args = array($product_id);
$client = new SOAP_Client($wsdl, true);
$session_id = $client->call(
'login',
array(
'username'=>$username,
'apiKey'=> $pasword
)
);
$ret = $client->call(
'call',
array(
'sessionId'=>$session_id,
'resourcePath'=>$method,
'args'=>$args
)
);
I am trying to call a web service which is expecting a complex type.. I did some research and found this is a big issue in php... maybe somebody has some tips?
Doing basic Soap requests work fine, such as
$client->GetClientById(array('ClientID'=>123');
However, for updating, it is expecting a Client object... I already tried different things such as
$clientobj = $client->GetClientById(array('ClientID'=>123');
$client->UpdateClient($clientobj, $params);
Can anyone suggest me how to acomplish this?
Thanks.
I'd suggest trying SoapVar class. It allows you to specify the type name, etc. Example usage from the manual:
class SOAPStruct {
function SOAPStruct($s, $i, $f)
{
$this->varString = $s;
$this->varInt = $i;
$this->varFloat = $f;
}
}
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
'uri' => "http://test-uri/"));
$struct = new SOAPStruct('arg', 34, 325.325);
$soapstruct = new SoapVar($struct, SOAP_ENC_OBJECT, "SOAPStruct", "http://soapinterop.org/xsd");
$client->echoStruct(new SoapParam($soapstruct, "inputStruct"));