vvb/yandex-smart-captcha

Yandex Smart Captcha integration for Laravel 10/11/12/13

Maintainers

Package info

github.com/VVBphp/yandex-captcha-laravel

Homepage

Issues

pkg:composer/vvb/yandex-smart-captcha

Transparency log

Statistics

Installs: 207

Dependents: 0

Suggesters: 0

Stars: 2

v1.0.1 2026-07-26 17:08 UTC

This package is auto-updated.

Last update: 2026-07-26 17:10:08 UTC


README

Latest Version PHP Version Laravel Version

Пакет для интеграции Yandex Cloud Smart Captcha в Laravel приложения. Поддерживает Blade-компоненты, Vue 3 компонент, JS-хелпер для API-only проектов, валидацию через Rule, Facade и переводы.

Установка

composer require vvb/yandex-smart-captcha

Миграция с v0.x

Breaking Changes

  • Конфиг: добавлены новые ключи (script_url, validate_url, language, theme, test, http_timeout, enabled, validate_host). После обновления выполните:
    php artisan vendor:publish --tag=config --force
  • Имя скрытого поля токена: теперь всегда smart-token (ранее было настраиваемое)
  • Новые пропсы Blade-компонента: container, formId, lang, theme, test, invisible, shieldPosition, hideShield, enabled
  • Конструктор Service: теперь принимает массив конфига вместо двух строк
  • Синглтон привязан к строке 'yandex-smart-captcha' (исправлен баг с Facade/Rule)

Что продолжает работать без изменений

  • Facade YandexSmartCaptcha::verify()
  • Rule new YandexSmartCaptchaRule()
  • Синглтон app('yandex-smart-captcha')

What's New in v1.0

  • Invisible-режим (execute/executePromise)
  • Vue 3 компонент с v-model и lazy load
  • JS-хелпер (ES-модуль) для SPA/API-only
  • Опциональная валидация хоста (validate_host)
  • Переводы сообщений валидации (ru/en)
  • Тестовый режим (test)

Настройка

  1. Получите ключи в Yandex Cloud Console
  2. Добавьте в .env:
YANDEX_SMART_CAPTCHA_CLIENT_KEY=your_client_key
YANDEX_SMART_CAPTCHA_SERVER_KEY=your_server_key
# Опционально:
YANDEX_SMART_CAPTCHA_SCRIPT_URL=https://smartcaptcha.cloud.yandex.ru/captcha.js
YANDEX_SMART_CAPTCHA_VALIDATE_URL=https://smartcaptcha.cloud.yandex.ru/validate
YANDEX_SMART_CAPTCHA_LANGUAGE=ru
YANDEX_SMART_CAPTCHA_THEME=auto
YANDEX_SMART_CAPTCHA_TEST=false
YANDEX_SMART_CAPTCHA_HTTP_TIMEOUT=30
YANDEX_SMART_CAPTCHA_ENABLED=true
YANDEX_SMART_CAPTCHA_VALIDATE_HOST=false
  1. Опубликуйте конфиг (при обновлении — с флагом --force):
php artisan vendor:publish --tag=config --provider="vvb\YandexSmartCaptcha\YandexSmartCaptchaServiceProvider"

Использование

Blade-компонент

<form method="POST">
    @csrf
    
    {{-- Стандартный вид --}}
    <x-yandex-smart-captcha::smart-captcha />

    {{-- С кастомным контейнером --}}
    <div id="my-captcha-container"></div>
    <x-yandex-smart-captcha::smart-captcha container="my-captcha-container" />

    {{-- Invisible режим (требует JS вызов executeWidget) --}}
    <x-yandex-smart-captcha::smart-captcha invisible form-id="my-form" />
    
    {{-- С переопределением языка/темы --}}
    <x-yandex-smart-captcha::smart-captcha lang="en" theme="dark" />

    <button type="submit">Отправить</button>
</form>

Пропсы компонента:

Пропс Тип По умолчанию Описание
container string null auto (uniqid)
formId string null null
lang string config('yandex-smart-captcha.language') Язык виджета (ru, en, uk, tr, lv)
theme string config('yandex-smart-captcha.theme') Тема: light, dark, auto
test bool config('yandex-smart-captcha.test') Тестовый режим Яндекса
invisible bool false Невидимый режим (требует ручной вызов executeWidget)
shieldPosition string null null
hideShield bool false Скрыть уведомление об обработке данных
enabled bool config('yandex-smart-captcha.enabled') Отключает рендер капчи (возвращает пустой div)

Важно: Виджет создаёт <input type="hidden" name="smart-token" value="..."> внутри контейнера. Используйте имя поля smart-token при валидации.

Валидация (PHP Rule)

use vvb\YandexSmartCaptcha\Rules\YandexSmartCaptchaRule;

public function store(Request $request)
{
    $request->validate([
        'smart-token' => [new YandexSmartCaptchaRule],
    ]);
    
    // Ваша логика
}

Кастомные сообщения:

new YandexSmartCaptchaRule(
    message: 'Неверная капча!',
    emptyMessage: 'Пожалуйста, пройдите проверку'
)

Или через языковые файлы (resources/lang/{locale}/validation.php):

return [
    'yandex_smart_captcha_rule' => 'Капча не пройдена',
    'yandex_smart_captcha_empty' => 'Требуется подтверждение капчи',
];

PHP API (Facade / Service)

use vvb\YandexSmartCaptcha\Facades\YandexSmartCaptcha;

// Проверка токена
YandexSmartCaptcha::verify($token, $ip = null);

// Получить client_key
YandexSmartCaptcha::getClientKey();

// Получить публичный конфиг (без server_key)
YandexSmartCaptcha::getConfig();

Или через сервис:

$service = app('yandex-smart-captcha');
$service->verify($token);
$service->getClientKey();
$service->getConfig();

Invisible-режим (Blade + JS)

<x-yandex-smart-captcha::smart-captcha invisible form-id="my-form" />
// В вашем JS перед отправкой формы
const formId = 'my-form';
const widgetId = window.__smartcaptchaContainers[formId]?.widgetId;

if (widgetId) {
    const token = await window.smartCaptcha.executePromise(widgetId);
    // token содержит одноразовый токен
    // добавьте его в форму и отправьте
}

Vue 3 компонент

Установка и регистрация:

// resources/js/app.js
import YandexSmartCaptcha from 'vvb/yandex-smart-captcha/resources/js/vue/YandexSmartCaptcha.vue';

app.component('YandexSmartCaptcha', YandexSmartCaptcha);

Или локально в компоненте:

<script setup>
import YandexSmartCaptcha from 'vvb/yandex-smart-captcha/resources/js/vue/YandexSmartCaptcha.vue';
</script>

Использование:

<template>
    <YandexSmartCaptcha
        v-model="captchaToken"
        :enabled="true"
        :invisible="false"
        :lang="lang"
        :theme="theme"
        @success="onCaptchaSuccess"
        @token-expired="onTokenExpired"
        ref="captchaRef"
    />
</template>

<script setup>
import { ref } from 'vue';
import YandexSmartCaptcha from 'vvb/yandex-smart-captcha/resources/js/vue/YandexSmartCaptcha.vue';

const captchaToken = ref('');
const captchaRef = ref(null);
const lang = 'ru';
const theme = 'auto';

const onCaptchaSuccess = (token) => {
    console.log('Token received:', token);
};

const onTokenExpired = () => {
    captchaRef.value.resetToken();
};

// При ошибке валидации (422)
const handleFormSubmit = async () => {
    try {
        await submitForm();
    } catch (e) {
        if (e.response?.status === 422) {
            captchaRef.value.resetToken(); // сброс виджета + обнуление v-model
        }
    }
};
</script>

Пропсы Vue:

Пропс Тип По умолчанию Описание
modelValue (v-model) string '' Токен капчи
container string auto ID контейнера или CSS-селектор
lang string VITE_SMARTCAPTCHA_LANG или ru Язык
theme string VITE_SMARTCAPTCHA_THEME или auto Тема
test bool VITE_SMARTCAPTCHA_TEST Тестовый режим
invisible bool false Невидимый режим
shieldPosition string null null
hideShield bool false Скрыть уведомление об обработке данных
enabled bool true Включить/выключить капчу
formId string null null
scriptUrl string null VITE_SMARTCAPTCHA_SCRIPT_URL

Эмиты:

  • update:modelValue (token) — новый токен
  • success (token) — успешное прохождение
  • token-expired — токен устарел
  • network-error — ошибка сети
  • javascript-error (error) — JS ошибка
  • challenge-visible / challenge-hidden — состояние челленджа

Expose-методы (через ref):

  • getResponse() — текущий токен
  • reset() — сброс виджета
  • resetToken() — сброс виджета + обнуление v-model
  • execute() — запуск invisible капчи
  • executePromise() — Promise с токеном (invisible)

Переменные окружения (Vite):

VITE_SMARTCAPTCHA_KEY=your_client_key
VITE_SMARTCAPTCHA_SCRIPT_URL=https://smartcaptcha.cloud.yandex.ru/captcha.js
VITE_SMARTCAPTCHA_LANG=ru
VITE_SMARTCAPTCHA_THEME=auto
VITE_SMARTCAPTCHA_TEST=false

JS-хелпер (ES-модуль)

Для API-only проектов или ручного управления:

import {
    loadSmartCaptchaScript,
    destroySmartCaptcha,
    getResponse,
    resetWidget,
    executeWidget,
    executeWidgetPromise
} from 'vvb/yandex-smart-captcha/resources/js/captcha.js';

// Загрузка скрипта (один раз на приложение)
await loadSmartCaptchaScript({
    scriptUrl: 'https://smartcaptcha.cloud.yandex.ru/captcha.js',
});

// Рендер виджета вручную
const widgetId = window.smartCaptcha.render(container, {
    sitekey: 'your_client_key',
    hl: 'ru',
    theme: 'auto',
});

// Invisible
const token = await executeWidgetPromise(widgetId);

// Получение токена
const token = getResponse(widgetId);

// Сброс
resetWidget(widgetId);

// Очистка при unmount
destroySmartCaptcha(widgetId, containerId);

Важно — токены

  • Токен SmartCaptcha можно использовать только один раз. После отправки формы токен сгорает.
  • При ошибке валидации (422) необходим новый токен:
    • Vue: используйте resetToken() через defineExpose
    • Blade: перезагрузка страницы
  • Время жизни токена — 5 минут. По истечении токен недействителен.

Конфигурация (config/yandex-smart-captcha.php)

return [
    'client_key' => env('YANDEX_SMART_CAPTCHA_CLIENT_KEY'),
    'server_key' => env('YANDEX_SMART_CAPTCHA_SERVER_KEY'),
    'script_url' => env('YANDEX_SMART_CAPTCHA_SCRIPT_URL', 'https://smartcaptcha.cloud.yandex.ru/captcha.js'),
    'validate_url' => env('YANDEX_SMART_CAPTCHA_VALIDATE_URL', 'https://smartcaptcha.cloud.yandex.ru/validate'),
    'language' => env('YANDEX_SMART_CAPTCHA_LANGUAGE', 'ru'),
    'theme' => env('YANDEX_SMART_CAPTCHA_THEME', 'auto'),
    'test' => env('YANDEX_SMART_CAPTCHA_TEST', false),
    'http_timeout' => env('YANDEX_SMART_CAPTCHA_HTTP_TIMEOUT', 30),
    'enabled' => env('YANDEX_SMART_CAPTCHA_ENABLED', true),
    'validate_host' => env('YANDEX_SMART_CAPTCHA_VALIDATE_HOST', false),
];

Логирование

При ошибках API логируется на уровень ERROR:

  • HTTP ошибки (не 200)
  • Некорректный JSON ответ
  • Ошибки соединения (таймаут, DNS, SSL)

При status: failed с непустым messageWARNING (диагностика неверного ключа/токена). При validate_host=true и несовпадении хоста — WARNING.

При enabled=false — никаких HTTP запросов и логирования.

Тестирование

Установлены dev-зависимости: pestphp/pest, orchestra/testbench.

./vendor/bin/pest

Лицензия

MIT License.

Документация Yandex SmartCaptcha