Magento 2 - Cara menambahkan captcha ke formulir kustom

28

Saya sedang mengembangkan modul khusus yang berisi pengiriman formulir. Saya ingin menambahkan captcha ke dalamnya. Dan kami ingin menggunakan perpustakaan captcha default Magento sehingga captcha konsisten dengan yang ada di formulir pendaftaran.

Paul
sumber

Jawaban:

35

Anda perlu mengikuti beberapa langkah untuk menggunakan magento captcha ke modul khusus.

Langkah 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>
        <customer>
            <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> Formulir Khusus </label>
                    </custom_form>
                </as>>
            </frontend>
        </captcha>
    </default>
</config>

Langkah 2: Masuk ke Admin -> Toko -> Konfigurasi -> Pelanggan -> Konfigurasi Pelanggan -> Captcha 'dan konfigurasikan. Anda dapat melihat nilai formulir baru 'Formulir Kustom'

Langkah 3: Buat Vendor/Module/view/frontend/layout/yourroutid_index_index.xml

<? xml version = "1.0"?>
<halaman xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" layout = "1column" xsi: noNamespaceSchemaLocation = "urn: magento: framework: Lihat / Tata Letak / etc / page_configuration.xsd">
    <head>
        <title> Formulir Kustom </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 Info Tambahan">
                    <block class = "Magento \ Captcha \ Block \ Captcha" name = "captcha" after = "-" cacheable = "false">
                        <action method = "setFormId">
                            <argumen name = "formId" xsi: type = "string"> custom_form </argument>
                        </action>
                        <action method = "setImgWidth">
                            <argumen name = "width" xsi: type = "string"> 230 </argument>
                        </action>
                        <action method = "setImgHeight">
                            <argumen 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>

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

namespace Vendor \ Module \ Block;


kelas CaptchaForm meluas \ Magento \ Framework \ View \ Element \ Template
{
    fungsi publik getFormAction ()
    {
        return $ this-> getUrl ('yourroute / index / post', ['_secure' => true]);
    }
}

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

<form class = "form contact"
      action = "<? php / * @escapeNotVerified * / echo $ block-> getFormAction ();?>"
      id = "formulir kontak"
      metode = "posting"
      data-hasrequired = "<? php / * @escapeNotVerified * / echo __ ('* Bidang yang Diperlukan')?>"
      data-mage-init = '{"validation": {}}'>
    <fieldset class = "fieldset">
        <legend class = "legend"> <span> <? php / * @escapeNotVerified * / echo __ ('Tulis Kami')?> </span> </legend> <br />

        <div class = "nama bidang wajib diisi">
            <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 = "email bidang wajib diisi">
            <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 = "{wajib: true, 'validate-email': true}" />
            </div>
        </div>
        <? php echo $ block-> getChildHtml ('form.additional.info'); ?>
    </fieldset>
    <div class = "action-toolbar">
        <div class = "primary">
            <input type = "hidden" name = "hideit" id = "hideit" value = "" />
            <button type = "submit" title = "<? php / * @escapeNotVerified * / echo __ ('Kirim')?>" class = "action submit primary">
                <span> <? php / * @escapeNotVerified * / echo __ ('Kirim')?> </span>
            </button>
        </div>
    </div>
</form>

Sekarang Anda dapat melihat captcha ke dalam formulir Anda. Sekarang perlu memvalidasi captcha Anda menggunakan pengamat. Jadi saya menggunakan predispatch post controller untuk validasi.

Langkah 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">
        <nama pengamat = "captcha_custom_form" instance = "Vendor \ Module \ Observer \ CheckCustomFormObserver" />
    </event>
</config>

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

namespace Vendor \ Module \ Observer;

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

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

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

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

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

    / **
     * @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
     * /
    fungsi publik __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;
    }

    / **
     * Periksa CAPTCHA pada Formulir Kustom
     *
     * @param \ Magento \ Framework \ Event \ Observer $ observer
     * @return batal
     * /
    eksekusi fungsi publik (\ 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-> resol ($ controller-> getRequest (), $ formId))) {
                $ this-> messageManager-> addError (__ ('CAPTCHA salah.'));
                $ 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');
            }
        }
    }

    / **
     * Dapatkan Data Persistor
     *
     * @return DataPersistorInterface
     * /
    fungsi pribadi getDataPersistor ()
    {
        if ($ this-> dataPersistor === null) {
            $ this-> dataPersistor = ObjectManager :: getInstance ()
                -> get (DataPersistorInterface :: class);
        }

        kembalikan $ this-> dataPersistor;
    }
}
Sohel Rana
sumber
Sangat detail. Saya akan mencobanya.
Paul
@Sohel Rana bagaimana bisa menambahkannya ke dalam formulir ulasan produk
supriya mishra
@supriyamishra perlu memeriksa
Sohel Rana
1
Hai captcha ditampilkan tetapi pengamat controller_action_predispatch _ ** adalah saya pikir tidak berfungsi karena captcha ini tidak sedang divalidasi
AbdulBasit
1
Saya menyelesaikan kesalahan di atas tetapi saya tidak dapat melihat captcha dalam bentuk khusus saya
jafar pinjar
1

Bagi Anda yang tidak dapat melakukan ini, Anda mungkin perlu melakukan apa yang saya lakukan:

Alasan Anda captcha mungkin tidak ditampilkan adalah karena pengaturan dasar adalah untuk menggunakan blok captcha Default yang dalam _toHtml melakukan pemeriksaan untuk melihat apakah captcha diperlukan.

Jika Anda memiliki pengaturan untuk captcha untuk selalu ditampilkan daripada Anda mungkin tidak mengalami masalah ini, namun jika tidak diatur untuk selalu menampilkan captcha dan Anda tidak ingin selalu menampilkan captcha (yaitu pembuatan akun / login dll) daripada yang Anda perlukan atur logika hanya captcha khusus Anda ke "Selalu diperlukan".

pada baris 69 dari vendor / magento / module-captcha / Block / Captcha / DefaultCaptcha.php Anda akan melihat:

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

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

$this->getCaptchaModel()panggilan $this->_captchaData->getCaptcha()yang ada di 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];
}

Di sini, metode getCaptcha memeriksa nilai konfigurasi untuk jenis captcha yang akan di-render dan memuat pabriknya $this->_factory->create()

Namun melangkah ke kelas pabrik ini, Anda akan melihat

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

Masalahnya di sini adalah tidak peduli apa pun pabrik akan terlihat dalam modul Magento Captcha untuk model Pabrik apa pun .. jadi

Kita perlu membuat plugin untuk membungkus helper dan memeriksa kunci form kita dan jika itu kunci form kita digunakan, kita perlu membuat kelas pabrik baru yang memuat model kita yang meluas \ Magento \ Captcha \ Model \ DefaultModel dan overides metode isRequired (). Sesuatu yang terlihat seperti ini:

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

di \ Module \ Plugin \ Helper \ CaptchaData Anda

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

}

}

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

dan akhirnya model Anda untuk mengungguli param yang diperlukan di \ Your \ Module \ Model \ Captcha :

<?php

namespace Your\Module\Model;

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

Saya butuh captcha di halaman pelanggan buletin terima kasih sohan saya sudah terbiasa dengan pengamat buletin dan captcha bekerja di halaman buletin untuk saya.

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) Admin '-> Toko -> Konfigurasi -> Pelanggan -> Konfigurasi Pelanggan -> Captcha' dan konfigurasikan. Anda dapat melihat nilai formulir baru 'Formulir Newsletter'.

3) menyalin file layout dengan 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) Buat pengamat -> buat file event.xml di 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) Buat model pengamat dan periksa aplikasi captcha / kode / 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);
                }
            }
        }
Raja
sumber