- Overview
- Getting Started
- Reference
- Tutorials
- PHP Quickstart
- Set Up the Soap Client
- Securing the Connection
- getPhone API in PHP
- How to Execute a Soap Call
- The XML for the getPhone Soap Call
- Specifying name and returnedTags
- Getting the Response
- Sample Excerpt of the $response array/object
- Accessing the Elements of the $response
- listUser -- A More Complex AXL Request
- Specify searchCriteria and returnedTags
- A Complete Example of a listUser Request
- addUser - How to Handle Duplicate Tags
- The associatedGroups Tag has Multiple userGroup Tags
- This Will Not Work
- Create a userGroup Class
- Create Objects Based on the userGroup Class
- Load the Objects into an Array
- Complete addUser Code Sample
- PHP FAC/CMC Handling
- Java/JAX-WS Quickstart
- Staying Updated with AXL Schemas
- Managing User Roles
- Configure VG224 Ports
- PHP Quickstart
- Troubleshooting
- Developer Resources
- Community and Support
PHP Quickstart
PHP is a terrific language for processing the AXL Soap API. The built-in Soap handling is very easy to use. Plus, you can install PHP separately from your web server and run PHP scripts from the command line like you would any other scripting language. This tutorial uses PHP 5.6.4 and CUCM 10.5 along with the AXL toolkit that comes with CUCM 10.5.
Set Up the Soap Client
The first thing you want to do is instantiate a Soap client
. You need to specify the AXLAPI.wsdl
WSDL file as the first parameter. In this case, the WSDL file is in the same directory as the PHP code. You should also have the AXLSoap.xsd
and AXLEnums.xsd
files in the same directory. You can get these files from your CUCM installation via the web user interface by going to Application->Plugins
, click Find
and then download the Cisco AXL Toolkit.
Copy<?php
$host="cucm-pub.abc.inc";
$username="Administrator";
$password="password";
$context =
stream_context_create(array('ssl'=>array('verify_peer_name'=>true,
'allow_self_signed'=>true,
'cafile'=>"/var/www/html/PHP-Sample/cucm-pub.abc.inc"
)));
$client = new SoapClient("/var/www/html/PHP-Sample/AXLAPI.wsdl",
array('trace'=>true,
'exceptions'=>true,
'location'=>"https://".$host.":8443/axl",
'login'=>$username,
'password'=>$password,
'stream_context'=>$context
));
?>
Securing the Connection
The AXL service requires a secure HTTPS connection to work. It is best practice, certainly in production, to have the client authenticate the AXL service by checking its certificate. By default PHP will make this attempt, and will fail with a cannot connect to host
error if the certificate check fails.
Copy<?php
$context = stream_context_create(array('ssl'=>array('verify_peer_name'=>true,
'allow_self_signed'=>true,
'cafile'=>"/var/www/html/PHP-Sample/DS-UCM105.cisco.com"
)));
?>
The process for obtaining the CUCM web certificate and making it available to PHP for authentication can differ by browser, OS and PHP config. The following process was used with this sample:
- Use Firefox to browse to the CUCM host, for example https://ds-ucm105.cisco.com
- In the address bar to the far left, click on the 'lock' icon
- Click on More Information > View Certificate > Details
- Click on Export and save the certificate to the PHP application's working directory in 'X.509 Certificate (PEM)' format
Note: The 'stream_context'=>$context
parameter given in the SoapClient constructor. This stream context allows specific parameters for handling of the request context to be given – here we will request that the SSL implementation use the request's host-name to verify the certificate match, that the AXL service's self-signed-certificate be allowed, and that the CUCM certificate previously downloaded above be used as the basis for the check.
Note: To disable certificate checking, for example during development, remove the verify_peer_name
and cafile
array elements, as shown in the Disable certificate checking code sample.
Disable certificate checking
Copy<?php
$context = stream_context_create(array('ssl'=>array('allow_self_signed'=>true)));
?>
getPhone API in PHP
How to Execute a Soap Call
Now that you have instantiated a client
object, you're ready to implement any of the APIs specified in the WSDL. You call getPhone
with $client->getPhone
. In this first example, we simply specify the name of the phone (you have a choice between specifying the name
or the uuid
of the phone). That's all there is to it.
Note: This simple call will return every element for the selected phone. We'll specify which elements to return in the next exercise.
getPhone
Copy<?php
$response = $client->getPhone(array("name"=>"SEP010101010101"));
?>
The XML for the getPhone Soap Call
There are times when you only want to retrieve certain bits of information about a phone. You can specify what you want to see by defining returnedTags
, as shown in this XML sample. In this next example, we narrow the returned data down to name
, description
, product
, model
, class
, and protocol
, as shown in the XML.
getPhone XML
Copy<soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="https://www.cisco.com/AXL/API/10.5">
<soapenv:Header/>
<soapenv:Body>
<ns:getPhone sequence="?">
<name>SEP010101010101</name>
<!-- OR <uuid>uuid-goes-here</uuid> -->
<returnedTags ctiid="?" uuid="?">
<name/>
<description/>
<product/>
<model/>
<class/>
<protocol/>
</returnedTags>
</ns:getPhone>
</soapenv:Body>
</soapenv:Envelope>
Specifying name and returnedTags
Note that we created a single array of two elements, name
and returnedTags
. However, the latter element, returnedTags
points to another array of the names of the elements we want returned. Each of these key=>value
pairs points to an empty string. This is equivalent to creating a closed XML tag like <name/>
or <description/>
.
Copy<?php
$payload = array(
"name"=>"SEP010101010101",
"returnedTags"=>array("name"=>"",
"description"=>"",
"product"=>"",
"class"=>"",
"protocol"=>""
)
);
$response = $client->getPhone($payload);
?>
Getting the Response
This time, let's take a look at the $response
, which is an array of objects you can traverse to get the returned information. If you're not sure how to interpret the $response
object that comes back, you can employ this little trick to examine the information.
This code will echo to your browser the entire structure of the $response
object.
A trick to peek at the complete $response
Copy<?php
echo "<pre>";
var_dump(get_object_vars($response));
echo "</pre>";
?>
Sample Excerpt of the $response array/object
This is a sample of the information as a result of the var_dump
. The main key in this array is return
, which points to the object phone
, which, in turn, points to various properties of that object, strings of data. So if you want to see the name of the phone, you would access the name with $response->return->phone->name
.
Copy<?php
array(1) {
["return"]=>
object(stdClass)#3 (1) {
["phone"]=>
object(stdClass)#4 (7) {
["name"]=>
string(15) "SEP010101010101"
["description"]=>
string(13) "npetrele CIPC"
["product"]=>
string(21) "Cisco IP Communicator"
["class"]=>
string(5) "Phone"
["protocol"]=>
string(3) "SIP"
["ctiid"]=>
int(21)
["uuid"]=>
string(38) "{BCD3D84F-AE8C-7A97-D555-DCB326D0DEEB}"
}
}
}?>
Accessing the Elements of the $response
Now that we know the structure of the $response
, we can access the data we need with a handful of simple lines of code.
This completes our getPhone
example.
Now you know how to access the details you want from $response
Copy<?php
echo("Name: ".$response->return->phone->name)."<br>";
echo("Description: ".$response->return->phone->description)."<br>";
echo("Product: ".$response->return->phone->product)."<br>";
echo("Class: ".$response->return->phone->class)."<br>";
echo("Protocol: ".$response->return->phone->protocol)."<br>";
?>
listUser -- A More Complex AXL Request
Specify searchCriteria and returnedTags
Now let's look at an AXL request that includes both searchCriteria
and returnedTags
.
Examine the XML for this request. If you check the WSDL file, you'll see that you can search by firstName
, lastName
, userid
, and department
. This example searches only by userid
, and we use the wild card %
so that we'll end up listing every user.
This example also specifies firstName
, lastName
and userid
as the returned tags.
XML for listUser defining returned tags
Copy<soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="https://www.cisco.com/AXL/API/10.5">
<soapenv:Header/>
<soapenv:Body>
<ns:listUser sequence="?">
<searchCriteria>
<userid>%</userid>
</searchCriteria>
<returnedTags uuid="?">
<firstName/>
<lastName/>
<userid/>
</returnedTags>
</ns:listUser>
</soapenv:Body>
</soapenv:Envelope>
A Complete Example of a listUser Request
Here is a working example of listUser
, including code to iterate through the returned values and echo them to the screen or browser. We pass both the search criteria and specified returned tags as arrays to the Soap client. As we did in the getPhone
example, we specify key=>value
pairs pointing to empty strings for the returned tags.
Note: This example also uses exception handling for the API call.
Here's how you translate that XML into PHP Soap code, and then list the results
Copy<?php
$host="cucm-pub.abc.inc";
$username="Administrator";
$password="password";
$context = stream_context_create(array('ssl'=>array('verify_peer_name'=>true,
'allow_self_signed'=>true,
'cafile'=>"/var/www/html/PHP-Sample/cucm-pub.abc.inc"
)));
$client = new SoapClient("/var/www/html/PHP-Sample/AXLAPI.wsdl",
array('trace'=>true,
'exceptions'=>true,
'location'=>"https://".$host.":8443/axl",
'login'=>$username,
'password'=>$password,
'stream_context'=>$context
));
// Just set every tag you want returned to an empty string ("") in this array
$returnedTags = array("firstName"=>"","lastName"=>"","userid"=>"");
// "%" is a wild card to find every user
$searchCriteria = array("userid"=>"%");
try {
$response = $client->listUser(array("returnedTags"=>
$returnedTags,"searchCriteria"=>$searchCriteria));
}
catch (SoapFault $sf) {
echo "SoapFault: " . $sf . "<BR>";
}
catch (Exception $e) {
echo "Exception: ". $e ."<br>";
}
// Iterate through array of returned values (as specified by $returnedTags)
foreach($response->return->user as $user) {
echo("First Name: ".$user->firstName."<br>");
echo("Last Name: ".$user->lastName."<br>");
echo("User ID: ".$user->userid."<br>");
echo("<hr>");
}
?>
addUser - How to Handle Duplicate Tags
The associatedGroups Tag has Multiple userGroup Tags
Up until now, we've been passing arrays to the AXL functions. That is precisely what makes AXL and PHP so easy.
However, arrays can present a problem when the XML must include duplicate tags. For example, suppose you want to add a user and define a number of the user's associated groups. Note that this would require duplicate userGroup
keys.
Copy<soapenv:Envelope xmlns:soapenv="https://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="https://www.cisco.com/AXL/API/10.5">
<soapenv:Header/>
<soapenv:Body>
<ns:addUser sequence="?">
<user>
<firstName>Joey</firstName>
<lastName>Bishop</lastName>
<userid>joey</userid>
<password>bishop</password>
<enableCti>true</enableCti>
<enableMobility>true</enableMobility>
<imAndPresenceEnable>true</imAndPresenceEnable>
<associatedGroups>
<userGroup>
<name>Application Client Users</name>
</userGroup>
<userGroup>
<name>Standard CTI Enabled</name>
</userGroup>
<userGroup>
<name>Standard CTI Secure Connection</name>
</userGroup>
<userGroup>
<name>Third Party Application Users</name>
</userGroup>
</associatedGroups>
</user>
</ns:addUser>
</soapenv:Body>
</soapenv:Envelope>
Up until now, we've been passing arrays to the AXL functions. That is precisely what makes AXL and PHP so easy.
However, arrays can present a problem when the XML must include duplicate tags. For example, suppose you want to add a user and define a number of the user's associated groups. Note that this would require duplicate userGroup
keys.
This Will Not Work
You can't load a PHP array with multiple key=>value
pairs where the key is always userGroup
. Actually, PHP won't complain if you define an array that way, but you won't get the correct results, because PHP expects array keys to be unique.
Copy<?php
array(
"userGroup"=>array("name"=>"Application Client Users"),
"userGroup"=>array("name"=>"Standard CTI Enabled"),
"userGroup"=>array("name"=>"Standard CTI Secure Connection"),
"userGroup"=>array("name"=>"Third Party Application Users")
);
?>
Create a userGroup Class
Because you can't use an array of userGroup
tags, use instead an array of objects with properties. First, create the class userGroup
with the property name
.
Instead, create a userGroup class
Copy<?php
class userGroup
{
public $name;
}
?>
Create Objects Based on the userGroup Class
Create objects instead of an array of key=>value
pairs
Now you can create multiple userGroup
objects and define the name property as you would have if it was an array value.
Copy<?php
$userGroup1 = new userGroup();
$userGroup2 = new userGroup();
$userGroup3 = new userGroup();
$userGroup4 = new userGroup();
$userGroup1->name = 'Application Client Users';
$userGroup2->name = 'Standard CTI Enabled';
$userGroup3->name = 'Standard CTI Secure Connection';
$userGroup4->name = 'Third Party Application Users';
?>
Load the Objects into an Array
Then you can load these userGroup
objects into an array. An array of objects does not violate the unique key requirement for PHP arrays of keys in key=>value
pairs.
Array of objects
Copy<?php
$something = array(
$userGroup1,
$userGroup2,
$userGroup3,
$userGroup4);
?>
Complete addUser Code Sample
Now let's put that all together as a sample application that adds the user Joey Bishop.
Complete code sample integrating the array of objects
Copy<?php
$host="cucm-pub.abc.inc";
$username="Administrator";
$password="password";
$context = stream_context_create(array('ssl'=>array('verify_peer_name'=>true,
'allow_self_signed'=>true,
'cafile'=>"/var/www/html/PHP-Sample/cucm-pub.abc.inc"
)));
$client = new SoapClient("/var/www/html/PHP-Sample/AXLAPI.wsdl",
array('trace'=>true,
'exceptions'=>true,
'location'=>"https://".$host.":8443/axl",
'login'=>$username,
'password'=>$password,
'stream_context'=>$context
));
class userGroup
{
public $name;
}
echo "<p>Add User Test</p>";
$userGroup1 = new userGroup();
$userGroup2 = new userGroup();
$userGroup3 = new userGroup();
$userGroup4 = new userGroup();
$userGroup1->name = 'Application Client Users';
$userGroup2->name = 'Standard CTI Enabled';
$userGroup3->name = 'Standard CTI Secure Connection';
$userGroup4->name = 'Third Party Application Users';
$user=array("user"=>
array("firstName"=>"Joey",
"lastName"=>"Bishop",
"userid"=>"joey",
"password"=>"bishop",
"enableCti"=>"true",
"enableMobility"=>"true",
"imAndPresenceEnable"=>"true",
"presenceGroupName"=>"Standard Presence group",
"associatedGroups"=>array(
$userGroup1,
$userGroup2,
$userGroup3,
$userGroup4)
)
);
try {
$response = $client->addUser($user);
}
catch (SoapFault $sf) {
echo "SoapFault: " . $sf . "<BR>";
}
catch (Exception $e) {
echo "Exception: ". $e ."<br>";
}
?>