Provisioning Module Developer Docs
Provisioning Modules, also referred to as Product or Server Modules, allow you to create modules to allow for the provisioning and management of products & services in WHMCS.
The core functionality of a module is for creating, suspending, unsuspending & terminating of products as various events occur such as new orders being paid for, items becoming overdue, overdue invoices being paid & cancellations being requested. But a module in WHMCS can do much more than just that, including automated password resets, upgrades/downgrades, renewals, admin based links, client area output, and more via custom functions.
Other types of modules that can be created in WHMCS are Payment Gateways, Domain Registrars and Addons.
Contents
Getting Started
Begin by downloading the Provisioning Module Template file for sample code to refer to here: http://www.whmcs.com/members/dl.php?type=d&id=14
Naming Conventions
Provisioning Modules are stored in the /modules/servers/ directory. The module name you choose must be unique, and should be all lowercase, containing only letters & numbers, always starting with a letter.
Within the module itself, all functions must then be prefixed with the module filename, followed by an underscore, and then the function name. For example if your module was called "mymodule" the create function would be named "mymodule_CreateAccount".
Product Configuration Options
The required function of all provisioning modules is the ConfigOptions function. This is what defines the settings that can be configured on a per product basis when assigning a product to the module. The name of this function must be mymodule_ConfigOptions matching the name of your module.
The supported field types are Text, Password, Yes/No Checkboxes, Dropdown Menus, Radio Buttons & Text Areas
Below are examples of the available parameters for each field type. Provisioning modules support up to 24 options defined in this way.
$configarray = array(
"username" => array (
"FriendlyName" => "UserName",
"Type" => "text", # Text Box
"Size" => "25", # Defines the Field Width
"Description" => "Textbox",
"Default" => "Example",
),
"password" => array (
"FriendlyName" => "Password",
"Type" => "password", # Password Field
"Size" => "25", # Defines the Field Width
"Description" => "Password",
"Default" => "Example",
),
"usessl" => array (
"FriendlyName" => "Enable SSL",
"Type" => "yesno", # Yes/No Checkbox
"Description" => "Tick to use secure connections",
),
"package" => array (
"FriendlyName" => "Package Name",
"Type" => "dropdown", # Dropdown Choice of Options
"Options" => "Starter,Advanced,Ultimate",
"Description" => "Sample Dropdown",
"Default" => "Advanced",
),
"disk" => array (
"FriendlyName" => "Disk Space",
"Type" => "radio", # Radio Selection of Options
"Options" => "100MB,200MB,300MB",
"Description" => "Radio Options Demo",
"Default" => "200MB",
),
"comments" => array (
"FriendlyName" => "Notes",
"Type" => "textarea", # Textarea
"Rows" => "3", # Number of Rows
"Cols" => "50", # Number of Columns
"Description" => "Description goes here",
"Default" => "Enter notes here",
),
);
return $configarray;
Supported Functions
What follows here is a brief overview of all the possible functions that a product provisioning module in WHMCS can contain. All functions within a module are optional and can be omitted from the module if they don’t apply. Remember, within the code itself, all functions are prefixed with the module filename, followed by an underscore, and then the function name as shown in bold in these descriptions.
- CreateAccount - This function is called when a new product is due to be provisioned. This can be invoked automatically by WHMCS upon checkout or payment for a new order, or manually by an admin user from the Products/Services tab under a clients profile within the admin area.
- SuspendAccount - This function is called when a suspension is requested. This is invoked automatically by WHMCS when a product becomes overdue on payment, or can be called manually by admin user.
- UnsuspendAccount - This function is called when an unsuspension is requested. This is invoked automatically upon payment of an overdue invoice for a product.
- TerminateAccount - This function is called when a termination is requested. This can be invoked automatically for long overdue products if enabled (auto termination is disabled by default in Setup > Automation Settings) or requested manually by an admin user.
- Renew - This function is called each time a renewal invoice for a product is paid.
- ChangePassword - This function is called when a client requests a password change from the client area. For this option to show up this function must be declared in the module, the status of the product must be active. Admins can also invoke this command from the admin area.
- ChangePackage - This function is used for upgrading and downgrading of products. This function will be called automatically when an upgrade or downgrade order placed by the client is paid for, or can be invoked manually by admin users from the product management pages. This same function is called for upgrades and downgrades of both products and configurable options.
- ClientArea - This function can be used to define module specific client area output. It accepts a return of HTML for display on the product details page of the client area. The output can alternatively be specified via a template file within the module folder named “clientarea.tpl” to allow for end user customisation. This function is discussed in more detail later on in the docs.
- AdminArea - This function is used to define HTML code to be displayed within the admin area server configuration page (Setup > Servers) and is commonly used to provide an automated shortcut/login link to the server control panel being integrated with.
- LoginLink - This function can be used to define HTML code used to link specifically to the customers account within a servers control panel. It is displayed on the product management page within the admin area if defined and must be an HTML output or link (no forms).
- ClientAreaCustomButtonArray - This function can be used to define custom functions that your module supports that customers are allowed to invoke and run from the client area. These functions can perform actions or product page output in the clientarea. Some example usages for this are to provide product management pages, bandwidth reporting pages, etc…
- AdminCustomButtonArray - This function can be used to define custom functions that your module supports, similar to the above, but that admin users are allowed to run. This can contain more functions than the client area is allowed.
- UsageUpdate - This function is used to perform a daily import of the disk and bandwidth usage for accounts from a server. The data imported is then used to display the usage stats both within the client and admin areas of WHMCS, and also in disk and bandwidth overage billing calculations if enabled for a product.
- AdminServicesTabFields - This function can be used to define additional fields and output to be displayed on the admin product management pages.
- AdminServicesTabFieldsSave - This function is used in conjunction with the above to handle the values submitted in any custom fields when a save request is submitted.
Module Parameters
The module parameters are the data/values passed into each function when called. Every module function is passed the same parameters. These variables provide information about the specific product/service the module command is being invoked for, along with the settings from the product itself as defined in the product configuration.
Var Name | Description |
serviceid | the unique ID of the service Database Field: tblhosting.id |
pid | the product ID that the service is assigned to Database Field: tblproducts.id |
serverid | the server ID that the service is assigned to Database Field: tblservers.id |
domain | the domain entered by the customer when ordering Database Field: tblhosting.domain |
username | the username generated for the service (defaults to first 8 letters of
the domain) Database Field: tblhosting.username |
password | the password generate for the service (10 char randomly generated on first creation consisting of letters & numbers, both upper & lowercase) Database Field: tblhosting.password |
producttype | the product type which can be one of sharedhosting, reselleraccount, server or other |
moduletype | the module name being called (will match filename of module) |
configoptionX | with X being from 1 to 24, these fields contain all the module settings for the product in the order defined in the ConfigOptions function of the module |
clientsdetails | This variable contains a sub-array of all the clients details for the client who owns the service in question. This contains things like firstname, lastname, email, address1, country, etc… |
customfields | this variable contains a sub-array of all the custom fields defined for the product, with the key being the custom field name - $params[‘customfields’][‘Field Name’] |
configoptions | This variable contains a sub-array of all the configurable options defined for the product, again with the key being the option name in this case - $params[‘configoption’][‘Option Name Here’] |
server | true/false to define if the product is assigned to a server |
serverip | the IP Address of the selected server |
serverhostname | the Hostname of the selected server |
serverusername | the Username of the selected server |
serverpassword | the Password of the selected server |
serveraccesshash | the Access Hash of the selected server |
serversecure | true/false to define if Use SSL is enabled in the Server Configuration |
Config Options
Config options (not to be confused with Configurable Options) are the module's settings, defined in the ConfigOptions function of the module, and set on a per product basis. These are supplied as a numbered list, so the first option would be $params[‘configoption1’] , the second $params[‘configoption2’], etc… The order is defined by the order in which you specify the options in the ConfigOptions function of the module.
Custom Fields & Configurable Options
The values from any custom fields & configurable options are loaded and passed into modules as parameters so that they can be easily used. They are passed as an array with the key being the name of the field or option.
For example if you created a custom field called “Username”, then that would be referenced using $params[‘customfields’][‘Username’] Similarly if you created a configurable option named “Disk Space”, then that would be referenced using $params[‘configoptions’][‘Disk Space’]
Core Module Functions
The core module functions are the Create, Suspend, Unsuspend, Terminate, Renew, ChangePassword and ChangePackage functions.
These 7 functions all operate in a very similar manner. They can all be invoked both manually and automatically, and they are all expected to return either a success or error response.
Response Handling
Each one of these functions after performing the actions they are required to, must either return a success message or error response.
For a successful result the code must actually return the word “success” to end the function. If WHMCS receives that it will know that the function completed in full as intended and continue on that basis.
However, should the function fail, what you return should be a user understandable error message, as it will be displayed directly to staff users.
Action Events
When a function is successful, there are various actions that are performed as follows:
- CreateAccount - Changes status to Active + Sends Product Welcome Email
- SuspendAccount - Changes status to Suspended
- UnsuspendAccount - UnsuspendAccount
- TerminateAccount - Changes status to Terminated
- ChangePassword - Updates password in database
In addition to the above actions, admin users are given a confirmation of successful functions completing, and errors in the case of them failing. If the functions were invoked automatically such as on payment of a new order, then that notification can be in the form of an email. And in the case of the ChangePassword function, any errors returned from that function are also displayed to end users within the client area also.
The UsageUpdate Function
The UsageUpdate function can be used to perform a daily import of the disk and bandwidth usage for accounts from a server. The data imported is then used to display the usage stats both within the client and admin areas of WHMCS, and also in disk and bandwidth overage billing calculations if enabled for a product.
The UsageUpdate function is called by the daily cron if present in a module, for any active and enabled server, on a per server basis (important: it is called per server not per product). Therefore this can only be used if your module has a server created in WHMCS for it, products alone do not invoke it.
The function is passed the id, ip, hostname, username/hash, & password variables and is then expected to query the disk and bandwidth stats for all accounts on that server, and update them within the database directly all in a single call for speed and efficiency. An example of how to do this is included below.
function mymodule_UsageUpdate($params) {
$serverid = $params['serverid'];
$serverhostname = $params['serverhostname'];
$serverip = $params['serverip'];
$serverusername = $params['serverusername'];
$serverpassword = $params['serverpassword'];
$serveraccesshash = $params['serveraccesshash'];
$serversecure = $params['serversecure'];
# Run connection to retrieve usage for all domains/accounts on $serverid
# Now loop through results and update DB
foreach ($results AS $domain=>$values) {
update_query("tblhosting",array(
"diskused"=>$values['diskusage'],
"disklimit"=>$values['disklimit'],
"bwused"=>$values['bwusage'],
"bwlimit"=>$values['bwlimit'],
"lastupdate"=>"now()",
),array("server"=>$serverid,"domain"=>$values['domain']));
}
}
Custom Functions
Custom functions allow you to define additional operations that can be performed using the module. The custom functions can perform actions, or define additional client area pages/output. Permissions can be granted for who can use each custom function, be it just clients, just admins, or both.
The naming convention for custom functions follows the same as any other function within a module so it must begin with the module filename, followed by an underscore, and then the custom function name.
The easiest way to demonstrate this is with an example so let’s take an example of a reboot & shutdown function in a VM/VPS system:
function template_reboot($params) {
# Code to perform reboot action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
function template_shutdown($params) {
# Code to perform shutdown action goes here...
if ($successful) {
$result = "success";
} else {
$result = "Error Message Goes Here...";
}
return $result;
}
In the above you can see how the custom functions are defined, being passed all the same module parameters as all other functions, & returning either “success” for a success or an error message to indicate a failure. Now let’s say we wanted to allow clients to perform reboots, but only admin users to be able to perform a shutdown, here’s how we would define that:
function template_ClientAreaCustomButtonArray() {
$buttonarray = array(
"Reboot Server" => "reboot",
);
return $buttonarray;
}
function template_AdminCustomButtonArray() {
$buttonarray = array(
"Reboot Server" => "reboot",
"Shutdown Server" => "shutdown",
);
return $buttonarray;
}
What we are saying here is that clients are allowed perform the “reboot” function, but admins can perform both “reboot” and “shutdown”.
The key value of the array is what get’s displayed to admins/clients on the button or menu options for the commands. And the value is the custom function name excluding the modulename_ prefix.
If you want to provide clients with a custom button or way to invoke a function, then this can be done as follows within a .tpl file described in the previous Client Area Output section:
<form method="post" action="clientarea.php?action=productdetails"> <input type="hidden" name="id" value="{$serviceid}" /> <input type="hidden" name="modop" value="custom" /> <input type="hidden" name="a" value="reboot" /> <input type="submit" value="Reboot VPS Server" /> </form>
Client Area Output
Another key function of a module is to give clients access to extra options and output within the client area. This can be done either on the product details page itself (using the ClientArea function of a module) or as a custom function/action described above.
Product Details Page Output
Creating output to be displayed on the same page as the product details in the client area, it's simply a case of creating a template file named “clientarea.tpl” within your module folder. This template file will be processed as a Smarty template file as with all templates in WHMCS, and so can make use of smarty variables which will be the same module vars as are passed to every module function, as well as other smarty functions such as custom PHP code blocks and logic functions.
If you need something a little more advanced, such as being able to perform API calls and defining custom variables for use in the output, then you can define a ClientArea function within your custom module that can run any custom code required and then return an array defining both the template file to use, and any variables that template should have available in addition to the defaults. By returning different templatefile values based on values in the $_GET or $_POST array data, you can create multiple pages with different output and link between them from your custom output.
function mymodule_ClientArea($vars) {
return array(
'templatefile' => 'clientarea',
'vars' => array(
'test1' => 'hello',
'test2' => 'world',
),
);
}
Custom Pages
There may be situations where rather than output being displayed on the product details page below the general information for a product, you might want to have a completely custom page for it. And with WHMCS that is certainly possible. This is done by using custom functions as described earlier in this article, and from that function returning an array something like as follows:
function mymodule_mycustomfunction($vars) {
return array(
'templatefile' => 'customfunc',
'breadcrumb' => array(
'stepurl.php?action=this&var=that' => 'Custom Function',
),
'vars' => array(
'test1' => 'hello',
'test2' => 'world',
),
);
}
You then just need to authorize clients to use this custom function, and provide a link to it for them in the product details page output using the same methods as described earlier in the ‘’’ Custom Functions’’’ section of the docs.
Admin Services Tab
Available in WHMCS V4.3 and later, the Admin Services Tab functions of a module allow you to define additional fields that should appear on the product details page of the admin area for staff use. These can be used just for informational output, or for settings and values stored in cus-tom tables or remotely outside of WHMCS.
An example of what we use it for in the core WHMCS system is for our licensing addon module, where the license specific fields of the allowed domains, IPs and Directory can then be viewed and set from the product details view.
There are 2 functions relating to the services tab - AdminServicesTabFields and AdminServicesTab-FieldsSave. The first of these allows you to define the additional fields to output, and the latter (optionally) allows you to handle any input in them on submission/save.
So on to an example, below we show you how you could define 4 extra fields that would show an input field, dropdown, textarea and info only output as examples, and then update them in a cus-tom table of the database via the save event.
function mymodule_AdminServicesTabFields($params) {
$result = select_query("mod_customtable","",array("serviceid"=>$params['serviceid']));
$data = mysql_fetch_array($result);
$var1 = $data['var1'];
$var2 = $data['var2'];
$var3 = $data['var3'];
$var4 = $data['var4'];
$fieldsarray = array(
'Field 1' => '<input type="text" name="modulefields[0]" size="30" value="'.$var1.'" />',
'Field 2' => '<select name="modulefields[1]"><option>Val1</option</select>',
'Field 3' => '<textarea name="modulefields[2]" rows="2" cols="80">'.$var3.'</textarea>',
'Field 4' => $var4, # Info Output Only
);
return $fieldsarray;
}
function mymodule_AdminServicesTabFieldsSave($params) {
update_query("mod_customtable",array(
"var1"=>$_POST['modulefields'][0],
"var2"=>$_POST['modulefields'][1],
"var3"=>$_POST['modulefields'][2],
),array("serviceid"=>$params['serviceid']));
}
Module Logging
To make reviewing and debugging module calls easier, WHMCS has a built in logging function that allows you to record the request and response strings for every call your module makes, in an easily accessible way via the WHMCS admin interface. If you ultimately plan to release your module publically, this also makes it easier for end users to troubleshoot and debug issues they experience using your module on their own, and for you to be able to debug issues they experience while using it.
The logging is not something that is enabled permenantly, to avoid logs growing uncontrollably and unecessarily, so it's something that needs to be enabled for the logging to actually happen. This is done in Utilities > Logs > Module Debug Log which is the same place as where the logs can be reviewed.
To utilise this functionality, you simply need to make a call as follows:
logModuleCall($module,$action,$requeststring,$responsedata,$processeddata,$replacevars);
- $module - This should be the name of your module, for example "cpanel", "plesk", "resellerclub", etc...
- $action - This should be the action being performed, ie. create, suspend, register, etc...
- $requeststring - This should be the variables being posted to the remote API. This can be in either string or array format.
- $responsedata - This is where you return the raw API response. This can be in either string or array format also.
- $processeddata - Similar to the above, but this can be used for a post processing API response, such as after conversion into a friendly format, an array for example
- $replacevars - This accepts an array of strings to replace, so for example you might want to pass the username and password for the API into this function, which would then be replaced with *'s wherever they appear in either the request or response strings for extra security