├── CHANGELOG ├── UserGuide.pdf ├── composer.json ├── .github └── no-response.yml ├── registration.php ├── view ├── adminhtml │ ├── layout │ │ ├── admin_recaptcha.xml │ │ ├── msp_recaptcha.xml │ │ ├── adminhtml_auth_login.xml │ │ └── adminhtml_auth_forgotpassword.xml │ ├── web │ │ └── css │ │ │ └── style.css │ └── templates │ │ └── captcha.phtml └── frontend │ ├── layout │ ├── hyva_default.xml │ └── default.xml │ ├── templates │ ├── captcha.phtml │ └── hyva │ │ └── captcha.phtml │ └── web │ └── js │ └── captcha.js ├── etc ├── frontend │ └── events.xml ├── module.xml ├── adminhtml │ ├── events.xml │ └── system.xml ├── di.xml ├── acl.xml ├── config.xml └── csp_whitelist.xml ├── Model └── System │ └── Config │ └── Source │ ├── Theme.php │ ├── Size.php │ ├── RecaptchaType.php │ ├── Position.php │ ├── Forms.php │ ├── Frontend │ └── Forms.php │ └── Language.php ├── USER-GUIDE.md ├── Observer ├── Adminhtml │ ├── Login.php │ └── Forgot.php └── Captcha.php ├── Console └── Adminhtml │ └── Command │ ├── Enable.php │ └── Disable.php ├── .travis.yml ├── Block ├── Adminhtml │ └── Captcha.php └── Captcha.php ├── LICENSE ├── i18n └── en_US.csv ├── Helper └── Data.php └── README.md /CHANGELOG: -------------------------------------------------------------------------------- 1 | CHANGELOG: https://www.mageplaza.com/releases/google-recaptcha -------------------------------------------------------------------------------- /UserGuide.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mageplaza/magento-2-google-recaptcha/HEAD/UserGuide.pdf -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mageplaza/module-google-recaptcha", 3 | "description": "Magento 2 Google Recaptcha Extension", 4 | "require": { 5 | "mageplaza/module-core": "^1.5.14", 6 | "google/recaptcha": "^1.2" 7 | }, 8 | "type": "magento2-module", 9 | "version": "4.0.5", 10 | "license": "proprietary", 11 | "authors": [ 12 | { 13 | "name": "Mageplaza", 14 | "email": "support@mageplaza.com", 15 | "homepage": "https://www.mageplaza.com", 16 | "role": "Technical Support " 17 | } 18 | ], 19 | "autoload": { 20 | "files": [ 21 | "registration.php" 22 | ], 23 | "psr-4": { 24 | "Mageplaza\\GoogleRecaptcha\\": "" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an Issue is closed for lack of response 4 | daysUntilClose: 7 5 | # Label requiring a response 6 | responseRequiredLabel: waiting-customer-response 7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable 8 | closeComment: > 9 | This issue has been automatically closed because there has been no response 10 | to our request for more information from the original author. With only the 11 | information that is currently in the issue, we don't have enough information 12 | to take action. Please reach out if you have or find the answers we need so 13 | that we can investigate further. 14 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /view/adminhtml/layout/msp_recaptcha.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /etc/frontend/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /view/adminhtml/web/css/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Mageplaza 3 | * 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the Mageplaza.com license that is 7 | * available through the world-wide-web at this URL: 8 | * https://www.mageplaza.com/LICENSE.txt 9 | * 10 | * DISCLAIMER 11 | * 12 | * Do not edit or add to this file if you wish to upgrade this extension to newer 13 | * version in the future. 14 | * 15 | * @category Mageplaza 16 | * @package Mageplaza_GoogleRecaptcha 17 | * @copyright Copyright (c) Mageplaza (https://www.mageplaza.com/) 18 | * @license https://www.mageplaza.com/LICENSE.txt 19 | */ 20 | .g-recaptcha { 21 | margin-left: -23px; 22 | -webkit-transform: scale(0.95); 23 | -moz-transform: scale(0.95); 24 | -ms-transform: scale(0.95); 25 | -o-transform: scale(0.95); 26 | transform: scale(0.95); 27 | -webkit-transform-origin: 0 0; 28 | -moz-transform-origin: 0 0; 29 | -ms-transform-origin: 0 0; 30 | -o-transform-origin: 0 0; 31 | transform-origin: 0 0; 32 | } -------------------------------------------------------------------------------- /view/frontend/layout/hyva_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /view/frontend/layout/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /view/adminhtml/layout/adminhtml_auth_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /etc/adminhtml/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /view/adminhtml/layout/adminhtml_auth_forgotpassword.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Theme.php: -------------------------------------------------------------------------------- 1 | __('Dark'), 'value' => 'dark'], 39 | ['label' => __('Light'), 'value' => 'light'] 40 | ]; 41 | 42 | return $options; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Size.php: -------------------------------------------------------------------------------- 1 | __('Compact'), 'value' => 'compact'], 39 | ['label' => __('Normal'), 'value' => 'normal'] 40 | ]; 41 | 42 | return $options; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /view/adminhtml/templates/captcha.phtml: -------------------------------------------------------------------------------- 1 | isCaptchaBackend() && $block->showInForm()): ?> 23 | 26 |
27 |
28 |
32 |
33 |
34 |
35 | 36 | -------------------------------------------------------------------------------- /Model/System/Config/Source/RecaptchaType.php: -------------------------------------------------------------------------------- 1 | __('Visible'), 'value' => 'visible'], 39 | ['label' => __('Invisible'), 'value' => 'invisible'] 40 | ]; 41 | 42 | return $recaptchaTypeOptionArray; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | Mageplaza\GoogleRecaptcha\Console\Adminhtml\Command\Enable 28 | Mageplaza\GoogleRecaptcha\Console\Adminhtml\Command\Disable 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Position.php: -------------------------------------------------------------------------------- 1 | __('Bottom Right'), 'value' => 'bottomright'], 39 | ['label' => __('Bottom Left'), 'value' => 'bottomleft'], 40 | ['label' => __('Inline'), 'value' => 'inline'], 41 | ]; 42 | 43 | return $positionOptionArray; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /etc/acl.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 | 26 | 27 | magento/google-recaptcha 28 | 29 | 30 | 0 31 | normal 32 | light 33 | 34 | 35 | 0 36 | invisible 37 | body.customer-account-create #form-validate.form-create-account 38 | bottomleft 39 | light 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Forms.php: -------------------------------------------------------------------------------- 1 | getOptionHash() as $value => $label) { 42 | $options[] = [ 43 | 'value' => $value, 44 | 'label' => $label 45 | ]; 46 | } 47 | 48 | return $options; 49 | } 50 | 51 | /** 52 | * @return array 53 | */ 54 | public function getOptionHash() 55 | { 56 | return [ 57 | self::TYPE_LOGIN => __('Admin Login'), 58 | self::TYPE_FORGOT => __('Admin Forgot Password') 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /USER-GUIDE.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | - Installation guide: https://www.mageplaza.com/install-magento-2-extension/#solution-1-ready-to-paste 4 | - User Guide: https://docs.mageplaza.com/google-recaptcha-m2/ 5 | - Product page: https://www.mageplaza.com/magento-2-google-recaptcha/ 6 | - FAQs: https://www.mageplaza.com/faqs/ 7 | - Get Support: https://github.com/mageplaza/magento-2-google-recaptcha/issues 8 | - Changelog: https://www.mageplaza.com/releases/google-recaptcha 9 | - License agreement: https://www.mageplaza.com/LICENSE.txt 10 | 11 | ## How to install 12 | 13 | ### Install via composer [Recommend] 14 | 15 | Run the following command in Magento 2 root folder 16 | 17 | ``` 18 | composer require mageplaza/module-google-recaptcha 19 | php bin/magento setup:upgrade 20 | php bin/magento setup:static-content:deploy 21 | ``` 22 | 23 | ### Install ready-to-paste package (Recommended) 24 | 25 | - Installation guide: https://www.mageplaza.com/install-magento-2-extension/ 26 | 27 | ## How to upgrade 28 | 29 | 1. Backup 30 | 31 | Backup your Magento code, database before upgrading. 32 | 33 | 2. Remove GoogleRecaptcha folder 34 | 35 | In case of customization, you should backup the customized files and modify in newer version. 36 | Now you remove `app/code/Mageplaza/GoogleRecaptcha` folder. In this step, you can copy override GoogleRecaptcha folder but this may cause of compilation issue. That why you should remove it. 37 | 38 | 3. Upload new version 39 | Upload this package to Magento root directory 40 | 41 | 4. Run command line: 42 | 43 | ``` 44 | php bin/magento setup:upgrade 45 | php bin/magento setup:static-content:deploy 46 | ``` 47 | 48 | 49 | ## FAQs 50 | 51 | 52 | #### Q: I got error: `Mageplaza_Core has been already defined` 53 | A: Read solution: https://github.com/mageplaza/module-core/issues/3 54 | 55 | 56 | #### Q: My site is down 57 | A: Please follow this guide: https://www.mageplaza.com/blog/magento-site-down.html 58 | 59 | 60 | ## Support 61 | 62 | - FAQs: https://www.mageplaza.com/faqs/ 63 | - https://mageplaza.freshdesk.com/ 64 | - support@mageplaza.com -------------------------------------------------------------------------------- /Observer/Adminhtml/Login.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 50 | } 51 | 52 | /** 53 | * @param Observer $observer 54 | * 55 | * @throws PluginAuthenticationException 56 | */ 57 | public function execute(Observer $observer) 58 | { 59 | if ($this->_helperData->isCaptchaBackend() && 60 | in_array('backend_login', $this->_helperData->getFormsBackend(), true) && 61 | $this->_helperData->getVisibleKey() && $this->_helperData->getVisibleSecretKey() 62 | ) { 63 | $response = $this->_helperData->verifyResponse('visible'); 64 | if (empty($response['success'])) { 65 | throw new PluginAuthenticationException(new Phrase($response['message'])); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Console/Adminhtml/Command/Enable.php: -------------------------------------------------------------------------------- 1 | helperData = $helperData; 59 | $this->_configWriter = $configWriter; 60 | 61 | parent::__construct($name); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | protected function configure() 68 | { 69 | $this->setName('mpgooglerecaptcha:backend:enable') 70 | ->setDescription(__('Enable backend captcha')); 71 | 72 | parent::configure(); 73 | } 74 | 75 | /** 76 | * @param InputInterface $input 77 | * @param OutputInterface $output 78 | * 79 | * @return int 80 | */ 81 | protected function execute(InputInterface $input, OutputInterface $output) 82 | { 83 | if ($this->helperData->isCaptchaBackend()) { 84 | $output->writeln(__('The captcha is enabled for your admin website.')); 85 | } else { 86 | $path = 'googlerecaptcha/backend/enabled'; 87 | $this->_configWriter->save($path, '1'); 88 | $output->writeln(__('The captcha backend has been successfully enabled. Please run the flush cache command again')); 89 | } 90 | 91 | return 0; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Console/Adminhtml/Command/Disable.php: -------------------------------------------------------------------------------- 1 | helperData = $helperData; 59 | $this->_configWriter = $configWriter; 60 | 61 | parent::__construct($name); 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | protected function configure() 68 | { 69 | $this->setName('mpgooglerecaptcha:backend:disable') 70 | ->setDescription(__('Disable backend captcha')); 71 | 72 | parent::configure(); 73 | } 74 | 75 | /** 76 | * @param InputInterface $input 77 | * @param OutputInterface $output 78 | * 79 | * @return int 80 | */ 81 | protected function execute(InputInterface $input, OutputInterface $output) 82 | { 83 | if (!$this->helperData->isCaptchaBackend()) { 84 | $output->writeln(__('The captcha is disable for your admin website.')); 85 | } else { 86 | $path = 'googlerecaptcha/backend/enabled'; 87 | $this->_configWriter->save($path, '0'); 88 | $output->writeln(__('The captcha backend has been successfully disabled. Please run the flush cache command again')); 89 | } 90 | 91 | return 0; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 7.0 4 | - 7.1 5 | sudo: required 6 | dist: trusty 7 | env: 8 | global: 9 | - COMPOSER_BIN_DIR=~/bin 10 | - INTEGRATION_SETS=3 11 | - NODE_JS_VERSION=6 12 | - MAGENTO_HOST_NAME="magento2.travis" 13 | - COMPOSER_MODULE=mageplaza/module-google-recaptcha 14 | matrix: 15 | - MAGENTO_VERSION=2.2.1 TEST_SUITE=integration INTEGRATION_INDEX=1 16 | - MAGENTO_VERSION=2.2.1 TEST_SUITE=integration INTEGRATION_INDEX=2 17 | - MAGENTO_VERSION=2.2.1 TEST_SUITE=integration INTEGRATION_INDEX=3 18 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=static 19 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=js GRUNT_COMMAND=static 20 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=integration INTEGRATION_INDEX=1 21 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=integration INTEGRATION_INDEX=2 22 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=integration INTEGRATION_INDEX=3 23 | - MAGENTO_VERSION=2.2.5 TEST_SUITE=integration INTEGRATION_INDEX=1 24 | - MAGENTO_VERSION=2.2.5 TEST_SUITE=integration INTEGRATION_INDEX=2 25 | - MAGENTO_VERSION=2.2.5 TEST_SUITE=integration INTEGRATION_INDEX=3 26 | - MAGENTO_VERSION=2.2.6 TEST_SUITE=integration INTEGRATION_INDEX=1 27 | - MAGENTO_VERSION=2.2.6 TEST_SUITE=integration INTEGRATION_INDEX=2 28 | - MAGENTO_VERSION=2.2.6 TEST_SUITE=integration INTEGRATION_INDEX=3 29 | 30 | matrix: 31 | exclude: 32 | - php: 7.0 33 | env: MAGENTO_VERSION=2.2.2 TEST_SUITE=js GRUNT_COMMAND=static 34 | - php: 7.0 35 | env: MAGENTO_VERSION=2.2.2 TEST_SUITE=static 36 | cache: 37 | apt: true 38 | directories: 39 | - "$HOME/.composer/cache" 40 | - "$HOME/.nvm" 41 | addons: 42 | apt: 43 | packages: 44 | - mysql-server-5.6 45 | - mysql-client-core-5.6 46 | - mysql-client-5.6 47 | - postfix 48 | firefox: '46.0' 49 | hosts: 50 | - magento2.travis 51 | before_install: 52 | - git clone https://github.com/magento/magento2 --branch $MAGENTO_VERSION 53 | - cd magento2 54 | - bash ./dev/travis/before_install.sh 55 | install: 56 | - composer install --no-interaction --prefer-dist 57 | - composer require $COMPOSER_MODULE 58 | before_script: 59 | #- cp -f ${TRAVIS_BUILD_DIR}/dev/tests/integration/phpunit.xml.dist dev/tests/integration/ 60 | - echo "vendor/$COMPOSER_MODULE" > dev/tests/static/testsuite/Magento/Test/Less/_files/whitelist/common.txt 61 | - echo "vendor/$COMPOSER_MODULE" > dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt 62 | - echo "vendor/$COMPOSER_MODULE/**/*.js" > dev/tests/static/testsuite/Magento/Test/Js/_files/whitelist/magento.txt 63 | - bash ./dev/travis/before_script.sh 64 | script: 65 | - test $TEST_SUITE = "static" && TEST_FILTER='--filter "Magento\\Test\\Php\\LiveCodeTest"' || true 66 | - test $TEST_SUITE = "functional" && TEST_FILTER='dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests.php' || true 67 | 68 | 69 | -------------------------------------------------------------------------------- /etc/csp_whitelist.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 25 | 26 | 27 | 28 | *.googleapis.com 29 | *.google.com 30 | *.gstatic.com 31 | 32 | 33 | 34 | 35 | *.googleapis.com 36 | *.google.com 37 | *.gstatic.com 38 | 39 | 40 | 41 | 42 | https://fonts.gstatic.com 43 | https://www.google.com 44 | https://www.gstatic.com 45 | 46 | 47 | 48 | 49 | http://dpm.demdex.net 50 | https://www.google.com 51 | https://www.gstatic.com 52 | 53 | 54 | 55 | 56 | www.google.com 57 | www.gstatic.com 58 | apis.google.com 59 | 60 | 61 | 62 | 63 | self 64 | www.google.com 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /view/frontend/templates/captcha.phtml: -------------------------------------------------------------------------------- 1 | isCaptchaFrontend()): ?> 24 | getCurrentTheme(); 26 | $key = $block->getInvisibleKey(); 27 | $recaptchaType = $block->getRecaptchaType(); 28 | if ($recaptchaType === 'visible') { 29 | $key = $block->getVisibleKey(); 30 | } 31 | ?> 32 | 74 | 89 | 90 | -------------------------------------------------------------------------------- /Block/Adminhtml/Captcha.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 53 | 54 | parent::__construct($context, $data); 55 | } 56 | 57 | /** 58 | * @return mixed 59 | */ 60 | public function getVisibleKey() 61 | { 62 | return $this->_helperData->getVisibleKey(); 63 | } 64 | 65 | /** 66 | * @return mixed 67 | */ 68 | public function getSize() 69 | { 70 | return $this->_helperData->getSizeBackend(); 71 | } 72 | 73 | /** 74 | * @return mixed 75 | */ 76 | public function getTheme() 77 | { 78 | return $this->_helperData->getThemeBackend(); 79 | } 80 | 81 | /** 82 | * @return mixed 83 | */ 84 | public function isCaptchaBackend() 85 | { 86 | return $this->_helperData->isCaptchaBackend(); 87 | } 88 | 89 | /** 90 | * @return bool 91 | */ 92 | public function showInForm() 93 | { 94 | $form = $this->_helperData->getFormsBackend(); 95 | if (!empty($form)) { 96 | if ($this->_request->getFullActionName() === 'adminhtml_auth_login') { 97 | return in_array(FormsAdmin::TYPE_LOGIN, $form); 98 | } 99 | if ($this->_request->getFullActionName() === 'adminhtml_auth_forgotpassword') { 100 | return in_array(FormsAdmin::TYPE_FORGOT, $form); 101 | } 102 | } 103 | 104 | return false; 105 | } 106 | 107 | /** 108 | * @return mixed 109 | */ 110 | public function getLanguageCode() 111 | { 112 | return $this->_helperData->getLanguageCode(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2016-present Mageplaza Co. Ltd. 2 | 3 | This License is entered by Mageplaza to govern the usage or redistribution of Mageplaza software. This is a legal agreement between you (either an individual or a single entity) and Mageplaza for Mageplaza software product(s) which may include extensions, templates and services. 4 | 5 | By purchasing, installing, or otherwise using Mageplaza products, you acknowledge that you have read this License and agree to be bound by the terms of this Agreement. If you do not agree to the terms of this License, do not install or use Mageplaza products. 6 | 7 | The Agreement becomes effective at the moment when you acquire software from our site or receive it through email or on data medium or by any other means. Mageplaza reserves the right to make reasonable changes to the terms of this license agreement and impose its clauses at any given time. 8 | 9 | 1. GRANT OF LICENSE: By purchasing a product of Mageplaza: 10 | 11 | 1. Customer will receive source code open 100%. 12 | 13 | 2. Customer will obtain a License Certificate which will remain valid until the Customer stops using the Product or until Mageplaza terminates this License because of Customer’s failure to comply with any of its Terms and Conditions. Each License Certificate includes a license serial which is valid for one live Magento installation only and unlimited test Magento installations. 14 | 15 | 3. You are allowed to customize our products to fit with your using purpose. 16 | 17 | 4. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS 18 | 19 | 5. Installation and Use 20 | 21 | 6. For each new Software installation, you are obliged to purchase a separate License. You are not permitted to use any part of the code in whole or part in any other software or product or website. You are legally bound to preserve the copyright information intact including the text/link at bottom. 22 | 23 | 2. Distribution: You are not allowed to distribute Mageplaza software to third parties. Any distribution without our permission, including non commercial distribution is considered as violation of this Agreement and entails liability, according to the current law. You may not place the Software onto a server that allows access to the Software via a public network or the Internet for distribution purposes. 24 | 25 | 3. Rental: You may not give, sell, sub-license, rent, lease or lend any portion of the Software to anyone. 26 | 27 | 4. Compliance with Applicable Laws: You must comply with all applicable laws regarding use of software products. Mageplaza software and a portion of it are protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. Accordingly, customer is required to treat the software like any other copyrighted material. Any activity violating copyright law will be prosecuted according to the current law. We retain the right to revoke the license of any user holding an invalid license. 28 | 29 | 5. TERMINATION: Without prejudice to any other rights, Mageplaza may terminate this License at any time if you fail to comply with the terms and conditions of this License. In such event, it constitutes a breach of the agreement, and your license to use the program is revoked and you must destroy all copies of Mageplaza products in your possession. After being notified of termination of your license, if you continue to use Mageplaza software, you hereby agree to accept an injunction to prevent you from its further use and to pay all costs (including but not limited to reasonable attorney fees) to enforce our revocation of your license and any damages suffered by us because of your misuse of the Software. We are not bound to return you the amount spent for purchase of the Software for the termination of this License. 30 | 31 | 6. LIMITATION OF LIABILITY: In no event shall Mageplaza be liable for any damages (including, without limitation, lost profits, business interruption, or lost information) rising out of ‘Authorized Users’ use of or inability to use the Mageplaza products, even if Mageplaza has been advised of the possibility of such damages. In no event will Mageplaza be liable for prosecution arising from use of the Software against law or for any illegal use. 32 | 33 | The latest License: https://www.mageplaza.com/LICENSE.txt -------------------------------------------------------------------------------- /Observer/Adminhtml/Forgot.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 92 | $this->_request = $httpRequest; 93 | $this->_messageManager = $messageManager; 94 | $this->_responseInterface = $responseInterface; 95 | $this->_actionFlag = $actionFlag; 96 | $this->_urlInterface = $urlInterface; 97 | } 98 | 99 | /** 100 | * @param Observer $observer 101 | */ 102 | public function execute(Observer $observer) 103 | { 104 | if ($this->_helperData->isCaptchaBackend() 105 | && $this->_request->getParam('g-recaptcha-response') !== null 106 | && (in_array('backend_forgotpassword', $this->_helperData->getFormsBackend(), true)) 107 | && ($this->_helperData->getVisibleKey() !== null && $this->_helperData->getVisibleSecretKey() !== null) 108 | ) { 109 | $controller = $this->_urlInterface->getCurrentUrl(); 110 | try { 111 | $response = $this->_helperData->verifyResponse('visible'); 112 | if (!array_key_exists('success', $response) || empty($response['success'])) { 113 | $this->redirectError($controller, $response['message']); 114 | } 115 | } catch (Exception $e) { 116 | $this->redirectError($controller, $e->getMessage()); 117 | } 118 | } 119 | } 120 | 121 | /** 122 | * @param string $url 123 | * @param string $message 124 | */ 125 | public function redirectError($url, $message) 126 | { 127 | $this->_messageManager->addErrorMessage($message); 128 | $this->_actionFlag->set('', Action::FLAG_NO_DISPATCH, true); 129 | $this->_responseInterface->setRedirect($url); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Frontend/Forms.php: -------------------------------------------------------------------------------- 1 | _moduleManager = $moduleManager; 61 | } 62 | 63 | /** 64 | * @return array 65 | */ 66 | public function toOptionArray() 67 | { 68 | $options = []; 69 | foreach ($this->getOptionHash() as $value => $label) { 70 | $options[] = [ 71 | 'value' => $value, 72 | 'label' => $label 73 | ]; 74 | } 75 | 76 | return $options; 77 | } 78 | 79 | /** 80 | * @return array 81 | */ 82 | public function getOptionHash() 83 | { 84 | $labels = [ 85 | self::TYPE_LOGIN => __('Login'), 86 | self::TYPE_CREATE => __('Create User'), 87 | self::TYPE_FORGOT => __('Forgot Password'), 88 | self::TYPE_CONTACT => __('Contact Us'), 89 | self::TYPE_EDITACCOUNT => __('Edit Account'), 90 | self::TYPE_PRODUCTREVIEW => __('Product Review'), 91 | ]; 92 | if ($this->_moduleManager->isEnabled('Mageplaza_SocialLogin')) { 93 | $labels[self::TYPE_SOCIAl_KEY] = __('Social Login Popup'); 94 | } 95 | 96 | if ($this->checkModuleEnable('Mageplaza_AgeVerification')) { 97 | $labels = array_merge($labels, [self::TYPE_AGEVERIFICATION => __('Age Verification')]); 98 | } 99 | 100 | return $labels; 101 | } 102 | 103 | /** 104 | * @return array 105 | */ 106 | public function defaultForms() 107 | { 108 | $forms = [ 109 | self::TYPE_LOGIN => 'customer/account/loginPost/', 110 | self::TYPE_CREATE => 'customer/account/createpost/', 111 | self::TYPE_FORGOT => 'customer/account/forgotpasswordpost/', 112 | self::TYPE_CONTACT => 'contact/index/post/', 113 | self::TYPE_EDITACCOUNT => 'customer/account/editPost/', 114 | self::TYPE_PRODUCTREVIEW => 'review/product/post/' 115 | ]; 116 | if ($this->checkModuleEnable('Mageplaza_AgeVerification')) { 117 | $forms = array_merge($forms, [self::TYPE_AGEVERIFICATION => '']); 118 | } 119 | 120 | return $forms; 121 | } 122 | 123 | /** 124 | * @param $moduleName 125 | * 126 | * @return bool 127 | */ 128 | public function checkModuleEnable($moduleName) 129 | { 130 | return $this->_moduleManager->isEnabled($moduleName); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Language.php: -------------------------------------------------------------------------------- 1 | __('-- Auto Detected --'), 'value' => 'en'], 39 | ['label' => __('Arabic'), 'value' => 'ar'], 40 | ['label' => __('Afrikaans'), 'value' => 'af'], 41 | ['label' => __('Amharic'), 'value' => 'am'], 42 | ['label' => __('Armenian'), 'value' => 'hy'], 43 | ['label' => __('Azerbaijani'), 'value' => 'az'], 44 | ['label' => __('Basque'), 'value' => 'eu'], 45 | ['label' => __('Bengali'), 'value' => 'bn'], 46 | ['label' => __('Bulgarian'), 'value' => 'bg'], 47 | ['label' => __('Catalan'), 'value' => 'ca'], 48 | ['label' => __('Chinese (Hong Kong)'), 'value' => 'zh-HK'], 49 | ['label' => __('Chinese (Simplified)'), 'value' => 'zh-CN'], 50 | ['label' => __('Chinese (Traditional)'), 'value' => 'zh-TW'], 51 | ['label' => __('Croatian'), 'value' => 'hr'], 52 | ['label' => __('Czech'), 'value' => 'cs'], 53 | ['label' => __('Danish'), 'value' => 'da'], 54 | ['label' => __('Dutch'), 'value' => 'nl'], 55 | ['label' => __('English (UK)'), 'value' => 'en-GB'], 56 | ['label' => __('English (US)'), 'value' => 'en'], 57 | ['label' => __('Estonian'), 'value' => 'et'], 58 | ['label' => __('Filipino'), 'value' => 'fil'], 59 | ['label' => __('Finnish'), 'value' => 'fi'], 60 | ['label' => __('French'), 'value' => 'fr'], 61 | ['label' => __('French (Canadian)'), 'value' => 'fr-CA'], 62 | ['label' => __('Galician'), 'value' => 'gl'], 63 | ['label' => __('Georgian'), 'value' => 'ka'], 64 | ['label' => __('German (Austria)'), 'value' => 'de-AT'], 65 | ['label' => __('German (Switzerland)'), 'value' => 'de-CH'], 66 | ['label' => __('Greek'), 'value' => 'el'], 67 | ['label' => __('Gujarati'), 'value' => 'gu'], 68 | ['label' => __('Hebrew'), 'value' => 'iw'], 69 | ['label' => __('Hindi'), 'value' => 'hi'], 70 | ['label' => __('Hungarain'), 'value' => 'hu'], 71 | ['label' => __('Icelandic'), 'value' => 'is'], 72 | ['label' => __('Indonesian'), 'value' => 'id'], 73 | ['label' => __('Italian'), 'value' => 'it'], 74 | ['label' => __('Japanese'), 'value' => 'ja'], 75 | ['label' => __('Kannada'), 'value' => 'kn'], 76 | ['label' => __('Korean'), 'value' => 'ko'], 77 | ['label' => __('Laothian'), 'value' => 'lo'], 78 | ['label' => __('Latvian'), 'value' => 'lv'], 79 | ['label' => __('Lithuanian'), 'value' => 'lt'], 80 | ['label' => __('Malay'), 'value' => 'ms'], 81 | ['label' => __('Malayalam'), 'value' => 'ml'], 82 | ['label' => __('Marathi'), 'value' => 'mr'], 83 | ['label' => __('Mongolian'), 'value' => 'mn'], 84 | ['label' => __('Norwegian'), 'value' => 'no'], 85 | ['label' => __('Persian'), 'value' => 'fa'], 86 | ['label' => __('Polish'), 'value' => 'pl'], 87 | ['label' => __('Portuguese'), 'value' => 'pt'], 88 | ['label' => __('Portuguese (Brazil)'), 'value' => 'pt-BR'], 89 | ['label' => __('Portuguese (Portugal)'), 'value' => 'pt-PT'], 90 | ['label' => __('Romanian'), 'value' => 'ro'], 91 | ['label' => __('Russian'), 'value' => 'ru'], 92 | ['label' => __('Serbian'), 'value' => 'sr'], 93 | ['label' => __('Sinhalese'), 'value' => 'si'], 94 | ['label' => __('Slovak'), 'value' => 'sk'], 95 | ['label' => __('Slovenian'), 'value' => 'sl'], 96 | ['label' => __('Spanish'), 'value' => 'es'], 97 | ['label' => __('Spanish (Latin America)'), 'value' => 'es-419'], 98 | ['label' => __('Swahili '), 'value' => 'sw'], 99 | ['label' => __('Swedish'), 'value' => 'sv'], 100 | ['label' => __('Tamil'), 'value' => 'ta'], 101 | ['label' => __('Telugu'), 'value' => 'te'], 102 | ['label' => __('Thai'), 'value' => 'th'], 103 | ['label' => __('Turkish'), 'value' => 'tr'], 104 | ['label' => __('Ukrainian'), 'value' => 'uk'], 105 | ['label' => __('Urdu'), 'value' => 'ur'], 106 | ['label' => __('Vietnamese'), 'value' => 'vi'], 107 | ['label' => __('Zulu'), 'value' => 'zu'], 108 | ]; 109 | 110 | return $languageOptionArray; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /i18n/en_US.csv: -------------------------------------------------------------------------------- 1 | "Disable backend captcha","Disable backend captcha" 2 | "The captcha is disable for your admin website.","The captcha is disable for your admin website." 3 | "The captcha backend has been successfully disabled. Please run the flush cache command again","The captcha backend has been successfully disabled. Please run the flush cache command again" 4 | "Enable backend captcha","Enable backend captcha" 5 | "The captcha is enabled for your admin website.","The captcha is enabled for your admin website." 6 | "The captcha backend has been successfully enabled. Please run the flush cache command again","The captcha backend has been successfully enabled. Please run the flush cache command again" 7 | "The response parameter is missing.","The response parameter is missing." 8 | "The request is invalid or malformed.","The request is invalid or malformed." 9 | "Admin Login","Admin Login" 10 | "Admin Forgot Password","Admin Forgot Password" 11 | Login,Login 12 | "Create User","Create User" 13 | "Forgot Password","Forgot Password" 14 | "Contact Us","Contact Us" 15 | "Edit Account","Edit Account" 16 | "Product Review","Product Review" 17 | "Age Verification","Age Verification" 18 | "-- Auto Detected --","-- Auto Detected --" 19 | Arabic,Arabic 20 | Afrikaans,Afrikaans 21 | Amharic,Amharic 22 | Armenian,Armenian 23 | Azerbaijani,Azerbaijani 24 | Basque,Basque 25 | Bengali,Bengali 26 | Bulgarian,Bulgarian 27 | Catalan,Catalan 28 | "Chinese (Hong Kong)","Chinese (Hong Kong)" 29 | "Chinese (Simplified)","Chinese (Simplified)" 30 | "Chinese (Traditional)","Chinese (Traditional)" 31 | Croatian,Croatian 32 | Czech,Czech 33 | Danish,Danish 34 | Dutch,Dutch 35 | "English (UK)","English (UK)" 36 | "English (US)","English (US)" 37 | Estonian,Estonian 38 | Filipino,Filipino 39 | Finnish,Finnish 40 | French,French 41 | "French (Canadian)","French (Canadian)" 42 | Galician,Galician 43 | Georgian,Georgian 44 | "German (Austria)","German (Austria)" 45 | "German (Switzerland)","German (Switzerland)" 46 | Greek,Greek 47 | Gujarati,Gujarati 48 | Hebrew,Hebrew 49 | Hindi,Hindi 50 | Hungarain,Hungarain 51 | Icelandic,Icelandic 52 | Indonesian,Indonesian 53 | Italian,Italian 54 | Japanese,Japanese 55 | Kannada,Kannada 56 | Korean,Korean 57 | Laothian,Laothian 58 | Latvian,Latvian 59 | Lithuanian,Lithuanian 60 | Malay,Malay 61 | Malayalam,Malayalam 62 | Marathi,Marathi 63 | Mongolian,Mongolian 64 | Norwegian,Norwegian 65 | Persian,Persian 66 | Polish,Polish 67 | Portuguese,Portuguese 68 | "Portuguese (Brazil)","Portuguese (Brazil)" 69 | "Portuguese (Portugal)","Portuguese (Portugal)" 70 | Romanian,Romanian 71 | Russian,Russian 72 | Serbian,Serbian 73 | Sinhalese,Sinhalese 74 | Slovak,Slovak 75 | Slovenian,Slovenian 76 | Spanish,Spanish 77 | "Spanish (Latin America)","Spanish (Latin America)" 78 | "Swahili ","Swahili " 79 | Swedish,Swedish 80 | Tamil,Tamil 81 | Telugu,Telugu 82 | Thai,Thai 83 | Turkish,Turkish 84 | Ukrainian,Ukrainian 85 | Urdu,Urdu 86 | Vietnamese,Vietnamese 87 | Zulu,Zulu 88 | "Bottom Right","Bottom Right" 89 | "Bottom Left","Bottom Left" 90 | Inline,Inline 91 | Visible,Visible 92 | Invisible,Invisible 93 | Compact,Compact 94 | Normal,Normal 95 | Dark,Dark 96 | Light,Light 97 | message,message 98 | "Missing required parameters recaptcha!","Missing required parameters recaptcha!" 99 | "Missing Url in ""Form Post Paths"" configuration field!","Missing Url in ""Form Post Paths"" configuration field!" 100 | "You need select captcha","You need select captcha" 101 | "Google Recaptcha","Google Recaptcha" 102 | General,General 103 | Enable,Enable 104 | "This extension is fully compatible with One Step Checkout.
105 | 1. Increase 25% conversion rate with Layered Navigation
106 | 2. Magento stores see upwards of 30% revenue 💰 with AVADA. Learn more","This extension is fully compatible with One Step Checkout.
107 | 1. Increase 25% conversion rate with Layered Navigation
108 | 2. Magento stores see upwards of 30% revenue 💰 with AVADA. Learn more" 109 | "Google API Key","Google API Key" 110 | "Create app here.","Create app here." 111 | "Google API Secret Key","Google API Secret Key" 112 | "Language Code","Language Code" 113 | "Backend Configuration","Backend Configuration" 114 | Forms,Forms 115 | Size,Size 116 | Theme,Theme 117 | "Frontend Configuration","Frontend Configuration" 118 | "Recaptcha Type","Recaptcha Type" 119 | "Badge Position","Badge Position" 120 | "Custom Form Position","Custom Form Position" 121 | "Form Post Paths","Form Post Paths" 122 | "For Example: newsletter/subscriber/new/

Compatible with Mageplaza SocialLogin:
123 | customer/ajax/login/
124 | sociallogin/popup/create/
125 | sociallogin/popup/forgot/
126 |
Each Url Post must be separated by a new line","For Example: newsletter/subscriber/new/

Compatible with Mageplaza SocialLogin:
127 | customer/ajax/login/
128 | sociallogin/popup/create/
129 | sociallogin/popup/forgot/
130 |
Each Url Post must be separated by a new line" 131 | "CSS Selectors","CSS Selectors" 132 | -------------------------------------------------------------------------------- /Observer/Captcha.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 97 | $this->_request = $request; 98 | $this->messageManager = $messageManager; 99 | $this->_actionFlag = $actionFlag; 100 | $this->_responseInterface = $responseInterface; 101 | $this->redirect = $redirect; 102 | $this->requestInterface = $requestInterface; 103 | } 104 | 105 | /** 106 | * @param Observer $observer 107 | * 108 | * @return array|void 109 | */ 110 | public function execute(Observer $observer) 111 | { 112 | if ($this->_helperData->isEnabled() && $this->_helperData->isCaptchaFrontend()) { 113 | $checkResponse = 1; 114 | $captcha = false; 115 | if ($this->_request->getFullActionName() === 'wishlist_index_add') { 116 | return; 117 | } 118 | foreach ($this->_helperData->getFormPostPaths() as $item) { 119 | if ($item !== '' && strpos($this->_request->getRequestUri(), trim($item, ' ')) !== false) { 120 | $checkResponse = 0; 121 | $captcha = $this->_request->getParam('g-recaptcha-response'); 122 | // case ajax login 123 | if ($item === 'customer/ajax/login' && !empty($captcha) && $this->_request->isAjax()) { 124 | $formData = HelperData::jsonDecode($this->requestInterface->getContent()); 125 | if (array_key_exists('g-recaptcha-response', $formData)) { 126 | $captcha = $formData['g-recaptcha-response']; 127 | } else { 128 | return $this->redirectUrlError(__('Missing required parameters recaptcha!')); 129 | } 130 | } 131 | if (!empty($captcha)) { 132 | $type = $this->_helperData->getRecaptchaType(); 133 | $response = $this->_helperData->verifyResponse($type); 134 | if (isset($response['success']) && !$response['success']) { 135 | $this->redirectUrlError($response['message']); 136 | } 137 | } else { 138 | $this->redirectUrlError(__('Missing required parameters recaptcha!')); 139 | } 140 | } 141 | } 142 | 143 | if ($checkResponse === 1 && $captcha !== false) { 144 | $this->redirectUrlError(__('Missing Url in "Form Post Paths" configuration field!')); 145 | } 146 | } 147 | } 148 | 149 | /** 150 | * @param string $message 151 | * 152 | * @return array 153 | */ 154 | public function redirectUrlError($message) 155 | { 156 | if (strpos($this->_request->getRequestUri(), 'customer/ajax/login') !== false 157 | || strpos($this->_request->getRequestUri(), 'sociallogin/popup/forgot') !== false 158 | ) { 159 | return [ 160 | 'errors' => true, 161 | 'message' => $message 162 | ]; 163 | } 164 | if (strpos($this->_request->getRequestUri(), 'sociallogin/popup/create') !== false) { 165 | return [ 166 | 'success' > false, 167 | 'message' => $message 168 | ]; 169 | } 170 | 171 | $this->messageManager->getMessages(true); 172 | $this->messageManager->addErrorMessage($message); 173 | $this->_actionFlag->set('', Action::FLAG_NO_DISPATCH, true); 174 | $this->_responseInterface->setRedirect($this->redirect->getRefererUrl()); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /Block/Captcha.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 85 | $this->_themeProvider = $themeProvider; 86 | 87 | parent::__construct($context, $data); 88 | } 89 | 90 | /** 91 | * @return string 92 | */ 93 | public function getForms() 94 | { 95 | $useLogin = false; 96 | $ageVerification = false; 97 | $this->_dataFormId = $this->_helperData->getFormsFrontend(); 98 | 99 | if ($this->_helperData->checkHyvaTheme()) { 100 | foreach ($this->_dataFormId as $item) { 101 | switch ($item) { 102 | case $this->actionName[0]: 103 | $this->_dataFormId[] = 'form#customer-login-form'; 104 | break; 105 | case $this->actionName[1]: 106 | $this->_dataFormId[] = 'form#accountcreate'; 107 | break; 108 | case $this->actionName[2]: 109 | $this->_dataFormId[] = 'form#user_forgotpassword'; 110 | break; 111 | case $this->actionName[3]: 112 | $this->_dataFormId[] = 'form#contact'; 113 | break; 114 | case $this->actionName[4]: 115 | $this->_dataFormId[] = 'form#review_form'; 116 | break; 117 | case $this->actionName[5]: 118 | $this->_dataFormId[] = 'form#form-validate'; 119 | break; 120 | default: 121 | break; 122 | } 123 | } 124 | } else { 125 | foreach ($this->_dataFormId as $item => $value) { 126 | switch ($value) { 127 | case Forms::TYPE_LOGIN: 128 | $actionName = $this->actionName[0]; 129 | $useLogin = true; 130 | break; 131 | case Forms::TYPE_CREATE: 132 | $actionName = $this->actionName[1]; 133 | break; 134 | case Forms::TYPE_FORGOT: 135 | $actionName = $this->actionName[2]; 136 | break; 137 | case Forms::TYPE_CONTACT: 138 | $actionName = $this->actionName[3]; 139 | break; 140 | case Forms::TYPE_PRODUCTREVIEW: 141 | $actionName = $this->actionName[4]; 142 | break; 143 | case Forms::TYPE_EDITACCOUNT: 144 | $actionName = $this->actionName[5]; 145 | break; 146 | default: 147 | $ageVerification = true; 148 | $actionName = ''; 149 | } 150 | $this->unsetDataFromId($item, $actionName); 151 | } 152 | } 153 | 154 | if ($useLogin) { 155 | if (!$this->_helperData->allowGuestCheckout()) { 156 | $this->_dataFormId[] = Forms::TYPE_FORMSEXTENDED[0]; 157 | } 158 | } 159 | 160 | if ($this->isAgeVerificationEnabled() && $ageVerification) { 161 | $this->_dataFormId[] = Forms::TYPE_AGEVERIFICATION; 162 | } 163 | 164 | $actionName = $this->_request->getFullActionName(); 165 | 166 | if ($actionName === $this->actionName[6]) { 167 | $this->_dataFormId[] = '.form.form-login'; 168 | } 169 | if ($actionName === $this->actionName[7]) { 170 | $this->_dataFormId[] = '#form-validate.form-create-account'; 171 | } 172 | if ($actionName === $this->actionName[8]) { 173 | $this->_dataFormId[] = Forms::TYPE_FORMSEXTENDED[1]; 174 | } 175 | $data = array_merge( 176 | $this->_helperData->getCssSelectors(), 177 | $this->_dataFormId 178 | ); 179 | if ($this->_helperData->isModuleOutputEnabled('Mageplaza_SocialLogin') 180 | && $isHaveSocialForm) { 181 | $data = array_merge( 182 | $data, 183 | Forms::TYPE_SOCIAl 184 | ); 185 | } 186 | 187 | return AbstractData::jsonEncode($data); 188 | } 189 | 190 | /** 191 | * @param $item 192 | * @param $text 193 | */ 194 | public function unsetDataFromId($item, $text) 195 | { 196 | if ($this->_request->getFullActionName() !== $text) { 197 | unset($this->_dataFormId[$item]); 198 | } 199 | } 200 | 201 | /** 202 | * @return mixed 203 | */ 204 | public function getInvisibleKey() 205 | { 206 | return $this->_helperData->getInvisibleKey(); 207 | } 208 | 209 | /** 210 | * @return mixed 211 | */ 212 | public function getVisibleKey() 213 | { 214 | return $this->_helperData->getVisibleKey(); 215 | } 216 | 217 | /** 218 | * @return array|mixed 219 | */ 220 | public function getPositionFrontend() 221 | { 222 | return $this->_helperData->getPositionFrontend(); 223 | } 224 | 225 | /** 226 | * @return array|mixed 227 | */ 228 | public function isCaptchaFrontend() 229 | { 230 | $storeId = $this->_storeManager->getStore()->getId(); 231 | return $this->_helperData->isCaptchaFrontend($storeId); 232 | } 233 | 234 | /** 235 | * @return mixed 236 | */ 237 | public function getLanguageCode() 238 | { 239 | return $this->_helperData->getLanguageCode(); 240 | } 241 | 242 | /** 243 | * @return array|mixed 244 | */ 245 | public function getThemeFrontend() 246 | { 247 | return $this->_helperData->getThemeFrontend(); 248 | } 249 | 250 | /** 251 | * @return array|mixed 252 | * @throws NoSuchEntityException 253 | */ 254 | public function getRecaptchaType() 255 | { 256 | return $this->_helperData->getRecaptchaType($this->getStoreId()); 257 | } 258 | 259 | /** 260 | * @param null $storeId 261 | * 262 | * @return array|mixed 263 | */ 264 | public function isAgeVerificationEnabled($storeId = null) 265 | { 266 | return $this->_helperData->isAgeVerificationEnabled($storeId); 267 | } 268 | 269 | /** 270 | * @return int 271 | * @throws NoSuchEntityException 272 | */ 273 | public function getStoreId() 274 | { 275 | return $this->_storeManager->getStore()->getId(); 276 | } 277 | 278 | /** 279 | * @return array|mixed 280 | */ 281 | public function getSize() 282 | { 283 | return $this->_helperData->getSizeFrontend(); 284 | } 285 | 286 | /** 287 | * @return string 288 | */ 289 | public function getCurrentTheme() 290 | { 291 | $themeId = $this->_helperData->getConfigValue(DesignInterface::XML_PATH_THEME_ID); 292 | 293 | /** 294 | * @var $theme ThemeInterface 295 | */ 296 | $theme = $this->_themeProvider->getThemeById($themeId); 297 | 298 | return $theme->getCode(); 299 | } 300 | } 301 | -------------------------------------------------------------------------------- /Helper/Data.php: -------------------------------------------------------------------------------- 1 | _curlFactory = $curlFactory; 79 | $this->_formPaths = $formPaths; 80 | $this->encryptor = $encryptor; 81 | 82 | parent::__construct($context, $objectManager, $storeManager); 83 | } 84 | 85 | /** 86 | * Backend 87 | */ 88 | 89 | /** 90 | * @param null $storeId 91 | * 92 | * @return mixed 93 | */ 94 | public function getVisibleKey($storeId = null) 95 | { 96 | return $this->encryptor->decrypt($this->getConfigGeneral('visible/api_key', $storeId)); 97 | } 98 | 99 | /** 100 | * @param null $storeId 101 | * 102 | * @return mixed 103 | */ 104 | public function getVisibleSecretKey($storeId = null) 105 | { 106 | return $this->encryptor->decrypt($this->getConfigGeneral('visible/api_secret', $storeId)); 107 | } 108 | 109 | /** 110 | * @param null $storeId 111 | * 112 | * @return mixed 113 | */ 114 | public function isCaptchaBackend($storeId = null) 115 | { 116 | if (!$this->isEnabled()) { 117 | return false; 118 | } 119 | 120 | return $this->getConfigBackend('enabled', $storeId); 121 | } 122 | 123 | /** 124 | * @param null $storeId 125 | * 126 | * @return array 127 | */ 128 | public function getFormsBackend($storeId = null) 129 | { 130 | $data = $this->getConfigBackend('forms', $storeId); 131 | 132 | return explode(',', $data); 133 | } 134 | 135 | /** 136 | * @param null $storeId 137 | * 138 | * @return mixed 139 | */ 140 | public function getSizeBackend($storeId = null) 141 | { 142 | return $this->getConfigBackend('size', $storeId); 143 | } 144 | 145 | /** 146 | * @param null $storeId 147 | * 148 | * @return mixed 149 | */ 150 | public function getThemeBackend($storeId = null) 151 | { 152 | return $this->getConfigBackend('theme', $storeId); 153 | } 154 | 155 | /** 156 | * @param string $code 157 | * @param null $storeId 158 | * 159 | * @return mixed 160 | */ 161 | public function getConfigBackend($code = '', $storeId = null) 162 | { 163 | $code = ($code !== '') ? '/' . $code : ''; 164 | 165 | return $this->getConfigValue(static::CONFIG_MODULE_PATH . static::BACKEND_CONFIGURATION . $code, $storeId); 166 | } 167 | 168 | /** 169 | * Frontend 170 | */ 171 | 172 | /** 173 | * @param string $code 174 | * @param null $storeId 175 | * 176 | * @return array|mixed 177 | */ 178 | public function getConfigFrontend($code = '', $storeId = null) 179 | { 180 | $code = ($code !== '') ? '/' . $code : ''; 181 | 182 | return $this->getConfigValue(static::CONFIG_MODULE_PATH . static::FRONTEND_CONFIGURATION . $code, $storeId); 183 | } 184 | 185 | /** 186 | * @param null $storeId 187 | * 188 | * @return array|mixed 189 | */ 190 | public function isCaptchaFrontend($storeId = null) 191 | { 192 | if (!$this->isEnabled()) { 193 | return false; 194 | } 195 | 196 | return $this->getConfigFrontend('enabled', $storeId); 197 | } 198 | 199 | /** 200 | * @param null $storeId 201 | * 202 | * @return array|mixed 203 | */ 204 | public function getPositionFrontend($storeId = null) 205 | { 206 | return $this->getConfigFrontend('position', $storeId); 207 | } 208 | 209 | /** 210 | * @param null $storeId 211 | * 212 | * @return array|mixed 213 | */ 214 | public function getThemeFrontend($storeId = null) 215 | { 216 | return $this->getConfigFrontend('theme', $storeId); 217 | } 218 | 219 | /** 220 | * @param null $storeId 221 | * 222 | * @return array 223 | */ 224 | public function getFormsFrontend($storeId = null) 225 | { 226 | $data = $this->getConfigFrontend('forms', $storeId); 227 | 228 | return explode(',', $data); 229 | } 230 | 231 | /** 232 | * @param null $storeId 233 | * 234 | * @return mixed 235 | */ 236 | public function getInvisibleKey($storeId = null) 237 | { 238 | return $this->encryptor->decrypt($this->getConfigGeneral('invisible/api_key', $storeId)); 239 | } 240 | 241 | /** 242 | * @param null $storeId 243 | * 244 | * @return mixed 245 | */ 246 | public function getInvisibleSecretKey($storeId = null) 247 | { 248 | return $this->encryptor->decrypt($this->getConfigGeneral('invisible/api_secret', $storeId)); 249 | } 250 | 251 | /** 252 | * @param null $storeId 253 | * 254 | * @return array|mixed 255 | */ 256 | public function getFormPostPaths($storeId = null) 257 | { 258 | $data = []; 259 | foreach ($this->_formPaths->defaultForms() as $key => $value) { 260 | if (in_array($key, $this->getFormsFrontend())) { 261 | $data[] = $value; 262 | } 263 | } 264 | $custom = explode("\n", str_replace("\r", '', $this->getConfigFrontend('custom/paths', $storeId) ?: '')); 265 | if (!$custom) { 266 | return $data; 267 | } 268 | 269 | return array_merge($data, $custom); 270 | } 271 | 272 | /** 273 | * @param null $storeId 274 | * 275 | * @return array|mixed 276 | */ 277 | public function getCssSelectors($storeId = null) 278 | { 279 | $data = $this->getConfigFrontend('custom/css', $storeId); 280 | $forms = explode("\n", str_replace("\r", '', $data ?: '')); 281 | foreach ($forms as $key => $value) { 282 | $forms[$key] = trim($value, ' '); 283 | } 284 | 285 | return $forms; 286 | } 287 | 288 | /** 289 | * @param null $storeId 290 | * 291 | * @return array|mixed 292 | */ 293 | public function allowGuestCheckout($storeId = null) 294 | { 295 | return $this->getConfigValue(CheckoutData::XML_PATH_GUEST_CHECKOUT, $storeId); 296 | } 297 | 298 | /** 299 | * @param null $storeId 300 | * 301 | * @return mixed 302 | */ 303 | public function getLanguageCode($storeId = null) 304 | { 305 | return $this->getConfigGeneral('language', $storeId); 306 | } 307 | 308 | /** 309 | * get reCAPTCHA server response 310 | * 311 | * @param null $end 312 | * @param null $recaptcha 313 | * 314 | * @return array 315 | */ 316 | public function verifyResponse($end = null, $recaptcha = null) 317 | { 318 | $result['success'] = false; 319 | $recaptcha = $recaptcha ?: $this->_request->getParam('g-recaptcha-response'); 320 | if (empty($recaptcha)) { 321 | $result['message'] = __('The response parameter is missing.'); 322 | 323 | return $result; 324 | } 325 | try { 326 | $recaptchaClass = new ReCaptcha($end === 'visible' ? $this->getVisibleSecretKey() : $this->getInvisibleSecretKey()); 327 | $resp = $recaptchaClass->verify($recaptcha, $this->_request->getClientIp()); 328 | if ($resp && $resp->isSuccess()) { 329 | $result['success'] = true; 330 | } else { 331 | $result['message'] = __('The request is invalid or malformed.'); 332 | } 333 | } catch (Exception $e) { 334 | $result['message'] = $e->getMessage(); 335 | } 336 | 337 | return $result; 338 | } 339 | 340 | /** 341 | * @param null $storeId 342 | * 343 | * @return array|mixed 344 | */ 345 | public function getRecaptchaType($storeId = null) 346 | { 347 | return $this->getConfigFrontend('type', $storeId); 348 | } 349 | 350 | /** 351 | * @param null $storeId 352 | * 353 | * @return array|mixed 354 | */ 355 | public function isAgeVerificationEnabled($storeId = null) 356 | { 357 | return $this->getConfigValue('mpageverify/general/enabled', $storeId); 358 | } 359 | 360 | /** 361 | * @param $storeId 362 | * 363 | * @return array|mixed 364 | */ 365 | public function getSizeFrontend($storeId = null) 366 | { 367 | return $this->getConfigFrontend('size', $storeId); 368 | } 369 | 370 | /** 371 | * @param null $storeId 372 | */ 373 | public function isSocialLoginEnabled($storeId = null) 374 | { 375 | return $this->getConfigValue('sociallogin/general/enabled', $storeId); 376 | } 377 | } 378 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 25 |
26 | separator-top 27 | 28 | mageplaza 29 | Mageplaza_GoogleRecaptcha::configuration 30 | 31 | 32 | 33 | 34 | Magento\Config\Model\Config\Source\Yesno 35 | One Step Checkout.
36 | 1. Increase 25% conversion rate with Layered Navigation
37 | 2. Magento stores see upwards of 30% revenue 💰 with AVADA. Learn more]]>
38 |
39 | 40 | 41 | 42 | 43 | Magento\Config\Model\Config\Backend\Encrypted 44 | here.]]> 45 | 46 | 47 | 48 | Magento\Config\Model\Config\Backend\Encrypted 49 | 50 | 51 | 52 | 53 | 54 | 55 | Magento\Config\Model\Config\Backend\Encrypted 56 | here.]]> 57 | 58 | 59 | 60 | Magento\Config\Model\Config\Backend\Encrypted 61 | 62 | 63 | 64 | 65 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Language 66 | 67 |
68 | 69 | 70 | 71 | 72 | Magento\Config\Model\Config\Source\Yesno 73 | 74 | 75 | 76 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Forms 77 | 78 | 1 79 | 80 | 81 | 82 | 83 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Size 84 | 85 | 1 86 | 87 | 88 | 89 | 90 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Theme 91 | 92 | 1 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | Magento\Config\Model\Config\Source\Yesno 101 | 102 | 103 | 104 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\RecaptchaType 105 | 106 | 1 107 | 108 | 109 | 110 | 111 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Position 112 | 113 | 1 114 | invisible 115 | 116 | 117 | 118 | 119 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Size 120 | 121 | 1 122 | visible 123 | 124 | 125 | 126 | 127 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Theme 128 | 129 | 1 130 | 131 | 132 | 133 | 134 | Mageplaza\GoogleRecaptcha\Model\System\Config\Source\Frontend\Forms 135 | 136 | 1 137 | 138 | 139 | 140 | 141 | 142 | 143 |
Compatible with Mageplaza SocialLogin:
144 | customer/ajax/login/
145 | sociallogin/popup/create/
146 | sociallogin/popup/forgot/
147 |
Each Url Post must be separated by a new line]]>
148 |
149 | 150 | 151 |
Compatible with Mageplaza SocialLogin:
#social-form-login
152 | #social-form-create
#social-form-password-forget

Compatible with Mageplaza OSC:
.onestepcheckout-index-index .block-content .form.form-login

Each CSS Selector must be separated by a new line]]>
153 |
154 | 155 | 1 156 | 157 |
158 |
159 |
160 |
161 |
162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Magento 2 Google reCAPTCHA Free Extension 2 | 3 | **Magento 2 Google reCAPTCHA** keeps abusive activities away. By creating a human-friendly shield, bots will be not allowed to access your admin panel and your store, while humans can pass through with ease. 4 | 5 | [![Latest Stable Version](https://poser.pugx.org/mageplaza/module-google-recaptcha/v/stable)](https://packagist.org/packages/mageplaza/module-google-recaptcha) 6 | [![Total Downloads](https://poser.pugx.org/mageplaza/module-google-recaptcha/downloads)](https://packagist.org/packages/mageplaza/module-google-recaptcha) 7 | 8 | 9 | * Add **Invisible CAPTCHA** to all forms on the frontend 10 | * Add **Visible CAPTCHA** to **the backend** *(Featured)* 11 | * Works on **any kinds of forms** *(Featured)* 12 | * Compatible with [Mageplaza extensions](https://www.mageplaza.com/magento-2-extensions/) 13 | 14 | ![google recaptcha](https://i.imgur.com/bmMVYO3.gif) 15 | 16 | **IMPORTANT NOTE:** This version of Mageplaza Google reCAPTCHA extension on Github is free as a contribution to the Magento community from Mageplaza. This package does not include the technical support. Should you need technical support for this extension, you will have to buy a license from Mageplaza. [Click here to buy](https://www.mageplaza.com/magento-2-google-recaptcha/). 17 | 18 | ## 1. Documentation 19 | 20 | - [Installation guide](https://www.mageplaza.com/install-magento-2-extension/) 21 | - [User guide](https://docs.mageplaza.com/google-recaptcha/index.html) 22 | - [Introduction page](http://www.mageplaza.com/magento-2-google-recaptcha/) 23 | - [Contribute on Github](https://github.com/mageplaza/magento-2-google-recaptcha) 24 | - [Get Support](https://github.com/mageplaza/magento-2-google-recaptcha/issues) 25 | 26 | ## 2. FAQs 27 | 28 | **Q: I got error: Mageplaza_Core has been already defined** 29 | 30 | A: Read solution [here](https://github.com/mageplaza/module-core/issues/3) 31 | 32 | **Q: What types of forms that Google reCAPTCHA can be displayed on?** 33 | 34 | A: There are 6 forms which can be selected to display reCAPTCHA on frontend: Login, Forget password, Change password, Product review, Contact us and Registration form. However, admins can insert URL paths and CSS selectors to display reCAPTCHA on any forms they want. 35 | 36 | **Q: What types of CAPTCHA that your module is applying?** 37 | 38 | A: reCAPTCHA v2 and invisible CAPTCHA are integrated in Magento 2 Google reCAPTCHA. 39 | 40 | **Q: Where in a form can I display reCAPTCHA?** 41 | 42 | A: You can display reCAPTCHA on the Bottom left, Bottom right and Inline. 43 | 44 | **Q: Can I change the language of reCAPTCHA?** 45 | 46 | A: Yes, you can choose a language code to display reCAPTCHA on the backend. 47 | 48 | ## 3. How to install Magento 2 Google reCAPTCHA extension 49 | 50 | Run the following command in Magento 2 root folder: 51 | 52 | With Marketing Automation (recommend): 53 | 54 | ``` 55 | composer require mageplaza/module-google-recaptcha mageplaza/module-smtp 56 | php bin/magento setup:upgrade 57 | php bin/magento setup:static-content:deploy 58 | ``` 59 | 60 | Without Marketing Automation: 61 | ``` 62 | composer require mageplaza/module-google-recaptcha 63 | php bin/magento setup:upgrade 64 | php bin/magento setup:static-content:deploy 65 | ``` 66 | 67 | ## 4. Google reCAPTCHA highlight features 68 | 69 | ### Invisible reCAPTCHA 70 | 71 | **Mageplaza Google reCAPTCHA extension** integrates **invisible reCAPTCHA** which allows humans to pass through the protection with ease, yet it stops bots from abusive activities. 72 | 73 | There is no CAPTCHA box within the form’s area, invisible CAPTCHA appears on the right/left bottom of the page which ensures not to distract the user. Invisible CAPTCHA will only popped up if any abusive activities from bots are found, and let humans go through without any interruption. 74 | 75 | ### Add Google reCAPTCHAs to any forms 76 | 77 | There’s no limit to add reCAPTCHAs to any kinds of form on the frontend. Admins can either select available forms or insert URL paths/CSS selectors to display reCAPTCHAs to anywhere they want. There are 6 forms which are available to select with ease: 78 | 79 | * Login form 80 | * Registration form 81 | * Forgot password form 82 | * Contact us 83 | * Change password 84 | * Product review 85 | 86 | ### Backend reCAPTCHAs 87 | 88 | **Magento 2 Google reCAPTCHA** also allows **adding CAPTCHA to the backend** in two forms: 89 | 90 | * Admin Login 91 | * Admin Forgot Password 92 | 93 | ![backend captchas](https://i.imgur.com/0ZTFv2i.png) 94 | 95 | ## 5. More features 96 | 97 | ### Customize reCaptcha forms 98 | 99 | Set no limit to which forms to display **Google reCAPTCHA** by inserting URL post paths and CSS selectors. 100 | 101 | ### Compatibility 102 | **Google reCaptcha for Magento 2** is highly compatible with other extensions: Mageplaza Blog, Mageplaza Security, Mageplaza Social Login, Mageplaza Gift Card, Mageplaza One Step Checkout. 103 | 104 | ### Badge positions 105 | **Google reCAPTCHAs** can be displayed right in the form or on the bottom left or on the bottom right of the page 106 | 107 | ### Multi-language CAPTCHAs 108 | Add a language code to change the language of reCAPTCHAs. 109 | 110 | ## 6. Full Magento 2 Google ReCaptcha feature list 111 | 112 | ### For admins 113 | * Turn on/off module 114 | * Change reCAPTCHAs’ language 115 | * Invisible reCAPTCHAs are added to all forms on the frontend 116 | * Visible CAPTCHAs are added to the backend 117 | * CAPTCHA is added to the admin login form 118 | * CAPTCHA is added to the admin’s forgot-password form 119 | * Turn on/off reCAPTCHAs on the frontend 120 | * Be able to add CAPTCHAs to all kinds of forms on the frontend 121 | * Be able to add CAPTCHAs at 3 positions: inline, right bottom and left bottom 122 | * Be able to select themes and sizes for CAPTCHAs 123 | * Compatible with Mageplaza extensions: Blog, Security, Social Login, Gift Card, One Step Checkout. 124 | 125 | ### For users 126 | 127 | * Invisible CAPTCHAs: users are not disrupted by visible reCAPTCHAs. Humans pass through easily while bots are not allowed to access. 128 | 129 | ## 7. How to configure Google Recaptcha extension 130 | 131 | ![How to configure Google Recaptcha extension](https://i.imgur.com/XhPOWBt.png) 132 | 133 | ### Configuration 134 | 135 | #### General configuration 136 | 137 | ![general configuration](https://i.imgur.com/uZV1gjS.png) 138 | 139 | * **Enable**: Choose Yes to turn the module on 140 | * **Language Code** : Select a language to display Google reCAPTCHAs on frontend. 141 | 142 | - In the **Invisible** field: 143 | 144 | ``Note``: Invisible CAPTCHAs are implemented to the frontend only 145 | 146 | * **Google API Key**: Enter the Google API Key 147 | * **Google API Secret Key**: Enter the Secret Key 148 | * **How to create reCAPTCHA**: See how to add Google reCAPTCHAs [here](https://www.mageplaza.com/blog/how-to-add-google-recaptcha-into-magento-2.html) 149 | 150 | - In the **Visible** field: 151 | 152 | ``Note``: Visible CAPTCHAs are implemented to the backend only 153 | 154 | * **Google API Key**: Enter the Google API Key for reCAPTCHAs 155 | * **Google API Secret Key**: Enter the API Secret Key 156 | * **How to create reCAPTCHA**: See how to create Google reCAPTCHA here 157 | 158 | #### Backend Configuration 159 | 160 | ![backend configuration](https://i.imgur.com/5Lq6eSI.png) 161 | 162 | * **Enable**: Select Yes to allow Google reCAPTCHA to work on the backend 163 | * **Forms**: Select one or two forms to which are implemented Google reCAPTCHAs: 164 | * **Forms = Admin Login**: when admins log in to the admin panel, visible reCAPTCHAs will be activated 165 | * **Forms = Admin Forgot Password**: when admins click on Forgot password to reset it, Google reCAPTCHA is displayed 166 | 167 | * **Size**: Select how to display Google reCAPTCHA 168 | 169 | ![How to configure Magento 2 Google Recaptcha](https://i.imgur.com/fnSovK5.png) 170 | 171 | * Size = Compact: When Compact is selected, Google reCAPTCHA is displayed as below 172 | 173 | ![size 2](https://i.imgur.com/lPqlIUc.png) 174 | 175 | * Size = Normal: if Normal is selected, Google reCAPTCHA is shown as below: 176 | 177 | ![size 3](https://i.imgur.com/tcSLJEq.png) 178 | 179 | * **Theme** 180 | 181 | ![theme](https://i.imgur.com/nJZr4Ha.png) 182 | 183 | * **Theme = Light**: The light color is applied for reCAPTCHA 184 | * **Theme = Dark**: The dark color is applied for reCAPTCHA 185 | 186 | #### Frontend Configuration 187 | 188 | ![frontend configuration](https://i.imgur.com/9Os1kit.png) 189 | 190 | * **Enable**: Select Yes to turn on invisible reCAPTCHA on the frontend 191 | * **Forms**: Admins can select one or some forms to implement reCAPTCHAs to 192 | * **Forms = Login**: when visitors log in to the page 193 | * **Forms = Create User**: when visitors fill in the registration form 194 | * **Forms = Forgot Password**: when visitors forget their passwords and fill in the Forget-password form 195 | * **Forms = Contact Us**: when visitors fill in the Contact Us form 196 | * **Forms = Change Password**: when visitors fill a form to change password 197 | * **Forms = Product Review**: when visitors visit a product page to leave a product review 198 | 199 | * **Badge Position** 200 | 201 | ![badge position](https://i.imgur.com/NNUWZLj.png) 202 | 203 | * **Badge Position = Inline**: display reCAPTCHA in selected forms 204 | * **Badge Position = Bottom Right**: display reCAPTCHA on the bottom right of the page 205 | * **Badge Position = Bottom Left**: display reCAPTCHA the bottom left of the page 206 | 207 | * **Theme** 208 | 209 | ![theme 2](https://i.imgur.com/bLmnEkB.png) 210 | 211 | * **Theme = Light**: The light color is applied for reCAPTCHA 212 | * **Theme = Dark**: The dark color is applied for reCAPTCHA 213 | 214 | * **Custom Form Position**: display reCAPTCHA to any kinds of forms 215 | 216 | ![custom form position](https://i.imgur.com/eWjgErF.png) 217 | 218 | 219 | * **Form Post Paths** 220 | 221 | * Enter the path (url) where will process your form information 222 | 223 | * For example: newsletter/subscriber/new/, display reCAPTCHA in the email address field on the website. 224 | 225 | * **Below are some detailed steps**: 226 | 227 | - **Step 1**: Log in to your website 228 | - **Step 2**: Choose Form that you want to display reCAPTCHA and open the Test window 229 | - **Step 3**: After that, choose Element tab, then choose the form that contains the field you want to add reCAPTCHA 230 | 231 | ![example](https://i.imgur.com/IqaJHxq.png) 232 | 233 | - **Step 4**: In the Subscriber Form in the Action field, copy the URL path. (In this example, the URL is "newsletter/subscriber/new/") 234 | - **Step 5**: Paste the URL into the Form Post Paths field 235 | * The paths are separated by downstream. 236 | * If you this field is empty and you fill in the information in the CSS Selectors field, reCAPTCHA is still displayed on the form that you fill in the CSS Selectors field, but it still doesn’t work on that form. 237 | 238 | ![example 2](https://i.imgur.com/SiWJCdB.png) 239 | 240 | * **CSS Selectors** 241 | * You need to take CSS Selector of the form. At our example, we will take ID of the form. 242 | 243 | * For example: #newsletter-validate-detail, display reCAPTCHA in the Subscriber 244 | 245 | ![example 3](https://i.imgur.com/dfrLQnR.png) 246 | 247 | * The IDs should be separated by downstream. 248 | * If you leave this field empty while filling in the information in Form Post Paths field, reCAPTCHA won't be displayed on the form you want. 249 | 250 | ``Note``: 251 | 252 | * To display Google reCAPTCHAs in a custom form, you have to fill in two fields: Form Post Paths and CSS Selectors. 253 | * If you are not able to access to the backend while reCAPTCHA is enabled, you can use the following command to disable the module via composer. After that, you can access the admin panel again. 254 | 255 | `php bin/magento module:disable Mageplaza_Recaptcha` 256 | 257 | Or, use this command below to disable the configuration: 258 | 259 | `php bin/magento mageplaza:core:disable Mageplaza_Recaptcha` 260 | 261 | #### How Google reCAPTCHA is displayed on the Magento 2 frontend 262 | 263 | ![the display on the frontend](https://i.imgur.com/rMoqd2v.png) 264 | 265 | ![display on frontend 1](https://i.imgur.com/9i3SkDQ.png) 266 | 267 | #### How Google reCAPTCHA is displayed in the Magento 2 backend 268 | 269 | ![the display in the backend](https://i.imgur.com/91H3ERd.png) 270 | 271 | 272 | **People also search:** 273 | - mageplaza google recaptcha 274 | - magento 2 recaptcha 275 | - google recaptcha magento 2 276 | - magento 2 invisible recaptcha 277 | - google captcha magento 2 278 | - magento 2 recaptcha extension 279 | - recaptcha magento 2 280 | - magento 2 google captcha 281 | - magento 2 captcha extension free 282 | - google invisible recaptcha magento 2 283 | - invisible recaptcha magento 2 284 | - magento 2 recaptcha v3 285 | - magento 2 google invisible recaptcha 286 | - recaptcha v3 magento 2 287 | 288 | 289 | **Other free extension on Github** 290 | - [Magento 2 SEO](https://github.com/mageplaza/magento-2-seo) 291 | - [Magento 2 Google Maps](https://github.com/mageplaza/magento-2-google-maps) 292 | - [Magento 2 Blog](https://github.com/mageplaza/magento-2-blog) 293 | - [Magento 2.x GDPR compliance](https://github.com/mageplaza/magento-2-gdpr) 294 | - [Magento 2 social login](https://github.com/mageplaza/magento-2-social-login) 295 | - [Magento 2 Same Order Number](https://github.com/mageplaza/magento-2-same-order-number) 296 | - [Magento 2 Layered Navigation](https://github.com/mageplaza/magento-2-ajax-layered-navigation) 297 | - [Magento 2 security](https://github.com/mageplaza/magento-2-security) 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | -------------------------------------------------------------------------------- /view/frontend/templates/hyva/captcha.phtml: -------------------------------------------------------------------------------- 1 | isCaptchaFrontend()): ?> 25 | getCurrentTheme(); 27 | $key = $block->getInvisibleKey(); 28 | $recaptchaType = $block->getRecaptchaType(); 29 | if ($recaptchaType === 'visible') { 30 | $key = $block->getVisibleKey(); 31 | } 32 | ?> 33 | 75 |
76 | 389 | 390 | -------------------------------------------------------------------------------- /view/frontend/web/js/captcha.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Mageplaza 3 | * 4 | * NOTICE OF LICENSE 5 | * 6 | * This source file is subject to the Mageplaza.com license that is 7 | * available through the world-wide-web at this URL: 8 | * https://www.mageplaza.com/LICENSE.txt 9 | * 10 | * DISCLAIMER 11 | * 12 | * Do not edit or add to this file if you wish to upgrade this extension to newer 13 | * version in the future. 14 | * 15 | * @category Mageplaza 16 | * @package Mageplaza_GoogleRecaptcha 17 | * @copyright Copyright (c) Mageplaza (https://www.mageplaza.com/) 18 | * @license https://www.mageplaza.com/LICENSE.txt 19 | */ 20 | 21 | define([ 22 | 'jquery', 23 | 'mage/translate' 24 | ], function ($,$t) { 25 | 'use strict'; 26 | 27 | $.widget('mageplaza.captcha', { 28 | options: { 29 | key: "", 30 | language: "en", 31 | position: "inline", 32 | theme: "light", 33 | forms: [], 34 | type: "" 35 | }, 36 | captchaForm: [], 37 | activeForm: [], 38 | stopSubmit: false, 39 | 40 | /** 41 | * This method constructs a new widget. 42 | * @private 43 | */ 44 | _create: function () { 45 | var self = this, 46 | stop = 0; 47 | 48 | $(function () { 49 | var ID = setInterval(function () { 50 | if (stop === 0) { 51 | stop++; 52 | self.createCaptcha(); 53 | } 54 | clearInterval(ID); 55 | }, 1500); 56 | }); 57 | }, 58 | 59 | /** 60 | * Init Create reCaptcha 61 | */ 62 | createCaptcha: function () { 63 | var self = this, 64 | widgetIDCaptcha, 65 | sortEvent, 66 | number = 0, 67 | resetForm = 0; 68 | 69 | window.recaptchaOnload = function () { 70 | //get form active 71 | var forms = self.options.forms, 72 | result = false; 73 | 74 | if (forms && forms.length > 0) { 75 | forms.forEach(function (element) { 76 | if (element === '.onestepcheckout-index-index .block-content .form.form-login') { 77 | var checkOSC = setInterval(function () { 78 | if ($(element).length === 2) { 79 | $(element).last().attr('id', 'Osccaptcha'); 80 | result = true; 81 | self.processOscCaptcha(result, '#Osccaptcha'); 82 | clearInterval(checkOSC); 83 | } 84 | }, 100); 85 | 86 | } else if (element !== '' 87 | && $(element).length > 0 88 | && $(element).prop("tagName").toLowerCase() === 'form') { 89 | self.activeForm.push(element); 90 | result = true; 91 | } else if (element === '.opc-wrapper.one-step-checkout-wrapper' && $(element).length > 0) { 92 | self.activeForm.push(element); 93 | result = true; 94 | } 95 | }); 96 | } 97 | if (result) { 98 | forms = self.activeForm; 99 | forms.forEach(function (value) { 100 | var element = $(value); 101 | 102 | //Multi ID 103 | if (element.length > 1) { 104 | element = $(element).first(); 105 | } 106 | 107 | /** 108 | * Create Widget 109 | */ 110 | var buttonElement = element.find('button[type=button]').length > 0 ? element.find('button[type=button]') : element.find('button[type=submit]'); 111 | var divCaptcha = $('
'); 112 | var divAction = $('.actions-toolbar'); 113 | var divError = $('
'); 114 | var checkBox = $(''); 115 | 116 | divError.text($t('You need select captcha')).attr('style', 'display:none;color:red'); 117 | divCaptcha.attr('id', 'mp' + '_recaptcha_' + number); 118 | checkBox.attr('name', 'mp' + '_recaptcha_' + number); 119 | 120 | 121 | if (self.options.type === 'visible') { 122 | if (element.attr('id') === 'mpageverify-form') { 123 | element.find('.mpageverify-verify-action').before(divCaptcha).before(checkBox).before(divError); 124 | } else { 125 | element.find(divAction).first().before(divCaptcha).before(divError); 126 | } 127 | element.find(divAction).first().before(checkBox); 128 | } else { 129 | element.append(divCaptcha); 130 | } 131 | 132 | var target = 'mp' + '_recaptcha_' + number, 133 | parameters = { 134 | 'sitekey': self.options.key, 135 | 'size': 'invisible', 136 | 'callback': function (token) { 137 | if (token) { 138 | if (self.options.type === 'visible') { 139 | var name = element.find('.g-recaptcha').attr('id'); 140 | 141 | $("input[name='" + name + "']").prop('checked', true); 142 | } else { 143 | self.stopSubmit = token; 144 | 145 | if (value === '#social-form-login' 146 | || value === '#social-form-create' 147 | || value === '#social-form-password-forget' 148 | || value === '.popup-authentication #login-form.form.form-login' 149 | || value === '.opc-wrapper.one-step-checkout-wrapper' 150 | || (value === '#review-form' && self.options.type === 'invisible') 151 | ) { 152 | buttonElement.trigger('click'); 153 | } else { 154 | element.submit(); 155 | } 156 | } 157 | } else { 158 | grecaptcha.reset(resetForm); 159 | resetForm = 0; 160 | } 161 | }, 162 | 'expired-callback': function () { 163 | if (self.options.type === 'visible') { 164 | var name = element.find('.g-recaptcha').attr('id'); 165 | 166 | $("input[name='" + name + "']").prop('checked', false); 167 | } 168 | }, 169 | 'theme': self.options.theme, 170 | 'badge': self.options.position, 171 | 'hl': self.options.language 172 | }; 173 | 174 | if (self.options.type === 'visible') { 175 | parameters.size = self.options.size; 176 | } 177 | widgetIDCaptcha = grecaptcha.render(target, parameters); 178 | self.captchaForm[widgetIDCaptcha] = target; 179 | number++; 180 | 181 | /** 182 | * Check form submit 183 | */ 184 | if (self.options.type !== 'visible') { 185 | if (value === '#social-form-login' 186 | || value === '#social-form-create' 187 | || value === '#social-form-password-forget' 188 | || value === '.popup-authentication #login-form.form.form-login' 189 | || value === '.opc-wrapper.one-step-checkout-wrapper' 190 | || (value === '#review-form' && self.options.type === 'invisible') 191 | ) { 192 | if (value === '.opc-wrapper.one-step-checkout-wrapper') { 193 | $('button.checkout').on('click', function (event) { 194 | if (!self.stopSubmit) { 195 | $.each(self.captchaForm, function (form, value) { 196 | if (element.find('#' + value).length > 0) { 197 | grecaptcha.reset(form); 198 | grecaptcha.execute(form); 199 | resetForm = form; 200 | event.preventDefault(event); 201 | event.stopImmediatePropagation(); 202 | 203 | return false; 204 | } 205 | }); 206 | } 207 | }); 208 | } 209 | buttonElement.on('click', function (event) { 210 | if (!(element.validation() && element.validation('isValid'))) { 211 | return; 212 | } 213 | 214 | if (!self.stopSubmit) { 215 | $.each(self.captchaForm, function (form, value) { 216 | if (element.find('#' + value).length > 0) { 217 | grecaptcha.reset(form); 218 | grecaptcha.execute(form); 219 | resetForm = form; 220 | event.preventDefault(event); 221 | event.stopImmediatePropagation(); 222 | 223 | return false; 224 | } 225 | }); 226 | } 227 | }); 228 | 229 | sortEvent = $._data(buttonElement[0], 'events').click; 230 | sortEvent.unshift(sortEvent.pop()); 231 | 232 | } else { 233 | element.submit(function (event) { 234 | if (!self.stopSubmit) { 235 | $.each(self.captchaForm, function (form, value) { 236 | if (element.find('#' + value).length > 0) { 237 | grecaptcha.reset(form); 238 | grecaptcha.execute(form); 239 | resetForm = form; 240 | event.preventDefault(event); 241 | event.stopImmediatePropagation(); 242 | 243 | return false; 244 | } 245 | }); 246 | } 247 | }); 248 | sortEvent = $._data(element[0], 'events').submit; 249 | sortEvent.unshift(sortEvent.pop()); 250 | } 251 | } else { 252 | if (value === '#social-form-login' 253 | || value === '#social-form-create' 254 | || value === '#social-form-password-forget' 255 | || value === '.popup-authentication #login-form.form.form-login' 256 | ) { 257 | buttonElement.on('click', function (event) { 258 | var name = element.find('.g-recaptcha').attr('id'); 259 | var check = $("input[name='" + name + "']").prop('checked'); 260 | 261 | if (!(element.validation() && element.validation('isValid')) && check === false) { 262 | $.each(self.captchaForm, function (form, value) { 263 | if (element.find('#' + value).length > 0) { 264 | self.showMessage(divError, 5000); 265 | grecaptcha.reset(form); 266 | event.preventDefault(event); 267 | event.stopImmediatePropagation(); 268 | } 269 | }); 270 | } 271 | }); 272 | } else { 273 | element.submit(function (event) { 274 | var name = element.find('.g-recaptcha').attr('id'), 275 | buttonSubmit = element.find('button.submit'); 276 | var check = $("input[name='" + name + "']").prop('checked'); 277 | 278 | if (check === false) { 279 | $.each(self.captchaForm, function (form, value) { 280 | if (element.find('#' + value).length > 0) { 281 | self.showMessage(divError, 5000); 282 | buttonSubmit.removeAttr('disabled'); 283 | grecaptcha.reset(form); 284 | event.preventDefault(event); 285 | event.stopImmediatePropagation(); 286 | } 287 | }); 288 | } 289 | }); 290 | } 291 | } 292 | }); 293 | 294 | for (var i = 1; i < number; i++){ 295 | var badge = $('#mp_recaptcha_' + i + ' .grecaptcha-badge'); 296 | 297 | badge.removeAttr("style"); 298 | badge.attr("style", $('#mp_recaptcha_0 .grecaptcha-badge').attr("style")); 299 | } 300 | } 301 | }; 302 | require(['//www.google.com/recaptcha/api.js?onload=recaptchaOnload&render=explicit']); 303 | }, 304 | 305 | /** 306 | * compatible with form OSC 307 | */ 308 | processOscCaptcha: function (result, value) { 309 | var self = this, 310 | widgetIDCaptcha, 311 | sortEvent, 312 | resetForm = 0; 313 | 314 | if (result) { 315 | var element = $(value); 316 | 317 | /** 318 | * Create Widget 319 | */ 320 | var buttonElement = element.find('button[type=button]').length > 0 ? element.find('button[type=button]') : element.find('button[type=submit]'); 321 | var divCaptcha = $('
'); 322 | var divAction = $('.actions-toolbar'); 323 | var divError = $('
'); 324 | var checkBox = $(''); 325 | divError.text('You need select captcha').attr('style', 'display:none;color:red'); 326 | divCaptcha.attr('id', 'mp' + '_recaptcha_' + 'osc'); 327 | checkBox.attr('name', 'mp' + '_recaptcha_' + 'osc'); 328 | 329 | 330 | if (self.options.type === 'visible') { 331 | element.find(divAction).before(divCaptcha).before(divError); 332 | element.find(divAction).first().before(checkBox); 333 | } else { 334 | element.append(divCaptcha); 335 | } 336 | 337 | var target = 'mp' + '_recaptcha_' + 'osc', 338 | parameters = { 339 | 'sitekey': self.options.key, 340 | 'size': 'invisible', 341 | 'callback': function (token) { 342 | if (token) { 343 | if (self.options.type === 'visible') { 344 | var name = element.find('.g-recaptcha').attr('id'); 345 | $("input[name='" + name + "']").prop('checked', true); 346 | } else { 347 | self.stopSubmit = token; 348 | buttonElement.trigger('click'); 349 | } 350 | } else { 351 | grecaptcha.reset(resetForm); 352 | } 353 | }, 354 | 'expired-callback': function () { 355 | if (self.options.type === 'visible') { 356 | var name = element.find('.g-recaptcha').attr('id'); 357 | $("input[name='" + name + "']").prop('checked', false); 358 | } 359 | }, 360 | 'theme': self.options.theme, 361 | 'badge': self.options.position, 362 | 'hl': self.options.language 363 | }; 364 | 365 | if (self.options.type === 'visible') { 366 | parameters.size = self.options.size; 367 | } 368 | widgetIDCaptcha = grecaptcha.render(target, parameters); 369 | self.captchaForm[widgetIDCaptcha] = target; 370 | 371 | 372 | /** 373 | * Check form submit 374 | */ 375 | if (self.options.type !== 'visible') { 376 | buttonElement.on('click', function (event) { 377 | if (!(element.validation() && element.validation('isValid'))) { 378 | return; 379 | } 380 | if (!self.stopSubmit) { 381 | $.each(self.captchaForm, function (form, value) { 382 | if (element.find('#' + value).length > 0) { 383 | grecaptcha.reset(form); 384 | grecaptcha.execute(form); 385 | resetForm = form; 386 | event.preventDefault(event); 387 | event.stopImmediatePropagation(); 388 | 389 | return false; 390 | } 391 | }); 392 | } 393 | }); 394 | sortEvent = $._data(buttonElement[0], 'events').click; 395 | sortEvent.unshift(sortEvent.pop()); 396 | } else { 397 | buttonElement.on('click', function (event) { 398 | var name = element.find('.g-recaptcha').attr('id'); 399 | var check = $("input[name='" + name + "']").prop('checked'); 400 | 401 | if (!(element.validation() && element.validation('isValid')) && check === false) { 402 | $.each(self.captchaForm, function (form, value) { 403 | if (element.find('#' + value).length > 0) { 404 | self.showMessage(divError, 5000); 405 | grecaptcha.reset(form); 406 | event.preventDefault(event); 407 | event.stopImmediatePropagation(); 408 | } 409 | }); 410 | } 411 | }); 412 | } 413 | 414 | var badge = $('#mp_recaptcha_' + 'osc' + ' .grecaptcha-badge'); 415 | 416 | badge.removeAttr("style"); 417 | badge.attr("style", $('#mp_recaptcha_osc .grecaptcha-badge').attr("style")); 418 | } 419 | }, 420 | 421 | /** 422 | * Show error message 423 | */ 424 | showMessage: function (el, timeDelay) { 425 | el.show(); 426 | if (timeDelay <= 0) timeDelay = 5000; 427 | setTimeout(function () { 428 | el.hide(); 429 | }, timeDelay); 430 | } 431 | }); 432 | 433 | return $.mageplaza.captcha; 434 | }); 435 | --------------------------------------------------------------------------------