Интеграция dCAPTCHA на сайт

Выберите способ интеграции — добавление виджета в HTML-форму или прямое управление виджетом через JavaScript.

Капча обычно используется внутри HTML-форм: например для валидации пользователя при регистрации, входе на сайт, отправке комментария. В таком случае вы можете добавить виджет напрямую в форму, чтобы данные о прохождении CAPTCHA отправлялись при отправке формы.

Чтобы встроить виджет dCAPTCHA на странице сайта, добавьте скрипт в HTML страницы:

<script src="https://captcha.ddos-guard.net/static/api.js" defer></script>

Внутрь самой формы, в которой нужно разместить виджет, добавьте div с классом ddg-captcha-container. Обязательно укажите Site key в атрибуте data-sitekey:

<form action="https://example.com/register" method="post">
  <label>
    Email
    <input type="email" name="email" required />
  </label>
  <div
    class="ddg-captcha-container"
    data-sitekey="YOUR_SITEKEY"
  ></div>
  <button type="submit">Зарегистрироваться</button>
</form>
<script src="https://captcha.ddos-guard.net/static/api.js" defer></script>

Когда пользователь успешно проходит капчу, в форму добавляется скрытое поле ddg-captcha-token с уникальным токеном. Поскольку контейнер находится внутри формы, браузер автоматически отправляет это поле вместе с данными формы на бэкенд.

<!-- Это поле добавится автоматически после прохождения CAPTCHA -->
<input type="hidden" name="ddg-captcha-token" value="токен">

Бэкенд-сервер должен будет проверить полученный токен через API DDoS-Guard, чтобы убедиться, что клиент не подделал результат прохождения.

Проверку полученного ddg-captcha-token нельзя выполнять с фронтенда — private_key может храниться только на сервере

После добавления dCAPTCHA в форму переходите к конфигурации бэкенд-сервера для проверки токена

Этот способ используется для явного управления виджетом (explicit rendering). Ваше приложение в нужный момент выводит виджет dCAPTCHA и само отправляет результат (ddg-captcha-token) на бэкенд для проверки.

Подключение скрипта

Добавьте скрипт в HTML страницы, добавив query-параметр ?onload=initCaptcha. initCaptcha будет названием функции, которая запускает капчу после полной загрузки API.

Чтобы использовать явный рендер (скрипт не будет вставлять виджет в ddg-captcha-container, даже если такой элемент есть на странице) добавьте ?render=explicit.

<script src="https://captcha.ddos-guard.net/static/api.js?render=explicit&onload=initCaptcha" defer></script>

Объявление функции инициализации dCAPTCHA 

В коде приложения до загрузки API-скрипта объявите глобальную функцию initCaptcha (название функции может быть любым, но должно совпадать в коде и в query-параметре). Параметр onload=initCaptcha вызовет ее после загрузки API. Внутри функции используйте метод ready(), чтобы рендер происходил только после загрузки скрипта. 

Обработка токена dCAPTCHA через callback

При автоматическом рендере (как в способе 1, где скрипт сам находит место для виджета по классу ddg-captcha-container) название обработчика нужно указать в атрибуте data-callback контейнера dCAPTCHA:

<div
  class="ddg-captcha-container"
  data-sitekey="YOUR_SITEKEY"
  data-callback="handleCaptchaToken"
></div>

При явном рендере (explicit rendering, как в примере ниже) передайте саму функцию через параметр callback метода render().

Пример кода страницы (explicit rendering)

<div id="captcha-slot"></div>
<script>
  let registrationCaptchaId;
  async function submitCaptcha(token) {
    try {
      const response = await fetch("https://example.com/register", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          email: "visitor@example.com",
          "ddg-captcha-token": token,
        }),
      });
      if (!response.ok) {
        window.ddgcaptcha.reset(registrationCaptchaId);
      }
    } catch {
      window.ddgcaptcha.reset(registrationCaptchaId);
    }
  }
  window.initCaptcha = function () {
    window.ddgcaptcha.ready(() => {
      registrationCaptchaId = window.ddgcaptcha.render("captcha-slot", {
        sitekey: "YOUR_SITEKEY",
        callback: submitCaptcha,
      });
    });
  };
</script>
<script
  src="https://captcha.ddos-guard.net/static/api.js?render=explicit&onload=initCaptcha"
  defer
></script>
МетодПример

ready(callback)

Позволяет вызвать другой метод только после загрузки скрипта

window.ddgcaptcha.ready(() => { registrationCaptchaId = window.ddgcaptcha.render("captcha-slot", { sitekey: "YOUR_SITEKEY" }); });

render(container, parameters, inherit?)

Рендер виджета в элементе HTML (по ID или CSS-селектору).

  • inherit = true — использовать data-sitekey и data-callback из выбранного элемента в качестве резервных параметров
  • inherit = false — не использовать параметры выбранного элемента, всегда рендерить с параметрами, указанными в методе

 

registrationCaptchaId = window.ddgcaptcha.render("#captcha-slot", { sitekey: "YOUR_SITEKEY" }, false);

getResponse(widgetId?)

Получить текущий токен dCAPTCHA (или пустую строку, если dCAPTCHA еще не пройдена). Используйте, если нужно сохранить или дополнительно обработать токен на фронтенде

const token = window.ddgcaptcha.getResponse(registrationCaptchaId);

reset(widgetId?)

Сбросить состояние интерфейса без перезагрузки iframe. Используйте после неудачной проверки или для обновления виджета

function retryRegistration() { 
 window.ddgcaptcha.reset(registrationCaptchaId); 
}

Если в getResponse() или reset() не передан widgetId, метод сработает для первого виджета на странице. Если на странице несколько виджетов, используйте уникальный ID конкретного виджета (в примере выше — registrationCaptchaId).

Эти параметры указываются в качестве query-параметров в ссылке на загрузку скрипта (…/static/api.js?) и определяют его поведение на странице.

  • render=onload — автоматический рендер (используется по умолчанию), скрипт ищет контейнеры dCAPTCHA и отображает виджеты
  • render=explicit — явный рендер, отключает автоматический поиск контейнеров, приложение должно вызвать render() самостоятельно
  • onload={function} (например onload=initCaptcha) вызывает выбранную приложением глобальную функцию window.initCaptcha после загрузки API

 

После того как посетитель прошел проверку на фронтенде, ваш бэкенд-сервер должен проверить валидность полученного токена (ddg-captcha-token). Это необходимо, чтобы не дать злоумышленникам обойти капчу.

Запрос

Отправьте полученный токен вместе с валидным Private key на эндпоинт https://captcha.ddos-guard.net/siteverify:

Метод: POST   
Content-Type: application/json   
Тело запроса:

{
"response": "значение_ddg-captcha-token",
"private_key": "string"
}
  • response — одноразовый токен dCAPTCHA из поля ddg-captcha-token
  • private_key — Private Key вашего ключа dCAPTCHA

Не храните Private Key на фронтенде и не коммитьте его в публичные репозитории. Используйте безопасные методы хранения секретов на вашем бэкенде: переменные окружения или системы хранения секретов, например Vault. Убедитесь, что он не отображается в логах и сообщениях об ошибках

Ответ

Сервер вернет JSON-объект с результатом проверки:

{
"success": true,
"challenge_ts": "2023-10-05T12:34:56Z",
"hostname": "example.com",
"error-codes": []
}
  • "success": true — токен валиден, пользователь прошел проверку
  • "success": false — токен невалиден, причина указана в массиве error-codes

Примеры реализации

Пример с использованием фреймворка Express. createUser здесь представляет целевую операцию, например регистрацию пользователя. Она должна выполняться только после успешной проверки dCAPTCHA.

async function register(req, res) {
  const token = req.body["ddg-captcha-token"];
  if (!token) {
    return res.status(400).json({ error: "Пройдите CAPTCHA." });
  }
  let verificationResponse;
  try {
    verificationResponse = await fetch(
      "https://captcha.ddos-guard.net/siteverify",
      {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          response: token,
          private_key: process.env.DDG_CAPTCHA_PRIVATE_KEY,
        }),
      }
    );
  } catch {
    return res.status(503).json({ error: "Не удалось проверить CAPTCHA." });
  }
  if (!verificationResponse.ok) {
    return res.status(503).json({ error: "Не удалось проверить CAPTCHA." });
  }
  let verification;
  try {
    verification = await verificationResponse.json();
  } catch {
    return res.status(503).json({ error: "Не удалось проверить CAPTCHA." });
  }
  if (verification.success !== true) {
    return res.status(400).json({
      error: "CAPTCHA не пройдена.",
      codes: verification["error-codes"],
    });
  }
  const user = await createUser(req.body);
  return res.status(201).json({ id: user.id });
}

Настройте middleware в зависимости от способа получения токена. При получении токена через форму используйте express.urlencoded(), при получении токена из callback используйте express.json()

Пример кода для проверки токена (PHP, cURL)

Пример на чистом PHP. createUser($_POST) здесь представляет целевую операцию, например регистрацию пользователя. Она должна выполняться только после успешной проверки dCAPTCHA.

Пример написан для получения токена через форму (способ 1). Если токен отправляется через callback (способ 2), ddg-captcha-token нужно брать из переданного JSON, а не из $_POST

<?php
function respond(int $status, array $body): void
{
    http_response_code($status);
    header('Content-Type: application/json');
    echo json_encode($body);
    exit;
}
function register(): void
{
    $token = $_POST['ddg-captcha-token'] ?? '';
    if ($token === '') {
        respond(400, ['error' => 'Пройдите CAPTCHA.']);
    }
    $requestBody = json_encode([
        'response' => $token,
        'private_key' => $_ENV['DDG_CAPTCHA_PRIVATE_KEY'],
    ]);
    $curl = curl_init('https://captcha.ddos-guard.net/siteverify');
    curl_setopt_array($curl, [
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS => $requestBody,
        CURLOPT_RETURNTRANSFER => true,
    ]);
    $body = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    $curlFailed = $body === false;
    curl_close($curl);
    if ($curlFailed || $status !== 200) {
        respond(503, ['error' => 'Не удалось проверить CAPTCHA.']);
    }
    $verification = json_decode($body, true);
    if (!is_array($verification)) {
        respond(503, ['error' => 'Не удалось проверить CAPTCHA.']);
    }
    if (($verification['success'] ?? false) !== true) {
        respond(400, [
            'error' => 'CAPTCHA не пройдена.',
            'codes' => $verification['error-codes'] ?? [],
        ]);
    }
    $user = createUser($_POST);
    respond(201, ['id' => $user['id']]);
}

 

Обработка ошибок

Код ошибкиОписаниеРекомендуемое действие
missing-input-secretОтсутствует private_key в запросеПроверить конфигурацию бэкенда и передачу Private Key
missing-input-responseОтсутствует токен (response) в запросеУбедиться, что контейнер dCAPTCHA находится внутри формы и виджет создал поле ddg-captcha-token; потребовать от посетителя пройти капчу
invalid-input-secretПолученный токен сгенерирован другим ключом dCAPTCHAПроверить соответствие Site key на фронтенде и Private key на бэкенде: они должны относиться к одному ключу dCAPTCHA
invalid-input-responseТокен неверный или поддельныйЗаблокировать запрос, такая ошибка с высокой вероятностью указывает на попытку обхода защиты
timeout-or-duplicateТокен устарел или уже был использован ранееПопросить пользователя повторно пройти капчу
bad-requestНевалидный формат запросаПроверить конфигурацию бэкенда. Ошибка может возникать, если допущена ошибка в Private key

 

Оформление виджета dCAPTCHA гибко настраивается с помощью data-атрибутов, которые позволяют стилизовать каждый элемент виджета и адаптировать его к дизайну защищаемой страницы.

Подробнее о настройке внешнего вида читайте в инструкции Стилизация виджета