Как решить reCAPTCHA v3 на PHP и задать action

solve recaptcha v3 in php - How to Solve reCAPTCHA v3 in PHP and Set an Action

reCAPTCHA v3 никогда не показывает задачу. Она незаметно оценивает визит и выдаёт странице токен, который затем проверяет backend сайта. Для вашего кода это значит, что кликать не по чему, поэтому вся задача сводится к тому, чтобы получить токен, который примет сайт. В PHP это тот же самый recaptcha метод, который вы использовали бы для v2, с флагом версии в массиве options.

От чего зависит, сработает ли это, — так это action.

Настройка

# PHP 8.0+, with the curl and json extensions.
composer require capskip/capskip
use CapSkip\CapSkip;

$solver = new CapSkip([
    'host' => '127.0.0.1',
    'port' => 8080,
    'recaptchaTimeout' => 300,   // seconds, shared with Turnstile and GeeTest
]);

CapSkip работает на вашем компьютере, поэтому сначала должно быть открыто десктопное приложение.

Базовый вызов

$result = $solver->recaptcha(
    '6Lc...YOUR_SITEKEY',
    'https://example.com/checkout',
    [
        'version' => 'v3',
        'action' => 'submit',
    ]
);

echo $result['code'];   // the v3 token

Два отличия от v2. version должен быть v3, и action должен совпадать с тем, что страница передаёт в grecaptcha.execute. Опустите его, и по умолчанию будет verify.

Почему действие имеет значение

Action — это метки, которые сайт присваивает каждому защищённому взаимодействию, чтобы вход и оформление заказа могли оцениваться отдельно. Большинство бэкендов проверяют, что action, содержащийся в токене, совпадает с тем, который они ожидали для этого эндпоинта.

Отправьте неверную метку — и токен будет настоящим, но помеченным для другого взаимодействия, что многие проверяющие системы отклоняют сразу. Считывайте реальное значение со страницы, а не угадывайте:

$html = file_get_contents('https://example.com/checkout');

// Sites normally call execute() with the action as a string literal.
preg_match('/execute\([^,]+,\s*\{\s*action:\s*[\'"]([^\'"]+)/', $html, $m);
$action = $m[1] ?? 'verify';

$result = $solver->recaptcha($sitekey, $pageUrl, [
    'version' => 'v3',
    'action' => $action,
]);

Обычные значения — login, submit, homepage и checkout, но это произвольные строки, выбранные тем, кто создавал сайт.

Enterprise v3

$result = $solver->recaptcha($sitekey, $pageUrl, [
    'version' => 'v3',
    'enterprise' => 1,
    'action' => 'submit',
]);

Enterprise — это ортогональный флаг, а не отдельный продукт, поэтому он накладывается на вызов v3. Различайте их по скрипту, который загружает страница: Enterprise подгружает enterprise.js, стандартный извлекает api.js. Неверная догадка приводит к сбою решения, а не к возврату плохого токена, поэтому проверить ничего не стоит.

Отправка токена

$ch = curl_init('https://example.com/checkout');

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'token' => $result['code'],
        'order_id' => '...',
    ]),
]);

$response = curl_exec($ch);
curl_close($ch);

В отличие от v2, здесь нет стандартного виджета формы, ограничивающего структуру, поэтому интеграции v3 различаются. Некоторые используют скрытое g-recaptcha-response input, другие отправляют JSON с пользовательским ключом. Проверьте собственный JavaScript страницы, прежде чем предполагать имя поля.

Ошибки

use CapSkip\Exceptions\ApiException;
use CapSkip\Exceptions\NetworkException;
use CapSkip\Exceptions\TimeoutException;

try {
    $result = $solver->recaptcha($sitekey, $pageUrl, ['version' => 'v3']);
} catch (NetworkException $e) {
    // CapSkip is not running on the configured port
} catch (ApiException $e) {
    // the sitekey or pageurl was rejected
} catch (TimeoutException $e) {
    // exceeded recaptchaTimeout
}

Обратите внимание на CapSkip\Exceptions пространство имён. Копирование импортов из примеров для Python или Node — частый источник фатальных ошибок здесь.

Часто задаваемые вопросы

Могу ли я проверить оценку перед отправкой?

Нет. Score хранится у Google и раскрывается владельцу сайта только когда его backend проверяет токен. На стороне клиента вы получаете лишь токен и ничего больше, поэтому заранее нечего проверять или фильтровать.

Стоит ли решать капчу внутри веб-запроса?

Желательно нет. PHP синхронен, а решение может занять несколько секунд, поэтому выполнение его во время рендеринга страницы занимает воркер на всё это время. Вынесите его в задачу очереди или в CLI-воркер.

Что, если страница вообще не задаёт action?

Некоторые страницы вызывают execute без него, и в этом случае по умолчанию verify верен. Если ваше регулярное выражение ничего не находит, обычно причина именно в этом, а не в ошибке парсинга.

Сводка

Установить version в v3, сопоставьте action к тому, что выполняет страница, добавьте enterprise когда она загружается enterprise.js, импортируйте исключения из CapSkip\Exceptions, и отправляйте токен быстро, потому что он истекает примерно через две минуты.

Другие языки рассматриваются на решение для reCAPTCHA v3 странице, детали Enterprise на Сервис распознавания Enterprise страница, а более широкий охват PHP — на Решатель капчи для PHP страница. Посмотрите, как токен генерируется вживую на нашей демо v3. CapSkip — это распознавание капчи который работает на вашем оборудовании.