Яндекс SmartCaptcha + Contact Form 7 (обычная)

Это классический вариант: каптча видна в форме, и человек проходит её до отправки.
Ниже даю готовый блок для functions.php и тег для Contact Form 7.

Что нужно

  • Установлен и включён Contact Form 7

  • Ключи Yandex SmartCaptcha: sitekey и secret

Куда вставлять код

Я открываю functions.php активной темы
и вставляю блок ниже целиком. Если старый вариант уже стоит, просто заменяю его.

Полный код для functions.php

php
// Yandex Smart Captcha для Contact Form 7 - тег [yandex_captcha]
if (!defined('YANDEX_SMARTCAPTCHA_SITEKEY')) {
    define('YANDEX_SMARTCAPTCHA_SITEKEY', 'ваш_клиентский_ключ');
}
if (!defined('YANDEX_SMARTCAPTCHA_SECRET')) {
    define('YANDEX_SMARTCAPTCHA_SECRET', 'ваш_серверный_ключ');
}

add_action('wpcf7_before_send_mail', 'yandex_smart_captcha_verify', 10, 3);
function yandex_smart_captcha_verify($contact_form, &$abort = false, $submission = null) {
    $submission = WPCF7_Submission::get_instance();
    if (!$submission) {
        return;
    }

    $smart_captcha_token = isset($_POST['smart-token']) ? sanitize_text_field(wp_unslash($_POST['smart-token'])) : '';

    if ($smart_captcha_token === '') {
        $submission->set_status('spam');
        $submission->set_response('Пройдите проверку каптчи');
        $abort = true;
        return;
    }

    // POST https://captcha-api.yandex.ru/validate (без /v1/ - иначе 404)
    $url = 'https://captcha-api.yandex.ru/validate';

    $response = wp_remote_post($url, [
        'timeout' => 10,
        'body' => [
            'secret' => YANDEX_SMARTCAPTCHA_SECRET,
            'token' => $smart_captcha_token,
            'ip' => isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '',
        ],
    ]);

    if (is_wp_error($response) || (int) wp_remote_retrieve_response_code($response) !== 200) {
        $submission->set_status('spam');
        $submission->set_response('Ошибка проверки каптчи');
        $abort = true;
        return;
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);

    if (!is_array($body) || !isset($body['status']) || $body['status'] !== 'ok') {
        $submission->set_status('spam');
        $submission->set_response('Каптча не пройдена');
        $abort = true;
    }
}

add_action('wpcf7_init', 'kpv_add_yandex_captcha_cf7_tag');
function kpv_add_yandex_captcha_cf7_tag() {
    if (function_exists('wpcf7_add_form_tag')) {
        wpcf7_add_form_tag('yandex_captcha', 'kpv_yandex_captcha_tag_handler', ['nameless' => true]);
    } elseif (function_exists('wpcf7_add_shortcode')) {
        wpcf7_add_shortcode('yandex_captcha', 'kpv_yandex_captcha_tag_handler');
    }
}

function kpv_yandex_captcha_tag_handler($tag) {
    $uid = 'ysc-token-' . wp_generate_password(12, false, false);
    $sitekey = YANDEX_SMARTCAPTCHA_SITEKEY;

    return sprintf(
        '<div class="form__captcha"><span class="wpcf7-form-control-wrap yandex-captcha-wrap" data-token-field="%1$s">'
        . '<div class="smart-captcha" data-sitekey="%2$s" data-token-field="%1$s"></div>'
        . '<input type="hidden" name="smart-token" id="%1$s" value="" />'
        . '</span></div>',
        esc_attr($uid),
        esc_attr($sitekey)
    );
}

add_action('wp_enqueue_scripts', 'kpv_yandex_captcha_inline_style', 20);
function kpv_yandex_captcha_inline_style() {
    wp_add_inline_style('main', '.form__captcha{margin-bottom:20px;}');
}

add_action('wp_footer', 'kpv_yandex_captcha_scripts', 20);
function kpv_yandex_captcha_scripts() {
    if (is_admin()) {
        return;
    }
    if (!defined('WPCF7_VERSION')) {
        return;
    }
    ?>
    <script src="https://smartcaptcha.yandexcloud.net/captcha.js" defer></script>
    <script>
    (function () {
        function renderAll() {
            if (!window.smartCaptcha || typeof window.smartCaptcha.render !== 'function') {
                return false;
            }
            document.querySelectorAll('.smart-captcha[data-sitekey]').forEach(function (el) {
                if (el.getAttribute('data-ysc-rendered')) {
                    return;
                }
                var tokenId = el.getAttribute('data-token-field');
                var input = tokenId ? document.getElementById(tokenId) : null;
                window.smartCaptcha.render(el, {
                    sitekey: el.getAttribute('data-sitekey'),
                    hl: 'ru',
                    callback: function (token) {
                        if (input) {
                            input.value = token;
                        }
                    }
                });
                el.setAttribute('data-ysc-rendered', '1');
            });
            return true;
        }
        function tick() {
            if (renderAll()) {
                return;
            }
            setTimeout(tick, 50);
        }
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', tick);
        } else {
            tick();
        }
    })();
    </script>
    <?php
}

Что писать в форме CF7

В редакторе формы добавляю тег:

text
[yandex_captcha]

Пример целиком:

text
[text* your-name placeholder "Имя"]
[tel* your-phone placeholder "Телефон"]
[submit "Отправить"]
[yandex_captcha]

Проверка

  1. Откройте страницу с формой

    Обновляю страницу с очисткой кэша через Ctrl+F5.

  2. Отправка без каптчи

    Проверяю, что без каптчи отправка блокируется сообщением вроде «Пройдите проверку каптчи».

  3. Пройдите каптчу и отправьте

    Прохожу каптчу и смотрю, что письмо и статус CF7 проходят штатно.

Элемент Роль
[yandex_captcha] Показывает виджет и добавляет hidden-поле smart-token
wpcf7_before_send_mail На сервере проверяет токен через API Яндекса
captcha-api.yandex.ru/validate URL проверки, важно использовать без /v1/

Безопасность ключей

Я храню ключи не в теме, а в wp-config.php —
так при смене темы ничего не теряется:

php
define('YANDEX_SMARTCAPTCHA_SITEKEY', 'ваш_клиентский_ключ');
define('YANDEX_SMARTCAPTCHA_SECRET', 'ваш_серверный_ключ');
Про видимую и невидимую версии.

В этом варианте виджет всегда перед глазами.
Если хотите без чекбокса, берите мою статью про invisible SmartCaptcha.

← К списку статей

Поделиться

Комментарии

Пока нет комментариев — можете написать первый.

Оставить комментарий

Войти с помощью

или оставьте комментарий как гость

Отправка защищена сервисом Yandex SmartCaptcha. Подробности — в политике конфиденциальности.