Captcha v2 для встраивания на сайт
Captcha v2 для встраивания на сайт
================================
Цель: как у reCAPTCHA v3 — сначала «невидимо», при необходимости — проверка
в модальном окне, без вставки лишних блоков в разметку формы.
Онлайн: этот текст доступен на публичной странице сервиса — к вашему
`index.php` добавьте `?route=/docs/v2-flow` (или откройте раздел «Обзор»
по `?route=/docs`).
Привязка к сайту
----------------
В личном кабинете задаётся домен. Запросы из браузера к API капчи должны
идти с Origin/Referer, чей хост совпадает с доменом или является поддоменом.
Быстрый старт (HTML)
--------------------
1. URL точки входа API — базовый адрес `index.php` капчи, как показан
в личном кабинете (все маршруты вида `?route=/…`).
2. Подключите скрипт **после** разметки формы (или с атрибутом `defer`),
чтобы в момент выполнения скрипта форма уже была в DOM:
<script defer
src="https://example.com/captcha/index.php?route=/assets/loader-v2.js">
</script>
База API берётся из `src` скрипта (origin + путь до `index.php`).
3. На `<form>` обязательно:
- `data-site-key="ck_pub_…"` — публичный ключ из ЛК;
- `data-captcha-guard="v2"` — без этого скрипт форму не привязывает.
Опционально: `data-field-message="message"` — имя поля с текстом письма
(по умолчанию ищутся имена: message, body, text, comment).
Опционально: `data-captcha-strict-network="1"` — всегда при ошибке сети
или не-2xx от `/v2/decide` **не** отправлять форму (перекрывает политику
сервиса). Иначе загрузчик запрашивает `GET /v2/client-policy?site_key=…` и
ведёт себя по `CAPTCHA_SUBMIT_WHEN_CAPTCHA_UNREACHABLE` в конфиге сервиса
(разрешить отправку с `captcha_service_unavailable=1` или блокировать). В ответе может быть
`form_min_total_chars` (если в ЛК задан «Свой минимум символов»): тогда
при сумме длин имя+телефон+сообщение меньше этого числа отправка не идёт,
страница перезагружается (без `/v2/decide` и без POST на ваш бэкенд).
Ответ `POST /v2/decide` может содержать `quiet_reload_excessive_decide_submits: true`,
если в ЛК включена настройка «лишние нажатия Отправить» (поле
`opt_same_body_min_ips`, порог N≥2): в счёт идут только запросы `action=submit`,
где нужна модалка, а в JSON **нет** поля `attestation` (ещё одно «лишнее» нажатие
без досыла после решения капчи). Запрос с `attestation` после модалки и
успешный невидимый проход счётчик не увеличивают (после невидимого / успешного
attestation счётчик сбрасывается). С (N+1)-го такого нажатия загрузчик один раз
перезагружает страницу вместо модалки; POST на ваш бэкенд не выполняется.
Порог «разных IP с одним текстом» для эвристики same-body задаёт только
администратор сервиса в глобальных настройках.
Пример полей, которые читает загрузчик: `name` / `fio` / `fullname`,
`phone` / `tel` / `telephone`, текст — по `data-field-message` или
перечисленные выше имена.
4. При успешной проверке скрипт сам отправит форму с одним из скрытых
полей:
- `captcha_invisible_pass` — невидимый проход;
- `captcha_attestation` — после решения модалки step-up (challenge).
5. Если `/v2/decide` недоступен (сеть, таймаут ~14 с, HTTP не 2xx,
невалидный JSON): при `CAPTCHA_SUBMIT_WHEN_CAPTCHA_UNREACHABLE=1` в конфиге
и без `data-captcha-strict-network="1"` скрипт может отправить форму
с `captcha_service_unavailable=1`. При политике «строго» — форма не уйдёт,
пользователь увидит ошибку. На сервере сайта при маркере решайте сами:
отклонять, модерация или `CAPTCHA_VERIFY_FAIL_OPEN` (в примерах
`examples/server_verify.php` и `.py` — переменная в начале файла;
в MODX — `captcha.verify_fail_open` и при необходимости свой URL в
`captcha.verify_submission_url`; см. `modx/INSTALL.txt`). Это не синхронизируется с кабинетом
и задаётся только в вашем коде.
Сервер сайта
------------
- Принять POST формы.
- **Проще всего (PHP):** один запрос `POST https://s.go-up.info/index.php?route=/v2/verify-submission`
с заголовком `Authorization: Bearer cs_sec_…` и JSON-телом:
`invisible_pass`, `attestation`, `captcha_service_unavailable`, `user_ip` (IP посетителя),
`verify_fail_open` (bool), опционально дублируйте секрет полем `secret` (тот же `cs_sec_…`) —
на части PHP/хостингов исходящий `file_get_contents` не передаёт `Authorization`. Ответ: `valid: true/false`.
См. `examples/server_verify.php`.
- Если есть `captcha_invisible_pass` — вызвать
`POST …/index.php?route=/v2/verify-invisible` с секретом сайта
(`Authorization: Bearer cs_sec_…`) и телом JSON:
`{ "invisible_pass": "<значение из формы>", "user_ip": "<IP клиента>" }`.
IP — тот же, что видит ваш веб-сервер для этого запроса (за прокси —
первый адрес из `X-Forwarded-For` или эквивалент).
- Если пришёл `captcha_attestation` (после step-up) — проверить подпись на сервере:
`POST …/index.php?route=/v1/verify` с секретом и телом `{"attestation":"…"}`
(см. примеры в `examples/server_verify.*`).
- Если пришло только `captcha_service_unavailable=1` (без токенов) — сервис
капчи был недоступен в браузере; при необходимости примите заявку при
`CAPTCHA_VERIFY_FAIL_OPEN=1` или отложите в модерацию.
Примеры PHP и Python — в `examples/server_verify.php` и
`examples/server_verify.py`. MODX — `modx/INSTALL.txt` и сниппет
`snippet.CaptchaVerify.php` (один POST на `/v2/verify-submission`).
Клиент (кратко)
---------------
Скрипт `loader-v2.js` создаёт сессию в cookie, перед отправкой запрашивает
политику и вызывает `/v2/decide`; при необходимости показывает модалку
с короткой задачей и подставляет скрытые поля. Повторные отправки с одной
сессии браузера могут потребовать прохождения модалки; при отказе сервис
возвращает понятное сообщение пользователю — обрабатывайте ответ формы
на своём бэкенде как обычно.
Политика fail-open на **вашем** сайте
--------------------------------------
- В примерах `examples/server_verify.php` и `server_verify.py` в начале файла
задаётся `$CAPTCHA_VERIFY_FAIL_OPEN` / `CAPTCHA_VERIFY_FAIL_OPEN` (`0` или `1`):
при сетевой ошибке verify или при `captcha_service_unavailable=1` без токенов
считать проверку пройденной. В своём коде можно вынести то же значение в
конфиг или переменные окружения. Согласуйте с разделом «Правила» в ЛК.