Category: WHMCS

1 Jul

Stripe alipay module for WHMCS

Stripe payment API integration with WHMCS is easy to do. This article covered payment using stripe with alipay.

1) First let’s create a source using the below code

 $response = \Stripe\Source::create(array(
      "type" => "alipay",
      "currency" => "usd",
      "amount" => $params['amount'] * 100,
      "metadata" => array(  
          "invoiceid" => $invoiceid,
          "userid" => $params['clientdetails']['userid'],
          "order_id" => $invoiceid . "_" . date( "YmdHis" )
      "redirect" => array(
        "return_url" => $systemUrl . "/modules/gateways/callback/stripe_alipay.php?invoiceid=$invoiceid"

2)Then we need to make use of the hook feature of stripe.

Hooks we have to use are
surce.chargeable, charge.succeeded.

From surce.chargeable we have to create charge as

 $charge = \Stripe\Charge::create(array(
        "amount" => $amount,
        "currency" => "usd",
        "source" => $source_id,

And then from charge.succeeded, We have to add transaction details as shown below.

    $source_meta_data = $event_json->data->object->source;
    $source_id = $event_json->data->object->id;
    $amount = ($event_json->data->object->amount) / (100.00);
    $invoiceid = $source_meta_data->metadata->invoiceid;
    $order_id = $source_meta_data->metadata->order_id;
    $userid = $source_meta_data->metadata->userid;
    $invoiceid = checkCbInvoiceID($invoiceid, "stripe_alipay");
    addInvoicePayment($invoiceid, $source_id, $amount, 0, "stripe_alipay");
    logTransaction("stripe_alipay", json_decode($body, true), "Successful");

This is a high level idea of the gateway module development.
If you would like to develop a stripe module or need more info, please contact from the link
Contact Us.
We will get back to you asap.

7 May

Smarty for WHMCS

In MVC, we always use view to display html contents. If we are not using any template engine, then we have to use php tags in the html page to add dynamic contents.

For example, we can use below code to loop through an array without any template engine.

<?php foreach ($users as $user) : ?>
    <h2><?php echo $user['name']; ?></h2>
    <p><?php echo $user['company']; ?></p>
<?php endforeach; ?>

Here we are using php tags to loop through the array. Also we are using php function to print it. WHMCS uses Smarty template engine, and we have to do loop in a different manner with Smarty template engine.

{foreach from=$users item=user}

This is just an example that shows the difference between Smarty and normal view files. For normal view files, we add .php as extension. But for Smarty files, by default .tpl is the extension of the view files.

Now let’s explore more smarty examples.
Let’s fist create a WHMCS page.

For any custom client area page, we have to add the below content at the top of the page.


//Let's include whmcs classes
use WHMCS\ClientArea;
use WHMCS\Database\Capsule;

define('CLIENTAREA', true);

require __DIR__ . '/init.php';

$ca = new ClientArea();

Let’s name our custom page as custom_page.php and upload it to the root folder of whmcs.
Now , we have the content required for any client area page on custom_page.php.
Now let’s display some html using the php file.
For that we have to create a tpl file.

Before that, let’s discuss about client area theming.

With whmcs, there are many themes available. For each theme,
there will be different css, images etc. Templates are stored in the folder templates/.
WHMCS has a default client area template with the name ‘six’. So the client area .tpl files are stored in the folder templates/six.

Now, back to our custom_page.php. For this page, we have to create a tpl file to add html contents. Let’s name the tpl file as custom_page.tpl, then it should be uploaded to the folder templates/six.

So our tpl file full path is templates/six/custom_page.tpl

Let’s just add content as

<p>Hello world!!!! </p>

To use the above file as tpl file, we have to define that in custom_page.php

That can be one as

$ca->setTemplate('custom_page');  //it will load the templates/six/custom_page.tpl

if our tpl file name was test.tpl, then we could load that as

$ca->setTemplate('test');  //it will load templates/six/test.tpl

Then to print the content, we have to add below line to the custom_page.php


So the full custom_page.php is


//Let's include whmcs classes
use WHMCS\ClientArea;
use WHMCS\Database\Capsule;

define('CLIENTAREA', true);

require __DIR__ . '/init.php';

$ca = new ClientArea();


And our templates/six/custom_page.tpl content is

<p>Hellow world!!!! </p>

Then browse the url

And you will see the html content
Hello world!!!!

Now we know how to display static content using smarty.

Now let’s see how to display dynamic contents using smarty.
For that, now let’s just display the logged in user’s email in the tpl.

We have to add the below code to the php file after the line $ca->initPage();

//get the logged in user id
$loggedin_user_id =  $_SESSION['uid'];
$client = Capsule::table('tblclients')
        ->where('id', '=', $loggedin_user_id)
$ca->assign('client_email', $client->email);

And below code to the tpl

        Client email is: {$client_email}

So the trick is, we havee to fetch what ever data to be displayed using a query and then pass that to the
tpl as

$ca->assign('client_email', $client->email);

Then we can just access that from the tpl as {$client_email}

If we were passing the email as

$ca->assign('clientMail', $client->email);

Then we can access it from the tpl as


We can do a lot more with smarty, Some of them are explained in the below links.


31 Mar

Useful Laravel Commands

#Reload the database
php artisan migrate:fresh –seed

#Install new packages and the compile
`composer install` & `npm install`

#Create a seeder file
php artisan make:seeder NewModelSeeder

#Run a single seeder file
php artisan db:seed –class=NewModelSeeder

#Create a model
php artisan make:model MyNewModel

#Create a controller
php artisan make:controller MyNewController –resource

#Create a migration file
php artisan make:migration create_my_new_table –create=my_new_table

#Run migration
php artisan migrate

11 Dec

How to get WHMCS date format?

To know the date format is set in the WHMCS, we can use the below query.

$date_format =  Capsule::table('tblconfiguration')
              ->where('setting', '=', 'DateFormat')

Some of the example date formats are MM-DD-YYYY, MM/DD/YYYY, DD-MM-YYYY etc.

We can convert that to the classical d m Y format by using the below code.

            $date_format = str_replace("DD", "d", $date_format);
            $date_format = str_replace("MM", "m", $date_format);
            $date_format = str_replace("YYYY", "Y", $date_format);
3 Oct

WHMCS Merchant Gateway Development

This type of WHMCS gateways can be used for payment using credit card. Let’s create a payment gateway with name test. For that we have to create a file named test.php and then we have to upload it to the folder modules/gateways.

Live mode and test mode.

Each payment gateway provides some test credit card details, we can use that for test payment.
In test mode, for any payment there won’t be any actual transaction.
In live mode, we have to use real credit card details and real transaction will happen in this mode. Payment gateway will give us both live url and test url for real and test payments respectively.

Our gateway module will decide weather we have to do real or test transactions based on the settings in the module config.

'testMode' => array(
            'FriendlyName' => 'Test Mode',
            'Type' => 'yesno',
            'Description' => 'Tick to enable test mode',

If we select testMode, then only test payments will work. If it’s unselected real transaction will happen.

Initially the test.php file looks like


if (!defined("WHMCS")) {
    die("This file cannot be accessed directly");

function test_MetaData()
    return array(
        'DisplayName' => 'Test payment gateway',
        'APIVersion' => '1.0',
        'DisableLocalCredtCardInput' => true,
        'TokenisedStorage' => false,

function test_config()
    return array(
        'FriendlyName' => array(
            'Type' => 'System',
            'Value' => 'Test payment gateway',
        'live_url' => array(
            'FriendlyName' => 'Live URL',
            'Type' => 'text',
            'Size' => '25',
            'Default' => '',
            'Description' => 'Enter your live url here',
        'test_url' => array(
            'FriendlyName' => 'Test URL',
            'Type' => 'text',
            'Size' => '25',
            'Default' => '',
            'Description' => 'Enter your test url here',
        'testMode' => array(
            'FriendlyName' => 'Test Mode',
            'Type' => 'yesno',
            'Description' => 'Tick to enable test mode',
        'user_id' => array(
            'FriendlyName' => 'User Id',
            'Type' => 'text',
            'Size' => '25',
            'Default' => '',
            'Description' => 'Enter your user id here',

function test_capture($params) {

        if($params['testMode'] == 'on') { //testmode
          $url = $params['test_url'];
        } else { // live mode
          $url = $params['live_url'];

We have to add payment code into the function, test_capture($params).
Inside that we have to use payment transfer code. Each gateway API will be diffrent, so the payment transfer code will be different for each gateway.

Let’s write a payment transfer code for an arbitrary gateway.

function test_capture($params) {
     $postfields = [
        'invoiceid' => $params['invoiceid'],
        'amount' => $params['amount'],
        'currency' => $params['currency'],
        'cardnumber' => $params['cardnum'],
        'cardexpiry' => $params['cardexp'],
        'cardcvv' => $params['cccvv'],

    if($params['testMode'] == 'on') { //testmode
          $url = 'https://test.myarbitrarygateway/api/payment';
    } else { // live mode
          $url = 'https://myarbitrarygateway/api/payment';

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postfields));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $response = curl_exec($ch);

    $data = json_docode($response);

    return array(
        'status' => ($data->success == 1) ? 'success' : 'declined',
        'rawdata' => $data,
        'transid' => $data->transaction_id,
        'fees' => $data->fees,
25 Sep

What is mean by WHMCS hook?

Standard way of modifying WHMCS features is using hook. WHMCS code is encrypted and we couldn’t change it. In addition to it, modifying core file is a bad idea. When we update WHMCS to the latest version all of our core file changes will be removed. So hook is a nice way to customize WHMCS features.

There are many hooks available in WHMCS. Available WHMCS hooks can be found in the link

Some of them can be used to run a piece of code just after an action is happened(ClientAdd executes just after a client is added to WHMCS). Some of them can be used used to run a piece of code just before an action(PreDeleteClient executes just before a client is deleted). There are hooks that can be used to run on certain pages(ClientAreaPageHome executes on the client area homepage).

Hooks can be include in the WHMCS in two ways.
1)We can create a php file with any name and can upload to the folder
2)We can create a file named hooks.php as a part of the addon module.

To get a better idea, let’s go through some examples now.
For now let’s just upload sample files to the folder /includes/hooks/.

Let’s add a hook ‘ClientAreaPage’ to a file named sample.php,
then let’s upload to the folder /includes/hooks/.

add_hook('ClientAreaPage', 1, function($vars) {
    echo "this is from clieant area hook";

Then take any page in the client side, you will get a blank page with content
this is from clieant area hook. As we have exit in the code, nothing else will be displayed.

Now let’s modify the hook as shown below.

add_hook('ClientAreaPage', 1, function($vars) {
    echo "<pre>"; print_r($vars);

Now the page will display an array.

To remove the hook, just delete the file from the folder /hooks/hook-index/.

Now let’s see another hook, ClientAreaPageCart.
Add the below code to a file named cart_hook.php and then upload to the folder

add_hook('ClientAreaPageCart', 1, function($vars) {
        echo "<pre>"; print_r($vars);

This hook won’t run in all of the client are pages. But it will run in all of the
cart pages. For example take the url /cart.php then you will see an array printed in it.

20 Sep

WHMCS Addon development

WHMCS addon can be used to develop additional features in your WHMCS.

Here briefly explaining steps required to develop a simple addon, that just print some strings.
That’s enough to get started. After developing this simple addon you can move on to complex addons.

Addon name and folder name

Name of addon do have importance while developing a WHMCS addon.
Let’s name our addon as hello_world.

Then we have to create a folder named hello_world.
Within the folder, develop a file named hello_world.php.
Name used for the folder and file is hello_world, which is the name of the addon.
We have to upload the folder to the WHMCS folder /modules/addons/.

Functions to be defined in hello_world.php

We have to define some functions in the file hello_world.php.
Prefix for those functions should be same as the addon name.
As our addon name is hello_world, prefix for those functions
must be hello_world_.

Those functions are listed below.


This function just returns an array.
Here we define addon name, version author etc.

function hello_world_config() {
    $configarray = array(
        "name" => "My first whmcs addon",
        "description" => "Just a sample addon, that just prints some strings",
        "version" => "1.0",
        "author" => "",
        "language" => "english",
    return $configarray;


This function is called when the addon module is activated from the admin side.
We can write table creation code within the function.

function hello_world_activate () {
    return array(
        'status' => 'success',
        'description' => 'Addon activated'


This function is called when we are deactivating the addon from the admin side.
All addon table drop code should be added here.

function hello_world_deactivate() {
    return array(
        'status' => 'success',
        'description' => 'Addon deactivated'


Code written within this function will be executed when we take the url

function hello_world_output($vars) {
    echo "just printing this in admin side";


This function is called when we take the url,

To display some contents in the client area, we have to create a smarty tpl file.
In the function hello_world_clientarea, we specified tpl file name as
‘templatefile’ => ‘template/clienthome’. So we have to create a folder named
template inside the folder /modules/addons/hello_world.
Then we have to create a file named clienthome.tpl in the folder template.
Note that we specified templatefile as ‘templatefile’ => ‘template/clienthome’, (no extension here) but we created file name as template/clienthome.tpl with the extension .tpl.

We have to pass parameters to the tpl file from the function hello_world_clientarea.
In the function we are passing the smarty key value pair as shown below.

'vars' => array(
            'name' => 'X ',
            'address' => 'Y',
            'phone' => 'Z',

Then in the tpl file we just have to write {$name} to display the name.

function hello_world_clientarea($vars) {
    $modulelink = $vars['modulelink'];
    return array(
        'pagetitle' => 'Addon Module',
        'breadcrumb' => array('index.php?m=hello_world'=>'Hello World Addon'),
        'templatefile' => 'template/clienthome', #smarty file name without .tpl extension
        'requirelogin' => true, # accepts true/false
        'forcessl' => false, # accepts true/false
        'vars' => array(  #smarty key value pair
            'name' => 'X ',
            'address' => 'Y',
            'phone' => 'Z',

Content of the file template/clienthome.tpl is

    <h4> My Details </h4>

        <li>My name is : {$name} </li>
       <li>My address is : {$address} </li>
        <li>My phone number is : {$phone} </li>
20 Sep

How to create and drop tables in WHMCS 7 using PHP 7?

We might have to create a table from WHMCS addon while activating the module.
Also we might have to drop the table while deactivating the module.
Here we are going to write PHP 7 compatible codes to create and drop the table.

Create a table

Assume that we have to create a table named sample_table
with the following fields.
It’s an auto increment field, also it’s primary key of the table.

This field is an integer

This field should store string and maximum character length is 100.

It’s a date field

It’s float field with two decimal points.

It’s a text field.

Then we can use below code for that.

 use Illuminate\Database\Capsule\Manager as Capsule;
 if (!Capsule::schema()->hasTable('sample_table')) {
        Capsule::schema()->create('sample_table', function($table) {
            $table->string('name', 100);
            $table->float('amount', 8, 2);

Drop the table.

To drop the table we can use the below code.

#add the below line only once in a file
use Illuminate\Database\Capsule\Manager as Capsule;
21 Aug

WHMCS Report Development

We can easily create a custom report in WHMCS.
First of all we have to create a file with any name and then we have to upload it to the folder modules/reports.

Let’s write a report to list down invoices that are paid between two dates.
Name of the file is invoice_report.php.
And it should be uploaded to the folder, modules/reports.

Th sample report code is below.


if (!defined("WHMCS")) die("This file cannot be accessed directly");

use Illuminate\Database\Capsule\Manager as Capsule;

# Report Title
$reportdata["title"] = "Invoice Report";

# Report Description
$reportdata["description"] = "";

$start_date = "2017-01-01";
$end_date =  date("Y-m-d");  

$reportdata["tableheadings"] = array(
      "DATE PAID", 
 if(!empty($start_date) && !empty($end_date)) {
        $invoices = Capsule::table('tblinvoices')
              ->whereBetween('datepaid', array($start_date, $end_date))
              ->where('status', 'Paid')

        foreach($invoices as $invoice) {
	         $reportdata["tablevalues"][] = array(
                    $invoice->tax + $invoice->tax2,

We have a ready made sales total report tool, with one time cost of $25.
Please Contact Us by filling the form. We will get back to you asap.