Magento 2 - Hinzufügen von Captcha zu einem benutzerdefinierten Formular

28

Ich entwickle ein benutzerdefiniertes Modul, das eine Formularübermittlung enthält. Ich möchte ein Captcha hinzufügen. Und wir möchten die Standard-Captcha-Bibliothek von Magento verwenden, damit das Captcha mit dem im Registrierungsformular übereinstimmt.

Paul
quelle

Antworten:

35

Sie müssen einige Schritte ausführen, um Magento Captcha in ein benutzerdefiniertes Modul zu integrieren.

Schritt 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">
    <default>
        <Kunde>
            <captcha>
                <shown_to_logged_in_user>
                    <custom_form> 1 </ custom_form>
                </ shown_to_logged_in_user>
                <always_for>
                    <custom_form> 1 </ custom_form>
                </ always_for>
            </ captcha>
        </ customer>
        <captcha translate = "label">
            <Frontend>
                <areas>
                    <custom_form>
                        <label> Benutzerdefiniertes Formular </ label>
                    </ custom_form>
                </ areas>
            </ frontend>
        </ captcha>
    </ default>
</ config>

Schritt 2: Gehen Sie zu " Admin -> Stores -> Configuration -> Customer -> Customer Configuration -> Captcha " und konfigurieren Sie. Sie können den neuen Formularwert "Benutzerdefiniertes Formular" sehen.

Schritt 3: Erstellen 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 = "urne: magento: framework: View / Layout / etc / page_configuration.xsd">
    <head>
        <title> Benutzerdefiniertes Formular </ 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 = "Form Additional Info">
                    <block class = "Magento \ Captcha \ Block \ Captcha" name = "captcha" after = "-" cacheable = "false">
                        <action method = "setFormId">
                            <argument name = "formId" xsi: type = "string"> benutzerdefinierte_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>

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

Namespace Vendor \ Module \ Block;


Die Klasse CaptchaForm erweitert \ Magento \ Framework \ View \ Element \ Template
{
    öffentliche Funktion getFormAction ()
    {
        return $ this-> getUrl ('yourroute / index / post', ['_secure' => true]);
    }
}

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

<form class = "Kontaktformular"
      action = "<? php / * @escapeNotVerified * / echo $ block-> getFormAction ();?>"
      id = "Kontaktformular"
      method = "post"
      data-hasrequired = "<? php / * @escapeNotVerified * / echo __ ('* Erforderliche Felder')?>"
      data-mage-init = '{"validation": {}}'>
    <fieldset class = "fieldset">
        <legend class = "legend"> <span> <? php / * @escapeNotVerified * / echo __ ('Write Us')?> </ span> </ legend> <br />

        <div class = "Feldname erforderlich">
            <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 = "Feld E-Mail erforderlich">
            <label class = "label" für = "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 = "{Erforderlich: 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 __ ('Submit')?> </ span>
            </ button>
        </ div>
    </ div>
</ form>

Jetzt können Sie Captcha in Ihrem Formular sehen. Jetzt müssen Sie Ihr Captcha mit Observer validieren. Daher verwende ich das Post-Controller-Predispatch-Ereignis zur Validierung.

Schritt 6: Vendor/Module/etc/frontend/events.xml

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

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

Namespace Vendor \ Module \ Observer;

Verwenden Sie Magento \ Framework \ Event \ ObserverInterface.
Verwenden Sie Magento \ Framework \ App \ Request \ DataPersistorInterface.
Verwenden Sie Magento \ Framework \ App \ ObjectManager.
Verwenden Sie Magento \ Captcha \ Observer \ CaptchaStringResolver.

Klasse CheckCustomFormObserver implementiert ObserverInterface
{
    / **
     * @var \ Magento \ Captcha \ Helper \ Data
     * /
    protected $ _helper;

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

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

    / **
     * @var \ Magento \ Framework \ App \ Response \ RedirectInterface
     * /
    protected $ redirect;

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

    / **
     * @var DataPersistorInterface
     * /
    private $ 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
     * /
    public function __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;
    }

    / **
     * Aktivieren Sie CAPTCHA im benutzerdefinierten Formular
     *
     * @param \ Magento \ Framework \ Event \ Observer $ observer
     * @return void
     * /
    public function execute (\ 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 (__ ('Falsches 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');
            }
        }
    }

    / **
     * Holen Sie sich Data Persistor
     *
     * @return DataPersistorInterface
     * /
    private Funktion getDataPersistor ()
    {
        if ($ this-> dataPersistor === null) {
            $ this-> dataPersistor = ObjectManager :: getInstance ()
                -> get (DataPersistorInterface :: class);
        }

        return $ this-> dataPersistor;
    }
}
Sohel Rana
quelle
Sehr detailiert. Ich werde es ausprobieren.
Paul
@ Sohel Rana, wie kann es in das Produktbewertungsformular aufgenommen werden
supriya mishra
@supriyamishra müssen überprüfen
Sohel Rana
1
Hallo Das Captcha wird angezeigt, aber der Beobachter controller_action_predispatch _ ** Ich denke, nicht funktioniert, da dieses Captcha nicht validiert wird
AbdulBasit
1
Ich habe den obigen Fehler behoben, aber ich kann das Captcha in meinem benutzerdefinierten Formular nicht sehen
jafar pinjar
1

Für diejenigen von Ihnen, die dies nicht zum Laufen bringen können, müssen Sie möglicherweise das tun, was ich getan habe:

Der Grund, warum Sie das Captcha möglicherweise nicht anzeigen, ist, dass die Grundeinstellungen den Block Standard-Captcha verwenden, der im _toHtml prüft, ob das Captcha erforderlich ist.

Wenn Sie Einstellungen haben, damit Captcha immer angezeigt wird, ist dieses Problem wahrscheinlich nicht aufgetreten. Wenn jedoch nicht festgelegt ist, dass Captchas immer angezeigt werden, und Sie nicht immer Captchas anzeigen möchten (dh Konto erstellen / anmelden usw.), müssen Sie dies tun Setzen Sie die Logik nur für Ihr benutzerdefiniertes Captcha auf "Immer erforderlich".

In Zeile 69 des Herstellers / magento / module-captcha / Block / Captcha / DefaultCaptcha.php sehen Sie:

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

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

$this->getCaptchaModel()ruft das auf, $this->_captchaData->getCaptcha()was sich in vendor / magento / module-captcha / Helper / Data.php befindet

    /**
 * 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];
}

Hier überprüft die Methode getCaptcha den Konfigurationswert für den Typ des zu rendernden Captcha und lädt dessen Factory mit $this->_factory->create()

Wenn Sie jedoch in diese Fabrikklasse eintreten, werden Sie sehen

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

Das Problem hierbei ist, dass im Magento Captcha-Modul für jedes Factory-Modell unabhängig von der Fabrik das Aussehen gewählt wird

Wir müssen ein Plugin erstellen, das den Helfer umschließt und nach unserem Formularschlüssel sucht. Wenn unser Formularschlüssel verwendet wird, müssen wir eine neue Factory-Klasse erstellen, die unser Modell lädt, das \ Magento \ Captcha \ Model \ DefaultModel und darüber hinaus erweitert Die Methode isRequired (). Etwas, das so aussieht:

in \ Ihr \ Modul \ 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>

in Ihrem \ 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);

}

}

in \ Ihr \ Modul \ Modell \ 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;
}
}

und schließlich Ihr Modell, um die erforderlichen Parameter in \ Your \ Module \ Model \ Captcha zu überschreiben :

<?php

namespace Your\Module\Model;

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

Ich brauche ein Captcha auf der Newsletter-Abonnenten-Seite, danke sohan, ich wurde als Newsletter-Beobachter verwendet und Captcha-Arbeit auf der Newsletter-Seite für mich.

1) app / code / Vendorname / Modulname / 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) Gehen Sie zu "Admin -> Stores -> Configuration -> Customer -> Customer Configuration -> Captcha" und konfigurieren Sie. Sie können den neuen Formularwert "Newsletter-Formular" sehen.

3) kopiere die Layoutdatei in das Theme (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) Beobachter erstellen -> Datei event.xml in app / code / Vendorname / Modulname / etc / frontend erstellen

 <?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) Beobachter-Modell erstellen und Captcha-App / Code / Vendorname / Modulname / Observer / CheckCustomFormObserver.php prüfen

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);
                }
            }
        }
Monarch
quelle