Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Kian last won the day on July 6

Kian had the most liked content!

Community Reputation

408 Excellent

About Kian

  • Rank
    Senior Member

Recent Profile Visitors

15174 profile views
  1. Okay, here is the hook which is based on this other one - this one has more features.
  2. Incidentally I am working on an action hook where I need to remove specific payment methods from payment method dropdown (the one accessible from viewinvoice.php) depending on clients' groups. It is almost what you need. Basically there's an array like this one. define('kt_companies', [ 1 => [ 'tax_exempt' => true, 'invoice_header' => 'Ferrari S.p.A.' . PHP_EOL . 'Via Emilia Est 1163' . PHP_EOL . '41121 Modena - Italia', 'allowed_payment_gateways' => [ 'paypalcheckout' ] ], 2 => [ 'tax_exempt' => false, 'invoice_header' => 'Juventus S.p.A.' . PHP_EOL . 'Via Druento 175' . PHP_EOL . '10151 Torino - Italia', 'allowed_payment_gateways' => [ 'banktransfer', // The first gateway is always used as default to override restricted gateways (the ones not listed here) on open invoices (not in Paid, Collections, Refund, Payment Pending status) 'katamaze_nexi' ] ] ]); The keys (1 and 2) correspond to WHMCS client group. If a customer belongs to group id 2 (the second element of the array), I read allowed_payment_gateways array where I store payment gateways that the customer beloning to this group is allowed to use. I compare this array against all payment gateways available on WHMCS to find the the ones that the group is not allowed to use. Here's an example. WHMCS has gateway X, Y and Z. Group id 2 can only use X and Y. As a consequence Z is the gateway I need to restrict. Okay now I do 2 things. First. I remove Z from payment method dropdown (viewinvoice.php page). Second. I update all open invoices (not in Paid, Collections, Refund and Payment Pending status) of the client in question replacing Z (if present) with the first payment gateway in my allowed_payment_gateways array. If you can wait, I can extract the part that you need from the hook that I am finishing (btw I'll post that too). If you can't wait that's how I remove gateways from the dropdown. <?php // Apply kt_companies settings when a client is viewing an invoice add_hook('ClientAreaPageViewInvoice', 1, function($vars) { $data = kt_LoadCompanySettings($vars['userid']); // There are no restrictions on payment gateways for the client. There's no need to continue. The standard "Payment method" dropdown of WHMCS is good if (!isset($data['settings']['restricted_gateways'])) { return; } // At least one payment gateway is restricted to client. I parse $vars['gatewaydropdown'] (it contains the entire HTML of the "Payment method" dropdown accessible from viewinvoice.php) as HTML $dom = new DOMDocument(); $dom->loadHTML($vars['gatewaydropdown']); // I need to use xPath to read all the "<option></option>" tags of the "<select></select>" as an array $xpath = new DomXPath($dom); // I use this array to store xPath select conditions. I need this to communicate to xPath that for example I don't want "paypal" and "banktransfer" inside "Payment method" dropdown $xpath_conditions = []; // Looping every restricted payment gateway foreach ($data['settings']['restricted_gateways'] as $v) { $xpath_conditions[] = '@value="' . $v . '"'; } // Imploding condition by " or " as xPath is expecting $xpath_conditions = implode($xpath_conditions, ' or '); // Looping every "<option></option>" to detect restricted payment gateways and remove them from "Payment method" dropdown foreach($xpath->query('//select/option[(' . $xpath_conditions . ')]') as $node) { // Removing the restricted payment gateway $node->parentNode->removeChild($node); } return [ 'gatewaydropdown' => $dom->saveXml() // Overriding default WHMCS dropdown with mine ]; }); You should change the $data = kt_LoadCompanySettings($vars['userid']); part with this: $data['settings']['restricted_gateways'] = [ // Gateways you want to restrict 'paypaycheckout', 'banktrasnfer' ] Keep in mind that I'm still working on this code. It works for me but I still haven't tested everything.
  3. I haven't a ready-made script for this but you can take as a refence this hook. When invoice balance is greater than or equal to a given amount, it prevents customers from changing payment gateways. In essence you just need to change the trigger and you're done.
  4. This. SELECT tblclients.id AS client_id, CONCAT(tblclients.firstname, " ", tblclients.lastname) AS client_name, tblclients.companyname AS client_company_name, SUM(tblcredit.amount) AS current_credit_balance FROM tblclients LEFT JOIN tblcredit ON tblclients.id = tblcredit.clientid GROUP BY tblclients.id
  5. There could be a better approach that I am not aware of but that's how I do it. When I started coding in WHMCS (2009) there were no Lang::trans() and autoloader so I had to find a way myself. In my module hooks.php file I require my autoloader (it can also be a normal php file) where the constructor perfoms various things including the loading of my language files depending on current user/visitor language. I also take into account overrides directory if present in modules/{MyModule}/lang/overrides. This way customers can override $_ADDONLANG like they already do for $_LANG. <?php require 'my_module_autoloader.php'; add_hook('AnnouncementAdd', 1, function($vars) { $hook = Hook::getInstance($vars); die($hook->addonlang->welcome_message); }); Over the years I used new(), singleton, and dependency injection approach. They all work.
  6. It doesn't show anything because the hook was made for WHMCS v5, v6 and v7. The current admin template has changes that prevent jQuery from finding a CSS selector on the page. Btw I updated the code so that the Run Daily Cron button is displayed on top of the sidebar as follows.
  7. I have no direct experience with twenty-one but are you sure that WHMCS gives only 10 records? As far as I know WHMCS doesn't use server-side processing of DataTables hence all rows are accessible from {$invoices}. For example at the moment I am browsing a system where I have almost 4000 invoices. Each of them is accessible from {$invoices}. In fact when I change page limite from "10" to "All" they all show up without any need of ajax POST.
  8. It's DataTables. Simply use pageLenght API.
  9. SELECT t3.date, t3.invoicenum, t2.domain, t3.status FROM tblinvoiceitems AS t1 LEFT JOIN tbldomains AS t2 ON t1.relid = t2.id LEFT JOIN tblinvoices AS t3 ON t1.invoiceid = t3.id WHERE t1.type IN ('Domain', 'DomainRegister', 'DomainTransfer') AND t3.status = 'Paid' AND t3.date >= '2022-03-01' order by t3.date DESC I personally finished checking tens of thousands of domains on several systems using this query. It selects all domains that have been renewed, registered and transfered starting from 2022-03-01. This date should safe to use. In fact I think the faulty version of IBS has been released 40 days ago. You need to get all the returned domains and check them in bulk on internetbs.net. I spent hours trying to understand how to identify potential issues but I wasn't able to do that so I focused on all domains with expiration date set on 2022 and checked them manually one by one 😩 Sorting them by expiration date DESC was very helpful. Sadly I found several domains that haven't been renewed even if end-users paid invoices and WHMCS performed renewals. At least there were less cases than I expected. Special note for .it domains. Unlike other TLDs where you explicitly need to send "Renew Domain" command, .it domains get automatically renewed. To avoid renewing domains that haven't been paid, IBS automatically sends "Delete Domain" command usually 14 days after expiration .This way NicIT (IT Registry) doesn't renew them automatically. With all this mess I am still figuring out what happened to .it domains. Maybe nothing or maybe IBS allowed NicIT to renew them even if they haven't been paid by customers. In conclusion you should update IBS module asap and perform the check I just described but there is a twist. You should do that only if you were running this buggy version of IBS. The problem is that the only way for me to explain how to determine if your IBS module is good or bad, is to describe the exploit 🥶 Okay enough drama for me today. See you 🕳️
  10. Yep, I was just responding to ComfortDrive since he/she suggested you to run a SEO audit. As you probably know better than me a SEO audit doesn't play any role when it comes to things like cPanel SEO, Ahrefs, Semrush etc.
  11. Ahref also has a free version that is good enough to analyse metrics. Same goes for neilpatel.com but... ... there is no audit to check here since cPanel SEO doesn't directly affect your SEO. It's a tool used track keywords, traffic, get recommendations, alerts etc. It will not automagically improve anything. There's no point looking at stats and graphs per se. Such tools only make sense if you have a SEO strategy in mind.
  12. There is another problem. Not only we have/had the exploit but as I can see their module even failed at renewing domains. I am seeing clients realizing they never renewed any domain during the last 40 or more days even if WHMCS performed renewals as normal and invoices have been paid. That said, I highly suggest you to double check manually that all renewals occurred during the last 3 months have been successful. I say 3 months because IBS module doesn't come with versioning so I can't tell the exact date starting from which we had this mess. For sure more than 40 days but it can be more!
  13. IBS released an update that fixes the issue. Download it asap! Trust me 😱
  14. Yes, it must be enabled and configured.
  15. John edited the title of this post so now everyone knows the name of the module in question. Balls of steel 😱😁 I'll do it but I suspect that WHMCS is not affected by this issue. Anyway I'll send you all details including the super-easy fix via DM and Bugcrowd so that you can take a look. I will not say anything here to avoid having people exploiting the bug.
  • 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