Citrix GoToWebinar API Response with teodortalov/citrix - php

Thank you for taking the time to review my question.
I have been trying to implement the Citrix Go2Webinar Api and found this nice framework: https://github.com/teodortalov/citrix
I have successfully registered users, but I can't figure out how to get the response from the API.
public function user_registration($user, $webinar_id)
{
$client = new \Citrix\Authentication\Direct([$this->api_key]);
$client->auth($this->username, $this->password);
$webinar = new \Citrix\GoToWebinar($client);
$registration = array('firstName' => $user['first_name'], 'lastName' => $user['last_name'], 'email' => $user['email']);
$registrant = $webinar->register($webinar_id, $registration);
return $registrant;
}
The response I get looks like a bunch of protected variables. My question shouldn't I be able to call a method to get the formatted response which looks like what the Citrix API expects to return:
{
"registrantKey": 0,
"joinUrl": "string"
}

those methods are in consumer.php
$registrant = $webinar->register($webinar_id, $registration);
$myJoinUrl = $registration->getJoinUrl();
$myRegistrantKey = $registration->getId();

Related

Build correct SOAP Request Header (PHP)

I have to do requets to a SOAP API with PHP and I need the following SOAP-Header structure:
<soapenv:Header>
<ver:authentication>
<pw>xxx</pw>
<user>xxx</user>
</ver:authentication>
</soapenv:Header>
How can I build this header?
I tried
$auth = [
"ver:authentication" => [
"pw" => $this->pw,
"user" => $this->user
]
];
$options = [];
$options["trace"] = TRUE;
$options["cache_wsdl"] = WSDL_CACHE_NONE;
$options["compression"] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP;
$client = new SoapClient("www.my-url.com/wsdl", $options);
$header = new SoapHeader("www.my-url.com", "authentication", $auth, false);
$client->__setSoapHeaders($header);
but it does not work. The respons is "failure" which I get, when the header structure is incorrect...
please help
the solution could be object driven. In the following code an example is given. Please keep in mind, that the following code is not testet.
class Authentication
{
protected $user;
protected $pw;
public function getUser() : ?string
{
return $this->user;
}
public function setUser(string $user) : Authentication
{
$this->user = $user;
return $this;
}
public function getPw() : string
{
return $this->pw;
}
public function setPw(string $pw) : Authentication
{
$this->pw = $pw;
return $this;
}
}
The above shown class is a simple entity, which contains two properties $user fpr the username and $pw for the password. Further it contains the getter and setter functions for retrieving or setting the values for the two properties.
For the next step just fill the class with data and store it in a SoapVar object.
$authentication = (new Authentication())
->setUser('Username')
->setPw('YourEncodedPassword');
$soapEncodedObject = new \SoapVar(
$authentication,
SOAP_ENC_OBJECT,
null,
null,
'authentication',
'http://www.example.com/namespace'
);
As you can see above, your authentication class will be stored as soap var object. It is encoded as soap object. The only thing you have to do is setting the namespace for this object. In your given example it is ver:. With this namespace prefix somewhere in your wsdl file a namespace is noted. You have to find out this namespace url and just replace the example url http://www.example.com/namespace with the right url noted in your wsdl.
The next step is setting this as soap header. That 's quite simple.
try {
$client = new SoapClient('http://www.example.com/?wsdl', [
'trace' => true,
'exception' => true,
'cache_wsdl' => WSDL_CACHE_NONE,
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
]);
// set the soap header
$header = new SoapHeader('http://www.example.com/namespace', 'authentication', $authentication, false);
$client->setSoapHeaders($header);
// send the request
$result = $client->someWsdlFunction($params);
} catch (SoapFault $e) {
echo "<pre>";
var_dump($e);
echo "</pre>";
if ($client) {
echo "<pre>";
var_dump($client->__getLastRequest());
echo "</pre>";
echo "<pre>";
var_dump($client->__getLastResponse());
echo "</pre>";
}
}
As you can see it 's a bit different from your given example. Instead of an array it 's the soap encoded authentication object, that is given to the soap header class. For failure purposes there is a try/catch block around your soap client. In that case you can identify the error and if the client was initiated correctly, you can also see the last request and last response in xml.
I hope, that I helped you. ;)
I would strongly advise you 2 things:
Use a WSDL to PHP generator in order to properly construct your request. In addition, it will ease you the response handling. Everything is then using the OOP which is much better. Take a look to the PackageGenerator project.
Use the WsSecurity project in order to easily add your dedicated SoapHeader without wondering how to construct it neither.

PHPUnit and mock request from Guzzle

I have a class with the following function :
public function get(string $uri) : stdClass
{
$this->client = new Client;
$response = $this->client->request(
'GET',
$uri,
$this->headers
);
return json_decode($response->getBody());
}
How can I mock the request method from PHPUnit? I tried different ways but it always tries to connect to the uri specified.
I tried with :
$clientMock = $this->getMockBuilder('GuzzleHttp\Client')
->setMethods('request')
->getMock();
$clientMock->expects($this->once())
->method('request')
->willReturn('{}');
But this didn't work. What can I do? I just need to mock the response to be empty.
Thanks
PD : Client comes from (use GuzzleHttp\Client)
I think as suggested is better to use http://docs.guzzlephp.org/en/stable/testing.html#mock-handler
as it looks like the most elegant way to do it properly.
Thank you all
The mocked Response doesn't need to be anything in particular, your code just expects it to be an object with a getBody method. So you can just use a stdClass, with a getBody method which returns some json_encoded object. Something like:
$jsonObject = json_encode(['foo']);
$uri = 'path/to/foo/bar/';
$mockResponse = $this->getMockBuilder(\stdClass::class)->getMock();
$mockResponse->method('getBody')->willReturn($jsonObject);
$clientMock = $this->getMockBuilder('GuzzleHttp\Client')->getMock();
$clientMock->expects($this->once())
->method('request')
->with(
'GET',
$uri,
$this->anything()
)
->willReturn($mockResponse);
$result = $yourClass->get($uri);
$expected = json_decode($jsonObject);
$this->assertSame($expected, $result);
I prefer this way to mock a Client in PHP. In this example I am using Guzzle Client.
Clone the code or install it via composer
$ composer require doppiogancio/mocked-client
And then...
$builder = new HandlerStackBuilder();
// Add a route with a response via callback
$builder->addRoute(
'GET', '/country/IT', static function (ServerRequestInterface $request): Response {
return new Response(200, [], '{"id":"+39","code":"IT","name":"Italy"}');
}
);
// Add a route with a response in a text file
$builder->addRouteWithFile('GET', '/country/IT/json', __DIR__ . '/fixtures/country.json');
// Add a route with a response in a string
$builder->addRouteWithFile('GET', '{"id":"+39","code":"IT","name":"Italy"}');
// Add a route mocking directly the response
$builder->addRouteWithResponse('GET', '/admin/dashboard', new Response(401));
$client = new Client(['handler' => $builder->build()]);
Once you have mocked the client you can use it like this:
$response = $client->request('GET', '/country/DE/json');
$body = (string) $response->getBody();
$country = json_decode($body, true);
print_r($country);
// will return
Array
(
[id] => +49
[code] => DE
[name] => Germany
)
In addition to the current answer about using MockHandler, it's possible to process the request so that you can validate the calls.
The following example passes a callable which just tests the request method and throws an exception if not POST, if that is OK it returns the response. The principle can be expanded to test other details about the request...
$mock = new MockHandler([
function ($request) {
$this->assertEquals('POST', $request->getMethod());
return new Response(
200,
[],
json_encode([ "access_token" => '1234e' ])
);
},
new Response(
200,
[],
json_encode([ "details" =>
[
[
"orderID" => 229783,
],
[
"orderID" => 416270,
],
],
])
),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
So the first call to the client has the test included, the second call just returns a response.
Just noticed that any time you use a callable to process the request, you MUST return a Response object if you expect the process to continue.

Plivo - 404 error, call not found, when I try to record inbound call

I am trying to record the inbound call but so far I am only getting the 404 call not found error when record is activated.
This is my code so far (I am using Laravel and latest Plivo SDK):
public function __construct(Request $request)
{
$this->authId = config('AUTH_ID');
$this->authToken = config('AUTH_TOKEN');
$this->sourceNumber = config('sms.SMS_SOURCE_NUMBER');
$this->_answerURL = config('voiceCall.CALL_ANSWER_URL');
$this->_recordURL = config('voiceCall.INBOUND_RECORD_URL');
$this->_hangupURL = config('voiceCall.HANGUP_URL');
$this->_plivo = new RestClient($this->authId, $this->authToken);
$this->_response = new Response();
$this->_mp3Url = 'https://s3.amazonaws.com/plivocloud/Trumpet.mp3';
$this->_request = $request;
}
The answer method:
public function answer()
{
$response = $this->_response;
$response->addPlay($this->_mp3Url);
$response->addRecord([
'action' => $this->_recordURL,
'startOnDialAnswer' => "true",
'redirect' => "false",
'maxLength' => 600
]);
Log::useDailyFiles(storage_path().'/logs/debug.log');
Log::info([
'Record' => 'This is from inbound answer',
'Response' => $response
]);
return response($response->toXML(), 200)
->header('Content-Type', 'text/xml');
}
The record method:
public function record()
{
Log::useDailyFiles(storage_path().'/logs/debug.log');
$uuid = $this->_request->input('CallUUID');
Log::info(['This is Call UUID' => $uuid]);
$response = $this->_plivo->calls->startRecording($uuid);
Log::info([
'Record' => 'This is from record inbound record',
'Response' => $response,
'CallUUID' => $this->_request->input('CallUUID'),
'Request' => $this->_request->all(),
]);
}
The request is giving back the proper call uuid, and
$response = $this->_plivo->calls->startRecording($uuid);
is the code which is used in the docs. Does anyone have an idea what am I doing wrong here?
Plivo Sales Engineer here.
Is this an incoming call to your Plivo number? I see that you're returning an XML that contains a Play and Record element. This Record XML will take care of recording the call after the Play ends.
Are you making a Record API request to record this again? Which Call UUID are you passing to this API request?
For an inbound call, the Call UUID is sent to the answer URL. Are you using this Call UUID?

PHP SOAP Client Error for none build-in functions

There is a wcf server and I am trying to connect it and send requests.
The code is :
$url = "http://serverip:8080/example.svc?wsdl";
$params = array(
'Username' => 'username',
'Password' => 'password'
);
$client = new SoapClient($url);
var_dump($client->__getTypes()); //it works
$result = $client->Login($params); //gives error
But everytime I am getting internal server error. I spend 5 days and searhed all the web and tried all different methods but I am always getting internal server error. Error is below :
protected 'message' => string 'The server was unable to process ...
private 'string' (Exception) => string '' (length=0) ...
If I use SOAP UI I can send and get data or if I call "$client->__getTypes()" from php server, I get types. But if I call implemented functions with PHP it doesn't work. Are there anyone to help me?
Thanks a lot,
Perhaps you should pass the parameters as object as in the following example
try {
$client = new SoapClient('http://serverip:8080/example.svc?wsdl');
$params = new stdClass();
$params->Username = 'Username';
$params->Password = 'Password';
$client->Login($params);
} catch (SoapFault $e) {
// error handling
}

Calling WCF with PHP -- variable structures

I have a WCF Service written in .Net 4.0 that accepts two parameters. One is a complex type consisting of User, MerchantName, and Password, the second variable is an int. The service returns a third complex type.
It's structure looks like the following:
//*C# Code *
public sub AccountData Log(Login LoginData, int AccountID)
{
//do stuff here
}
Using SoapClient and removing the int AccountID from the C# service, I can pass the complex data in and parse through the complex data output succesfully. Adding the AccountID parameter, breaks the soap call. I can't seem to compound the variables into one array in a fashion that WCF will accept.
The question is how to form the array to pass in the call?
I have tried the following:
//****Attempt one *******
$login = array('MerchantName' => 'merchantA',
'User' => 'userA',
'password' => 'passwordA');
$account = '68115'; //(also tried $account = 68115; and $account = (int)68115;)
$params = array('LoginData' => $login, 'AccountID' => $account);
$send = (object)$params; //Have tried sending as an object and not.
$client = new SoapClient($wsdl);
$client->soap_defencoding = 'UTF-8';
$result = $client->__soapCall('Log', array($send);
var_dump($send);
echo("<pre>");
var_dump($result);
The latest attempt was to class the variables but I got stuck when tring to form into the $client call.
class LogVar
{
public $MerchantName;
public $User;
public $Password;
}
class AccountID
{
public $AccountID;
}
$classLogin = new LogVar();
$classLogin->MerchantName = 'merchantA';
$classLogin->User = 'userA';
$classLogin->Password = 'passwordA';
$classAccount = new AccountID();
$classAccount->AccountID = '68115';
//How to get to $client->__soapCall('Log', ???????);
P.S. I'm a .Net coder, please be kind with the PHP explanations... Also NuSoap didn't seem much better, however it may have undiscovered ways of dealing with complex types.
This worked for me with standard SoapClient:
$client = new SoapClient($wsdl, array('trace' => true));
$data = $client->Log(array('AccountID' => 23, 'LoginData' => array('User' => '123', 'Password' => '123', 'MerchantName' => '123')));
// echo $client->__getLastRequest();
var_dump($data);
You can display the last request XML and compare it with what a WCF client is generating. This is how I figured it out: I generated a WCF client, inspected the XML message generated by it and compared to $client->__getLastRequest.
Note: You can call the method by its name on a SoapClient rather than use $client->__soapCall('operationName')

Categories