Prestashop : Ajouter un captcha sur les formulaires de vos modules

Ce tutoriel est compatible avec les versions de Prestashop suivantes :
1.6 1.7 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 8.0 8.1 +
Cet article est assez ancien, malgré toute l'attention que j' apporte à mes contenus il est possible que celui-ci ne soit plus d'actualité.
N'hésitez pas à me le signaler si nécessaire via le formulaire de contact.

Afin d’éviter le spam sur vos différents formulaires je recommande en général la mise en place d’un captcha.
Ça fait plusieurs années que j’édite un module de captcha gratuit ( eicaptcha ) qui permets de l’éviter sur les formulaires suivants :

  • Formulaire de contact
  • Formulaire de création de compte
  • Formulaire d’inscription à la newsletter

Celui-ci est disponible sur github et a été téléchargé des dizaines de milliers de fois : https://github.com/nenes25/eicaptcha

Je viens de sortir une nouvelle version de ce module ( 2.4.0 ) qui rajoute une nouvelle fonctionnalité qui permets d’utiliser la vérification du captcha intégrée dans le module directement dans vos modules spécifiques.

Ceci à travers 2 nouvelles méthodes :

hookDisplayEicaptchaVerification : permets de récupérer un template d’affichage complet du captcha ( le captcha s’affiche directement )
hookActionGetEicaptchaParams : permets  de récupérer les paramètres nécessaires à l’affichage du captcha ( il est possible de faire un affichage spécifique )

Nous allons voir à travers cet article comment le mettre en place à travers la création d’un module hhcustomform
Le captcha sera implémenté dans 2 situations

  • Dans un formulaire sur la fiche produit
  • Dans un controller front

Captcha dans un formulaire sur la fiche produit

Pour afficher un formulaire sur la fiche produit nous allons utiliser le hook displayProductExtraContent qui va nous permettre de l’afficher comme sur la capture ci-dessous, directement dans les onglets de la fiche produit.

Captcha dans un formulaire de la fiche produit

Voici le code du hook qui va permettre de gérer l’affichage du formulaire dans l’onglet.
La fonction importante du module eicaptcha utilisée est le hook displayEicaptchaVerification qui va permettre de récupérer le contenu nécessaire à l’affichage du captcha dans le formulaire.

/**
     * [Front office] Affichage des contenus dans les onglets de la fiche produit
     * @param array $params
     * @return array
     */
    public function hookDisplayProductExtraContent(array $params)
    {
        $return = [];
        $id_product = $params['product']->id;
 
        $return[] = (new PrestaShop\PrestaShop\Core\Product\ProductExtraContent())
            ->setTitle($this->l('Customization'))
            ->setContent($this->getFormContent($id_product));
 
        return $return;
    }
 
    /**
     * Récupération du contenu du formulaire
     * @param int $id_product
     * @return string
     */
    protected function getFormContent(int $id_product): string
    {
        try {
            $smartyParams = [
                'id_product' => $id_product,
                'formAction' => $this->context->link->getModuleLink(
                    $this->name,
                    'form'
                ),
                'backUrl' => $this->context->link->getProductLink(
                    $id_product
                ),
            ];
            //Gestion de l'affichage du captcha
            if ($eicaptcha = Module::getInstanceByName('eicaptcha')) {
                $smartyParams['renderCaptcha'] = $eicaptcha->hookDisplayEicaptchaVerification(['module' => $this->name]);
            }
            $this->context->smarty->assign($smartyParams);
            return $this->context->smarty->fetch(
                'module:'.$this->name.'/views/templates/hook/displayProductExtraContent.tpl'
            );
 
        } catch (Exception $e) {
            PrestaShopLogger::addLog(__METHOD__ . ' error : ' . $e->getMessage());
        }
 
        return '';
    }

Voici le fichier tpl views/templates/hook/displayProductExtraContent.tpl qui va gérer l’affichage du formulaire sur la fiche produit.

<div class="hhcustomform--form">
    <form name="hhcustomform--customization-form" method="post" action="{$formAction}" class="form">
        <input type="hidden" name="id_product" value="{$id_product}">
        <input type="hidden" name="submit_form" value="1">
        <input type="hidden" name="back" value="{$backUrl}">
        <div class="form-group">
            <label for="name">{l s='your name' mod='hhcustomform'}</label>
            <input type="text" name="name" class="form-control" placeholder="{l s='your name' mod='hhcustomform'}" required="">
        </div>
        <div class="form-group">
            <label for="email">{l s='your email' mod='hhcustomform'}</label>
            <input type="email" name="email" class="form-control" placeholder="{l s='your email' mod='hhcustomform'}" required="">
        </div>
        <div class="form-group">
            <label for="customization">{l s='your customization' mod='hhcustomform'}</label>
            <textarea name="customization" class="form-control" rows="4" required="" placeholder="{l s='explain your requested customization' mod='hhcustomform'}"></textarea>
        </div>
        {* On utilise la fonctionnalité de eicaptcha *}
        {$renderCaptcha nofilter}
        <button type="submit" class="btn btn-primary">{l s='Send' mod='hhcustomform'}</button>
    </form>
</div>

Captcha dans un controller front

Dans cet exemple j’utilise l’autre fonctionnalité d’affichage du captcha ( hookActionGetEicaptchaParams )

Affichage du captcha sur un controller front

Voici le code du controller controllers/front/form.php qui va appeller le module.

<?php
class HhcustomformFormModuleFrontController extends ModuleFrontController
{
    /**
     * Manage Post Vars
     */
    public function postProcess()
    {
        if (Tools::isSubmit('submit_form')) {
            parent::postProcess();
            if (false !== $this->processCustomizationForm()) {
                $this->success[] = $this->l('Thank you. Your message have been send with success');
            } else {
                $this->errors[] = $this->l('Error when sending your message');
            }
            $redirectUrl = Tools::getValue('back');
            if ($redirectUrl) {
                $this->redirectWithNotifications($redirectUrl);
            }
        }
    }
    /**
     * Generate controller breadCrumb
     * @return array
     */
    public function getBreadcrumbLinks()
    {
        $breadcrumb = parent::getBreadcrumbLinks();
        $breadcrumb['links'][] = [
            'title' => 'form',
            'url' => '#'
        ];
        return $breadcrumb;
    }
    /**
     * Traitement du formulaire
     * @return bool|int
     */
    protected function processCustomizationForm()
    {
        //Captcha validation
        if ($eicaptcha = Module::getInstanceByName('eicaptcha')) {
            if (!$eicaptcha->hookActionValidateCaptcha()) {
                return false;
            }
        }
        //Traitement du formulaire à implémenter
        return true;
    }
    /**
     * Controller Content
     * @throws PrestaShopException
     */
    public function initContent()
    {
        parent::initContent();
        $this->context->smarty->assign(
            'formAction',
            $this->context->link->getModuleLink($this->module->name, 'form')
        );
        //Récupération des paramètres du captcha pour affichage custom
        if ($eicaptcha = Module::getInstanceByName('eicaptcha')) {
            $this->context->smarty->assign('captchaParams', $eicaptcha->hookActionGetEicaptchaParams([]));
        }
        $this->setTemplate('module:hhcustomform/views/templates/front/form.tpl');
    }
}

Et voici le code du template d’affichage associé

{extends file='page.tpl'}
{block name="content"}
    <div class="hhcustomform--form">
        <form name="hhcustomform--customization-form" method="post" action="{$formAction}" class="form">
            <div class="form-group">
                <label for="name">{l s='your name' mod='hhcustomform'}</label>
                <input type="text" name="name" class="form-control" placeholder="{l s='your name' mod='hhcustomform'}" required="">
            </div>
            <div class="form-group">
                <label for="email">{l s='your email' mod='hhcustomform'}</label>
                <input type="email" name="email" class="form-control" placeholder="{l s='your email' mod='hhcustomform'}" required="">
            </div>
            <div class="form-group">
                <label for="customization">{l s='your customization' mod='hhcustomform'}</label>
                <textarea name="customization" class="form-control" rows="4" required="" placeholder="{l s='explain your requested customization' mod='hhcustomform'}"></textarea>
            </div>
            {* On utilise la fonctionnalité de eicaptcha mais avec un formulaire qu'on défini comme on veut *}
            <div class="form-group row">
                {if $captchaParams.captchaVersion == 2}
                    <label class="col-md-3">{l s='Captcha' mod='eicaptcha'}</label>
                    <div class="col-md-9">
                        <div class="g-recaptcha" data-sitekey="{$captchaParams.publicKey|escape:'html'}" id="captcha-box" data-theme="{$captchaParams.captchatheme}"></div>
                        <script src="https://www.google.com/recaptcha/api.js{if isset($captchaParams.captchaforcelang)}?hl={$captchaParams.captchaforcelang}{/if}" async="" defer=""></script>
                    </div>
                {else}
                    <input type="hidden" id="captcha-box-custom" name="g-recaptcha-response">
                    <script src="https://www.google.com/recaptcha/api.js?render={$publicKey|escape:'html'}"></script>
                    <script>
                        grecaptcha.ready(function () {ldelim}
                            grecaptcha.execute('{$captchaParams.publicKey|escape:'html'}', {ldelim}action: 'contact'{rdelim}).then(function (token) {ldelim}
                                var recaptchaResponse = document.getElementById('captcha-box-custom');
                                recaptchaResponse.value = token;
                                {rdelim});
                            {rdelim});
                    </script>
                {/if}
            </div>
            <button type="submit" class="btn btn-primary">{l s='Send' mod='hhcustomform'}</button>
        </form>
    </div>
{/block}

A travers ces différents exemples vous pouvez donc voir qu’il est relativement facile d’ajouter un captcha sur n’importe quel formulaire de vos modules 🙂
Pour télécharger le module de captcha eicaptcha, ou signaler des problèmes vous rendre directement sur github : https://github.com/nenes25/eicaptcha

3 réflexions sur “Prestashop : Ajouter un captcha sur les formulaires de vos modules”

  1. Bonjour,
    Je suis sous PS 1.7.8.7 et j’ai récupéré la version eCaptcha 2.4.0.
    J’ai activé la V3 et collé les clés de sécurités correspondantes. Cependant, j’ai une erreur
    Erreurs
    Le module n’est pas greffé sur le hook actionContactFormSubmitCaptcha
    Avez-vous une solution ?
    Merci 🙂

  2. Bonjour,
    Hi thanks for you work! I have been trying to get this working because I’m spammed with fake accounts.
    It does work on the contact form but not on registration page. Captcha seems active but it doesn’t check if valid. I also replied on a open issue on github.
    Recaptcha version : 2 and 3
    Prestashop version : 8.0.3
    Theme name : classic
    Php version : 7.4.33

Répondre à Jerome Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *