Jump to content

Recommended Posts

So I'm working with the licensing addon, and attempting to figure out the hook part..

 

add_hook('LicensingAddonVerify', 1, function($vars) {
    return [
        'Hash' => 'Hash Here',
    ];
}
);

The hash actually shows in the license how it should, but I'm trying to do it since I make several softwares, and not only one, so what I'm trying to do is something like

if ($productid == "prodID number") {
add_hook('LicensingAddonVerify', 1, function($vars) {
    return [
        'Hash' => 'Hash Here',
    ];
}
);
}
else -- run get different product

It doesn't retrieve the product id at all.. What am I missing here? The hash is basically there to tell the system if a new version has been released. 

 

Thanks

Share this post


Link to post
Share on other sites

i'd move that IF statement inside the hook instead of leaving it outside of it, and then return the various hash responses inside each of the IF statements.

Share this post


Link to post
Share on other sites

Hi @mfoland,

Based on your description, it sounds like something like the following may be useful for your needs:

<?php

use WHMCS\Service\Service;

add_hook('LicensingAddonVerify', 1, function($vars) {

    try {
        $service = Service::findorFail($vars['serviceid']);
        $productID = $service->packageId;
    } catch (\Exception $e) {
        $productID = 0;
    }

    switch ((int)$productID) {
        case 0:
            return [
                'Hash' => 'error',
            ];
            break;
        case 1:
            return [
                'Hash' => '1',
            ];
            break;
        case 2:
            return [
                'Hash' => '2',
            ];
            break;
        case 3:
            return [
                'Hash' => '3',
            ];
            break;
    }
});

Naturally, in the switch you'd need to replace 1, 2, 3 with your actual Product ID's. In my example, I use 0 to return an error (Product ID not found).

This sample is provided as-is with no guarantee or warranty however, I trust it provides you with the information you require for your customisations.

The documentation I used in this example was:

https://developers.whmcs.com/hooks-reference/addon/#licensingaddonverify
https://docs.whmcs.com/classes/7.6/WHMCS/Service/Service.html
http://php.net/manual/en/control-structures.switch.php
https://docs.whmcs.com/Using_Models

I hope this helps!

Share this post


Link to post
Share on other sites
40 minutes ago, WHMCS Peter said:

Hi @mfoland,

Based on your description, it sounds like something like the following may be useful for your needs:


<?php

use WHMCS\Service\Service;

add_hook('LicensingAddonVerify', 1, function($vars) {

    try {
        $service = Service::findorFail($vars['serviceid']);
        $productID = $service->packageId;
    } catch (\Exception $e) {
        $productID = 0;
    }

    switch ((int)$productID) {
        case 0:
            return [
                'Hash' => 'error',
            ];
            break;
        case 1:
            return [
                'Hash' => '1',
            ];
            break;
        case 2:
            return [
                'Hash' => '2',
            ];
            break;
        case 3:
            return [
                'Hash' => '3',
            ];
            break;
    }
});

Naturally, in the switch you'd need to replace 1, 2, 3 with your actual Product ID's. In my example, I use 0 to return an error (Product ID not found).

This sample is provided as-is with no guarantee or warranty however, I trust it provides you with the information you require for your customisations.

The documentation I used in this example was:

https://developers.whmcs.com/hooks-reference/addon/#licensingaddonverify
https://docs.whmcs.com/classes/7.6/WHMCS/Service/Service.html
http://php.net/manual/en/control-structures.switch.php
https://docs.whmcs.com/Using_Models

I hope this helps!

@WHMCS Peter could I assign multiple cases so I can do it for multiple product ID's since some are Owned and Monthly?

Thanks for your help! 🙂

Share this post


Link to post
Share on other sites

Hi @mfoland,

Sure thing! As documented in the PHP Manual, this can be achieved like so:

Let's say you wanted cases 1, 2 and 3 to do the same thing:

switch ((int)$productID) {

    case 0:
        return [
            'Hash' => 'error',
        ];
        break;
    case 1:
    case 2:
    case 3:
        return [
            'Hash' => 'MySecretHash',
        ];
        break;
}

Here's that link again for reference 🙂 - http://php.net/manual/en/control-structures.switch.php

Share this post


Link to post
Share on other sites

Perfect.

I was thinking it could do this: 

switch ((int)$productID) {
        case 0:
            return [
                'Hash' => 'error',
            ];
            break;
        case 31 - 32:
            return [

but then I got to looking on that! Thanks so much!

Share this post


Link to post
Share on other sites

@WHMCS Peter

While on the licensing topic... I have this code:

 

//--Check Addons validity
$addonarray = array();
$addonslist = explode('|',$results['addons']);
	foreach ($addonslist as $addons){
		$addondata = explode(';',$addons);
		$addonname = $addonnextduedate = $addonstatus = "";
	foreach ($addondata as $addon){
		$addonnvp = explode('=',$addon);
		if($addonnvp[0] == 'name') $addonname = $addonnvp[1];
		if($addonnvp[0] == 'nextduedate') $addonnextduedate = $addonnvp[1];
		if($addonnvp[0] == 'status') $addonstatus = $addonnvp[1];
}

$addonarray[$addonname] = array("nextduedate"=>$addonnextduedate,"status"=>$addonstatus);
$hisAddon = array("$addonname");
$arrlength = count($hisAddon);

for($x = 0; $x < $arrlength; $x++) {
    $addonFinal[] = $hisAddon[$x];
    $addonStat[]  = $addonstatus[$x];
 $hisAddon[$x] = $hisAddons;
//$hisAddons = "$hisAddon";
}}

//-- Branding Option Force 9/6/18.. Completed 9/8/2018.
$astat = str_replace("A", "Active", $addonStat[0]);
$bname = "Branding Removal";
$badd = $addonFinal[0];
	if ($badd == $bname && $astat == "Active") {
	$bReq2 = "N";
	$brandRemov2 = "Yes";
	} else {
	$bReq2 = "Y";
	$brandRemov2 = "No";
	}*/
//--Ends Force Branding
//--Do we have Support and Updates Allowed?
$lkey  = $license_key;
$key   = explode("-", $lkey);
$bstat = str_replace("A", "Active", $addonStat[0]);
$cname = "SupportAccess";
$cadd  = $addonFinal[0];
if ($cadd == $cname && $astat == "Active")
{
                $supportUpdates = "Yes";
} 
else
{
                $supportUpdates = "No";
}

What's going on, is If I suspend one of the addons they both show Not Allowed, and if I have one of them enabled, both are enabled. I was working with the license key portion to automatically say Monthly has Support Access (which would of been what the hash was for to get the updates). But why in the world would both be active or suspended, if one of them were and the other was an opposite status? This is so mind boggoling

 

Thanks!

Share this post


Link to post
Share on other sites

Hi,

The first thing that stands out to me is this line:

$addonname = $addonnextduedate = $addonstatus = "";

That to me looks like it's reassigning more than 1 variable. I'd recommend stepping through your code, making sure each variable is returning exactly as you expect it to.

You can use something like die(var_dump($variable)); to achieve that.

Share this post


Link to post
Share on other sites
Posted (edited)
8 minutes ago, WHMCS Peter said:

Hi,

The first thing that stands out to me is this line:


$addonname = $addonnextduedate = $addonstatus = "";

That to me looks like it's reassigning more than 1 variable. I'd recommend stepping through your code, making sure each variable is returning exactly as you expect it to.

You can use something like die(var_dump($variable)); to achieve that.

@WHMCS Peter

Changed the lining to

$addonarray = array();
$addonslist = explode('|',$results['addons']);
	foreach ($addonslist as $addons){
		$addondata = explode(';',$addons);
		$addonname = $addonnextduedate = $addonstatus = "";
		die(var_dump($results[status]));
	foreach ($addondata as $addon){
		$addonnvp = explode('=',$addon);
		if($addonnvp[0] == 'name') $addonname = $addonnvp[1];
		if($addonnvp[0] == 'nextduedate') $addonnextduedate = $addonnvp[1];
		if($addonnvp[0] == 'status') $addonstatus = $addonnvp[1];
}

I went to do $addonname and it gave a 0 string. For the results[status] i'm getting Active, and when I try to do $addonstatus there's no data. Not sure why it's giving an issue.

 

Here's what my Addon Array looks like:

string(117) "name=SupportAccess;nextduedate=2019-09-09;status=Active|name=Branding Removal;nextduedate=0000-00-00;status=Suspended"

 

Edited by mfoland
Added addon array

Share this post


Link to post
Share on other sites
10 minutes ago, mfoland said:

@WHMCS Peter

Changed the lining to


$addonarray = array();
$addonslist = explode('|',$results['addons']);
	foreach ($addonslist as $addons){
		$addondata = explode(';',$addons);
		$addonname = $addonnextduedate = $addonstatus = "";
		die(var_dump($results[status]));
	foreach ($addondata as $addon){
		$addonnvp = explode('=',$addon);
		if($addonnvp[0] == 'name') $addonname = $addonnvp[1];
		if($addonnvp[0] == 'nextduedate') $addonnextduedate = $addonnvp[1];
		if($addonnvp[0] == 'status') $addonstatus = $addonnvp[1];
}

I went to do $addonname and it gave a 0 string. For the results[status] i'm getting Active, and when I try to do $addonstatus there's no data. Not sure why it's giving an issue.

 

Here's what my Addon Array looks like:


string(117) "name=SupportAccess;nextduedate=2019-09-09;status=Active|name=Branding Removal;nextduedate=0000-00-00;status=Suspended"

 

Here's what the actual Array looks like when I var dump addon array..

 

Array ( [SupportAccess] => Array ( [nextduedate] => 2019-09-09 [status] => Active ) ) Array ( [SupportAccess] => Array ( [nextduedate] => 2019-09-09 [status] => Active ) [Branding Removal] => Array ( [nextduedate] => 2019-03-12 [status] => Suspended ) ) 

That part knows what it's suppose to do, based on the above script, so not sure why I would be having the issue 😞

Share this post


Link to post
Share on other sites

Hi @mfoland,

I'm seeing two array keys called "SupportAccess". If one is expired but another is Active, it's possible that one is overwriting the other.

Array ( 
    [SupportAccess] => Array ( 
        [nextduedate] => 2019-09-09 
        [status] => Active 
    )
) 
Array ( 
    [SupportAccess] => Array ( 
        [nextduedate] => 2019-09-09 
        [status] => Active 
    )
    [Branding Removal] => Array ( 
        [nextduedate] => 2019-03-12 
        [status] => Suspended 
    )
)

 

Share this post


Link to post
Share on other sites
3 hours ago, WHMCS Peter said:

Hi @mfoland,

I'm seeing two array keys called "SupportAccess". If one is expired but another is Active, it's possible that one is overwriting the other.


Array ( 
    [SupportAccess] => Array ( 
        [nextduedate] => 2019-09-09 
        [status] => Active 
    )
) 
Array ( 
    [SupportAccess] => Array ( 
        [nextduedate] => 2019-09-09 
        [status] => Active 
    )
    [Branding Removal] => Array ( 
        [nextduedate] => 2019-03-12 
        [status] => Suspended 
    )
)

 

@WHMCS Peter

Array ( [SupportAccess] => Array ( [nextduedate] => 2019-03-12 [status] => Active ) )

Now I have Branding Removal gone out of the license.. but it still shows ENABLED in my script

Share this post


Link to post
Share on other sites

Hi @mfoland,

At this point, you would need to step through each part of your code performing var_dump($var) along the way. By doing this, you can ensure each part of your script is working as expected.

When you reach a point where a variable is returning one thing but should in fact be another, you'll narrow down the area in which the defect lies.

I'd recommend reaching out to a qualified PHP Developer if you are still uncertain. Unfortunately, our support scope is fairly limited.

Share this post


Link to post
Share on other sites

Well here's the array... 

array(3) {
  [0]=>
  string(18) "name=SupportAccess"
  [1]=>
  string(22) "nextduedate=2019-03-12"
  [2]=>
  string(13) "status=Active"
}
array(3) {
  [0]=>
  string(21) "name=Branding Removal"
  [1]=>
  string(22) "nextduedate=0000-00-00"
  [2]=>
  string(13) "status=Active"
}

It's weird because for Active it still says Branding is required, and if suspended it's still showing required. So I'm not sure what the heck is going on. I find this REALLY ODD! I use to name my products the original product name.. so in the case of the radio CMS, it would be Monthly WaveCMS Standard or Owned WaveCMS Standard . I use to do Unbranded or Branded at the end. I'm thinking of possibly going back to that! This is really weird haha. I'm going to continue to figure this one out.

Share this post


Link to post
Share on other sites

@WHMCS Peter

Any ideas? It seems like it wants to rely on one of the statuses. Not sure what else is going on. Even though the status is in the loop right, and the array, I'm not sure what else could be going on here. I'm at a loss. This one is tricky!

Share this post


Link to post
Share on other sites

I found a solution that works by using the $addonarray part of my code!

if (in_array("Active", $addonarray[BrandingRemoval])) {
$bReq = "N";
$brandRemov = "Yes";
}
else{
$bReq = "Y";
	$brandRemov = "No";
}

It works 🙂

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By WHMCS Josh
      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!
    • By Cubeboy
      I need to get rid of the date when I add files on the admin side.
       
      when I upload a file the a clients account in the admin section, it displays in the client area and it time stamps it. how can I remove the time stamp? OR remove the whole hook and add it back with my own var?
       
       
      <?php
      use WHMCS\View\Menu\Item;
      add_hook('ClientAreaHomepagePanels', 1, function (Item $homePagePanels)
      {
      $homePagePanels->removeChild('your files:dateadded');
      });
    • By sitesme
      Hi
      I need to add a code from a similar tool like Google Analytics into my WHMCS installation.
      I know how to add it in the header files but I was wondering if I could use a hook file to avoid the theme files to be overwritten. If so, could someone give me the exact hook code file syntax so I just add my code there?
      Thank you
    • By robetus
      I found an older post regarding this but I wanted to post a working hook that adds recaptcha to the checkout page. I think this a great thing especially if you're being bombarded with fake accounts and orders.
      /includes/hooks/checkout-recaptcha.php:
      <?php if (!defined("WHMCS")) die("This file cannot be accessed directly"); function limitOrders($vars) { $url = 'https://www.google.com/recaptcha/api/siteverify'; $privatekey = "YOUR_RECAPTCHA_SECRET_KEY_HERE"; $response = file_get_contents($url . "?secret=" . $privatekey . "&response=" . $_POST['g-recaptcha-response'] . "&remoteip=" . $_SERVER['REMOTE_ADDR']); $data = json_decode($response); if (isset($data->success) AND $data->success == true) { // everything is ok! } else { $pm = $vars['paymentmethod']; if ($pm == "paypalpaymentspro") { global $errormessage; $errormessage.= "<li> Please, confirm that you are not a robot! <br/></li>"; } //if CC } } //function add_hook("ShoppingCartValidateCheckout", 1, "limitOrders"); Change YOUR_RECAPTCHA_SECRET_KEY_HERE to your the recaptcha private/secret key Google gives you. I'm using for my credit card checkout which is "paypalpaymentspro" but you can use it for any payment method. I think you really only need if you accept credits though. To get your payment method view source on the checkout page and search for "paymentmethod" your payment method will be near this.
      In your checkout.tpl file you also need to add somewhere under the "Complete Payment" button:
      <div class="g-recaptcha" data-sitekey="YOUR_RECAPTCHA_PUBLIC_KEY_HERE"></div> Replace YOUR_RECAPTCHA_PUBLIC_KEY_HERE with your public recaptcha key provided by Google.
      This is tested working on WHMCS v7.5.1.
    • By WHMCS Josh
      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!
  • Recently Browsing   0 members

    No registered users viewing this page.

×

Important Information

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