3.3. PHP clients

To make it easier to integrate Cyclos in PHP applications, a PHP library is provided. The library uses web-rpc calls with JSON objects internally, handling requests and responses, as well as mapping exceptions. As such, the same rules described in Section 3.4.2, “Details on JSON handling” are applied. A PHP class is generated for each Cyclos service interface, and all methods are generated on them. The parameters and result types, however, are not generated, and are either handled as strings, numbers, booleans or generic objects (stdclass).

You can download the PHP client for the corresponding Cyclos version here.

3.3.1. Dependencies

  • PHP 5.3 or newer
  • PHP CURL extension (package php5-curl in Debian / Ubuntu)
  • PHP JSON extension (package php5-json in Debian / Ubuntu)

3.3.2. Using services from a 3rd party PHP application

In order to use the Cyclos classes, we first register an autoload function to load the required classes automatically, like this:

function load($c) {
    if (strpos($c, "Cyclos\\") >= 0) {
    include str_replace("\\", "/", $c) . ".php";
    }
}
spl_autoload_register("load");

Then, Cyclos is configured with the server root URL and authentication details:

Cyclos\Configuration::setRootUrl("http://192.168.1.27:8888/england");
Cyclos\Configuration::setAuthentication("admin", "1234");
// OR Cyclos\Configuration::setSessionToken("sessionToken");
// OR Cyclos\Configuration::setAccessClientToken("accessClientToken");

To specify a channel other than Web Services, call Cyclos\Configuration::setChannel("channel");

Afterwards, services can be instantiated using the new operator, and the corresponding methods will be available:

$userService = new Cyclos\UserService();
$page = $userService->search(new stdclass());

3.3.3. Examples

3.3.3.1. Configuration

All the following examples include the configureCyclos.php file, which contains the following:

<?php

function load($c) {
    if (strpos($c, "Cyclos\\") >= 0) {
        include str_replace("\\", "/", $c) . ".php";
    }    
}

spl_autoload_register('load'); 

Cyclos\Configuration::setRootUrl("http://192.168.1.27:8888/england");
Cyclos\Configuration::setAuthentication("admin", "1234");

3.3.3.2. Search users

<?php

require_once 'configureCyclos.php';

$userService = new Cyclos\UserService();
$query = new stdclass();
$query->keywords = 'Consumer*';
$query->pageSize = 5;
$query->ignoreProfileFieldsInList = true;
$page = $userService->search($query);

echo("Found a total of $page->totalCount users\n");

if (!empty($page->pageItems)) {
	foreach ($page->pageItems as $user) {
		echo("* $user->display ($user->shortDisplay)\n");	
	}
}

3.3.3.3. Search advertisements

<?php

require_once 'configureCyclos.php';

$adService = new Cyclos\AdService();
$query = new stdclass();
$query->keywords = 'Computer*';
$query->pageSize = 10;
$query->orderBy = 'PRICE_LOWEST';
$page = $adService->search($query);

echo("Found a total of $page->totalCount advertisements\n");

if (!empty($page->pageItems)) {
	foreach ($page->pageItems as $ad) {
		echo("* $ad->name\n");	
	}
}

3.3.3.4. Login user

<?php

// Configure Cyclos and obtain an instance of LoginService 
require_once 'configureCyclos.php';
$loginService = new Cyclos\LoginService();

// Set the parameters
$params = new stdclass();
$params->user = array("principal" => $_POST['username']);
$params->password = $_POST['password'];
$params->remoteAddress = $_SERVER['REMOTE_ADDR'];

// Perform the login
try {
	$result = $loginService->loginUser($params);
} catch (Cyclos\ConnectionException $e) {
	echo("Cyclos server couldn't be contacted");
	die();
} catch (Cyclos\ServiceException $e) {
	switch ($e->errorCode) {
		case 'VALIDATION':
			echo("Missing username / password");
			break;
		case 'LOGIN':
			echo("Invalid username / password");
			break;
		case 'REMOTE_ADDRESS_BLOCKED':
			echo("Your access is blocked by exceeding invalid login attempts");
			break;
		default:
			echo("Error while performing login: {$e->errorCode}");
			break;
	}
	die();
}

// Redirect the user to Cyclos with the returned session token
header("Location: "
	. Cyclos\Configuration::getRootUrl()
	. "?sessionToken="
	. $result->sessionToken);

3.3.3.5. Perform payment from system to user

<?php
require_once 'configureCyclos.php';

$transactionService = new Cyclos\TransactionService();
$paymentService = new Cyclos\PaymentService();

try {
    $data = $transactionService->getPaymentData('SYSTEM', array('username' => 'c1'));
    
    $parameters = new stdclass();
    $parameters->from = $data->from;
    $parameters->to = $data->to;
    $parameters->type = $data->paymentTypes[0];
    $parameters->amount = 5;
    $parameters->description = "Test from system to user";
    
    $paymentResult = $paymentService->perform($parameters);
    if ($paymentResult->authorizationStatus == 'PENDING_AUTHORIZATION') {
        echo("Not yet authorized\n");
    } else {
        echo("Payment done with id $paymentResult->id\n");
    }
} catch (Cyclos\ServiceException $e) {
    echo("Error while calling $e->service.$e->operation: $e->errorCode");
}

3.3.3.6. Perform payment from user to user

<?php
require_once 'configureCyclos.php';

//Perform the payment from user c1 to c2
Cyclos\Configuration::setAuthentication("c1", "1234");

$transactionService = new Cyclos\TransactionService();
$paymentService = new Cyclos\PaymentService();

try {
    $data = $transactionService->getPaymentData(
        array('username' => 'c1'), 
        array('username' => 'c2'));
    
    $parameters = new stdclass();
    $parameters->from = $data->from;
    $parameters->to = $data->to;
    $parameters->type = $data->paymentTypes[0];
    $parameters->amount = 5;
    $parameters->description = "Test payment to user";
    
    $paymentResult = $paymentService->perform($parameters);
    if ($paymentResult->authorizationStatus == 'PENDING_AUTHORIZATION') {
        echo("Not yet authorized\n");
    } else {
        echo("Payment done with id $paymentResult->id\n");
    }
} catch (Cyclos\ServiceException $e) {
    switch ($e->errorCode) {
        case "VALIDATION":
            echo("Some of the parameters is invalid\n");
            var_dump($e->error);
            break;
        case "INSUFFICIENT_BALANCE":
            echo("Insufficient balance to perform the payment\n");
            break;
        case "MAX_AMOUNT_PER_DAY_EXCEEDED":
            echo("Maximum amount exeeded today\n");
            break;
        default:
            echo("Error with code $e->errorCode while performing the payment\n");
            break;
    }
}

3.3.4. Error handling

All errors thrown by the server are translated into PHP by throwing Cyclos\ServiceException. This class has the following properties:

  • service: The service path which generated the error. For example, paymentService, accountService and so on.
  • operation: The name of the operation which generated the error. Is the same name as the method invoked on the service.
  • errorCode: Is the simple Java exception class name, uppercased, with the word 'Exception' removed. Check the API (as described above) to see which exceptions can be thrown by each service method. Keep in mind that many times the declared exception is a superclass, of many possible concrete exceptions. All methods declare to throw FrameworkException, but it is abstract, and is implemented by several concrete exception types, like PermissionException. In this example, the errorCode will be PERMISSION. Another example is the InsufficientBalanceException class, which has as errorCode the string INSUFFICIENT_BALANCE.
  • error: Contains details about the error. Only some specific exceptions have this field. For example, if the errorCode is VALIDATION, and the exception variable name $e, $e->error->validation will provide information on errors by property, custom field or general errors.