Manage CMC and FAC with PHP and AXL

This is a tutorial on how to use PHP and AXL to manage your Client Matter Codes and Forced Authorization Codes. We’ll start by reviewing how to create a PHP Soap Client for AXL, and then address the various ways to manage these codes. This tutorial uses PHP 5.5.15 and CUCM 10.5 along with the AXL toolkit that comes with CUCM 10.5.

PHP Soap Client

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.

Set up the Soap client

Set up the Soap client

<?php
    $host="hostname";
    $username="username";
    $password="password";

    $client = new SoapClient("AXLAPI.wsdl",
        array('trace'=>true,
       'exceptions'=>true,
       'location'=>"https://".$host.":8443/axl",
       'login'=>$username,
       'password'=>$password,
    ));
?>

The first thing you want to do is instantiate a Soap client object. You need to specify the AXLAPI.wsdl WSDL file as the first parameter. In this case, we placed the WSDL file 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.

Client Matter Code (CMC) handling

CMC

Client Matter Codes (CMC) assist with call accounting and billing for billable clients. A CMC forces the user to enter a code to specify that the call relates to a specific client matter. You can assign client matter codes to customers, students, or other populations for call accounting and billing purposes.

List CMC Info

List CMC Info

<?php
    function listCmcInfo($client) {

        // Just set every tag you want returned to "" in this array
        $returnedTags = array("code"=>"","description"=>"");

        // "%" is a wild card to find every CMC
        $searchCriteria = array("code"=>"%");

        try {
            $response = $client->listCmcInfo(array("returnedTags"=>$returnedTags,
                                "searchCriteria"=>$searchCriteria));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }
?>

Start by writing a function to list the CMC information you already have stored. You can define the tags you want returned from the list command as an array of the desired elements pointing to empty strings.

Then define the search criteria. This example returns all CMC entries because the code in the search criteria is set to the wild card %.

Now that you’ve defined the searchCriteria and the returnedTags, proceed with the listCmcInfo Soap request function.

Handling the returned data

Handle the returned data

<?php 
        // Iterate through array of returned values (as specified by $returnedTags)
        // Make sure it's an array before iterating through it
        if ( is_array($response->return->cmcInfo) ) {
            foreach($response->return->cmcInfo as $cmcInfo) {
                echo("Uuid: ".$cmcInfo->uuid."<br>");
                echo("Code: ".$cmcInfo->code."<br>");
                echo("Description: ".$cmcInfo->description."<br>");
                echo("<hr>");
            }
        // if it's not an array, then just get the values
        } else {
            echo("Uuid: ".$response->return->cmcInfo->uuid."<br>");
            echo("Code: ".$response->return->cmcInfo->code."<br>");
            echo("Description: ".$response->return->cmcInfo->description."<br>");
            echo("<hr>");
        }
    } // end function
?>

If there is only one CMC entry, $response->return->cmcInfo will be an object. If there are multiple CMC entries, $response->return->cmcInfo will be an array of cmcInfo objects. We can handle both possibilities by checking to see if $response->return->cmcInfo is an array with is_array.

This function will print the CMC uuid, code and description for one or more entries, depending on how many you have created. On our test system, there are three entries:

Uuid: {78E07494-EDAE-980E-383B-18EC7948AE1F}
Code: 777
Description: Heavenly Calls

Uuid: {3420C42A-DDD9-B7D2-CDEE-74B5F427F09F}
Code: 666
Description: Helly Calls

Uuid: {825703AF-FA47-42DC-AC9F-87EDA26119CF}
Code: 555
Description: Earthly Calls

Get CMC Info

Get CMC Info

<?php
    function getCmcInfo($client,$code) {

        // Just set every tag you want returned to "" in this array
        $returnedTags = array("code"=>"","description"=>"");

        try {
            $response = $client->getCmcInfo(array("code"=>$code),array("returnedTags"=>$returnedTags));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }

        echo("Uuid: ".$response->return->cmcInfo->uuid."<br>");
        echo("Code: ".$response->return->cmcInfo->code."<br>");
        echo("Description: ".$response->return->cmcInfo->description."<br>");
        echo("<hr>");
    }
?>

If you want to retrieve information about a single CMC info entry, use the getCmcInfo API call. You can retrieve it by code or by uuid. This example retrieves it by the code tag.

As with most PHP AXL requests, this contains the XML information stored as arrays and arrays within arrays (nested arrays), mirroring the nesting in the XML.

Here’s how the arrays mirror the XML:

<code>somecode</code> <- array(“code”=>“somecode”);
<returnedTags> <- array(“returnedTags”=>array(
    <code/> <- “code”=>“”,
    <description/> <- “description”=>“”)
</returnedTags> <- );

Removing a CMC entry

Remove a CMC entry

<?php
    function removeCmcInfo($client,$code) {
        try {
            $response = $client->removeCmcInfo(array("code"=>$code));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }
    }
?>

Identify the entry you want deleted by code or by uuid. Then, invoke the removeCmcInfo API to delete that entry. Our example removes an entry by code.

Adding a CMC entry

Add a CMC entry

<?php
    function addCmcInfo($client,$code,$description) {
        $cmcInfo = array("code"=>$code,"description"=>$description);
        try {
            $response = $client->addCmcInfo(array("cmcInfo"=>$cmcInfo));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }
    }
?>

A Client Matter Code consists of only a dial code and a description. Simply define the code and description in an array, and invoke the addCmcInfo API to add a new CMC.

Updating a CMC entry

Update a CMC entry

<?php
    function updateCmcInfo($client,$code,$description) {
        // update the CMC information
        try {
            $response = $client->updateCmcInfo(array("code"=>$code,"description"=>$description));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }
    }
?>

You can update a CMC entry by identifying the entry by code or by uuid. In this example, we only want to update the description. If you don’t want to change the code when you perform the update, then you only need to specify the code as your search term and then change the value for description.

If you want to change the code with the update in addition to the description, then set "code"=>$old_code and "newCode"=>$new_code in the array you pass to the API (with the desired values in the variables $old_code and $new_code). If you want to leave the description alone, just omit it from the array. For example, $client->updateCmcInfo(array("code"=>$old_code,"newCode"=>$new_code).

Putting it all together

A complete sample application

<?php

    echo "<h1>CMC Info Test</h1>";

    $host="hostname";
    $username="username";
    $password="password";

    $client = new SoapClient("AXLAPI.wsdl",
        array('trace'=>true,
       'exceptions'=>true,
       'location'=>"https://".$host.":8443/axl",
       'login'=>$username,
       'password'=>$password,
    ));


    function listCmcInfo($client) {

        // Just set every tag you want returned to "" in this array
        $returnedTags = array("code"=>"","description"=>"");

        // "%" is a wild card to find every CMC
        $searchCriteria = array("code"=>"%");

        try {
            $response = $client->listCmcInfo(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)
        // Make sure it's an array before iterating through it
        if ( is_array($response->return->cmcInfo) ) {
            foreach($response->return->cmcInfo as $cmcInfo) {
                echo("Uuid: ".$cmcInfo->uuid."<br>");
                echo("Code: ".$cmcInfo->code."<br>");
                echo("Description: ".$cmcInfo->description."<br>");
                echo("<hr>");
            }
        // if it's not an array, then just get the values
        } else {
            echo("Uuid: ".$response->return->cmcInfo->uuid."<br>");
            echo("Code: ".$response->return->cmcInfo->code."<br>");
            echo("Description: ".$response->return->cmcInfo->description."<br>");
            echo("<hr>");
        }
    }

    function getCmcInfo($client,$code) {

        // Just set every tag you want returned to "" in this array
        $returnedTags = array("code"=>"","description"=>"");

        try {
            $response = $client->getCmcInfo(array("code"=>$code),array("returnedTags"=>$returnedTags));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }

        echo("Uuid: ".$response->return->cmcInfo->uuid."<br>");
        echo("Code: ".$response->return->cmcInfo->code."<br>");
        echo("Description: ".$response->return->cmcInfo->description."<br>");
        echo("<hr>");
    }

    function removeCmcInfo($client,$code) {
        try {
            $response = $client->removeCmcInfo(array("code"=>$code));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }
    }

    function addCmcInfo($client,$code,$description) {
        $cmcInfo = array("code"=>$code,"description"=>$description);
        try {
            $response = $client->addCmcInfo(array("cmcInfo"=>$cmcInfo));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }
    }

    function updateCmcInfo($client,$code,$description) {
        // update the CMC information
        try {
            $response = $client->updateCmcInfo(array("code"=>$code,"description"=>$description));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<br>";
        }
    }

    echo "<h2>List CMC Info</h2>";
    listCmcInfo($client);

    echo "<h2>Get CMC Info</h2>";
    getCmcInfo($client,"777");

    echo "<h2>Remove CMC Info</h2>";
    removeCmcInfo($client,"555");
    listCmcInfo($client);

    echo "<h2>Add CMC Info</h2>";
    addCmcInfo($client,"555","Earthly Calls");
    listCmcInfo($client);

    echo "<h2>Update CMC Info</h2>";
    updateCmcInfo($client,"777","Up There");
    updateCmcInfo($client,"666","Down There");
    updateCmcInfo($client,"555","Neither");
    listCmcInfo($client);

    echo "<h2>Update CMC Info</h2>";
    updateCmcInfo($client,"777","Heavenly Calls");
    updateCmcInfo($client,"666","Helly Calls");
    updateCmcInfo($client,"555","Earthly Calls");
    listCmcInfo($client);

?>

This sample application demonstrates the APIs that list, get, remove, add, and update CMC information. Each change to the CMC information is followed by a listCmcInfo so you can see the results of that operation. As noted above, the test starts with these three entries:

Uuid: {78E07494-EDAE-980E-383B-18EC7948AE1F}
Code: 777
Description: Heavenly Calls

Uuid: {3420C42A-DDD9-B7D2-CDEE-74B5F427F09F}
Code: 666
Description: Helly Calls

Uuid: {825703AF-FA47-42DC-AC9F-87EDA26119CF}
Code: 555
Description: Earthly Calls

Forced Authorization Code (FAC) handling

Forced Authorization Codes (FAC) allow you to regulate the types of calls that certain users can place. A FAC forces the user to enter a valid authorization code on the phone before the call completes. The values for the authorizationLevel parameter are largely arbitrary. You’ll want to define them to restrict such things as international calls.

This tutorial starts with three FAC Info entries in the system. Keep in mind that the authorization level must be a number between 0 and 255, so this example arbitrarily uses 100, 150, and 200. The records are as follows:

Uuid: {4FA8F305-1C65-1944-FDE6-CF8A279100DD}
Name: Regular Caller FAC
Code: 4321
Auth Level: 150

Uuid: {A334FF0C-1A9D-2F78-AB52-BC64F5EEA24D}
Name: Lowly Grunt FAC
Code: 1111
Auth Level: 100

Uuid: {62724065-ED78-EF16-E12D-BFB9A302F818}
Name: The Big Cheese FAC
Code: 1234
Auth Level: 200

List FAC Info

List FAC Info

<?php
    function listFacInfo($client) {

        // Just set every tag you want returned to "" in this array
        $returnedTags = array("name"=>"","code"=>"","authorizationLevel"=>"");

        // "%" is a wild card to find every FAC
        $searchCriteria = array("name"=>"%");

        try {
            $response = $client->listFacInfo(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)
        // Make sure it's an array before iterating through it
        if ( is_array($response->return->facInfo) ) {
            foreach($response->return->facInfo as $facInfo) {
                echo("Uuid: ".$facInfo->uuid."<br>");
                echo("Name: ".$facInfo->name."<br>");
                echo("Code: ".$facInfo->code."<br>");
                echo("Auth Level: ".$facInfo->authorizationLevel."<br>");
                echo("<hr>");
            }
            // if it's not an array, then just get the values
        } else {
            echo("Uuid: ".$response->return->facInfo->uuid."<br>");
            echo("Name: ".$response->return->facInfo->name."<br>");
            echo("Code: ".$response->return->facInfo->code."<br>");
            echo("Auth Level: ".$response->return->facInfo->authorizationLevel."<br>");
            echo("<hr>");
        }
    }
?>

Create a listFacInfo function so you can see the values and check them again after changes. This is almost the same as the listCmcInfo function in the previous section on CMC Info. Like the CMC function, the response value can contain a single object if there is only one FAC Info entry, or an array of objects if there are more. This function checks the response to see if it’s an array. If so, it iterates through the array. If not, it simply echoes the values of the object.

Get FAC Info

Get FAC Info

<?php
    function getFacInfo($client, $name) {
        $returnedTags = array("name"=>"","code"=>"","authorizationLevel"=>"");

        try {
            $response = $client->getFacInfo(array("name"=>$name),array("returnedTags"=>$returnedTags));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }

        echo("Uuid: ".$response->return->facInfo->uuid."<br>");
        echo("Name: ".$response->return->facInfo->name."<br>");
        echo("Code: ".$response->return->facInfo->code."<br>");
        echo("Auth Level: ".$response->return->facInfo->authorizationLevel."<br>");
        echo("<hr>");
    }
?>

If you have a specific FAC Info entry in mind, you can retrieve it with the getFacInfo request. You can specify which FAC Info you want to retrieve by name or by uuid. This example searches by name.

The getFacInfo request also requires a set of returnedTags in an array. Simply create an array of the tags you want returned, each pointing to an empty string. And then include that array as the value of another array with the element returnedTags.

Add FAC info

Add FAC Info

<?php
    function addFacInfo($client) {
        $facInfo = array("name"=>"New FAC","code"=>"5555","authorizationLevel"=>"250");
        try {
            $response = $client->addFacInfo(array("facInfo"=>$facInfo));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }
    }
?>

The addFacInfo API is probably the second easiest of the FAC commands. All it takes is an array with the element facInfo pointing to an array of the tags defining a FAC, that is, name, code, and authorizationLevel. In this case, we’re calling the FAC New FAC, giving it a code of 5555 and an authorizationLevel of 250.

Remove FAC Info

Remove FAC Info

<?php   
    function removeFacInfo($client) {
        try {
            $response = $client->removeFacInfo(array("name"=>"New FAC"));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }
    }
?>  

The removeFacInfo API is arguably the easiest. Simply identify the FAC you want removed by name or uuid. In this case, we use name and remove the FAC we just added.

Update FAC Info

Update FAC Info

<?php
    function updateFacInfo($client, $name, $authLevel) {
        try {
            $newresponse = $client->updateFacInfo(array("name"=>$name,
                                    "authorizationLevel"=>$authLevel));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }
    }
?>

Finally, the updateFacInfo API lets you change information in a FAC entry. This example changes the authorizationLevel, but you could also change the name (use the newName tag for that), and/or the code. In this case, we identify the FAC entry we want changed by name, but you could use the uuid instead.

Putting it all together

A complete sample application

<?php

    echo "<h1>Fac Info Test</h1>";

    $host="host";
    $username="username";
    $password="password";

    $client = new SoapClient("AXLAPI.wsdl",
        array('trace'=>true,
            'exceptions'=>true,
            'location'=>"https://".$host.":8443/axl",
            'login'=>$username,
            'password'=>$password
    ));


    function listFacInfo($client) {

        // Just set every tag you want returned to "" in this array
        $returnedTags = array("name"=>"","code"=>"","authorizationLevel"=>"");

        // "%" is a wild card to find every FAC
        $searchCriteria = array("name"=>"%");

        try {
            $response = $client->listFacInfo(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)
        // Make sure it's an array before iterating through it
        if ( is_array($response->return->facInfo) ) {
            foreach($response->return->facInfo as $facInfo) {
                echo("Uuid: ".$facInfo->uuid."<br>");
                echo("Name: ".$facInfo->name."<br>");
                echo("Code: ".$facInfo->code."<br>");
                echo("Auth Level: ".$facInfo->authorizationLevel."<br>");
                echo("<hr>");
            }
            // if it's not an array, then just get the values
        } else {
            echo("Uuid: ".$response->return->facInfo->uuid."<br>");
            echo("Name: ".$response->return->facInfo->name."<br>");
            echo("Code: ".$response->return->facInfo->code."<br>");
            echo("Auth Level: ".$response->return->facInfo->authorizationLevel."<br>");
            echo("<hr>");
        }
    }

    function getFacInfo($client, $name) {
        $returnedTags = array("name"=>"","code"=>"","authorizationLevel"=>"");

        try {
            $response = $client->getFacInfo(array("name"=>$name),array("returnedTags"=>$returnedTags));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }

        echo("Uuid: ".$response->return->facInfo->uuid."<br>");
        echo("Name: ".$response->return->facInfo->name."<br>");
        echo("Code: ".$response->return->facInfo->code."<br>");
        echo("Auth Level: ".$response->return->facInfo->authorizationLevel."<br>");
        echo("<hr>");
    }

    function addFacInfo($client) {
        $facInfo = array("name"=>"New FAC","code"=>"5555","authorizationLevel"=>"250");
        try {
            $response = $client->addFacInfo(array("facInfo"=>$facInfo));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }
    }

    function removeFacInfo($client) {
        try {
            $response = $client->removeFacInfo(array("name"=>"New FAC"));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }
    }

    function updateFacInfo($client, $name, $authLevel) {
        try {
            $newresponse = $client->updateFacInfo(array("name"=>$name,
                                    "authorizationLevel"=>$authLevel));
        }
        catch (SoapFault $sf) {
            echo "SoapFault: " . $sf . "<BR>";
        }
        catch (Exception $e) {
            echo "Exception: " . $e . "<BR>";
        }
    }

    echo "<h2>List Fac Info</h2>";
    listFacInfo($client);

    echo "<h2>Get Fac Info</h2>";
    getFacInfo($client, "The Big Cheese FAC");

    echo "<h2>Add Fac Info</h2>";
    addFacInfo($client);
    listFacInfo($client);

    echo "<h2>Remove Fac Info</h2>";
    removeFacInfo($client);
    listFacInfo($client);

    echo "<h2>Update Fac Info 170</h2>";
    // Change auth code of "Regular Caller FAC" to 170
    updateFacInfo($client, "Regular Caller FAC", "170");
    listFacInfo($client);

    echo "<h2>Update Fac Info back to 150</h2>";
    // Change it back for the next test
    updateFacInfo($client, "Regular Caller FAC", "150");
    listFacInfo($client);

?>

This sample application demonstrates the APIs that list, get, remove, add, and update FAC information. Each change to the FAC information is followed by a listCmcInfo so you can see the results of that operation. As noted above, the test starts with these three entries:

Uuid: {4FA8F305-1C65-1944-FDE6-CF8A279100DD}
Name: Regular Caller FAC
Code: 4321
Auth Level: 150

Uuid: {A334FF0C-1A9D-2F78-AB52-BC64F5EEA24D}
Name: Lowly Grunt FAC
Code: 1111
Auth Level: 100

Uuid: {62724065-ED78-EF16-E12D-BFB9A302F818}
Name: The Big Cheese FAC
Code: 1234
Auth Level: 200

PHP
cURL Java PHP Python Ruby