Magento 2-如何将验证码添加到自定义表单


28

我正在开发一个包含表单提交的自定义模块。我想添加一个验证码。我们想使用Magento默认的验证码库,以使验证码与注册表格中的验证码保持一致。

Answers:


35

您需要按照一些步骤将magento验证码用于自定义模块。

步骤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”>
    <默认>
        <客户>
            <验证码>
                <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 translation =“ label”>
            <前端>
                <区域>
                    <custom_form>
                        <label>自定义表单</ label>
                    </ custom_form>
                </ areas>
            </ frontend>
        </ captcha>
    </ default>
</ config>

步骤2:转到“ 管理员->商店->配置->客户->客户配置->验证码 ”并进行配置。您可以看到新表单值“自定义表单”

步骤3:建立 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”>
    <头>
        <title>自定义表单</ title>
    </ head>
    <身体>
        <referenceContainer name =“ content”>
            <block class =“ Vendor \ Module \ Block \ CaptchaForm” name =“ contactForm”模板=“ Vendor_Module :: captchaform.phtml”>
                <container name =“ form.additional.info” label =“表单其他信息”>
                    <block class =“ Magento \ Captcha \ Block \ Captcha” name =“验证码” 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>

第四步: Vendor/Module/Block/CaptchaForm.php

命名空间Vendor \ Module \ Block;


CaptchaForm类扩展\ Magento \ Framework \ View \ Element \ Template
{
    公共函数getFormAction()
    {
        返回$ this-> getUrl('yourroute / index / post',['_secure'=> true]);
    }
}

步骤5: Vendor/Moduel/view/frontend/templates/captchaform.phtml

<form class =“ form contact”
      action =“ <?php / * @escapeNotVerified * / echo $ block-> getFormAction();?>”
      id =“ contact-form”
      method =“ post”
      data-hasrequired =“ <?php / * @escapeNotVerified * / echo __('*必填字段')?>”
      data-mage-init ='{“验证”:{}}'>
    <fieldset class =“ fieldset”>
        <legend class =“ legend”> <span> <?php / * @escapeNotVerified * / echo __('Write Us')?> </ span> </ legend> <br />

        <div class =“必填字段名称”>
            <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 =“必填字段电子邮件”>
            <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 __('Submit')?> </ span>
            </ button>
        </ div>
    </ div>
</ form>

现在您可以在表单中看到验证码了。现在需要使用观察者来验证您的验证码。因此,我使用控制器后预调度事件进行验证。

步骤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>

步骤7: Vendor/Module/Observer/CheckCustomFormObserver.php

命名空间Vendor \ Module \ Observer;

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

CheckCustomFormObserver类实现ObserverInterface
{
    / **
     * @var \ Magento \ Captcha \ Helper \ Data
     * /
    受保护的$ _helper;

    / **
     * @var \ Magento \ Framework \ App \ ActionFlag
     * /
    受保护的$ _actionFlag;

    / **
     * @var \ Magento \ Framework \ Message \ ManagerInterface
     * /
    受保护的$ messageManager;

    / **
     * @var \ Magento \ Framework \ App \ Response \ RedirectInterface
     * /
    受保护的$ redirect;

    / **
     * @var CaptchaStringResolver
     * /
    受保护的$ captchaStringResolver;

    / **
     * @var DataPersistorInterface
     * /
    私人$ dataPersistor;

    / **
     * @参数\ Magento \ Captcha \ Helper \ Data $ helper
     * @param \ Magento \ Framework \ App \ ActionFlag $ actionFlag
     * @param \ Magento \ Framework \ Message \ ManagerInterface $ messageManager
     * @param \ Magento \ Framework \ App \ Response \ RedirectInterface $ redirect
     * @参数CaptchaStringResolver $ captchaStringResolver
     * /
    公共功能__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;
    }

    / **
     *在自定义表单上检查验证码
     *
     * @param \ Magento \ Framework \ Event \ Observer $ observer
     * @返回无效
     * /
    公共函数execute(\ Magento \ Framework \ Event \ Observer $ observer)
    {
        $ formId ='custom_form';
        $ captcha = $ this-> _ helper-> getCaptcha($ formId);
        如果($ captcha-> ​​isRequired()){
            / ** @var \ Magento \ Framework \ App \ Action \ Action $ controller * /
            $ controller = $ observer-> getControllerAction();
            如果(!$ captcha-> ​​isCorrect($ this-> captchaStringResolver-> resolve($ controller-> getRequest(),$ formId))){
                $ this-> messageManager-> addError(__('不正确的验证码。'));
                $ 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');
            }
        }
    }

    / **
     *获取数据持久化器
     *
     * @return DataPersistorInterface
     * /
    私有函数getDataPersistor()
    {
        如果($ this-> dataPersistor === null){
            $ this-> dataPersistor = ObjectManager :: getInstance()
                ->获取(DataPersistorInterface :: class);
        }

        返回$ this-> dataPersistor;
    }
}

非常详细。我会尝试的。
保罗

@Sohel Rana如何将其添加到产品审阅表单中
supriya mishra

@supriyamishra需要检查
Sohel Rana

1
嗨,显示了验证码,但我认为观察者controller_action_predispatch _ **不起作用,因为此验证码尚未通过验证
AbdulBasit

1
我已解决上述错误,但无法以自定义形式看到验证码
jafar pinjar

1

对于无法使用此功能的人,您可能需要做我做的事情:

您可能无法显示验证码的原因是,基本设置将使用默认验证码块,该代码在_toHtml中进行检查以查看是否需要验证码。

如果您已将验证码设置为始终显示,则可能未遇到此问题,但是,如果未将其设置为始终显示验证码,并且您不想始终显示验证码(即帐户创建/登录等),则不需要将仅您的自定义验证码的逻辑设置为“始终需要”。

vendor / magento / module-captcha / Block / Captcha / DefaultCaptcha.php的第69行上,您将看到:

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

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

$this->getCaptchaModel()呼叫$this->_captchaData->getCaptcha()是在 供应商/的magento /模块的验证码/助手/ 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];
}

在这里,getCaptcha方法检查要呈现的验证码类型的config值,并使用 $this->_factory->create()

但是,进入该工厂类,您将看到

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

这里的问题是,不管任何工厂型号的工厂在Magento Captcha模块中看起来是什么,.so

我们需要创建一个插件来包装帮助程序,并检查我们的表单密钥,如果正在使用我们的表单密钥,我们需要创建一个新的工厂类,以加载扩展了\ Magento \ Captcha \ Model \ DefaultModel并覆盖的模型 isRequired()方法。看起来像这样:

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

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

}

}

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

最后,您的模型可以覆盖\ Your \ Module \ Model \ Captcha中的必需参数 :

<?php

namespace Your\Module\Model;

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

0

我需要在新闻订阅者页面中的验证码,谢谢sohan,我曾被新闻观察者和新闻页面中的验证码工作用过。

1)应用程序/代码/供应商名称/模块名称/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)转到“管理员->商店->配置->客户->客户配置->验证码”并进行配置。您可以看到新表单值“ Newsletter Form”。

3)复制主题中的布局文件(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)创建观察者->在app / code / Vendorname / Modulename / etc / frontend中创建event.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_newsletter_subscriber_new">
        <observer name="captcha_newletter_form" instance="Vendorname/Modulename/Observer\CheckCustomFormObserver" />
    </event>
</config>

5)创建观察者模型并检查验证码app / code / 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);
                }
            }
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.