Magento 2 - Comment ajouter captcha à un formulaire personnalisé

28

Je développe un module personnalisé qui contient une soumission de formulaire. Je voudrais y ajouter un captcha. Et nous voulons utiliser la bibliothèque de captcha par défaut de Magento afin que le captcha soit cohérent avec celui du formulaire d'inscription.

Paul
la source

Réponses:

35

Vous devez suivre une étape pour utiliser le captcha magento dans le module personnalisé.

Étape 1 : Vendor/Module/etc/config.xml

<? xml version = "1.0"?>
<config xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: noNamespaceSchemaLocation = "urn: magento: module: Magento_Store: etc / config.xsd">
    <par défaut>
        <customer>
            <captcha>
                <shown_to_logged_in_user>
                    <custom_form> 1 </custom_form>
                </shown_to_logged_in_user>
                <toujours_pour>
                    <custom_form> 1 </custom_form>
                </always_for>
            </captcha>
        </customer>
        <captcha translate = "label">
            <frontend>
                <areas>
                    <custom_form>
                        <label> Formulaire personnalisé </label>
                    </custom_form>
                </areas>
            </frontend>
        </captcha>
    </default>
</config>

Étape 2: Goto ' Admin -> Stores -> Configuration -> Client -> Configuration client -> Captcha ' et configurez. Vous pouvez voir la nouvelle valeur des formulaires 'Formulaire personnalisé'

Étape 3: créer Vendor/Module/view/frontend/layout/yourroutid_index_index.xml

<? xml version = "1.0"?>
<page xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" layout = "1column" xsi: noNamespaceSchemaLocation = "urn: magento: framework: View / Layout / etc / page_configuration.xsd">
    <head>
        <title> Formulaire personnalisé </title>
    </head>
    <body>
        <referenceContainer name = "content">
            <block class = "Vendor \ Module \ Block \ CaptchaForm" name = "contactForm" template = "Vendor_Module :: captchaform.phtml">
                <container name = "form.additional.info" label = "Informations supplémentaires sur le formulaire">
                    <block class = "Magento \ Captcha \ Block \ Captcha" name = "captcha" after = "-" cacheable = "false">
                        <action method = "setFormId">
                            <argument name = "formId" xsi: type = "string"> custom_form </argument>
                        </action>
                        <action method = "setImgWidth">
                            <argument name = "width" xsi: type = "string"> 230 </argument>
                        </action>
                        <action method = "setImgHeight">
                            <argument name = "width" xsi: type = "string"> 50 </argument>
                        </action>
                    </block>
                </container>
            </block>
        </referenceContainer>
        <referenceBlock name = "head.components">
            <block class = "Magento \ Framework \ View \ Element \ Js \ Components" name = "captcha_page_head_components" template = "Magento_Captcha :: js / components.phtml" />
        </referenceBlock>
    </body>
</page>

Étape 4: Vendor/Module/Block/CaptchaForm.php

espace de noms Vendor \ Module \ Block;


classe CaptchaForm étend \ Magento \ Framework \ View \ Element \ Template
{
    fonction publique getFormAction ()
    {
        return $ this-> getUrl ('yourroute / index / post', ['_secure' => true]);
    }
}

Étape 5: Vendor/Moduel/view/frontend/templates/captchaform.phtml

<form class = "formulaire contact"
      action = "<? php / * @escapeNotVerified * / echo $ block-> getFormAction ();?>"
      id = "formulaire de contact"
      method = "post"
      data-hasrequired = "<? php / * @escapeNotVerified * / echo __ ('* Champs obligatoires')?>"
      data-mage-init = '{"validation": {}}'>
    <fieldset class = "fieldset">
        <legend class = "legend"> <span> <? php / * @escapeNotVerified * / echo __ ('Écrivez-nous')?> </span> </legend> <br />

        <div class = "nom de champ requis">
            <label class = "label" for = "name"> <span> <? php / * @escapeNotVerified * / echo __ ('Name')?> </span> </label>
            <div class = "control">
                <input name = "name" id = "name" title = "<? php / * @escapeNotVerified * / echo __ ('Name')?>" value = "" class = "input-text" type = "text" data-validate = "{required: true}" />
            </div>
        </div>
        <div class = "champ email requis">
            <label class = "label" for = "email"> <span> <? php / * @escapeNotVerified * / echo __ ('Email')?> </span> </label>
            <div class = "control">
                <input name = "email" id = "email" title = "<? php / * @escapeNotVerified * / echo __ ('Email')?>" value = "" class = "input-text" type = "email" data-validate = "{required: true, 'validate-email': true}" />
            </div>
        </div>
        <? php echo $ block-> getChildHtml ('form.additional.info'); ?>
    </fieldset>
    <div class = "actions-toolbar">
        <div class = "primary">
            <input type = "hidden" name = "hideit" id = "hideit" value = "" />
            <button type = "submit" title = "<? php / * @escapeNotVerified * / echo __ ('Submit')?>" class = "action submit primary">
                <span> <? php / * @escapeNotVerified * / echo __ ('Soumettre')?> </span>
            </button>
        </div>
    </div>
</form>

Vous pouvez maintenant voir le captcha dans votre formulaire. Vous devez maintenant valider votre captcha à l'aide d'un observateur. J'utilise donc l'événement prédispatch post-contrôleur pour la validation.

Étape 6: Vendor/Module/etc/frontend/events.xml

<? xml version = "1.0"?>
<config xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: noNamespaceSchemaLocation = "urn: magento: framework: Event / etc / events.xsd">
    <event name = "controller_action_predispatch_yourroute_index_post">
        <observer name = "captcha_custom_form" instance = "Vendor \ Module \ Observer \ CheckCustomFormObserver" />
    </event>
</config>

Étape 7: Vendor/Module/Observer/CheckCustomFormObserver.php

espace de noms Vendor \ Module \ Observer;

utilisez Magento \ Framework \ Event \ ObserverInterface;
utilisez Magento \ Framework \ App \ Request \ DataPersistorInterface;
utilisez Magento \ Framework \ App \ ObjectManager;
utilisez Magento \ Captcha \ Observer \ CaptchaStringResolver;

La classe CheckCustomFormObserver implémente ObserverInterface
{
    / **
     * @var \ Magento \ Captcha \ Helper \ Data
     * /
    $ _helper protégé;

    / **
     * @var \ Magento \ Framework \ App \ ActionFlag
     * /
    protected $ _actionFlag;

    / **
     * @var \ Magento \ Framework \ Message \ ManagerInterface
     * /
    $ messageManager protégé;

    / **
     * @var \ Magento \ Framework \ App \ Response \ RedirectInterface
     * /
    redirection $ protégée;

    / **
     * @var CaptchaStringResolver
     * /
    $ captchaStringResolver protégé;

    / **
     * @var DataPersistorInterface
     * /
    $ dataPersistor privé;

    / **
     * @param \ Magento \ Captcha \ Helper \ Data $ helper
     * @param \ Magento \ Framework \ App \ ActionFlag $ actionFlag
     * @param \ Magento \ Framework \ Message \ ManagerInterface $ messageManager
     * @param \ Magento \ Framework \ App \ Response \ RedirectInterface $ redirect
     * @param CaptchaStringResolver $ captchaStringResolver
     * /
    fonction publique __construct (
        \ Magento \ Captcha \ Helper \ Data $ helper,
        \ Magento \ Framework \ App \ ActionFlag $ actionFlag,
        \ Magento \ Framework \ Message \ ManagerInterface $ messageManager,
        \ Magento \ Framework \ App \ Response \ RedirectInterface $ redirect,
        CaptchaStringResolver $ captchaStringResolver
    ) {
        $ this -> _ helper = $ helper;
        $ this -> _ actionFlag = $ actionFlag;
        $ this-> messageManager = $ messageManager;
        $ this-> redirect = $ redirect;
        $ this-> captchaStringResolver = $ captchaStringResolver;
    }

    / **
     * Vérifiez CAPTCHA sur le formulaire personnalisé
     *
     * @param \ Magento \ Framework \ Event \ Observer $ observer
     * @return void
     * /
    fonction publique exécuter (\ Magento \ Framework \ Event \ Observer $ observer)
    {
        $ formId = 'custom_form';
        $ captcha = $ this -> _ helper-> getCaptcha ($ formId);
        if ($ captcha-> isRequired ()) {
            / ** @var \ Magento \ Framework \ App \ Action \ Action $ controller * /
            $ controller = $ observer-> getControllerAction ();
            if (! $ captcha-> isCorrect ($ this-> captchaStringResolver-> resolver ($ controller-> getRequest (), $ formId))) {
                $ this-> messageManager-> addError (__ ('Incorrect CAPTCHA.'));
                $ this-> getDataPersistor () -> set ($ formId, $ controller-> getRequest () -> getPostValue ());
                $ this -> _ actionFlag-> set ('', \ Magento \ Framework \ App \ Action \ Action :: FLAG_NO_DISPATCH, true);
                $ this-> redirect-> redirect ($ controller-> getResponse (), 'yourroute / index / index');
            }
        }
    }

    / **
     * Obtenir la persistance des données
     *
     * @return DataPersistorInterface
     * /
    fonction privée getDataPersistor ()
    {
        if ($ this-> dataPersistor === null) {
            $ this-> dataPersistor = ObjectManager :: getInstance ()
                -> get (DataPersistorInterface :: class);
        }

        return $ this-> dataPersistor;
    }
}
Sohel Rana
la source
Très détaillé. Je vais l'essayer.
Paul
@Sohel Rana comment l'ajouter dans le formulaire d'évaluation du produit
supriya mishra
@supriyamishra doit vérifier
Sohel Rana
1
Salut Le captcha est affiché mais l'observateur controller_action_predispatch _ ** est, je pense, ne fonctionne pas car ce captcha n'est pas validé
AbdulBasit
1
J'ai résolu l'erreur ci-dessus mais je ne vois pas le captcha dans mon formulaire personnalisé
jafar pinjar
1

Pour ceux d'entre vous qui ne peuvent pas faire fonctionner cela, vous devrez peut-être faire ce que j'ai fait:

La raison pour laquelle vous ne pouvez pas afficher le captcha est que les paramètres de base doivent utiliser le bloc Captcha par défaut qui, dans le _toHtml, vérifie si le captcha est requis.

Si vous avez vos paramètres pour que captcha s'affiche toujours, vous n'avez probablement pas rencontré ce problème, mais s'il n'est pas défini pour toujours afficher les captchas et que vous ne souhaitez pas toujours afficher les captchas (création de compte / connexion, etc.), vous devez définissez la logique de votre captcha personnalisé uniquement sur "Toujours requis".

sur la ligne 69 de vendor / magento / module-captcha / Block / Captcha / DefaultCaptcha.php vous verrez:

    /**
 * Renders captcha HTML (if required)
 *
 * @return string
 */
protected function _toHtml()
{

    if ($this->getCaptchaModel()->isRequired()) {
        $this->getCaptchaModel()->generate();
        return parent::_toHtml();
    }
    return '';
}

$this->getCaptchaModel()appels $this->_captchaData->getCaptcha()qui se trouvent dans vendeur / magento / module-captcha / Helper / Data.php

    /**
 * Get Captcha
 *
 * @param string $formId
 * @return \Magento\Captcha\Model\CaptchaInterface
 */
public function getCaptcha($formId)
{
    if (!array_key_exists($formId, $this->_captcha)) {
        $captchaType = ucfirst($this->getConfig('type'));
        if (!$captchaType) {
            $captchaType = self::DEFAULT_CAPTCHA_TYPE;
        } elseif ($captchaType == 'Default') {
            $captchaType = $captchaType . 'Model';
        }

        $this->_captcha[$formId] = $this->_factory->create($captchaType, $formId);
    }
    return $this->_captcha[$formId];
}

Ici, la méthode getCaptcha vérifie la valeur de configuration pour le type de captcha à restituer et charge sa fabrique avec $this->_factory->create()

Cependant, entrer dans cette classe d'usine, vous verrez

 public function create($captchaType, $formId)
{
    $className = 'Magento\Captcha\Model\\' . ucfirst($captchaType);

    $instance = $this->_objectManager->create($className, ['formId' => $formId]);
    if (!$instance instanceof \Magento\Captcha\Model\CaptchaInterface) {
        throw new \InvalidArgumentException(
            $className . ' does not implement \Magento\Captcha\Model\CaptchaInterface'
        );
    }
    return $instance;
}

Le problème ici est que peu importe ce que l'usine cherchera dans le module Magento Captcha pour n'importe quel modèle d'usine.

Nous devons créer un plugin pour envelopper l'aide et vérifier notre clé de formulaire et si c'est notre clé de formulaire utilisée, nous devons créer une nouvelle classe d'usine qui charge notre modèle qui étend \ Magento \ Captcha \ Model \ DefaultModel et les remplacements la méthode isRequired (). Quelque chose qui ressemble à ceci:

dans \ Votre \ Module \ etc \ di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">

<!--Custom Captcha-->
<type name="\Magento\Captcha\Helper\Data">
    <plugin name="custom-captcha" type="Your\Module\Plugin\Helper\CaptchaData" />
</type>

dans votre \ Module \ Plugin \ Helper \ CaptchaData

<?php

namespace Your\Module\Plugin\Helper;

class CaptchaData
{
protected $_captcha = [];

public function __construct(
    \Your\Module\Model\CaptchaFactory $captchaFactory
) {
    $this->captchaFactory = $captchaFactory;
}

/**
 * @param \Magento\Captcha\Helper\Data $subject
 * @param \Closure $proceed
 * @param $formId
 * @return mixed
 */
public function aroundGetCaptcha(\Magento\Captcha\Helper\Data $subject, \Closure $proceed, $formId)
{
    if ($formId == 'your_form_key') {
        $this->_captcha[$formId] = $this->captchaFactory->create();
        return $this->_captcha[$formId];

    }
    return $proceed($formId);

}

}

dans \ Votre \ Module \ Modèle \ CaptchaFactory

<?php
/**
* Captcha model factory
*
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Your\Module\Model;

class CaptchaFactory
{
/**
 * @var \Magento\Framework\ObjectManagerInterface
 */
protected $_objectManager;

/**
 * @param \Magento\Framework\ObjectManagerInterface $objectManager
 */
public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager)
{
    $this->_objectManager = $objectManager;
}

/**
 * Get captcha instance
 *
 * @param string $captchaType
 * @param string $formId
 * @return \Magento\Captcha\Model\CaptchaInterface
 * @throws \InvalidArgumentException
 */
public function create()
{
    $instance = $this->_objectManager->create('Your\Module\Model\Captcha', ['formId' => 'event_subscriber']);
    if (!$instance instanceof \Magento\Captcha\Model\CaptchaInterface) {
        throw new \InvalidArgumentException(
            'Your\Module\Model\Captcha does not implement \Magento\Captcha\Model\CaptchaInterface'
        );
    }
    return $instance;
}
}

et enfin votre modèle pour remplacer le paramètre requis dans \ Your \ Module \ Model \ Captcha :

<?php

namespace Your\Module\Model;

class Captcha extends \Magento\Captcha\Model\DefaultModel
{
    public function isRequired($login = null)
    {
        return true;
    }
 }
DOfficial
la source
0

J'ai besoin de captcha dans la page d'abonnement à la newsletter merci sohan j'ai été utilisé comme observateur de newsletter et captcha travaille dans la page de newsletter pour moi.

1) app / code / Vendorname / Modulename / etc / config.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
    <default>
        <customer>
            <captcha>
                <shown_to_logged_in_user>
                    <custom_newsletter>1</custom_newsletter>
                </shown_to_logged_in_user>
                <always_for>
                    <custom_newsletter>1</custom_newsletter>
                </always_for>
            </captcha>
        </customer>
        <captcha translate="label">
            <frontend>
                <areas>
                    <custom_newsletter>
                        <label>Newsletter Form</label>
                    </custom_newsletter>
                </areas>
            </frontend>
        </captcha>
    </default>
</config>

2) Goto 'Admin -> Stores -> Configuration -> Customer -> Configuration client -> Captcha' et configurez. Vous pouvez voir de nouveaux formulaires de valeur 'Formulaire Newsletter'.

3) Copiez le fichier de mise en page dans le thème (default.xml)

<block class="Magento\Newsletter\Block\Subscribe" name="subscribe form " template="Magento_Newsletter::subscribe.phtml">
                <container name="form.additional.info" label="Form Additional Info">
                    <block class="Magento\Captcha\Block\Captcha" name="captcha" after="-" cacheable="false">
                        <action method="setFormId">
                            <argument name="formId" xsi:type="string">custom_newsletter</argument>
                        </action>
                        <action method="setImgWidth">
                            <argument name="width" xsi:type="string">230</argument>
                        </action>
                        <action method="setImgHeight">
                            <argument name="width" xsi:type="string">50</argument>
                        </action>
                    </block>
                </container>

4) Créer un observateur -> créer un fichier event.xml dans app / code / Vendorname / Modulename / etc / frontend

 <?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="controller_action_predispatch_newsletter_subscriber_new">
        <observer name="captcha_newletter_form" instance="Vendorname/Modulename/Observer\CheckCustomFormObserver" />
    </event>
</config>

5) Créez un modèle d'observateur et vérifiez l'application / code captcha / Vendorname / Modulename / Observer / CheckCustomFormObserver.php

public function execute(\Magento\Framework\Event\Observer $observer)
        {   $formId = 'custom_newsletter';
            $captcha = $this->_helper->getCaptcha($formId);
            if ($captcha->isRequired()) {
                /** @var \Magento\Framework\App\Action\Action $controller */
                $controller = $observer->getControllerAction();
                $params=$controller->getRequest()->getPost();
                $currentpage = $params['currentpage'];


                if (!$captcha->isCorrect($this->captchaStringResolver->resolve($controller->getRequest(), $formId))) {                
                    $this->messageManager->addError(__('Incorrect CAPTCHA.'));
                    $this->getDataPersistor()->set($formId, $controller->getRequest()->getPostValue());
                    $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
                    $this->redirect->redirect($controller->getResponse(), $currentpage);
                }
            }
        }
Monarque
la source