1 Отредактировано AJIEKCAHDP (25-07-2017 15:45:59)

Тема: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Собственно, делал один модуль с формами, надо было прикрутить стандартную капчушку (которая реализована в библиотеке DX_Auth) к форме. Проблема встала сразу с её проверкой и выводе в попап окне самой каптчи и обновление её.

Лёгких путей искать не пришлось, "затрахавшись" - решено было сделать современную капту и не придумывать велосипед с квадратными колёсами. Выбор пал на API гугла и использование Rechaptcha 2.0.

Может кому пригодится код в своих проектах, было бы не плохо, если разрабочики прикрутили данный допил в свой новый релиз.

И так начнём:
Для того чтобы у нас работала каптча на сайте, нам надо получить код от гугла, секретные ключи:

1. Надо иметь гугл аккаунт и пройти по ссылке: https://www.google.com/recaptcha/admin?hl=ru#list

В название вводим своё имя сайта и доменны сайта на котором будет работать каптча.

2. Создаём библиотеку с названием в папке /application/libraries/Recaptcha.php

3. Помещаем код библиотеки для дальнейшего использования:

<?php
/**
 * CodeIgniter NO Captcha ReCAPTCHA a.k.a reCAPTCHA Version 2.0 library
 * 
 * This library is based on official reCAPTCHA library for PHP
 * 
 */
defined('BASEPATH') OR exit('No direct script access allowed');

class Recaptcha {
    private $signup_url = "https://www.google.com/recaptcha/admin";
    private $_siteVerifyUrl = "https://www.google.com/recaptcha/api/siteverify?";
    private $_secret, $_sitekey, $_lang;
    private $_version = "php_1.0";
    function __construct() {
        $this->ci = & get_instance();
        $this->ci->load->config('recaptcha', TRUE);
        if ($this->ci->config->item('recaptcha_secretkey', 'recaptcha') == NULL || $this->ci->config->item('recaptcha_secretkey', 'recaptcha') == "") {
            die("To use reCAPTCHA you must get an API key from <a href='"
                    . $this->signup_url . "'>" . $this->signup_url . "</a>");
        }
        if ($this->ci->config->item('recaptcha_sitekey', 'recaptcha') == NULL || $this->ci->config->item('recaptcha_sitekey', 'recaptcha') == "") {
            die("To use reCAPTCHA you must get an API key from <a href='"
                    . $this->signup_url . "'>" . $this->signup_url . "</a>");
        }
        $this->_secret = $this->ci->config->item('recaptcha_secretkey', 'recaptcha');
        $this->_sitekey = $this->ci->config->item('recaptcha_sitekey', 'recaptcha');
        if ($this->ci->config->item('lang', 'recaptcha') == NULL || $this->ci->config->item('lang', 'recaptcha') == "") {
            $this->_lang = 'en';
        } else {
            $this->_lang = $this->ci->config->item('lang', 'recaptcha');
        }
    }
    /**
     * Function to convert an array into query string
     * @param array $data Array of params
     * @return String query string of parameters
     */
    private function _encodeQS($data) {
        $req = "";
        foreach ($data as $key => $value) {
            $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
        }
        return substr($req, 0, strlen($req) - 1);
    }
    /**
     * HTTP GET to communicate with reCAPTCHA server
     * @param string $path URL to GET
     * @param array $data Array of params
     * @return string JSON response from reCAPTCHA server
     */
    private function _submitHTTPGet($path, $data) {
        $req = $this->_encodeQS($data);
        $response = file_get_contents($path . $req);
        return $response;
    }
    /**
     * Function for rendering reCAPTCHA widget into views
     * Call this function in your view
     * @return string embedded HTML
     */
    public function render() {
        $return = '<div class="g-recaptcha" data-sitekey="' . $this->_sitekey . '"></div><script src="https://www.google.com/recaptcha/api.js?hl=' . $this->_lang . '" async defer></script>';
        return $return;
    }
    /**
     * Function for verifying user's input
     * @param string $response User's input
     * @param string $remoteIp Remote IP you wish to send to reCAPTCHA, if NULL $this->input->ip_address() will be called
     * @return array Array of response
     */
    public function verifyResponse($response, $remoteIp = NULL) {
        if ($response == null || strlen($response) == 0) {
            // Empty user's input
            $return = array(
                'success' => FALSE,
                'error_codes' => 'missing-input'
            );
        }
        $getResponse = $this->_submitHttpGet(
                $this->_siteVerifyUrl, array(
            'secret' => $this->_secret,
            'remoteip' => (!is_null($remoteIp)) ? $remoteIp : $this->ci->input->ip_address(),
            'v' => $this->_version,
            'response' => $response
                )
        );
        $answers = json_decode($getResponse, TRUE);
        if (trim($answers ['success']) == true) {
            // Right captcha! 
            $return = array(
                'success' => TRUE,
                'error_codes' => ''
            );
        } else {
            // Wrong captcha!
            $return = array(
                'success' => FALSE,
                'error_codes' => $answers['error-codes']
            );
        }
        return $return;
    }
}

4. Создаём файл настроек, который будет распологаться application/config/recaptcha.php

5. Открываем файл и вносим код, там надо указать свои секретные ключи выданные гуглом при создании

<?php
if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}



$config['recaptcha_sitekey'] = "Сюда ввести ключ выданный гуглом";
$config['recaptcha_secretkey'] = "Сюда ввести ключ выданный гуглом";
// Определяем текущий язык сайта - вернёт ru - если язык является русский
$config['lang'] = MY_Controller::getCurrentLocale();
?>

6. Всё готово для работы.

Как использовать!?

В модуле контроллера добавить строку загрузки библиотеки, обычно помещают в конструктор

$this->load->library('Recaptcha');

Открываем файл шаблона модуля для вывода формы, перед закрывающим тэгом выводим это:

{echo $CI->recaptcha->render()}

Для проверки защитного кода используем проверку:

// Ответ защитного кода
        $captcha_answer = $this->input->post('g-recaptcha-response');
        // Проверка защитного кода
        $response = $this->recaptcha->verifyResponse($captcha_answer);
// Проверка на ошибки

        if ($response['success']) {
          // Если нет ошибок исполняем код, например отсылаем письмо
        } else {
            // Если ответ на защитный код не верный
            if($response['success'] === FALSE) {
                // Выводим сообщение об ошибки
                echo $captcha_error = tlang('Ошибка потверждения защиты');    
            }
            else {
                 echo $captcha_error = '';
            }
 }           
            

Посмотреть как работает и выглядит каптча
https://www.google.com/recaptcha/api2/demo



ДОПОЛНЕНИЕ: ПОЛНЫЙ КОД ДЛЯ МОДУЛЕЙ FEEDBACK и CALLBACK (version 4.12)

feedback.php

<?php

use cmsemail\email;

if (!defined('BASEPATH')) {
    exit('No direct script access allowed');
}

/**
 * Image CMS
 *
 * Feedback module
 */
class Feedback extends MY_Controller
{

    public $username_max_len = 30;

    public $message_max_len = 600;

    public $theme_max_len = 150;

    public $admin_mail = 'admin@localhost';

    public $message = '';

    protected $formErrors = [];

    public function __construct() {
        parent::__construct();
        $this->load->module('core');
        // Load library
        $this->load->library('Recaptcha');
        $this->load_settings();

        $this->formErrors = [
                             'required'    => lang('Field is required'),
                             'min_length'  => lang('Length is less than the minimum'),
                             'valid_email' => lang('Email is not valid'),
                             'max_length'  => lang('Length greater than the maximum'),
                            ];
        $lang = new MY_Lang();
        $lang->load('feedback');
    }

    public function autoload() {

    }

    public function captcha_check($code) {
        if (!$this->dx_auth->captcha_check($code)) {
            return FALSE;
        } else {
            return TRUE;
        }
    }

    public function recaptcha_check() {
        $result = $this->dx_auth->is_recaptcha_match();
        if (!$result) {
            $this->form_validation->set_message('recaptcha_check', lang('Improper protection code', 'feedback'));
        }

        return $result;
    }

    // Index function

    public function index() {
        $this->template->registerMeta('ROBOTS', 'NOINDEX, NOFOLLOW');

        $this->core->set_meta_tags(lang('Feedback', 'feedback'));

        $this->load->library('form_validation');

        // Create captcha
        //$this->dx_auth->captcha();
        //$tpl_data['cap_image'] = $this->dx_auth->get_captcha_image();

        $this->template->add_array($tpl_data);

        if (count($this->input->post()) > 0) {
            $this->form_validation->set_rules('name', lang('Your name', 'feedback'), 'trim|required|min_length[3]|max_length[' . $this->username_max_len . ']|xss_clean');
            $this->form_validation->set_rules('email', lang('Email', 'feedback'), 'trim|required|valid_email|xss_clean');
            $this->form_validation->set_rules('theme', lang('Subject', 'feedback'), 'trim|max_length[' . $this->theme_max_len . ']|xss_clean');
            $this->form_validation->set_rules('message', lang('Message', 'feedback'), 'trim|required|max_length[' . $this->message_max_len . ']|xss_clean');

            //if ($this->dx_auth->use_recaptcha) {
            //    $this->form_validation->set_rules('recaptcha_response_field', lang('Protection code', 'feedback'), 'trim|xss_clean|required|callback_recaptcha_check');
            //} else {
            //    $this->form_validation->set_rules('captcha', lang('Protection code', 'feedback'), 'trim|required|xss_clean|callback_captcha_check');
            //}

            // Ответ защитного кода
            $captcha_answer = $this->input->post('g-recaptcha-response');
            // Проверка защитного кода
            $response = $this->recaptcha->verifyResponse($captcha_answer);
            
            
            
            if ($this->form_validation->run($this) == FALSE OR $response['success']===FALSE) { // there are errors
                
                $recaptcha_error = tlang('Ошибка потверждения защиты');
                
                $this->form_validation->set_error_delimiters('', '');
                CMSFactory\assetManager::create()->setData(
                    'validation', $this->form_validation,
                    'recaptcha_error', $captcha_error);
                    
                form_error();
                
            } else { // form is validate

                $feedback_variables = [
                                       'Theme'       => $this->input->post('theme'),
                                       'userName'    => $this->input->post('name'),
                                       'userEmail'   => $this->input->post('email'),
                                       'userMessage' => $this->input->post('message'),
                                      ];
                 email::getInstance()->sendEmail($this->input->post('email'), 'feedback', $feedback_variables);
                CMSFactory\assetManager::create()->appendData('message_sent', TRUE);

            }
        }

        CMSFactory\assetManager::create()->render('feedback');
    }

    private function load_settings() {
        $this->db->limit(1);
        $this->db->where('name', 'feedback');
        $query = $this->db->get('components')->row_array();

        $settings = unserialize($query['settings']);

        if (is_int($settings['message_max_len'])) {
            $this->message_max_len = $settings['message_max_len'];
        }

        if ($settings['email']) {
            $this->admin_mail = $settings['email'];
        }
    }

}

/* End of file sample_module.php */

callbacks.php

<?php

use callbacks\Exceptions\ValidationException;
use cmsemail\email;
use CMSFactory\assetManager;
use CMSFactory\Events;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\Exception\PropelException;

(defined('BASEPATH')) OR exit('No direct script access allowed');

/**
 * Image CMS
 * Callbacks
 */
class Callbacks extends MY_Controller
{

    public function __construct() {

        parent::__construct();
        $lang = new MY_Lang();
        $lang->load('callbacks');
        // Load library
        $this->load->library('Recaptcha');
    }

    /**
     * Render form and save callback
     *
     * @return void
     * @throws PropelException
     */
    public function index() {

        $this->core->set_meta_tags(lang('Callback', 'callback'));
        $this->template->registerMeta('ROBOTS', 'NOINDEX, NOFOLLOW');

        $this->load->library('Form_validation');
        if ($this->input->post()) {
            try {
                $success = $this->createFromPost();
            
            } catch (ValidationException $e) {
                $success = false;
            }
            if (!$this->input->is_ajax_request()) {
                $this->session->set_flashdata('success_message', $success);
                redirect(site_url('/callbacks'));
            }
        }

        $message = isset($success) ? $success : $this->session->flashdata('success_message');

        assetManager::create()
            ->setData('themes', SCallbackThemesQuery::create()->setComment(__METHOD__)->joinWithI18n(MY_Controller::getCurrentLocale(), Criteria::INNER_JOIN)->find())
            ->setData(['success' => $message])
            ->render('callback');
    }

    /**
     * Create new callback from $_POST data
     * @return string
     * @throws ValidationException
     * @throws PropelException
     */
    public function createFromPost() {

        $this->load->library('Form_validation');

        $model = new SCallbacks;
        $this->form_validation->set_rules($model->rules());

        // Ответ защитного кода
        $captcha_answer = $this->input->post('g-recaptcha-response');
        // Проверка защитного кода
        $response = $this->recaptcha->verifyResponse($captcha_answer);
        
        
        if (!$this->form_validation->run() OR $response['success']===FALSE) {
            throw new ValidationException(
                [
                 'message' => validation_errors(),
                 'errors'  => $this->form_validation->getErrorsArray(),
                ]
            );
        }

        $theme = SCallbackThemesQuery::create()->setComment(__METHOD__)->orderByPosition()->findOne();
        $status = SCallbackStatusesQuery::create()->setComment(__METHOD__)->filterByIsDefault(TRUE)->findOne();

        $model->fromArray($this->input->post());
        $model->setThemeId($theme ? $theme->getId() : 0);
        $model->setStatusId($status ? $status->getId() : 0);
        $model->setDate(time());
        $model->save();

        $this->sendEmail($model);
        Events::create()->raiseEvent(['model' => $model], 'Shop:callback');
        return $this->getMessage();
    }

    /**
     * @todo move callback configs(success message etc.)
     *       from answer notifications && shop settings
     *       to own module configs
     *
     * @return string
     */
    protected function getMessage() {

        $notification = $this->db
            ->where('locale', \MY_Controller::getCurrentLocale())
            ->where('name', 'callback')->get('answer_notifications');

        return $notification->num_rows() > 0 ? $notification->row()->message : '';
    }

    /**
     * @param SCallbacks $callback
     * @return bool
     * @throws PropelException
     */
    protected function sendEmail(SCallbacks $callback) {

        $callback_variables = [
                               'callbackStatus' => $callback->getSCallbackStatuses() ? $callback->getSCallbackStatuses()->getText() : '',
                               'callbackTheme'  => $callback->getSCallbackThemes() ? $callback->getSCallbackThemes()->getText() : '',
                               'userName'       => $callback->getName(),
                               'userPhone'      => $callback->getPhone(),
                               'dateCreated'    => date('d-m-Y H:i:s', $callback->getDate()),
                               'userComment'    => $callback->getComment(),
                              ];
        return email::getInstance()->sendEmail($this->dx_auth->get_user_email(), 'callback', $callback_variables);
    }

}

/* End of file callbacks.php */

Пользуйтесь на здоровье....

ДОПОЛНЕНИЕ - ДЛЯ РЕГИСТРАЦИИ МАГАЗИНА 4.12
Заходим в конфиг файл /public_html/application/config/auth.php

Правим строчки на эти, это отключит стандартную каптчу в регистрации:

// Registration
$config['DX_captcha_registration'] = FALSE;

Если кому лень делать ручками и настраивать прикручу отдельно или напишу модуль под вас за деньги.

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

2

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Хорошая работа, молодец!

Разрабатываю модули для ImageCMS Corporate (оплата PayPal).

3

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Молодец. Комментарий от меня: там есть нюанс, если будет две рекапчи на странице. Например, одна в разделе Контакты, а вторая скрытая в каком-нибудь модальном окне. Так что имейте в виду, а в гугле есть как это решать...

Профессиональное создание сайтов любой сложности, аудит, продвижение, а также поддержка вашего интернет ресурса - web2life.ru

TIMEWEB > Всегда больше, чем просто хостинг для ImageCMS!

4 Отредактировано AJIEKCAHDP (09-11-2016 15:10:47)

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

supleader пишет:

Молодец. Комментарий от меня: там есть нюанс, если будет две рекапчи на странице. Например, одна в разделе Контакты, а вторая скрытая в каком-нибудь модальном окне. Так что имейте в виду, а в гугле есть как это решать...

Вы правильно подметили, cерверная сторона нас в этой ситуации не интересует, с ней проблем нет. С клиентской стороной есть решения.

Можно задать каждой форме свой ID и методом JQuery передовать вывод, я думаю сложностей больших не будет.

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

5

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Объясните, пожалуйста, тупому, что такое:

В модуле контроллера добавить строку загрузки библиотеки, обычно помещают в конструктор

Что такое модуль контроллера, что такое конструктор?
Хочу Recaptcha в Обратный звонок запихнуть не понимаю каким образом это сделать.

Thumbs up Thumbs down

6

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Модуль - на простой язык - папка с файлами, которая находиться в application ->module -> название модуля (если это будет обратная связь, то папка будет называться feedback - или другой ваш модуль)

Внутри этой папки бедет файл названием таким же как и называеться папка (к примеру feedback.php - по простомя это называеться контроллёр. Открываем его в редакторе.

Конструктор - это функция или попростому код заключённый  public function __construct() { ...суда вставить строку...}

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

AJIEKCAHDP пишет:

Модуль - на простой язык - папка с файлами, которая находиться в application ->module -> название модуля (если это будет обратная связь, то папка будет называться feedback - или другой ваш модуль)

Внутри этой папки бедет файл названием таким же как и называеться папка (к примеру feedback.php - по простомя это называеться контроллёр. Открываем его в редакторе.

Конструктор - это функция или попростому код заключённый  public function __construct() { ...суда вставить строку...}



а куда вставлять если надо для модуля callbacks

это добавил /application/modules/callbacks/callbacks.php:

    public function __construct() {

        parent::__construct();
        $lang = new MY_Lang();
    $this->load->library('Recaptcha');  //add line
        $lang->load('callbacks');
    }

это тоже: /templates/theme/callbacks/  в callback.tpl  и callbacks_modal.tpl

перед словом:   <!-- Submit button -->
добавил: {echo $CI->recaptcha->render()}


А куда добавить нужно в и в какой файл проверки? за ранее благодарен!

// Ответ защитного кода
        $captcha_answer = $this->input->post('g-recaptcha-response');
        // Проверка защитного кода
        $response = $this->recaptcha->verifyResponse($captcha_answer);

// Проверка на ошибки

        if ($response['success']) {
          // Если нет ошибок исполняем код, например отсылаем письмо
        } else {
            // Если ответ на защитный код не верный
            if($response['success'] === FALSE) {
                // Выводим сообщение об ошибки
                echo $captcha_error = tlang('Ошибка потверждения защиты');    
            }
            else {
                 echo $captcha_error = '';
            }
 }           
            
           
Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Up!!!!!!!!!

Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

9

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

2 Инъекция, там данные передаются ajax-ом, просто вставить пару строчек кода в нужное место не получиться. Нужно править скрипт. Черкните автору, думаю за денюжку он вам поможет.

Разрабатываю модули для ImageCMS Corporate (оплата PayPal).

10

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Инъекция пишет:

Up!!!!!!!!!

Я в ПМ попросил у вас полный код с вашего файла модуля, чтобы посмотреть куда тыркать! Если у вас используеться AJAX, то возможно надо будет доделывать код именно под вас.

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

11

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Кто поможет с установкой капчи? Заплачу smile

Thumbs up Thumbs down

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

написал вам александр! помогите пожалуйста!

Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

UP! ответа так и не получил! может кто еще может мне помочь? версия финальная изменений в скрипте не делал!

Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

то есть капча появилась а проверку не делает!!!((((((((((((

Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

да уж! печально! 3 строчки и никто не знает как вставить(((( жесть!

Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

16 Отредактировано Олег (15-02-2017 14:29:35)

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Инъекция пишет:

да уж! печально! 3 строчки и никто не знает как вставить(((( жесть!

волонтеры отсель сбежали, а др не интересно чужие проблемы.
Вот так тут и живут. sad

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

дам 300р если поможет кто!

Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

18

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Инъекция пишет:

дам 300р

Ой смотрите разбалуете вы их, энтих программистов!

Разрабатываю модули для ImageCMS Corporate (оплата PayPal).

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

да я как бы символически написал! там кто может реализовать пусть напишет свою сумму!

Код скидки на мебель от производителя для сайта ImageCMS: ic2016qp26 - 5%

20 Отредактировано AJIEKCAHDP (22-02-2017 12:18:33)

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Вопрос решён, сделано для модуля Feedback и Callbacks. Добавил файлы готовые в первом посте.

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

21

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

А для версии Shop подойдет такое решение?

Thumbs up Thumbs down

22

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Тестилось как для Корпорэйт версии так и для магазина, должно всё работать, если вы проделаете описанные шаги.

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

23

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Сделал все 5 пунктов.
Можете подробнее рассказать что и куда вставить, чтобы эта капча работала вместо стандартной на странице регистрации и комментариев. Шоп 4, .12 премиум.
А то боты уже достали. Или это не спасет от них?

Thumbs up Thumbs down

24

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Для регистрации и комментариев сделаю за малую оплату труда, так как это у меня отнимит время. Можете скинуться колективно, решения получат все. Кошелёк вебмони: R217323767724 - (для программиста на кофе)

Сделаю обновления вашего магазина до актуальной версии системы со вем переносом ваших товаров, просьба писать в приват.
https://novabench.com/image/742206.png

25

Re: Замена родной и древней каптчи в модулях на Recaptcha 2.0!

Цена вопроса ??

Thumbs up Thumbs down