Magento 2 - Cómo agregar captcha a un formulario personalizado

28

Estoy desarrollando un módulo personalizado que contiene un envío de formulario. Me gustaría agregarle un captcha. Y queremos usar la biblioteca de captcha predeterminada de Magento para que el captcha sea coherente con el del formulario de registro.

Paul
fuente

Respuestas:

35

Debe seguir algunos pasos para usar magento captcha en un módulo personalizado.

Paso 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">
    <predeterminado>
        <cliente>
            <captcha>
                <shown_to_logged_in_user>
                    <custom_form> 1 </custom_form>
                </shown_to_logged_in_user>
                <siempre_para>
                    <custom_form> 1 </custom_form>
                </always_for>
            </captcha>
        </customer>
        <captcha translate = "label">
            <frontend>
                <areas>
                    <custom_form>
                        <label> Formulario personalizado </label>
                    </custom_form>
                </areas>
            </frontend>
        </captcha>
    </default>
</config>

Paso 2: Ir a ' Admin -> Tiendas -> Configuración -> Cliente -> Configuración del cliente -> Captcha ' y configurar. Puede ver el nuevo valor de formularios 'Formulario personalizado'

Paso 3: crear 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> Formulario personalizado </title>
    </head>
    <cuerpo>
        <referenceContainer name = "content">
            <block class = "Vendor \ Module \ Block \ CaptchaForm" name = "contactForm" template = "Vendor_Module :: captchaform.phtml">
                <container name = "form.additional.info" label = "Información adicional del formulario">
                    <block class = "Magento \ Captcha \ Block \ Captcha" name = "captcha" after = "-" cacheable = "false">
                        <action method = "setFormId">
                            <argumento name = "formId" xsi: type = "string"> custom_form </argument>
                        </action>
                        <action method = "setImgWidth">
                            <argumento name = "width" xsi: type = "string"> 230 </argument>
                        </action>
                        <action method = "setImgHeight">
                            <argumento 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>

Etapa 4: Vendor/Module/Block/CaptchaForm.php

proveedor de espacio de nombres \ Módulo \ Bloque;


la clase CaptchaForm extiende \ Magento \ Framework \ View \ Element \ Template
{
    función pública getFormAction ()
    {
        return $ this-> getUrl ('yourroute / index / post', ['_secure' => true]);
    }
}

Paso 5: Vendor/Moduel/view/frontend/templates/captchaform.phtml

<form class = "formulario de contacto"
      action = "<? php / * @escapeNotVerified * / echo $ block-> getFormAction ();?>"
      id = "formulario de contacto"
      método = "publicar"
      data-hasrequired = "<? php / * @escapeNotVerified * / echo __ ('* Campos obligatorios')?>"
      data-mage-init = '{"" validación ": {}}'>
    <fieldset class = "fieldset">
        <legend class = "legend"> <span> <? php / * @escapeNotVerified * / echo __ ('Escríbanos')?> </span> </legend> <br />

        <div class = "se requiere nombre de campo">
            <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 = "{requerido: verdadero}" />
            </div>
        </div>
        <div class = "campo de correo electrónico requerido">
            <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 = "{requerido: verdadero, 'validar-correo electrónico': verdadero}" />
            </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 __ ('Submit')?> </span>
            </button>
        </div>
    </div>
</form>

Ahora puedes ver captcha en tu formulario. Ahora necesita validar su captcha usando observador. Así que uso el evento predispatch posterior al controlador para la validación.

Paso 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 = "Proveedor \ Módulo \ Observador \ CheckCustomFormObserver" />
    </event>
</config>

Paso 7: Vendor/Module/Observer/CheckCustomFormObserver.php

proveedor de espacio de nombres \ Módulo \ Observador;

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

La clase CheckCustomFormObserver implementa ObserverInterface
{
    / **
     * @var \ Magento \ Captcha \ Helper \ Data
     * /
    protegido $ _helper;

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

    / **
     * @var \ Magento \ Framework \ Message \ ManagerInterface
     * /
    protegido $ messageManager;

    / **
     * @var \ Magento \ Framework \ App \ Response \ RedirectInterface
     * /
    redirigido $ protegido;

    / **
     * @var CaptchaStringResolver
     * /
    protegido $ captchaStringResolver;

    / **
     * @var DataPersistorInterface
     * /
    privado $ dataPersistor;

    / **
     * @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
     * /
    función pública __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;
    }

    / **
     * Verifique CAPTCHA en el formulario personalizado
     * *
     * @param \ Magento \ Framework \ Event \ Observer $ observer
     * @return void
     * /
    función pública ejecutar (\ 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-> resolve ($ controller-> getRequest (), $ formId))) {
                $ this-> messageManager-> addError (__ ('CAPTCHA incorrecto'));
                $ this-> getDataPersistor () -> set ($ formId, $ controller-> getRequest () -> getPostValue ());
                $ this -> _ actionFlag-> set ('', \ Magento \ Framework \ App \ Action \ Action :: FLAG_NO_DISPATCH, verdadero);
                $ this-> redirect-> redirect ($ controller-> getResponse (), 'yourroute / index / index');
            }
        }
    }

    / **
     * Obtener datos persistor
     * *
     * @return DataPersistorInterface
     * /
    función privada getDataPersistor ()
    {
        if ($ this-> dataPersistor === null) {
            $ this-> dataPersistor = ObjectManager :: getInstance ()
                -> get (DataPersistorInterface :: class);
        }

        devuelve $ this-> dataPersistor;
    }
}
Sohel Rana
fuente
Muy detallado. Lo intentaré.
Paul
@Sohel Rana cómo se puede agregar en el formulario de revisión del producto
supriya mishra
@supriyamishra necesita verificar
Sohel Rana
1
Hola, se muestra el captcha pero el observador controller_action_predispatch _ ** es que creo que no funciona, ya que este captcha no se está validando
AbdulBasit
1
Resolví el
1

Para aquellos de ustedes que no pueden hacer que esto funcione, pueden necesitar hacer lo que hice:

La razón por la que puede que no se muestre captcha es porque la configuración básica es usar el bloque Captcha predeterminado que en el _toHtml verifica si se requiere el captcha.

Si tiene su configuración para que captcha siempre se muestre, probablemente no se encontró con este problema; sin embargo, si no está configurado para mostrar siempre captchas y no desea mostrar siempre captchas (es decir, crear / iniciar sesión en la cuenta, etc.) de lo que necesita. establece la lógica de solo tu captcha personalizado en "Siempre se requiere".

en la línea 69 de vendor / magento / module-captcha / Block / Captcha / DefaultCaptcha.php verá:

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

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

$this->getCaptchaModel()llamadas $this->_captchaData->getCaptcha()que se encuentran en vendor / 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];
}

Aquí, el método getCaptcha verifica el valor de configuración para el tipo de captcha para renderizar y carga su fábrica con $this->_factory->create()

Sin embargo, al entrar en esta clase de fábrica, verá

 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;
}

El problema aquí es que no importa qué aspecto tendrá la fábrica en el módulo Magento Captcha para cualquier modelo de fábrica ... entonces

Necesitamos crear un complemento para envolver el asistente y verificar nuestra clave de formulario y si es nuestra clave de formulario que se está utilizando, debemos crear una nueva clase de fábrica que cargue nuestro modelo que se extienda \ Magento \ Captcha \ Model \ DefaultModel y anule El método isRequired (). Algo que se parece a esto:

en \ Your \ 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>

en Your \ 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);

}

}

en \ Your \ Module \ Model \ 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;
}
}

y finalmente su modelo para anular el parámetro requerido en \ Your \ Module \ Model \ Captcha :

<?php

namespace Your\Module\Model;

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

Necesito captcha en la página del suscriptor del boletín de noticias, gracias a que fui utilizado como observador del boletín y captcha para mí.

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) Ir a 'Admin -> Tiendas -> Configuración -> Cliente -> Configuración del cliente -> Captcha' y configurar. Puede ver el valor del nuevo formulario 'Formulario de boletín informativo'.

3) copie el archivo de diseño en el tema (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) Crear observador -> crear archivo event.xml en 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) Cree un modelo de observador y verifique la aplicación / código captcha / Nombre del proveedor / Nombre del módulo / Observador / 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);
                }
            }
        }
Monarca
fuente