Jump to content

Remitur

Member
  • Content Count

    606
  • Joined

  • Last visited

  • Days Won

    8

Remitur last won the day on October 22

Remitur had the most liked content!

Community Reputation

65 Excellent

4 Followers

About Remitur

  • Rank
    Level 2 Member

Recent Profile Visitors

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

  1. In a template, it may be useful to know domain extension in order to customize available functions... But there's no smarty variable with domain extension: the only Smarty useful variable available is $domain... Question: how can I in Smarty get the right characters of $domain? I.e, in php I could write: if (substr($domain),-3) == '.es') But how can I get the same in Smarty?!?!
  2. It's a flawed design. It seems that renewal page uses standard price, whatever price has been set as "recurring amount". Instead it should be something like: if recurring amount = standard price use standard price for any number of years available and set else use custom price and allows just one year (or the different period set for this particular domain) renewal endif Implementing this logic into php code would be trivial, while implementing it using Smarty would be a nightmare (or even simply impossible...)
  3. I found a quick and dirty workaround. Far from being perfect, but fixing this issue should be a job for WHMCS's developers,,, Just edit /templates/orderforms/standard_cart/domain-renewals.tpl (or whatever cart you're using); find following lines: <h3>{$renewalData.domain}</h3> <p>{lang key='clientareadomainexpirydate'}: {$renewalData.expiryDate->format('j M Y')} ({$renewalData.expiryDate->diffForHumans()})</p> {if ($renewalData.pastGracePeriod && $renewalData.pastRedemptionGracePeriod) || !count($renewalData.renewalOptions)} {else} <form class="form-horizontal"> <div class="form-group row"> <label for="renewalPricing{$renewalData.id}" class="control-label col-md-5"> {lang key='domainRenewal.availablePeriods'} {if $renewalData.inGracePeriod || $renewalData.inRedemptionGracePeriod} * {/if} </label> <div class="col-sm-6"> <select class="form-control select-renewal-pricing" id="renewalPricing{$renewalData.id}" data-domain-id="{$renewalData.id}"> {foreach $renewalData.renewalOptions as $renewalOption} <option value="{$renewalOption.period}"> {$renewalOption.period} {lang key='orderyears'} @ {$renewalOption.rawRenewalPrice} {if $renewalOption.gracePeriodFee && $renewalOption.gracePeriodFee->toNumeric() != 0.00} + {$renewalOption.gracePeriodFee} {lang key='domainRenewal.graceFee'} {/if} {if $renewalOption.redemptionGracePeriodFee && $renewalOption.redemptionGracePeriodFee->toNumeric() != 0.00} + {$renewalOption.redemptionGracePeriodFee} {lang key='domainRenewal.redemptionFee'} {/if} </option> {/foreach} </select> </div> </div> </form> {/if} <div class="text-right"> {if !$renewalData.eligibleForRenewal || $renewalData.beforeRenewLimit || ($renewalData.pastGracePeriod && $renewalData.pastRedemptionGracePeriod)} {else} <button id="renewDomain{$renewalData.id}" class="btn btn-default btn-sm btn-add-renewal-to-cart" data-domain-id="{$renewalData.id}"> <span class="to-add"> <i class="fas fa-fw fa-spinner fa-spin"></i> {lang key='addtocart'} </span> <span class="added">{lang key='domaincheckeradded'}</span> </button> {/if} </div> </div> {/foreach} </div> and change it to: <h3 class="font-size-24">{$renewalData.domain}</h3> {if $renewalData.isPremium} <span class="label label-danger">Premium Domain - Open a support ticket to renew it</span> {/if} <p>{lang key='clientareadomainexpirydate'}: {$renewalData.expiryDate->format('j M Y')} ({$renewalData.expiryDate->diffForHumans()})</p> {if $renewalData.freeDomainRenewal} <p class="domain-renewal-desc">{lang key='domainRenewal.freeWithServiceDesc'}</p> {/if} {if ($renewalData.pastGracePeriod && $renewalData.pastRedemptionGracePeriod) || !count($renewalData.renewalOptions) || $renewalData.isPremium } {else} <form class="form-horizontal"> <div class="form-group row"> <label for="renewalPricing{$renewalData.id}" class="control-label col-md-5"> {lang key='domainRenewal.availablePeriods'} {if $renewalData.inGracePeriod || $renewalData.inRedemptionGracePeriod} * {/if} </label> <div class="col-sm-6"> <select class="form-control select-renewal-pricing" id="renewalPricing{$renewalData.id}" data-domain-id="{$renewalData.id}"> {foreach $renewalData.renewalOptions as $renewalOption} <option value="{$renewalOption.period}"> {$renewalOption.period} {lang key='orderyears'} @ {$renewalOption.rawRenewalPrice} {if $renewalOption.gracePeriodFee && $renewalOption.gracePeriodFee->toNumeric() != 0.00} + {$renewalOption.gracePeriodFee} {lang key='domainRenewal.graceFee'} {/if} {if $renewalOption.redemptionGracePeriodFee && $renewalOption.redemptionGracePeriodFee->toNumeric() != 0.00} + {$renewalOption.redemptionGracePeriodFee} {lang key='domainRenewal.redemptionFee'} {/if} </option> {/foreach} </select> </div> </div> </form> {/if} <div class="text-right"> {if !$renewalData.eligibleForRenewal || $renewalData.beforeRenewLimit || $renewalData.isPremium || ($renewalData.pastGracePeriod && $renewalData.pastRedemptionGracePeriod)} {else} <button id="renewDomain{$renewalData.id}" class="btn btn-default btn-sm btn-add-renewal-to-cart" data-domain-id="{$renewalData.id}"> <span class="to-add"> <i class="fas fa-fw fa-spinner fa-spin"></i> {lang key='addtocart'} </span> <span class="added">{lang key='domaincheckeradded'}</span> </button> {/if} </div> </div> {/foreach} </div> The result will be this:
  4. I've just realized another WHMCS issue in premium domain management. Further details:
  5. Premium Domain management in WHMCS is quite poorly managed, and a number of different issues may occur... I just realized another issue in premium domain renewal. Example: you manage a Premium domain; standard renewal price is 10, for that particular domain renewal price is 120 so you set "recurring amount" to 120 if domain is set to autorenew, the system will issue an invoice for 120; the user will pay 120, and everything will be fine and everyone will be happy But what's happen if the user decides to renew it manually? The user goes to /index.php/cart/domain/renew and ... SURPRISE! He will be proposed t renew the domain not for the "recurring amount" set, but for the standard price Long story short. the user will be able to renew his Premium domain paying just 10 instead than 120 ... 🥵 I've just realized this issue, and so I don't know if any easy fix exists, or if it's even possible to fix the issue any way... (Apart for the obvious way: do not try to manage premium domains using WHMCS...)
  6. It may happen that a customer (a web agency, a domain and hosting reseller or a webmaster) does not want to use your default nameservers, but wants to use his own, custom nameservers. He can specify custom nameservers during checkout, but it's annoying, time-consuming and far from error-proof. There's a way for the user to register his preferred custom nameserver in his profile, and have them automatically proposed during the domain registration process. You need to configure your WHMCS by following steps: in Setup -> Custom Client Fields ( /admin/configcustomfields.php ) create five custom fields, named (i.e.) "First custom nameserver", "second custom nameserver", "Third custom nameserver", "Fourth custom nameserver", "Fifth custom nameserver"; all of them as "text box" identify the ID of the Customs Fields you've just created That's to say: any user custom field created in WHMCS is identified by a numeric, progressive ID, and is available in SMARTY environment as $clientsdetails.customfields1, $clientsdetails.customfields2, $clientsdetails.customfields3... The easy way to identify it is by enabling Smarty debug mode and visiting any page in the client area. In this example, we'll set our nameserver custom fields to be $clientsdetails.customfields13 $clientsdetails.customfields14 $clientsdetails.customfields15 $clientsdetails.customfields16 $clientsdetails.customfields17 edit the file configuredomains.tpl of your active order form (i.e. standard_cart); look for the following code in configuredomains.tpl: <div class="row"> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs1">{$LANG.domainnameserver1}</label> <input type="text" class="form-control" id="inputNs1" name="domainns1" value="{$domainns1}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs2">{$LANG.domainnameserver2}</label> <input type="text" class="form-control" id="inputNs2" name="domainns2" value="{$domainns2}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs3">{$LANG.domainnameserver3}</label> <input type="text" class="form-control" id="inputNs3" name="domainns3" value="{$domainns3}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs1">{$LANG.domainnameserver4}</label> <input type="text" class="form-control" id="inputNs4" name="domainns4" value="{$domainns4}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs5">{$LANG.domainnameserver5}</label> <input type="text" class="form-control" id="inputNs5" name="domainns5" value="{$domainns5}" /> </div> </div> </div> And substitute it with the following code: <div class="row"> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs1">{$LANG.domainnameserver1}</label> <input type="text" class="form-control" id="inputNs1" name="domainns1" value="{if $clientsdetails.customfields13}{$clientsdetails.customfields13}{else}{$domainns1}{/if}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs2">{$LANG.domainnameserver2}</label> <input type="text" class="form-control" id="inputNs2" name="domainns2" value="{if $clientsdetails.customfields13}{$clientsdetails.customfields14}{else}{$domainns2}{/if}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs3">{$LANG.domainnameserver3}</label> <input type="text" class="form-control" id="inputNs3" name="domainns3" value="{if $clientsdetails.customfields13}{$clientsdetails.customfields15}{else}{$domainns3}{/if}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs1">{$LANG.domainnameserver4}</label> <input type="text" class="form-control" id="inputNs4" name="domainns4" value="{if $clientsdetails.customfields13}{$clientsdetails.customfields16}{else}{$domainns4}{/if}" /> </div> </div> <div class="col-sm-4"> <div class="form-group"> <label for="inputNs5">{$LANG.domainnameserver5}</label> <input type="text" class="form-control" id="inputNs5" name="domainns5" value="{if $clientsdetails.customfields13}{$clientsdetails.customfields17}{else}{$domainns5}{/if}" /> </div> </div> </div> (Warning: remember to modify $clientsdetails.customfieldsXX with the corresponding ID numbers of your WHMCS install!) That's all: if any user of yours will configure custom nameservers in his client area, these nameservers will be automatically proposed to him for any new domain registration or transfer. Further details: https://domainregister.international/index.php/knowledgebase/699/WHMCS---How-to-Automatically-Set-User-Custom-Nameservers--During-Checkout.html
  7. If it's used by two different companies (with different tax code), using the same WHMCS install may transform billing in a nightmare. A customer pay using credit card... but how is accounted his money? In company A or B ? Are you going to use different payment accounts for the two companies? The best way is using two different WHMCS installs. Services, domain pricing and so on may be easy synched on the two installs in the backend.
  8. Hello. I would like, in a hook, to call a certain custom function defined in a Registrar module. That's to say: in a Registrar module (MyRegistrarModule_) it's defined a CrateContact function (MyRegistrarModule_CreateContact ) I would like, in a hook (that may be internal or external to the Registrar module, it doesn't matter) call this MyRegistrarModule_CreateContact() function Is it somehow possible?!?!
  9. The sample code in doc about ClientAreaDomainDetailsOutput ( https://developers.whmcs.com/hooks-reference/output/#clientareadomaindetailsoutput ) seems to wrong: <?php add_hook('ClientAreaDomainDetailsOutput', 1, function($domain) { $domainName = $domain->domain; $clientModel = $domain->client; $domainStatus = $domain->status; $clientName = $clientModel->firstName . ' ' . $clientModel->lastName; return 'You can place any HTML here that will be output in the $hookOutput smarty variable array'; }); $domain is an object, not an array, and so $domainName in sample code is null ... I could convert the object in array and then parsing it, but I guess there should be a smarter way (that I don't know because I hate objects ... 😄 ) Any smart idea to retrieve domain data?
  10. If the company is the very same, just acting in two different countries, no issue: use two different languages, if needed two different currencies... it's all. If there're two different companies, acting in two different countries... the best solution is two different WHMCS install, on two different servers.
  11. Yes, you can: there's just a single field in tbldomains that shows if a domain is premium or not... nit this is useful just for renewals, because it works only after a domain has been inserted in tbldomains, that's to say after it has been ordered. To manage the order as Premium, I guess you should code in cart, identifying a domain as Premium, correcting the price, and explaining to the customer that he's going to register a Premium domain... BTW: also Hexonet manages premium domains: https://centralnic-reseller.github.io/centralnic-reseller/docs/hexonet/whmcs/whmcs-ispapi-registrar/
  12. There're two cases where you need to check this: during renewal invoice creation When a renewal invoice is issued, if there's available credit WHMCS will automatically apply to it in client area, when the user can select an unpaid invoice and decide to apply credit to it The second one, I guess, it's quite easy: just modify the involved .tpl with some kind of IF clause The first one is a little more complicated: here the code of a hook that prevent automatic credit application to new invoices if the credit is not sufficient to full pay the invoice: // // remove applied credit to invoices, when credit applied is not sufficient to fully pay // function remove_credit_from_new_invoice($vars) { if ($vars['status']=="Paid") { return; } $postData=array('invoiceid' => $vars['invoiceid'], ); $invoicedata = localAPI('GetInvoice', $postData); if ( $invoicedata['credit'] != 0 AND $invoicedata['balance'] != 0 ) { $postData = array( 'invoiceid' => $vars['invoiceid'], 'amount' => - $invoicedata['credit'], ); $res = localAPI('ApplyCredit', $postData); logactivity('Insufficient credit removed by hook: invoice id# '.$vars['invoiceid'].' - credit removed '.$invoicedata['credit'],$vars['user']); } } add_hook('InvoiceCreationPreEmail', 5, "remove_credit_from_new_invoice" ); You need to modify it in order to: check the kind of service billed set the status of the invoice back to "unpaid" if it was fully paid with credit Hope this will be helpful to you.
  13. I have no experience with Godaddy module, but if they have no lookup service with premium domain management, I guess it's better to give up about Premium Domains. Maybe you could try using another provider (that manages Premium domains) just for lookup, and then register on Godaddy... but try this in a sandbox before going live... I don't know if and how Premium domains are supported in Godaddy Registrar Module: with Resellerclub it's a mess (you need a third-party add-on, and customizations of .tpl files...)
  14. Beware: WHMCS namespinner does not manage Premium Domains, so if you set Premium Domain option ON, you must not use Namespinner, and if you use Namespinner you must not set on Premium Domain option. (This is not written anywhere in WHMCS's docs) Not for every registrar: Resellerclub has the very same call both for ordinary and premium domains (yes, in resellerclub's docs it's written differently, but it's wrong). If you issue an ordinary API "registerdomain" command to Resellerclub for a Premium domain, the domain will be regularly registered, and you will be charged the Premium fee. No reimbursement possible from Resellerclub, because with Resellerclub you're always wrong, and it's always your fault.
  15. Try to register a new user account on your own WHMCS. When you're asked for "first name", insert a random text, whatever length... i.e. something like this: Use the very same text also for surname. And for company name. And for address, and for whatever field does not check the data you inserted. And for email a fake address on a non-existing domain. It's not a joke: You'll be able to register a new account with those crazy data, because: 1- WHMCS does not check the data in any way 2 - the data are saved in db using a "text" type field for each one... and this means that the limit of a name, or of a surname, is 65535 chars Question: how many people has a name long 65535 chars? How many surnames long 65535 do you know? This is more than an issue, because i.e. in an attack it may be used to register hundreds of fake users, each using a huge amount of data, and bringing your db dimensions out of limits. Or registering using long string and special chars may bring your template going crazy... But you can also register using near-real data, but a disposable email address, and use this disposable email address to commit fraud (i.e., buying services using cloned credit cards). So I created a "check user data hook" that: 1 - limit the length of any field you can insert to 150 chars 2 - check the email address, in order not to allow registering using disposable addresses or on non-existing domains The hook is available for free on Github ( https://github.com/DomainRegister/WHMCS ) or on DomainRegister's site: https://domainregister.international/index.php/knowledgebase/696/Check-User-Data-for-Better-WHMCS-Security.html Credits: thank to @bear and @leemahoney3 for the help in silly bug hunting...
×
×
  • 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