Google Recaptcha V3 + ajax

Рабочий вариант recaptcha v3 + ajax (рабочий вариант на данный момент)
Cерверная часть php (размещаем в код ТДС показа формы):
$sSecretKey = "ваш секретный ключ recatpcha";

if (Core_Array::getPost('g-recaptcha-response'))
{
$sResponse = Core_Array::getPost('g-recaptcha-response');

$sUrl = 'https://www.google.com/recaptcha/api/siteverify';

    $Core_Http = Core_Http::instance('curl')
    ->clear()
    ->method('POST')
    ->url($sUrl)
    ->additionalHeader('Accept-Encoding', 'gzip, deflate')
    ->data('secret', $sSecretKey)
    ->data('response', $sResponse)
    ->execute();

$oAnswer = json_decode($Core_Http->getDecompressedBody(), true);
   
if ($oAnswer["score"] >= 0.5)
{
// Данные формы
        $form_name = Core_Array::getPost('name');
   $form_email = Core_Array::getPost('email');
   $form_text = Core_Array::getPost('message');

    // Тема
    $form_subject = 'Тема';
    $message = null;
    // Собираем сообщение
   $message .= 'Имя: '.$form_name."\r\n\r\n";
   $message .= 'Email: '.$form_email."\r\n\r\n";
   $message .= 'Сообщение: '.$form_text."\r\n\r\n";
      
   $oCore_Mail_Driver = Core_Mail::instance()
    ->to('rz300@ya.ru')
    ->from('no.reply@host.ru')
    ->subject($form_subject)
    ->message(trim($message))
    ->contentType('text/plain')
    ->header('Precedence', 'bulk')
    ->send();
    
   $result = array('status' => true, 'message' => 'ok','result' => 'success');

    echo json_encode($result);
    
   exit();
}
}
добавляем в <head>
<script src='https://www.google.com/recaptcha/api.js?render=публичный ключ рекапчи' async="async" defer="defer"></script>
Код javascript
grecaptcha.ready(function () {
grecaptcha.execute('публичный ключ рекапчи', {
   action: 'send'
   }).then(function(token) {
// add token to form
$('.formCallBack').prepend('<input type="hidden" name="g-recaptcha-response" value="' + token + '">');
});   
});

     $('.formCallBack').submit(function() {
      var data = $(this).serializeArray();
      $.ajax({
         type: 'post',
         url: './',
         data: data,
         dataType: 'html',
         success: function(e) {
            //console.log(true);
            $('.formCallBack').html('<p>Ваша заявка отправлена, спасибо!</p>');
            $('.formCallBack .btn').css('display', 'none');
         },
         error: function(e) {
            console.log(false);
         }
      });
      return false;
   });  

reCaptcha V3 в корзине

Подключаем в head скрипт reCaptcha

<script src="https://www.google.com/recaptcha/api.js" async="" defer=""></script>

и добавляем в макет корзины

  <script>
 function onSubmit(token) {
     document.getElementById("cmsm-form-cart").submit();
   }
  </script>

Ниже приведена ТДС корзины на одной странице. Если использовать данный вариант, то в XSL шаблонах для Адреса доставки, Доставок и Платёжных систем закомментировать тег form 

<!--form-->
....
<!--/form-->

В XSL шаблон Платёжных систем кнопка отправки заказа примет вид

<button type="submit" class="btn btn-blue btn-lg g-recaptcha" data-sitekey="ключ-reCaptcha" data-callback="onSubmit" data-action="submit">ОТПРАВИТЬ ЗАКАЗ →</button>

PHP . ТДС корзины с обработкой reCaptcha

<?php


$Shop_Cart_Controller_Show = Core_Page::instance()->object;


$oShop = $Shop_Cart_Controller_Show->getEntity();


Shop_Payment_System_Handler::checkAfterContent($oShop);


Shop_Delivery_Handler::checkAfterContent($oShop);


// ------------------------------------------------
// Вывод информации о статусе платежа после его совершения и перенаправления с платежной системы
// ------------------------------------------------
if (isset($_REQUEST['payment']) || (isset($_GET['action']) && ($_GET['action'] == 'PaymentSuccess' || $_GET['action'] == 'PaymentFail')) || isset($_REQUEST['pg_order_id']))
{
     // Получаем ID заказа
     if (isset($_REQUEST['order_id']))
     {
          $order_id = intval(Core_Array::getRequest('order_id'));
     }
     //от Яндекса
     elseif(isset($_GET['orderNumber']))
     {
          $order_id = intval(Core_Array::getGet('orderNumber'));
     }
     //от PayPal
     elseif(isset($_REQUEST['invoice']))
     {
          $oShop_Order = Core_Entity::factory('Shop_Order')->getByGuid(Core_Array::getRequest('invoice'));
          $order_id = $oShop_Order ? intval($oShop_Order->id) : NULL;
     }
     //от IntellectMoney
     elseif(isset($_REQUEST['orderId']))
     {
          $order_id = intval(Core_Array::getGet('orderId'));
     }
     //от Platron
     elseif(isset($_REQUEST['pg_order_id']))
     {
          $order_id = intval(Core_Array::getRequest('pg_order_id'));
     }
     else
     {
          $order_id = intval(Core_Array::getRequest('InvId'));
     }


     $oShop_Order = Core_Entity::factory('Shop_Order')->find($order_id);


     if (Core::moduleIsActive('siteuser'))
     {
          $siteuser_id = 0;


          $oSiteuser = Core_Entity::factory('Siteuser')->getCurrent();
          if ($oSiteuser)
          {
               $siteuser_id = $oSiteuser->id;
          }
     }
     else
     {
          $siteuser_id = FALSE;
     }


     // Если заказ принадлежит текущему авторизированному пользователю
     if ($oShop_Order->siteuser_id == $siteuser_id)
     {
          if (Core_Array::getRequest('payment') == 'success' || Core_Array::getRequest('action') == 'PaymentSuccess' || Core_Array::getRequest('pg_order_id') > 0)
          {
               ?><h1>Подтверждение платежа</h1>
               <p>Спасибо, информация об оплате заказа <strong>№ <?php echo $oShop_Order->invoice?></strong>
получена.</p>
               <?php
          }
          else
          {
               ?><h1>Платеж не получен</h1>
               <p>К сожалению при оплате заказа <strong>№ <?php echo $oShop_Order->invoice?></strong> произошла ошибка.</p>
               <?php
          }
     }
     // Для случаев, когда отключен модуль "Пользователи сайта"
     elseif ($siteuser_id === FALSE)
     {
          ?><h1>Подтверждение платежа</h1>
          <p>Благодарим за посещение нашего магазина!</p>
          <?php
     }
     else
     {
          ?><h1>Ошибка</h1>
          <p>Неверный номер заказа!</p>
          <?php
     }


     // Прерываем выполнение типовой динамической страницы
     return TRUE;
}

$xslName = Core_Array::get(Core_Page::instance()->libParams, 'cartXsl');


Core_Session::start();


if (Core_Array::getPost('oneStepCheckout'))
{
    // Сбрасываем информацию о последнем заказе
    $_SESSION['last_order_id'] = 0;


    // Оформление в один шаг
    $Shop_Cart_Controller = Shop_Cart_Controller::instance();
    $aShop_Cart = $Shop_Cart_Controller->getAll($oShop);
    foreach ($aShop_Cart as $oShop_Cart)
    {
        $Shop_Cart_Controller
            ->shop_item_id($oShop_Cart->shop_item_id)
            ->delete();
    }


    $shop_item_id = intval(Core_Array::getRequest('shop_item_id'));


    if ($shop_item_id)
    {
        Shop_Cart_Controller::instance()
            ->shop_item_id($shop_item_id)
            ->quantity(floatval(Core_Array::getRequest('count', 1)))
            ->add();
    }


    $_SESSION['hostcmsOrder'] = array();


    $_SESSION['hostcmsOrder']['shop_country_id'] = intval(Core_Array::getPost('shop_country_id', 0));
    $_SESSION['hostcmsOrder']['shop_country_location_id'] = intval(Core_Array::getPost('shop_country_location_id', 0));
    $_SESSION['hostcmsOrder']['shop_country_location_city_id'] = intval(Core_Array::getPost('shop_country_location_city_id', 0));
    $_SESSION['hostcmsOrder']['shop_country_location_city_area_id'] = intval(Core_Array::getPost('shop_country_location_city_area_id', 0));
    $_SESSION['hostcmsOrder']['postcode'] = Core_Str::stripTags(strval(Core_Array::getPost('postcode')));
    $_SESSION['hostcmsOrder']['address'] = Core_Str::stripTags(strval(Core_Array::getPost('address')));
    $_SESSION['hostcmsOrder']['house'] = Core_Str::stripTags(strval(Core_Array::getPost('house')));
    $_SESSION['hostcmsOrder']['flat'] = Core_Str::stripTags(strval(Core_Array::getPost('flat')));
    $_SESSION['hostcmsOrder']['surname'] = Core_Str::stripTags(strval(Core_Array::getPost('surname')));
    $_SESSION['hostcmsOrder']['name'] = Core_Str::stripTags(strval(Core_Array::getPost('name')));
    $_SESSION['hostcmsOrder']['patronymic'] = Core_Str::stripTags(strval(Core_Array::getPost('patronymic')));
    $_SESSION['hostcmsOrder']['phone'] = Core_Str::stripTags(strval(Core_Array::getPost('phone')));
    $_SESSION['hostcmsOrder']['email'] = Core_Str::stripTags(strval(Core_Array::getPost('email')));
    $_SESSION['hostcmsOrder']['description'] = Core_Str::stripTags(strval(Core_Array::getPost('description')));


    // Additional order properties
    $_SESSION['hostcmsOrder']['properties'] = array();


    $oShop_Order_Property_List = Core_Entity::factory('Shop_Order_Property_List', $oShop->id);


    $aProperties = $oShop_Order_Property_List->Properties->findAll();
    foreach ($aProperties as $oProperty)
    {
        // Св-во может иметь несколько значений
        $aPropertiesValue = Core_Array::getPost('property_' . $oProperty->id);


        if (!is_null($aPropertiesValue))
        {
            !is_array($aPropertiesValue) && $aPropertiesValue = array($aPropertiesValue);
            foreach ($aPropertiesValue as $sPropertyValue)
            {
                $_SESSION['hostcmsOrder']['properties'][] = array($oProperty->id, $sPropertyValue);
            }
        }
    }


    $shop_delivery_condition_id = strval(Core_Array::getPost('shop_delivery_condition_id', 0));


    if (is_numeric($shop_delivery_condition_id))
    {
        $_SESSION['hostcmsOrder']['shop_delivery_condition_id'] = intval($shop_delivery_condition_id);


        $oShop_Delivery_Condition = Core_Entity::factory('Shop_Delivery_Condition', $_SESSION['hostcmsOrder']['shop_delivery_condition_id']);
        $_SESSION['hostcmsOrder']['shop_delivery_id'] = $oShop_Delivery_Condition->shop_delivery_id;
    }


    $_POST['step'] = 4;
}


// Проверяем наличие товара в корзины
$Shop_Cart_Controller = Shop_Cart_Controller::instance();
$aShop_Cart = $Shop_Cart_Controller->getAll($oShop);


switch (Core_Array::getPost('recount') || !count($aShop_Cart) ? 0 : Core_Array::getPost('step'))
{
     // Окончание оформления заказа
     case 4:
          // Сбрасываем информацию о последнем заказе
          $_SESSION['last_order_id'] = 0;
         
          // Заполнение данных доставки
          $_SESSION['hostcmsOrder']['shop_country_id'] = intval(Core_Array::getPost('shop_country_id', 0));
          $_SESSION['hostcmsOrder']['shop_country_location_id'] = intval(Core_Array::getPost('shop_country_location_id', 0));
          $_SESSION['hostcmsOrder']['shop_country_location_city_id'] = intval(Core_Array::getPost('shop_country_location_city_id', 0));
          $_SESSION['hostcmsOrder']['shop_country_location_city_area_id'] = intval(Core_Array::getPost('shop_country_location_city_area_id', 0));
          $_SESSION['hostcmsOrder']['postcode'] = strval(Core_Array::getPost('postcode'));
          $_SESSION['hostcmsOrder']['address'] = strval(Core_Array::getPost('address'));
          $_SESSION['hostcmsOrder']['surname'] = strval(Core_Array::getPost('surname'));
          $_SESSION['hostcmsOrder']['name'] = strval(Core_Array::getPost('name'));
          $_SESSION['hostcmsOrder']['patronymic'] = strval(Core_Array::getPost('patronymic'));
          $_SESSION['hostcmsOrder']['company'] = strval(Core_Array::getPost('company'));
          $_SESSION['hostcmsOrder']['phone'] = strval(Core_Array::getPost('phone'));
          $_SESSION['hostcmsOrder']['fax'] = strval(Core_Array::getPost('fax'));
          $_SESSION['hostcmsOrder']['email'] = strval(Core_Array::getPost('email'));
          $_SESSION['hostcmsOrder']['description'] = strval(Core_Array::getPost('description'));
          $_SESSION['hostcmsOrder']['tin'] = strval(Core_Array::getPost('tin'));
          $_SESSION['hostcmsOrder']['kpp'] = strval(Core_Array::getPost('kpp'));


$_SERVER['send_emails'] = false;
$_SESSION['hostcmsOrder']['company'] = '0';

// RECAPTCHA

if (isset($_POST['g-recaptcha-response'])) {
    $captcha_token = $_POST['g-recaptcha-response'];
    $captcha_action = 'submit';
    
    $url = 'https://www.google.com/recaptcha/api/siteverify';
    $params = [
        'secret' => 'секретный-ключ-reCaptcha',
        'response' => $captcha_token,
        'remoteip' => $_SERVER['REMOTE_ADDR']
    ];
    
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    
    $response = curl_exec($ch);
    if(!empty($response)) $decoded_response = json_decode($response);
    
    //$success = false;
    
    if ($decoded_response && $decoded_response->success && 
        $decoded_response->action == $captcha_action && 
        $decoded_response->score > 0.5) 
    {
        $_SESSION['hostcmsOrder']['company'] = $decoded_response->score;
        $_SERVER['send_emails'] = true;
    }        
}
if ($_SERVER['send_emails'] == false) {
    $_SESSION['hostcmsOrder']['surname'] = 'SPAM ' . $_SESSION['hostcmsOrder']['surname'];
}

          // Additional order properties
          $_SESSION['hostcmsOrder']['properties'] = array();


          $oShop_Order_Property_List = Core_Entity::factory('Shop_Order_Property_List', $oShop->id);


          $aProperties = $oShop_Order_Property_List->Properties->findAll();
          foreach ($aProperties as $oProperty){
               // Св-во может иметь несколько значений
               $aPropertiesValue = Core_Array::getPost('property_' . $oProperty->id);


               if (!is_null($aPropertiesValue))
               {
                    !is_array($aPropertiesValue) && $aPropertiesValue = array($aPropertiesValue);
                    foreach ($aPropertiesValue as $sPropertyValue)
                    {
                         $_SESSION['hostcmsOrder']['properties'][] = array($oProperty->id, $sPropertyValue);
                    }
               }
          }
          //~~ Заполнение данных доставки
    
          // Выбор условия доставки
          $shop_delivery_condition_id = strval(Core_Array::getPost('shop_delivery_condition_id', 0));


          if (is_numeric($shop_delivery_condition_id))
          {
               $_SESSION['hostcmsOrder']['shop_delivery_condition_id'] = intval($shop_delivery_condition_id);
          }
          else
          {
               $_SESSION['hostcmsOrder']['shop_delivery_condition_id'] = 0;


               // в shop_delivery_condition_id тогда "123#", ID элемента массива в сессии, в котором
               // хранится стоимость доставки, налог, название специфичного условия доставки
               list($shopDeliveryInSession) = explode('#', $shop_delivery_condition_id);


               if (isset($_SESSION['hostcmsOrder']['deliveries'][$shopDeliveryInSession]))
               {
                    $aTmp = $_SESSION['hostcmsOrder']['deliveries'][$shopDeliveryInSession];


                    $_SESSION['hostcmsOrder']['shop_delivery_id'] = $aTmp['shop_delivery_id'];
                    $_SESSION['hostcmsOrder']['shop_delivery_price'] = $aTmp['price'];
                    $_SESSION['hostcmsOrder']['shop_delivery_rate'] = $aTmp['rate'];
                    $_SESSION['hostcmsOrder']['shop_delivery_name'] = $aTmp['name'];
               }
          }
          //~~ Выбор условия доставки
    
          // Выбор формы оплаты
          $shop_payment_system_id = $_SESSION['hostcmsOrder']['shop_payment_system_id'] = intval(Core_Array::getPost('shop_payment_system_id', 0));


          // Если выбрана платежная система
          if ($_SESSION['hostcmsOrder']['shop_payment_system_id'])
          {
               Shop_Payment_System_Handler::factory(
                    Core_Entity::factory('Shop_Payment_System', $shop_payment_system_id)
               )
               ->orderParams($_SESSION['hostcmsOrder'])
               ->execute();
          }
          else
          {
               ?><h1>Ошибка! Не указана ни одна платежная система.</h1><?php
          }
          //~~ Выбор формы оплаты
     break;    
     // Адрес доставки
     case 1:
     // Способ доставки
     case 2:
     // Форма оплаты
     case 3:
     default:
          echo '<form method="post" action="./" id="cmsm-form-cart">';
          echo '<scr'.strtolower('I').'pt>';
          echo '$(function(){
               $("#cmsm-form-cart").on("change", "select[name=shop_country_id], select[name=shop_country_location_id], select[name=shop_country_location_city_id], select[name=shop_country_location_city_area_id], input[name=postcode], input[name=coupon_text]", function(){
                    $.loadingScreen("show"); // Крутилка         
                    $.ajax({
                         url: "./",
                         type: "GET",
                         data: ({"CMSMajaxLoadDelivery" : 1, "shop_country_id" : $("select[name=shop_country_id] :selected").val(), "shop_country_location_id" : $("select[name=shop_country_location_id] :selected").val(), "shop_country_location_city_id" : $("select[name=shop_country_location_city_id] :selected").val(), "shop_country_location_city_area_id" : $("select[name=shop_country_location_city_area_id] :selected").val(), "postcode" : $("input[name=postcode]").val(), "coupon_text" : $("input[name=coupon_text]").val()}),
                         dataType: "html",
                         success: function(html){
                              $("#shop-delivery-block").empty().append(html);
                              $.loadingScreen("hide"); // Убираем крутилку
                              $("input[name=shop_delivery_condition_id]").change();
                         }
                    });
                    return true;
               });
              
               $("#cmsm-form-cart").on("change", "input[name=shop_delivery_condition_id]", function(){
                    $.loadingScreen("show"); // Крутилка         
                    $.ajax({
                         url: "./",
                         type: "GET",
                         data: ({"CMSMajaxLoadPayment" : 1, "shop_delivery_condition_id" : $("input[name=shop_delivery_condition_id]:checked").val()}),
                         dataType: "html",
                         success: function(html){
                              $("#shop-payment-block").empty().append(html);
                              $.loadingScreen("hide"); // Убираем крутилку
                         }
                    });
                    return true;
               });
              
               if ($("select[name=shop_country_id]").change())
                    $("input[name=shop_delivery_condition_id]").change();
          });
          ';
          echo '</sc'.'ri'.strtolower('PT').'>';
          // Корзина
          $Shop_Cart_Controller_Show
               ->couponText(Core_Array::get(Core_Array::get($_SESSION, 'hostcmsOrder', array()), 'coupon_text'))
               ->xsl(
                    Core_Entity::factory('Xsl')->getByName($xslName)
               )
               ->itemsProperties(TRUE)
               ->show();
         
          // Корзина не пуста


          if (count($aShop_Cart)){
         echo ' <div class="container"><h3><b>Оформление заказа</b></h3><div class="order row">';
         echo '<div id="shop-address-block" class="col-12">';
               // Адрес доставки
               $Shop_Address_Controller_Show = new Shop_Address_Controller_Show($oShop);
               $Shop_Address_Controller_Show->xsl(
                         Core_Entity::factory('Xsl')->getByName(
                              Core_Array::get(Core_Page::instance()->libParams, 'deliveryAddressXsl')
                         )
                    )
                    ->show();
                echo '</div>';


               echo '<div id="shop-delivery-block" class="col-12 col-md-6">';
               // Способ доставки
               $Shop_Delivery_Controller_Show = new Shop_Delivery_Controller_Show($oShop);
               $Shop_Delivery_Controller_Show
                    ->shop_country_id(Core_Array::get(Core_Array::get($_SESSION, 'hostcmsOrder', array()), 'shop_country_id'))
                    ->shop_country_location_id(Core_Array::get(Core_Array::get($_SESSION, 'hostcmsOrder', array()), 'shop_country_location_id'))
                    ->shop_country_location_city_id(Core_Array::get(Core_Array::get($_SESSION, 'hostcmsOrder', array()), 'shop_country_location_city_id'))
                    ->shop_country_location_city_area_id(Core_Array::get(Core_Array::get($_SESSION, 'hostcmsOrder', array()), 'shop_country_location_city_area_id'))
                    ->couponText(Core_Array::get(Core_Array::get($_SESSION, 'hostcmsOrder', array()), 'coupon_text'))
                    ->setUp()
                    ->xsl(
                         Core_Entity::factory('Xsl')->getByName(
                              Core_Array::get(Core_Page::instance()->libParams, 'deliveryXsl')
                         )
                    )
                    ->show();
               echo '</div>';
              
               echo '<div id="shop-payment-block" class="col-12 col-md-6">';
               // Форма оплаты
               $oShop_Delivery_Condition = Core_Entity::factory('Shop_Delivery_Condition', Core_Array::get(Core_Array::get($_SESSION, 'hostcmsOrder', array()), 'shop_delivery_condition_id'));


               $Shop_Payment_System_Controller_Show = new Shop_Payment_System_Controller_Show($oShop);
               $Shop_Payment_System_Controller_Show
                    ->shop_delivery_id($oShop_Delivery_Condition->shop_delivery_id)
                    ->xsl(
                         Core_Entity::factory('Xsl')->getByName(
                              Core_Array::get(Core_Page::instance()->libParams, 'paymentSystemXsl')
                         )
                    )
                    ->show();
               echo '</div>';
          }


          echo '</div></div></form>';
}


// Блок авторизации пользователя
/*
if (Core::moduleIsActive('siteuser'))
{
     $oSiteuser = Core_Entity::factory('Siteuser')->getCurrent();


     if (is_null($oSiteuser))
     {
          // Авторизация
          $Siteuser_Controller_Show = new Siteuser_Controller_Show(
               Core_Entity::factory('Siteuser')
          );


          $Siteuser_Controller_Show
               ->location(Core::$url['path'])
               ->xsl(
                    Core_Entity::factory('Xsl')->getByName(Core_Array::get(Core_Page::instance()->libParams, 'userAuthorizationXsl'))
               )
               ->show();


          // Регистрация
          $Siteuser_Controller_Show = new Siteuser_Controller_Show(
               Core_Entity::factory('Siteuser')
          );


          $Siteuser_Controller_Show->xsl(
                    Core_Entity::factory('Xsl')->getByName(Core_Array::get(Core_Page::instance()->libParams, 'userRegistrationXsl'))
               )
               ->location(Core::$url['path'])
               ->fastRegistration(TRUE)
               ->itemsProperties(TRUE)
               ->properties(TRUE)
               //->showMaillists(TRUE)
               ->show();
     }
}
*/

Замена стандартной капчи на Google reCaptcha

Рассмотрим пример замены капчи для модуля форм.

Получение регистрационных данных

1. Перейдите на страницу reCAPTCHA
2. Заполните форму "Регистрация сайта". Например,
   
3. После нажатия кнопки "Регистрация" произойдет переход на страницу с регистрационными данными. Необходима будет пара Ключ + Секретный ключ:
   

Интеграция на стороне клиента

Вставьте этот фрагмент перед закрывающим тегом </head> в HTML-коде:
<script src="https://www.google.com/recaptcha/api.js" type="text/javascript"></script>

Интеграция на стороне сервера

В XSL-шаблон в тег <form> вносим строку виджета каптчи там, где нужен показ:
<div class="g-recaptcha" data-sitekey="{/form/site_key}"></div>
Когда пользователи отправляют форму со встроенной проверкой reCAPTCHA, вместе с прочими данными вы получаете строку "g-recaptcha-response". Чтобы узнать, прошел ли пользователь проверку, отправьте POST-запрос. Если получили успешный ответ, то форма отправляется.
<?php
if (Core::moduleIsActive('form'))
{
    $oForm = Core_Entity::factory('Form', Core_Array::get(Core_Page::instance()->libParams, 'formId'));
    $Form_Controller_Show = new Form_Controller_Show($oForm);
    $xslName = Core_Array::get(Core_Page::instance()->libParams, 'formXsl');
    $sSecretKey = "xxx"; // Указывается секретный ключ reCAPTCHA
    if (!is_null(Core_Array::getPost($oForm->button_name)))
    {
        if (Core_Array::getPost('g-recaptcha-response'))
        {
           // $sResponse = Core_Array::getPost('g-recaptcha-response');
           // $sUrl = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $sSecretKey . "&response=" . $sResponse;    
       $sUrl = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $sSecretKey . '&response=' . (array_key_exists('g-recaptcha-response', $_POST) ? $_POST["g-recaptcha-response"] : '') . '&remoteip=' . $_SERVER['REMOTE_ADDR'];
            /*$Core_Http = Core_Http::instance('curl')
            ->clear()
            ->method('POST')
            ->url($sUrl)
            ->execute();
            $aAnswer = json_decode($Core_Http->getBody(), TRUE);*/
            $aAnswer = json_decode(file_get_contents($sUrl), TRUE);  
            if ($aAnswer['success'])
            {
                $Form_Controller_Show
                    ->values($_POST + $_FILES)
                    // 0 - html, 1- plain text
                    ->mailType(Core_Array::get(Core_Page::instance()->libParams, 'mailType'))
                    ->mailXsl(
                        Core_Entity::factory('Xsl')->getByName(Core_Array::get(Core_Page::instance()->libParams, 'notificationMailXsl'))
                    )
                    ->mailFromFieldName(Core_Array::get(Core_Page::instance()->libParams, 'emailFieldName'))
                    ->process();
            }
            else
            {
                Core_Log::instance()->clear()
                ->status(Core_Log::$ERROR)
                ->write('Google Recaptcha: ' . $aAnswer['error-codes'][0]);
          $Form_Controller_Show
                  ->addEntity(
                  Core::factory('Core_Xml_Entity')
                  ->name('recaptcha_error')->value('1')
               );
            }    
        }    
     else
            {
                
             $Form_Controller_Show
                  ->addEntity(
                  Core::factory('Core_Xml_Entity')
                  ->name('recaptcha_error')->value('1')
               );
            }
        //-------------------------- end recaptha
        
    }
    $Form_Controller_Show
        ->xsl(
            Core_Entity::factory('Xsl')->getByName($xslName)
        )
        ->addEntity(
            Core::factory('Core_Xml_Entity')
                ->name('site_key')->value('yyy') // Указываете ключ reCAPTCHA
        )
        ->show();
}
else
{
    ?>
    <h1>Формы</h1>
    <p>Функционал недоступен, приобретите более старшую редакцию.</p>
    <p>Модуль &laquo;<a href="http://www.hostcms.ru/hostcms/modules/forms/">Формы</a>&raquo; доступен в редакциях &laquo;<a href="http://www.hostcms.ru/hostcms/editions/corporation/">Корпорация</a>&raquo;, &laquo;<a href="http://www.hostcms.ru/hostcms/editions/business/">Бизнес</a>&raquo; и &laquo;<a href="http://www.hostcms.ru/hostcms/editions/small-business/">Малый бизнес</a>&raquo;.</p>
    <?php
}

Замена стандартной капчи на Google reCaptcha в комментариях

Рассмотрим пример замены капчи для комментариев магазина. Для комментариев информационных систем точно такой же алгоритм.

Получение регистрационных данных

1. Производим стандартнуюю регистрацию сайта.Перейдите на страницу reCAPTCHA
2. Заполните форму "Регистрация сайта". Например,
   
3. После нажатия кнопки "Регистрация" произойдет переход на страницу с регистрационными данными. Необходима будет пара Ключ + Секретный ключ:
   
Интеграция на стороне клиента
1. Если у вас стандартные комментарии системы, то вставьте этот фрагмент перед закрывающим тегом </head> в HTML-коде, указав вместо your_key ключ сайта, который был получен ранее:
<script type="text/javascript">
var CaptchaCallback = function(){
$('.g-recaptcha').each(function(index, el) {
grecaptcha.render(el, {'sitekey' : 'your_key'});
});
};
</script>
 <script src="https://www.google.com/recaptcha/api.js?onload=CaptchaCallback&render=explicit" async defer></script>
2. Если у вас комментарии без возможности ответов на уже добавленные комментарии, т.е. форма комментариев одна на странице, то вставьте этот фрагмент перед закрывающим тегом </head> в HTML-коде:
<script src="https://www.google.com/recaptcha/api.js" type="text/javascript"></script>

Интеграция на стороне сервера

В XSL-шаблоне карточки товара, в темлейт формирующий форму комментариев, в тег <form> вносим строку виджета каптчи там, где нужен показ:
<!-- Showing captcha -->
<xsl:if test="/shop/use_captcha = 1 and /shop/siteuser_id = 0">
<div class="g-recaptcha" data-sitekey="{/shop/site_key}"></div>
</xsl:if>
Когда пользователи отправляют форму со встроенной проверкой reCAPTCHA, вместе с прочими данными вы получаете строку "g-recaptcha-response". Чтобы узнать, прошел ли пользователь проверку, отправьте POST-запрос. Если получили успешный ответ, то форма отправляется.
Переходим в типовую динамическую страницу магазина и настраиваем её на обработку reCAPTCHA:
1. В коде типовой динамической страницы, после $Shop_Controller_Show = Core_Page::instance()->object;
добавляем передачу в XML ключа reCAPTCHA, который был получен при регистрации в Google reCaptcha.
   // Google reCaptcha
   $Shop_Controller_Show->addEntity(
   Core::factory('Core_Xml_Entity')
   ->name('site_key')->value('yyy') // Указываете ключ reCAPTCHA
   );

2. Следующий шаг - замена стандартной обработки капчи.

Для этого блок:

 if (Core_Array::getPost('add_comment') && Core_Array::get(Core_Page::instance()->libParams, 'showComments', 1))
   {
   ...
   }

заменяется на:
  
if (Core_Array::getPost('add_comment') && Core_Array::get(Core_Page::instance()->libParams, 'showComments', 1))
   {
   $oShop = $Shop_Controller_Show->getEntity();
   
   $sSecretKey = "xxx"; // Указывается секретный ключ reCAPTCHA
   
   $Shop_Controller_Show->cache(FALSE);
   
   $oLastComment = Core_Entity::factory('Comment')->getLastCommentByIp(
   Core_Array::get($_SERVER, 'REMOTE_ADDR')
   );
   
   $oXmlCommentTag = Core::factory('Core_Xml_Entity')
   ->name('document');
   
   $siteuser_id = 0;
   if (Core::moduleIsActive('siteuser'))
   {
   $oSiteuser = Core_Entity::factory('Siteuser')->getCurrent();
   
   if ($oSiteuser)
   {
   $siteuser_id = $oSiteuser->id;
   }
   }
   
   $oComment = Core_Entity::factory('Comment');
   
   $allowable_tags = '<b><strong><i><em>
<p><u><strike><ul><ol><li>';
   $oComment->parent_id = intval(Core_Array::getPost('parent_id', 0));
   $oComment->active = $oShop->comment_active;
   $oComment->author = Core_Str::stripTags(Core_Array::getPost('author'));
   $oComment->email = Core_Str::stripTags(Core_Array::getPost('email'));
   $oComment->phone = Core_Str::stripTags(Core_Array::getPost('phone'));
   $oComment->grade = intval(Core_Array::getPost('grade', 0));
   $oComment->subject = Core_Str::stripTags(Core_Array::getPost('subject'));
   $oComment->text = nl2br(Core_Str::stripTags(Core_Array::getPost('text'), $allowable_tags));
   $oComment->siteuser_id = $siteuser_id;
   
   $oShop_Item = Core_Entity::factory('Shop_Item', $Shop_Controller_Show->item);
   
   $oXmlCommentTag
   ->addEntity($oComment)
   ->addEntity($oShop_Item);
   
   if (is_null($oLastComment) || time() > Core_Date::sql2timestamp($oLastComment->datetime) + ADD_COMMENT_DELAY)
   {
   if (Core_Array::getPost('g-recaptcha-response'))
   {
   $sResponse = Core_Array::getPost('g-recaptcha-response');
   
   $sUrl = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $sSecretKey . "&response=" . $sResponse;
   
   $Core_Http = Core_Http::instance('curl')
   ->clear()
   ->method('POST')
   ->url($sUrl)
   ->execute();
   
   $oAnswer = json_decode($Core_Http->getBody());
   
   if ($oAnswer->success)
   {
   $oComment->save();
   
   $oComment
   ->dateFormat($oShop->format_date)
   ->dateTimeFormat($oShop->format_datetime);
   
   $oShop_Item->add($oComment)->clearCache();
   
   $oXmlCommentTag->addEntity($oShop);
   
   // Отправка письма администратору
   $sText = Xsl_Processor::instance()
   ->xml($oXmlCommentTag->getXml())
   ->xsl(Core_Entity::factory('Xsl')->getByName(Core_Array::get(Core_Page::instance()->libParams, 'addCommentAdminMailXsl')))
   ->process();
   
   $aFrom = array_map('trim', explode(',', EMAIL_TO));
   
   Core_Mail::instance()
   ->to(EMAIL_TO)
   ->from($aFrom[0])
   ->header('Reply-To', Core_Valid::email($oComment->email)
   ? $oComment->email
   : $aFrom[0]
   )
   ->subject(Core::_('Shop.comment_mail_subject'))
   ->message(trim($sText))
   ->contentType(Core_Array::get(Core_Page::instance()->libParams, 'commentMailNoticeType', 0) == 0
   ? 'text/plain'
   : 'text/html'
   )
   ->send();
   }
   else
   {
   Core_Log::write($oAnswer->error-codes);
   
   $oXmlCommentTag->addEntity(Core::factory('Core_Xml_Entity')
   ->name('error_captcha')->value(1)
   );
   
   $oComment->text = Core_Str::br2nl($oComment->text);
   $Shop_Controller_Show->addEntity($oComment);
   }
   }
   else
   {
   $oXmlCommentTag->addEntity(Core::factory('Core_Xml_Entity')
   ->name('error_captcha')->value(1)
   );
   
   $oComment->text = Core_Str::br2nl($oComment->text);
   $Shop_Controller_Show->addEntity($oComment);
   }
   }
   else
   {
   $oXmlCommentTag->addEntity(Core::factory('Core_Xml_Entity')
   ->name('error_time')->value(1)
   );
   
   $oComment->text = Core_Str::br2nl($oComment->text);
   $Shop_Controller_Show->addEntity($oComment);
   }
   
   // Результат добавления комментария
   $xsl_result = Xsl_Processor::instance()
   ->xml($oXmlCommentTag->getXml())
   ->xsl(Core_Entity::factory('Xsl')->getByName(
   Core_Array::get(Core_Page::instance()->libParams, 'addCommentNoticeXsl'))
   )
   ->process();
   
   $Shop_Controller_Show->addEntity(
   Core::factory('Core_Xml_Entity')
   ->name('message')->value($xsl_result)
   );
   }

где в переменной $sSecretKey указывается секретный ключ, который был получен вместе с ключом сайт при регистрации в Google reCAPTCHA.

Возможные ошибки

- При получении ошибки Exception: The property '_login' does not exist in the model 'lib' необходимо заменить:
- $Core_Http = Core_Http::instance('curl')
  ->clear()
  ->method('POST')
  ->url($sUrl)
  ->execute();
```
- $oAnswer = json_decode($Core_Http->getBody());

на:
- $oAnswer = json_decode(file_get_contents($sUrl));

---
Добавляем reCaptcha в форму, которая выводится в макете страницы
проверить работоспособность
<?php
       // Выводим шаблон страницы
       Core_Page::instance()->execute();
       echo '<div class="clear no-show"></div>';
       // add ФОРМА БЫСТРОГО ЗАКАЗА
       $oForm = Core_Entity::factory('Form', 4);  // Заменить id формы
       $Form_Controller_Show = new Form_Controller_Show($oForm);
       $sSecretKey = "6LeQXykUAAAAAGKJw3v6rNNXLPZ94QcuJEyqLkKK"; // Указывается секретный ключ reCAPTCHA
       if (!is_null(Core_Array::getPost($oForm->button_name)))
          {
       //------------------ add recaptha
        if (Core_Array::getPost('g-recaptcha-response'))
        {
            $sResponse = Core_Array::getPost('g-recaptcha-response');
            $sUrl = 'https://www.google.com/recaptcha/api/siteverify?secret='; . $sSecretKey . "&response=" . $sResponse;    
            $Core_Http = Core_Http::instance('curl')
            ->clear()
            ->method('POST')
            ->url($sUrl)
            ->execute();
            $aAnswer = json_decode($Core_Http->getBody(), TRUE);            
            
            if ($aAnswer['success'])
            {
         //------------------ end recaptha
         $Form_Controller_Show
         ->values($_POST + $_FILES)
         // 0 - html, 1- plain text
         ->mailType(0)
         ->mailXsl(
            Core_Entity::factory('Xsl')->getByName('ПисьмоКураторуФормыВФорматеHTML')
         )
         ->mailFromFieldName('reklama01@yandex.ru')
         ->process();
           //Отправляем письмо-подтверждение пользователю
           $Form_Controller_Show1 = clone $Form_Controller_Show;
           $sEmail = Core_Array::get($Form_Controller_Show1->values, 'email');
            if (Core_Valid::email($sEmail)){
            ob_start();
            $Form_Controller_Show1
                ->xsl(
                    Core_Entity::factory('Xsl')->getByName($Form_Controller_Show1->mailType == 0 ? 'ПисьмоПодтверждениеПользователюФормыВФорматеHTML' : 'ПисьмоПодтверждениеПользователюФормы')
                )
           ->show();
           $sMailText = ob_get_clean();
           if (mb_strpos($sMailText, 'ERROR TRUE') === FALSE){
           $subject = 'Вами была заполнена форма Быстрого заказа на сайте  krepco.ru';// Тема письма отредактировать
           // При текстовой отправке нужно преобразовать HTML-сущности в символы
           $Form_Controller_Show->mailType == 1 && $sMailText = html_entity_decode(strip_tags($sMailText), ENT_COMPAT, 'UTF-8');
           $oCore_Mail = Core_Mail::instance()
            ->to($sEmail)
            ->from(EMAIL_TO)
            ->subject($subject)
            ->message(trim($sMailText))
            ->contentType($Form_Controller_Show->mailType == 0 ? 'text/html' : 'text/plain')
            ->header('X-HostCMS-Reason', 'Form');
            // Массив содержащий пути прикрепленных файлов и их имена
            $aForm_Fields = $oForm->Form_Fields->findAll();
            foreach ($aForm_Fields as $oForm_Field){
            if ($oForm_Field->type == 2){// File
            $value = Core_Array::get($Form_Controller_Show->values, $oForm_Field->name);
            if (!is_null($value)){
            if (is_array($value) && $value['size'] > 0){
               $oForm_Fill_Fields = Core_Entity::factory('Form_Fill_Field');
               $oForm_Fill_Fields->queryBuilder()
                ->where('form_field_id', '=', $oForm_Field->id)
                ->where('value', '=', $value['name'])
                ->limit(1);
               $aForm_Fill_Fields = $oForm_Fill_Fields->findAll();
                 if (isset($aForm_Fill_Fields[0])){
                 $oCore_Mail->attach(array(
                    'filepath' => $aForm_Fill_Fields[0]->getPath(),
                    'filename' => $value['name']
                    ));
                   }
                  }
                 }
                }
               }
             $oCore_Mail->send();
            }
        }
        //-------------------------- add recaptha
         }
            else
            {
                Core_Log::instance()->clear()
                ->status(Core_Log::$ERROR)
                ->write('Google Recaptcha: ' . $aAnswer['error-codes'][0]);
         // add iNik
             $Form_Controller_Show
                  ->addEntity(
                  Core::factory('Core_Xml_Entity')
                  ->name('recaptcha_error')->value('1')
               );
           //----- end iNik
            }    
        }  
        //-------------------------- end recaptha
           }
       $Form_Controller_Show
          ->xsl(
        Core_Entity::factory('Xsl')->getByName('ОтобразитьФормуБыстрыйЗаказNEW3')
               )
           ->addEntity(
        Core::factory('Core_Xml_Entity')
           ->name('site_key')->value('6LeQXykUAAAAABVxo0YpLcOUaswIFlq519dGfWoP') // Указываете ключ reCAPTCHA
               )
           ->show();
    ?>