Problem Description
In WHMCS, domains that are not renewed before their expiry date are typically set to "Grace Period" status if a grace period is defined. This can lead to issues if the status is not updated promptly, such as:
-
Customers manually renewing domains that are no longer available (e.g., after deletion by the registrar).
-
Domain renewal lines being removed from invoices prematurely or incorrectly.
To address these issues, we will set a grace period of 29 days and automate the process of updating domain statuses to "Cancelled" after 29 days. This ensures the renewal line stays on the invoice during the grace period, and expired domains cannot be renewed after the defined duration.
Solution
Step 1: Configure Grace Period and Redemption Period
-
Log in to WHMCS Admin.
-
Navigate to Setup > Products/Services > Domain Pricing.
-
Set the Grace Period duration to 29 days.
-
Set the Redemption Period to None (0 days).
This configuration ensures that domains remain in the "Grace Period" for 29 days after expiry and move to "Expired" status on Day 30.
Step 2: Create a Script to Automate Domain Status Updates
This script will check for domains that have been "Expired" for more than 29 days and update their status to "Cancelled."
Steps to Create the Script
-
Create a new file in the WHMCS
crons
directory:nano /path-to-whmcs/crons/domains_update.php
-
Paste the following code into the file:
<?php // Define the path to WHMCS init.php require_once '../init.php'; // Use WHMCS Database Capsule for queries use WHMCS\Database\Capsule; // Define the log file path $logFile = 'domains_update.txt'; try { // Open the log file for writing $logHandle = fopen($logFile, 'a'); // 'a' mode appends data to the file if (!$logHandle) { throw new Exception("Unable to open log file: $logFile"); } // Get the list of domains to update $domains = Capsule::table('tbldomains') ->where('status', 'Expired') ->where('expirydate', '<', Capsule::raw('DATE_SUB(CURDATE(), INTERVAL 29 DAY)')) ->get(); // Update domains and log the changes foreach ($domains as $domain) { // Update the domain status Capsule::table('tbldomains') ->where('id', $domain->id) ->update(['status' => 'Cancelled']); // Log the domain name and status $logEntry = $domain->domain . " set to Cancelled on " . date('Y-m-d H:i:s') . "\n"; fwrite($logHandle, $logEntry); } echo "Successfully updated " . count($domains) . " domain(s). Check the log file for details.\n"; // Close the log file fclose($logHandle); } catch (\Exception $e) { // Handle errors and log them file_put_contents($logFile, "Error: " . $e->getMessage() . "\n", FILE_APPEND); echo "Error: " . $e->getMessage() . "\n"; }
-
Save and close the file.
Step 3: Add a Cron Job
To ensure the script runs daily, set up a cron job:
-
Open the cron jobs configuration file:
crontab -e
-
Add the following line to execute the script daily:
0 2 * * * php /path-to-whmcs/crons/
domains_update.phpThis example runs the script at 2:00 AM daily.
-
Save and exit the file.
Step 4: Behavior and Expected Outcomes
-
Grace Period: Domains will stay in the "Grace Period" for 29 days.
-
Invoice Renewal Line: The domain renewal line will remain on the invoice during the grace period.
-
Expired Status: On the 30th day, domains will transition from "Grace Period" to "Expired."
-
Cancelled Status: The script will update the status of domains from "Expired" to "Cancelled" on 30th day.
-
Log File: A
domains_update.txt
file will log all updated domains for tracking purposes. Each day's updates will be appended to the same file.
Notes
-
Ensure the script has the correct permissions to execute and write to the log file.
-
Test the script in a staging environment before deploying it to production.
-
Monitor the
domains_update.txt
file to verify the updates are occurring as expected.