Customizing WHMCS: Automatic Logins

In the past few months I've started dig in quite a bit with WHMCS, the billing platform that we use on Reclaim Hosting. Out of the box WHMCS does a lot of stuff really well. You can setup hosting plans, connect with domain registrars and cPanel servers, and accept payments with a variety of gateways and it will do all the heavy lifting of provisioning accounts, invoicing, etc. For UMW Domains we took advantage of that to make it our provisioning system although we had to strip out quite a bit of the cruft that had to do with invoicing, payments, etc since it's free for the user.

I plan on writing a few posts over the next few days about some of the ways we've been customizing WHMCS at UMW as well as Reclaim Hosting because I think it's useful to have this information out there given that the ecosystem of that software is an odd balance of powerful APIs and hooks but a ton of commercial work that's being wrapped in encrypted code to prevent reuse or sharing of any kind. The more open sharing of our work on it the better.

One of the issues we looked at with UMW Domains was that originally we had people logging into WHMCS just to sign up for their domain. They'd never go back because at that point they got a cPanel login and that's where they did their work (or at least until they installed WordPress and got a login for that. See a problematic trend here?). We started to look for ways that we could use Active Directory with WHMCS and didn't find anything but what we did find was the ability to have a user that was already logged into an external system remotely authenticated with WHMCS automatically. The feature is called AutoAuth and it basically works by taking a user's email address along with a private key and timestamp and creating a hash that is passed to WHMCS. When the email address matches a user in the system it will automatically treat them as if they are logged in without prompting for credentials.

We realized that we could flex the power of WordPress to serve as our "hub" of sorts on UMW Domains since there we could authenticate with our University's single sign-on and this would allow us to pass them into WHMCS seamlessly without a new login. So we lock down WHMCS so that the client area is inaccessible and the order form is only available by logging in. Then we used the API hooks to create a user in WHMCS if one doesn't already exist for them and then take their email address and generate the URL to send them to the order screen to get their domain. Here's the code that gets dropped in your theme's functions.php file and the code for the page template we're using to handle the order redirect. The only thing else required here is that the matching AutoAuth key is in the WHMCS configuration.php file and that the IP address of the server you're running WordPress on is whitelisted in WHMCS under Setup > General Settings > Security > API IP Access Restriction.

functions.php
function callwhmcsapi($action,$params){  
    $whmcsapiurl = "http://yourwhmcsurl.com/includes/api.php";
    $whmcsusername = "adminuser"; // User with API privileges
    $whmcspassword = "adminpassword";
    $params['username'] = $whmcsusername;
    $params['password'] = md5($whmcspassword);
    $params['action'] = $action;
    $params['responsetype'] = "json";
    $query_string = "";
    foreach ($params AS $k=>$v) $query_string .= "$k=".urlencode($v)."&";
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $whmcsapiurl);
    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);
    $jsondata = curl_exec($ch);
    if (curl_error($ch)) die("Connection Error: ".curl_errno($ch).' - '.curl_error($ch));
    curl_close($ch);
    $result = json_decode($jsondata,true);
    return $result;
}

function addwhmcsclient($name,$email){  
    $params["firstname"] = $name[0];
    $params["lastname"] = $name[1];
    $params["email"] = $email;
    $params["address1"] = "1301 College Avenue"; // We use the school's address for all users in the system
    $params["city"] = "Fredericksburg";
    $params["state"] = "Virginia";
    $params["postcode"] = "22401";
    $params["country"] = "US";
    $params["phonenumber"] = "5406541000";
    $params["password2"] = "";
    $result = callwhmcsapi("addclient",$params);
    return $result;
}
Page Template
<?php  
/*
Template Name: Dashboard  
*/

$current_user = wp_get_current_user();
$email = $current_user->user_email;
$name = array();
$name[0] = $current_user->user_firstname;
$name[1] = $current_user->user_lastname;
$clientsuccess = checkwhmcsclient($name,$email);

get_header();

$whmcsurl = "http://yourwhmcsurl.com/admin/dologin.php";
$autoauthkey = "c62fFpi7mu36X2M7rpBv";
$timestamp = time(); # Get current timestamp
$email = $clientsuccess['email']; # Clients Email Address to Login
$goto = "cart.php?a=add&pid=1";

$hash = sha1($email.$timestamp.$autoauthkey); # Generate Hash

# Generate AutoAuth URL & Redirect
$url = $whmcsurl."?email=$email&timestamp=$timestamp&hash=$hash&goto=".urlencode($goto); ?>
<script> window.location.href="<?php echo $url; ?>";</script>

<?php get_footer(); ?>