Search

Well so this is my situation:

I´m setting up a web hosting website, mainly to control my clients hosting plans, and try to sell some hosting plans along the way. So i have a hostgator resselers account, wich gives me a billing software to manage my clients invoces and due dates.

They provided me with a free license of the WHMCS software, wich intagrates with the WHM control panel.

The thing is, the WHMCS provides a API to control and retrieve data from the admin panel, like client lists, orders, invoces, product prices and etc...

In their tutorials they use CURL in a PHP file to connect to the API.

What i like to know is what would be the best way to use their API in symphony? maybe in a custom DS ( dont een know if is possible ), so here it it´s the code sample i grabed from their website, it uses curl to return a XML response with the data, my guess is if i could some how integrate this in my symphony website pages, i could use XSLT to processes the xml returned ( currect me if i´m wrong ):

    <?php
/* *** WHMCS XML API Sample Code *** */

$url = "http://www.yourdomain.com/includes/api.php"; # URL to WHMCS API file goes here
$username = "Admin"; # Admin username goes here
$password = "demoxyz"; # Admin password goes here

$postfields = array();
$postfields["username"] = $username;
$postfields["password"] = md5($password);
$postfields["action"] = "getclients";
$postfields["responsetype"] = "xml";

$query_string = "";
foreach ($postfields AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$xml = curl_exec($ch);
if (curl_error($ch) || !$xml) $xml = '<whmcsapi><result>error</result>'.
'<message>Connection Error</message><curlerror>'.
curl_errno($ch).' - '.curl_error($ch).'</curlerror></whmcsapi>';
curl_close($ch);

$arr = whmcsapi_xml_parser($xml); # Parse XML

print_r($arr); # Output XML Response as Array

/*
Debug Output - Uncomment if needed to troubleshoot problems
echo "<textarea rows=50 cols=100>Request: ".print_r($postfields,true);
echo "nResponse: ".htmlentities($xml)."nnArray: ".print_r($arr,true);
echo "</textarea>";
*/

function whmcsapi_xml_parser($rawxml) {
    $xml_parser = xml_parser_create();
    xml_parse_into_struct($xml_parser, $rawxml, $vals, $index);
    xml_parser_free($xml_parser);
    $params = array();
    $level = array();
    $alreadyused = array();
    $x=0;
    foreach ($vals as $xml_elem) {
      if ($xml_elem['type'] == 'open') {
         if (in_array($xml_elem['tag'],$alreadyused)) {
            $x++;
            $xml_elem['tag'] = $xml_elem['tag'].$x;
         }
         $level[$xml_elem['level']] = $xml_elem['tag'];
         $alreadyused[] = $xml_elem['tag'];
      }
      if ($xml_elem['type'] == 'complete') {
       $start_level = 1;
       $php_stmt = '$params';
       while($start_level < $xml_elem['level']) {
         $php_stmt .= '[$level['.$start_level.']]';
         $start_level++;
       }
       $php_stmt .= '[$xml_elem['tag']] = $xml_elem['value'];';
       @eval($php_stmt);
      }
    }
    return($params);
}

?>

If any one could just take a look, and help figure out the best way to do this in symphony, it will help me a lot.

Thanks in advance.

Yep, pop this into an event or a data source and you're away. You might want to brush up on your PHP first. Search the forum for "custom event" or "custom data source" and you'll find loads of examples.

So i clean up my php to the part where it returns a complete xml document with all the data from the api, now, how do i finish this data source, sience it returns a complete document with declarations and all, here is my code (ps: i´m starting to learn symphonys api just now, so i´m clueless about how to proceed):

require_once(TOOLKIT . '/class.datasource.php');

    Class datasourcewhmcs extends Datasource{

        public function about(){
            return array(
                     'name' => 'Whmcs',
                     'author' => array(
                            'name' => 'CMSadmin Team',
                            'website' => 'http://cmsadmin-cms.com',
                            'email' => 'team@cmsadmin-cms.com'),
                     'version' => '1.0',
                     'release-date' => '2010-05-04');
        }

        public function allowEditorToParse(){
            return false;
        }

        public function grab(&$param_pool=NULL){

            /****************************************************
            *****************************************************/
            $url = "http://layoutzhosting.com.br/central/includes/api.php"; # URL to WHMCS API file goes here
            $username = "layoutz"; # Admin username goes here
            $password = "09089816"; # Admin password goes here

            $postfields = array();
            $postfields["username"] = $username;
            $postfields["password"] = md5($password);
            $postfields["action"] = "getclients";
            $postfields["responsetype"] = "xml";

            $query_string = "";

            foreach ($postfields AS $k=>$v) {

            $query_string .= "$k=".urlencode($v)."&";

            }

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

            $result = curl_exec($ch);

            curl_close($ch);


            return $result;


        } 


    }

and here is the xml returned:

<?xml version="1.0" encoding="utf-8"?>
<whmcsapi version="4.5.2">
<action>getclients</action>
<result>success</result>
<totalresults>5</totalresults>
<startnumber>0</startnumber>
<numreturned>5</numreturned>
<clients>
<client>
<id>5</id>
<firstname>eduardo</firstname>
<lastname>Owner</lastname>
<companyname></companyname>
<email></email>
<datecreated>0000-00-00</datecreated>
<groupid>0</groupid>
<status>Active</status>
</client>
<client>
<id>1</id>
<firstname>junior</firstname>
<lastname>milanes</lastname>
<companyname>duhpc</companyname>
<email></email>
<datecreated>2011-08-01</datecreated>
<groupid>0</groupid>
<status>Active</status>
</client>
<client>
<id>3</id>
<firstname>layou731</firstname>
<lastname>Owner</lastname>
<companyname></companyname>
<email></email>
<datecreated>0000-00-00</datecreated>
<groupid>0</groupid>
<status>Active</status>
</client>
<client>
<id>2</id>
<firstname>paralelo</firstname>
<lastname>Owner</lastname>
<companyname></companyname>
<email></email>
<datecreated>0000-00-00</datecreated>
<groupid>0</groupid>
<status>Active</status>
</client>
<client>
<id>4</id>
<firstname>twtowers</firstname>
<lastname>Owner</lastname>
<companyname></companyname>
<email></email>
<datecreated>0000-00-00</datecreated>
<groupid>0</groupid>
<status>Active</status>
</client>
</clients>
</whmcsapi>

Can you give me a ideia of the next step?

Hey i acctualy did it, after getting the result xml, i used "PHP - xmlparseintostruct" to parse the result xml, and turn it into an array, after that i used "Arrayto_xml" to construct and append the data to a erlier created XMLelement wich gave me exatly what i needed.

Now one question remais, is this the best way to do it? sience i´m getting a fully structured XML document, turning into a array, and than turning it back into a XML using symphony?

If the CURL result is XML, then you might be able to shortcut it and just go $result->appendChild(new XMLElement('curl-result', $curl_result));

The thing is, it end up with a double xml declaration, giving me this error:

simplexml_load_string(): Entity: line 28: parser error : XML declaration allowed only at the start of the document

Any way i can work around that?

There might be a better solution, but if that's the only problem, perhaps something like:

$result->appendChild(new XMLElement('curl-result', str_replace('<?xml version="1.0" encoding="utf-8"?>','',$curl_result)));

Thanks, that did work, now, what if i get a Json result, does symphony have any function that can transform json in a xml?

I've never had to do it with Symphony yet. PHP has a nifty json_decode() function that will turn JSON into an array.

A quick search turns up this dynamic JSON datasource extension. It's been over a year since it received any updates, but you could try using its json_to_xml class. Include that file and then do:

$xml = Json_to_xml::convert($curl_result, 'fragment');

(I think you want "fragment" as the second parameter, if I'm reading the code correctly, to avoid getting an XML declaration in the resulting output.)

It's worth noting that the 2.3 release uses a similar (if not the same) class for supporting JSON out of the box.

It's worth noting that the 2.3 release uses a similar (if not the same) class for supporting JSON out of the box.

That's awesome!

You can also create your own custom API functions in WHMCS.

I have some code that might be interesting to share. It explains how the API can be invoked in the helper class in Symfony.

Please refer

http://bobcares.com/blog/extend-whmcs-create-your-own-whmcs-api-functions

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details