Services 6.x-2.0 PHP xmlrpc example with api key
Last updated on
30 April 2025
Here's some working logic that I cobbled together from various partial examples online and the deploy module. It's rough, but works. The key difference in this example from others is the fact that this version only uses Drupal API routines, rather than the 'experimental' PHP routines such as xmlrpc_encode_request() ( see http://php.net/manual/en/function.xmlrpc-encode-request.php ) and xmlrpc_decode(). Such routines may not exist in some environments and are also subject to change.
<?php
/***************************************************/
class DrupalXmlrpc {
function __construct( $domain = '', $apiKey = '', $endPoint = '', $verbose = FALSE )
{
// set local domain or IP address
// this needs to match the domain set when you created the API key
$this->domain = $domain;
// set API key
$this->kid = $apiKey;
// set target web service endpoint
$this->endpoint = $endPoint;
// extended debugging
$this->verbose = $verbose;
// call system.connect to get our required anonymous sessionId:
$retVal = $this->send( 'system.connect', array() );
$this->session_id = $retVal['sessid'];
if ($this->verbose) {
$func = 'DrupalXmlrpc->__construct:';
if ($this->session_id)
error_log( $func.' got anonymous session id fine' );
else error_log( $func.' failed to get anonymous session id!' );
}
}
/***********************************************************************
* Function for sending xmlrpc requests
*/
public function send( $methodName, $functionArgs = array() )
{
$protocolArgs = array();
// only the system.connect method does not require a sessionId:
if ($methodName == 'system.connect') {
$protocolArgs = array( $this->endpoint, $methodName );
}
else {
$timestamp = (string)time();
$nonce = $this->getUniqueCode("10");
// prepare a hash
$hash_parameters = array( $timestamp, $this->domain, $nonce, $methodName );
$hash = hash_hmac("sha256", implode(';', $hash_parameters), $this->kid);
// prepared the arguments for this service:
// note, the sessid needs to be the one returned by user.login
$protocolArgs = array( $this->endpoint, $methodName, $hash, $this->domain, $timestamp, $nonce, $this->session_id );
}
$params = array_merge( $protocolArgs, $functionArgs );
return call_user_func_array( 'xmlrpc', $params );
}
/***************************************************
* login and return user object
*/
public function userLogin( $userName = '', $userPass = '' )
{
if ($this->verbose)
error_log( 'DrupalXmlrpc->userLogin() called with userName "'.$userName.'" and pass "'.$userPass.'"' );
// clear out any lingering xmlrpc errors:
xmlrpc_error( NULL, NULL, TRUE );
$retVal = $this->send( 'user.login', array($userName, $userPass) );
if (!$retVal && xmlrpc_errno()) {
if ($this->verbose)
error_log( 'userLogin() failed! errno "'.xmlrpc_errno().'" msg "'.xmlrpc_error_msg().'"' );
return FALSE;
}
else {
// remember our logged in session id:
$this->session_id = $retVal['sessid'];
// we might need the user object later, so save it:
$user = new stdClass();
$user = (object)$response['user'];
$this->authenticated_user = $user;
return $user;
}
}
/***************************************************
* logout, returns 0 for okay, or -1 for error.
*/
public function userLogout()
{
$retVal = $this->send( 'user.logout', array() );
if (!$retVal) {
if ($this->verbose)
error_log( 'userLogout() failed! errno "'.xmlrpc_errno().'" msg "'.xmlrpc_error_msg().'"' );
return -1;
}
return 0; // meaning okay
}
/***************************************************
* Function for generating a random string, used for
* generating a token for the XML-RPC session
*/
private function getUniqueCode($length = "")
{
$code = md5(uniqid(rand(), true));
if ($length != "")
return substr($code, 0, $length);
else return $code;
}
}
?>
Use it like this:
<?php
// create a drupal session:
$localDomain = 'whatever domain you used when you created this api key';
$apiKey = 'Services generated api key string';
$endPoint = 'url to your destination endpoint';
$drupalSession = new DrupalXmlrpc( $localDomain, $apiKey, $endPoint );
if ($drupalSession->session_id) {
$userName = 'username used to login to remote system';
$userPass = 'password of user on remote system';
$drupalUser = $drupalSession->userLogin( $userName, $userPass );
if ($drupalUser) {
$result = $drupalSession->send( 'method.name-of-remote-function, array(remote-functions-parameters-in-an-array) );
if ($result == -1)
$retVal = SOME_SYMBOL_MEANING_REMOTE_WORK_FAILED;
$drupalSession->userLogout(); // all done communicating, so logout
}
else {
$retVal = SOME_SYMBOL_MEANING_LOGIN_FAILED;
}
}
else {
$retVal = SOME_SYMBOL_MEANING_CONNECTION_FAILED;
}
?>
I hope this is useful for others.
Help improve this page
Page status: Not set
You can:
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion