Jump to content


WHMCS Technical Analyst
  • Content Count

  • Joined

  • Last visited

  • Days Won


WHMCS Josh last won the day on January 30

WHMCS Josh had the most liked content!

Community Reputation

8 Neutral

1 Follower

About WHMCS Josh

  • Rank
    WHMCS Technical Analyst

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. A favicon is a small icon that browsers display at the top of the page (usually next to the address bar or page title). Some browsers such as FireFox and Opera may even use them for Bookmark icons as well. To add a favicon, simply upload a favicon.ico file to the WHMCS installation directory. Example: public_html/whmcs/favicon.ico Most modern browsers will automatically begin displaying the favicon once it has been uploaded, but some may also require a meta tag. To add the meta tag, open your whmcs/templates/YOUR_TEMPLATE/header.tpl file where YOUR_TEMPLATE is the name of your client area template and add this line just under the opening <head> tag: <link rel="shortcut icon" href="favicon.ico" /> You may need to clear your browser cache in order to see the changes take effect.
  2. Sometimes during the ordering process, you may wish to bypass the nameserver prefix fields which are required by default for VPS/Dedicated product types. For instance, you may always want to always use ns1.yourdomain.com and ns2.yourdomain.com instead of having users specify. This can be accomplished by changing the field type to hidden and specifying a value to be used. The following steps outline how to do this: Create a custom template directory at /templates Copy the /templates/orderforms/standard_cart/configureproduct.tpl file into the custom directory Create a theme.yaml file in the custom directory with the following contents: config: parent: standard_cart Edit the configureproduct.tpl file in your custom template directory and find the following line: <input type="text" name="ns1prefix" class="form-control" id="inputNs1prefix" value="{$server.ns1prefix}" placeholder="ns1"> Replace it with: <input type="hidden" name="ns1prefix" class="form-control" id="inputNs1prefix" value="ns1.yourdomain.com"> More information regarding how to create a new order form template based on a parent template can be found in the documentation here: https://docs.whmcs.com/Order_Form_Templates#Creating_a_New_Template_based_on_a_Parent I hope this helps and please feel free to post any further questions/comments.
  3. In the latest release, you may have noticed that the Request Cancellation link in the left sidebar has been removed for free and one time products and services. This change was made in response to a bug report relating to one time products not being automatically cancelled. There was some concern that allowing cancellation requests for free and one time items, which have no next due date, and therefore terminate immediately on the following cron run could lead to irrevocable data loss. It is important to note that this is only a visual change that removes the link to submit a cancellation request. Submitting a cancellation request for a free service is still possible. If you wish to restore the option to cancel free products, you can do so using a hook. I've prepared some sample code that uses the ClientAreaPrimarySidebar hook point to achieve this. Here is the code below: <?php /** * This hook restores the Request Cancellation sidebar option on free services * * @author WHMCS Josh * @see https://developers.whmcs.com/hooks-reference/client-area-interface/#clientareaprimarysidebar * @see https://developers.whmcs.com/advanced/db-interaction/ */ use WHMCS\Database\Capsule; use WHMCS\View\Menu\Item; add_hook('ClientAreaPrimarySidebar', 1, function($primarySidebar) { // Get the handle for the Service Details Overview sidebar $serviceDetailsOverview = $primarySidebar->getChild('Service Details Overview'); // Make sure the handle is not null if (!is_null($serviceDetailsOverview)) { // Make sure the ID is available if (!empty($_REQUEST['id'])) { $serviceId = (int) $_REQUEST['id']; // Check if this is a free service $billingCycle = Capsule::table('tblhosting') ->where('id', $serviceId) ->value('billingcycle'); if ($billingCycle === 'Free Account') { // Add the cancellation request menu item for the service to the sidebar $serviceDetailsOverview->addChild( 'freeServiceCancellationRequest', [ 'name' => 'CancellationRequest', 'label' => 'Request Cancellation', 'uri' => '/clientarea.php?action=cancel&id=' . $serviceId, 'order' => 90, ] ); } } } }); To install this, you can simply add the code to a file in your /includes/hooks directory such as /includes/hooks/free_product_cancellation_request.php. For convenience, I've attached the completed hook file to this post here: free_product_cancellation_requests.php Below is also a screenshot of how this looked on my test installation of WHMCS 7.7.0. Please note that this is being provided only as an example and is not guaranteed to work with future versions of WHMCS. Feel free to modify it to suit your needs and I hope it helps!
  4. Seeing an error like this could indicate that the file for that page (systemcleanup.php) doesn't exist on your server or does not have sufficient permissions for the server to read it. This could also be something that is caused by having custom .htaccess rules in place that are interfering with the stock WHMCS .htaccess rules.
  5. When you are experiencing issues with payment gateways, you should check the Billing > Gateway Log page in your admin area for more information on what may be causing the problem: https://docs.whmcs.com/Payment_Processing_Issues#Merchant_Gateway_Declining_or_Failing
  6. Thanks for providing the screenshots and additional information. I'm seeing that you have not set the System Cron to run every 5 minutes as per the documentation here: https://docs.whmcs.com/Crons#System_Cron The System Cron (cron.php file) needs to be executed by your server's crontab every 5 minutes. What will happen is when the cron file gets executed during your Time of Day hour, it will then perform all automation tasks and mark as completed in WHMCS. When the cron is able to complete all tasks and mark itself as completed, you will no longer receive that email notification saying that it didn't run during the expected time.
  7. It looks like your cron job is starting but not fully completing, which would trigger this notification email to be sent. Your cron is most likely failing to complete due to a fatal PHP error. Do you see any errors if you enable Display Errors on the Setup > General Settings > Other tab and manually execute your cron job from the shell using the all --force -vvv options? php -q /crons/cron.php all --force -vvv https://docs.whmcs.com/Cron_Job_Issues#Run_the_cron_job_from_the_server_command_line_with_debugging_enabled
  8. Thanks everyone for the feedback! To clarify, this file is not meant to run with the WHMCS hooks system as there is no add_hook() function call being made, so placing it in the /includes/hooks directory may not work. This file was meant to be a one-off solution to be used for removing the mass spam clients that were being created. In order to use it properly, you would simply place the file in your WHMCS root directory and then access the file from your browser to run it. It should provide you with the output of what clients were able to be deleted or which clients were not (if any). You can run the script as many times as needed until all of the spam clients have been removed. When you are done using the script, it should be removed from the server as it does contain code that destroys data (deletes clients). It shouldn't ever be an issue, but to be safe it is good practice to remove utility scripts when they aren't needed anymore. As always, please remember to take a database backup before using this tool.
  9. An unfortunate trait of the internet is spam and automated bots disseminating that spam. As a business operator on the internet, you may also receive orders submitted in bulk by automated bots. There can be situations where you need to delete lots of clients with the same first name. This small script leverages the local API to cleanly delete all clients who match the specified term. This script is provided as-is, without warranty, and in the understanding for the potential to permanently and irreversibly delete data. Before running this script, please make a database backup: <?php /** * Delete spam clients where the firstname contains 5666Q.COM * using advanced database interaction and the DeleteClient API * * @link https://developers.whmcs.com/advanced/db-interaction/ * @link https://developers.whmcs.com/api-reference/deleteclient/ * * @author WHMCS Limited <development@whmcs.com> * @copyright Copyright (c) WHMCS Limited 2005-2018 * @license https://www.whmcs.com/eula/ WHMCS Eula */ require 'init.php'; use WHMCS\Database\Capsule; // Replace ADMIN_USERNAME with your admin username $adminUsername = 'ADMIN_USERNAME'; echo '<pre>'; // Loop through all clients where firstname contains 5666Q.COM foreach (Capsule::table('tblclients')->where('firstname', 'like', '%5666Q.COM%')->get() as $client) { // Delete the client with DeleteClient API $results = localAPI('DeleteClient', ['clientid' => $client->id], $adminUsername); // Check for errors if ($results['result'] == 'success') { echo "Deleted Client ID: " . $client->id; } else { echo "Error deleting Client ID: " . $client->id; } } echo '</pre>'; Begin by entering your adminstrator's username on line 19: $adminUsername = 'ADMIN_USERNAME'; Upload the script to your WHMCS directory, and visit in your browser. The script will search through all the clients matching the criteria specified in this line: 'firstname', 'like', '%5666Q.COM%' It will then properly and permanently delete matching clients and associated records. The last step is to show which clients are deleted, and if a problem was occurred. The file should then be deleted from your server. At the time of writing this post, this script was tested on the latest stable release of WHMCS 7.5.1 and should work with any that fall under Active Support as per the LTS schedule here: https://docs.whmcs.com/Long_Term_Support#WHMCS_Version_.26_LTS_Schedule If you have any feedback, questions, or concerns that I did not cover in this post, please feel free to reach out! delete_spam_clients.php
  10. Hello Remitur, I can confirm that this hook does not block the use of TLDs such as .co.uk because the hook only affects the SLD field on the shopping cart. The TLD field will remain unaffected and allow the user to proceed through the checkout process. I have attached a couple screenshots to show how this looked on my test installation.
  11. When it comes time to order a hosting plan, sometimes you don't want your users to be able to enter in a subdomain when using an existing domain for their order. In this post I am going to walk you through a basic hook that prevents entering a subdomain by using some client-side JavaScript. Our first order of business will be to check out the WHMCS hooks index to see if there is a hook point that will fit our needs: https://developers.whmcs.com/hooks/hook-index/ It turns out, the ClientAreaFooterOutput hook will do nicely: https://developers.whmcs.com/hooks-reference/output/#clientareafooteroutput The reason for this is because that hook point will allow you to inject HTML code, which also can contain JavaScript, into the client-side template so you can make the magic happen. Before getting into more detail, let's go ahead and dive right into the code. You can also download it from this link block_subdomains.txt (then rename the extension to .php). Here is the entire snippet: <?php add_hook('ClientAreaFooterOutput', 1, function($vars) { $jqueryCode = '<script> $("#owndomainsld").on("keyup", function(e) { var str = $("#owndomainsld").val(); if ( str.indexOf(".") != -1 ) { $("#owndomainsld").val(""); alert("Subdomains are not allowed!"); } }); </script>'; if (strpos($_SERVER['REQUEST_URI'], 'cart.php') !== false ) { return $jqueryCode; } }); The first thing to notice is the add_hook function is being called with the ClientAreaFooterOutput hook point as the first argument and an anonymous function as the second argument. The anonymous function also has a $vars variable being passed into it. For this example the $vars variable is not actually being used in the body of the function, but it does contain some useful parameters should you need to access them. Those parameters can be found in the documentation for the hook point linked above. The next thing to notice is the $jqueryCode variable. which is actually a PHP string that contains the JavaScript code we will be injecting into our client-side page. Since WHMCS uses the jQuery JavaScript library and loads it on the page, we can use it in our code. First, we need to bind an event listener to the keyup event on the domain text box and provide it a callback function to execute when that event occurs. This can be easily done by targeting the element's HTML ID attribute. That is what is happening here: $("#owndomainsld").on("keyup", function(e) {... After that, the value of the domain text field is stored in a JavaScript variable called str. Since this code is inside our callback function, it will be executed every time the user presses a key on the keyboard and then releases it: var str = $("#owndomainsld").val(); Once we have that text stored in our str variable, we need to check it for a dot or period '.' character to see if it is a subdomain. This can be done with indexOf string function in JavaScript. If the text appears to be a subdomain, we'll go ahead and empty out the text field and then show an alert to the user to let them know that subdomains are not allowed: if ( str.indexOf(".") != -1 ) { $("#owndomainsld").val(""); alert("Subdomains are not allowed!"); } Finally, the last part of the hook does a case-insensitive string search on the $_SERVER['REQUEST_URI'] (the URL of the page you're visiting), to check and see if a cart page is being rendered. If a cart page is detected, the JavaScript code is injected into that page so it can run. if (strpos($_SERVER['REQUEST_URI'], 'cart.php') !== false ) { return $jqueryCode; } Putting it all together, we get the final results in WHMCS which look like the picture here: I hope this post proved helpful and gives some insight on some of the ways that WHMCS can be extended to do many different things outside the box! At the time of writing this post, this hook was tested on the latest stable release of WHMCS 7.4.2 and should work with any that fall under Active Support as per the LTS schedule here: https://docs.whmcs.com/Long_Term_Support#WHMCS_Version_.26_LTS_Schedule If you have any feedback, questions, or concerns that I did not cover in this post, please feel free to reach out!
  12. I did some quick testing on my WHMCS installation and was able to get the following hook function working to remove the 'Network Status' submenu item from the 'Support' menu. <?php use WHMCS\View\Menu\Item as MenuItem; add_hook('ClientAreaPrimaryNavbar', 1, function (MenuItem $primaryNavbar) { if (!is_null($primaryNavbar->getChild('Support'))) { $primaryNavbar->getChild('Support')->removeChild('Network Status'); } }); I simply placed this inside the /includes/hooks directory in a file called remove_network_status.php
  • 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