Jump to content

Add clients in bulk to WHMCS from a CSV file.


Recommended Posts

  • WHMCS Technical Analyst

Hello WHMCS Community,

I wanted to share a useful PHP script that I created to add clients from a CSV file to WHMCS using the internal API. This script is designed to be run on the same server (and directory) where WHMCS is installed, ensuring that it is secure and prevents unauthorized use.

Prerequisites:

  1. 1. WHMCS API Credentials: Ensure you have your WHMCS API identifier and secret.
  2. 2. CSV File: Prepare a CSV file with the following columns: firstname, lastname, email, address1, city, state, postcode, country, phonenumber, password.

PHP Script:

Here is the PHP script to read the CSV file and add clients to WHMCS:
 

<?php

// CONFIGURATION 
$secretKey = 'CHANGE_ME_TO_A_RANDOM_32_CHAR_STRING'; // REQUIRED: Script will refuse to run if unchanged
// Enter a valid WHMCS Admin username for the API context.
$adminUsername = 'YourAdminUsername'; 
// FILE CHECK & OPEN CSV
$csvPath = 'clients.csv';

// SECURITY CHECK
if ($secretKey === 'CHANGE_ME_TO_A_RANDOM_32_CHAR_STRING') {
    die("<h3>Security Error</h3><p>You must change the <code>$secretKey</code> value inside the script before running it.</p>");
}
if (!isset($_GET['key']) || $_GET['key'] !== $secretKey) {
    die("<h3>Access Denied</h3><p>Invalid or missing key.</p>");
}

// INITIALIZE WHMCS ENVIRONMENT
require_once 'init.php';

// Prevents the script from timing out on large files
set_time_limit(0);
ini_set('memory_limit', '512M');

// Force output to the browser so you see progress instantly
if (function_exists('apache_setenv')) { @apache_setenv('no-gzip', 1); }
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);

echo "<html><body style='font-family: sans-serif; padding: 20px;'>";
echo "<h2>Starting Client Import...</h2><hr>";

// FILE CHECK
if (!file_exists($csvPath)) {
    die("<p style='color:red; font-weight:bold;'>Error: The required file <code>clients.csv</code> was not found in the WHMCS folder.</p>");
}

$file = fopen($csvPath, 'r');
fgetcsv($file); // Skip header row

$count = 0;

// PROCESS ROWS
while (($data = fgetcsv($file)) !== false) {
    $count++;

    $values = [
        'firstname'   => $data[0] ?? '',
        'lastname'    => $data[1] ?? '',
        'email'       => $data[2] ?? '',
        'address1'    => $data[3] ?? '',
        'city'        => $data[4] ?? '',
        'state'       => $data[5] ?? '',
        'postcode'    => $data[6] ?? '',
        'country'     => $data[7] ?? '',
        'phonenumber' => $data[8] ?? '',
        'password'    => $data[9] ?? '',
        'noemail'     => true,
    ];

    // WHMCS API CALL
    $results = localAPI('AddClient', $values, $adminUsername);

    // OUTPUT RESULT
    if ($results['result'] === 'success') {
        echo "<div style='color:green;'>[OK] Row $count: Added Client ID {$results['clientid']} ({$values['email']})</div>";
    } else {
        echo "<div style='color:red;'>[FAIL] Row $count: {$values['email']} - Error: {$results['message']}</div>";
    }

    flush();
}

fclose($file);
echo "<hr><h3>Import Process Complete.</h3>";
echo "</body></html>";
?>

Running the Script

  1. 1. Save the script as add_clients.php and place it in your WHMCS root directory.
  2. 2. Ensure the clients.csv file is in the same directory.
  3. 3. Run the script from the command line or through your browser.
  4. 4. NOTE: Once the work is done, ENSURE that the script is deleted and NOT left on the server. 

 

This is provided on an as is basis. But I will try to answer any queries if anyone faces any issues with this. Hope it comes in handy. 

Edited by WHMCS Sachin
Code Update for security
Link to comment
Share on other sites

  • WHMCS Technical Analyst
17 hours ago, bear said:

Security check?
Appreciate the effort, but that's not terribly secure, especially when you spit out the answer in the failure routine if it's not included. 

Fair point, but it is mostly to stop any random bots from triggering it accidentally, and it can be easily modified by the person to remove it from the output once they are setting it up. 

Link to comment
Share on other sites

I'd suggest that your average user that grabs a script like this will not change anything in it, especially since they're not (apparently) being told to. I've seen users not change a "CHANGE_THIS" in scripts, then ask why it's not working. I've also seen them ignore the "remove this file after use", so relying on that might not be advisable either.

Best practice is not to spoon feed, keep this outside the publicly accessible directories, and instead of that simple URL parameter you reveal, make it a "secret key" that is defined within the script, with a note to change it (or better still they make their own that must be x long and have this or that in it; if empty, fail with "key needed").
Safety first.

Link to comment
Share on other sites

  • WHMCS Technical Analyst
3 hours ago, bear said:

I'd suggest that your average user that grabs a script like this will not change anything in it, especially since they're not (apparently) being told to. I've seen users not change a "CHANGE_THIS" in scripts, then ask why it's not working. I've also seen them ignore the "remove this file after use", so relying on that might not be advisable either.

Best practice is not to spoon feed, keep this outside the publicly accessible directories, and instead of that simple URL parameter you reveal, make it a "secret key" that is defined within the script, with a note to change it (or better still they make their own that must be x long and have this or that in it; if empty, fail with "key needed").
Safety first.

Excellent points. Feedback taken and code updated 🙂

Link to comment
Share on other sites

5 hours ago, WHMCS Sachin said:

Iteration is how we learn, dont we?

?

At any rate,  32 characters doesn't appear to be required (any length works, as long as it's not the given one, and as it's a GET, the parameter of the key needs to be in the URL as before, yes (script.php?key=xxxxx)? Without, it gets the invalid key error. You've removed that explanation/step. 

If you like, once this is working and explained, remove my comments. Just trying to help and it's kind of blown up your kind gesture of this script. Apologies. 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated