← На главную

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` без токенов
  считать проверку пройденной. В своём коде можно вынести то же значение в
  конфиг или переменные окружения. Согласуйте с разделом «Правила» в ЛК.