Расширенное подключение через JavaScript API
Расширенное подключение — это способ добавить Servicepipe Widget CAPTCHA на страницу сайта и управлять виджетом из JavaScript-кода.
Особенности подключения:
-
Доступно три варианта появления капчи: виджет уже стоит в нужном месте после загрузки страницы, виджет появляется на странице после определённого события (логику вы задаёте сами), модальное окно открывается после определённого события (логику вы задаёте сами).
-
Для создания и управления виджетом нужно написать JavaScript-код.
-
Виджет настраивается через опции JavaScript API.
-
Токен можно получить через callback-функцию, результат метода
SPCaptcha.execute()или скрытое поле. -
Этот способ подходит, если момент и способ показа капчи должны зависеть от логики вашего приложения.
|
Если вам достаточно постоянно показывать капчу в заданном месте страницы и настраивать её через HTML-атрибуты, используйте автоматическое подключение через HTML-атрибуты. |
Как работает эта интеграция:
-
Вы подключаете SDK Servicepipe Widget CAPTCHA на страницу и настраиваете запуск проверки через JavaScript API. Доступны два сценария на выбор:
-
Пользователь видит виджет с чекбоксом «Я не робот». Этот виджет может появиться сразу после загрузки страницы либо после заданного действия пользователя (момент настраиваете вы). Когда пользователь установит в чекбоксе флажок, откроется модальное окно.
-
Когда пользователь совершает заданное действие (например, жмёт кнопку «Войти»), откроется модальное окно.
-
-
Пользователь открывает вашу страницу, взаимодействует с ней и доходит до открытия модального окна.
-
Servicepipe рассчитывает bot score пользователя.
Если
bot scoreпользователя низкий, модальное окно закрывается автоматически. Проверка считается пройденной.Если bot score выше порогового значения, в модальном окне появляется задание капчи.
-
Пользователь проходит капчу.
Если прошёл неуспешно или поведение было похоже на бота, он получает новое задание. Новая капча может выдаваться бесконечно — это ловушка для ботов, которая заставляет их снова и снова тратить ресурсы на решение, не допуская до защищаемого действия.
Если прошёл успешно, модальное окно закрывается. Параллельно с этим Servicepipe присылает в браузер токен, который свидетельствует, что капча пройдена человеком.
-
Ваш JavaScript-код отправляет полученный токен на бекэнд вместе с данными защищаемого действия.
-
Ваш бекэнд обращается к Servicepipe, чтобы проверить полученный токен. Если с токеном всё в порядке, можно разрешить пользователю выполнить защищаемое действие. Если токен не прошёл проверку, действие лучше отклонить — скорее всего, его выполняет злоумышленник.
Следуя шагам ниже, вы подключите Servicepipe Widget CAPTCHA через JavaScript API, выберете способ показа капчи, настроите обработку полученного токена на бекэнде и протестируете интеграцию.
|
При работе с этой статьёй вам может пригодиться справочник по интеграции. Откройте ссылки в новой вкладке, чтобы нужная информация всегда была под рукой: Методы управления виджетом, Опции метода SPCaptcha.render(), Опции метода SPCaptcha.execute(), События виджета, Ошибки виджета в браузере, Ошибки при серверной проверке токена. |
1. Получите SiteKey и ApiKey
Мы передадим вам два значения:
-
SiteKey— публичный ключ виджета. На следующих шагах вы передадите его в JavaScript API, чтобы SDK узнал ваш сайт и отдал нужную конфигурацию капчи.SiteKeyбудет виден в коде страницы и не является секретом.
|
У вас может быть несколько |
-
ApiKey— приватный серверный ключ. Ваш бекэнд использует его, когда обращается к API Servicepipe, чтобы проверить токен пользователя. По этому ключу наша система узнает вас как клиента и выдаст результат проверки.
|
|
2. Подключите JavaScript-скрипт на страницу
Есть два варианта подключения скрипта. Выбор зависит от того, как ваш код должен узнать о том, что SDK загрузился и его методы стали доступны.
Вариант 1: когда SDK будет готов, он сам вызовет функцию инициализации капчи (вы создадите её на шаге 3). Функция должна находиться в глобальной области видимости.
Вариант 2: ваш код передаст функцию инициализации капчи (вы создадите её на шаге 3) непосредственно в SDK. Когда SDK будет готов, он вызовет эту функцию.
|
Если на вашем сайте используется Content Security Policy, браузер может заблокировать загрузку скрипта или iframe с капчей. В этом случае добавьте домен |
Если вам подходит вариант 1 (SDK сам вызывает функцию инициализации), добавьте скрипт Servicepipe Widget CAPTCHA в тег <head> так:
<script
src="https://captcha.servicepipe.tech/captcha.js?render=explicit&onload=initCaptcha"
async
defer
></script>
Здесь initCaptcha — имя функции инициализации. Вы можете выбрать для неё другое имя.
Если вам подходит вариант 2 (ваш код передаёт функцию инициализации в SDK), подключите SDK и файл с кодом приложения в теге <head>. Оба скрипта должны иметь атрибут defer, а файл приложения должен находиться после SDK:
<script
src="https://captcha.servicepipe.tech/captcha.js?render=explicit"
defer
></script>
<script src="/js/captcha-init.js" defer></script>
Браузер выполнит defer-скрипты в порядке их расположения: сначала SDK, затем captcha-init.js. Не добавляйте атрибут async, поскольку он не гарантирует порядок выполнения скриптов.
|
Параметры в URL выполняют следующие задачи:
|
3. Настройте показ капчи
На этом шаге вы выберете способ показа капчи, создадите функцию инициализации с нужной логикой и свяжете её со скриптом, подключённым на шаге 2.
JavaScript API поддерживает два сценария:
| Способ | Как работает |
|---|---|
|
Создаёт капчу в определённом месте страницы. Капчу можно показать сразу после загрузки SDK или после действия пользователя. |
|
Открывает капчу в модальном окне. |
Выберите подходящий сценарий. Дальше даём подробную инструкцию для каждого.
Сценарий 1. Показать капчу на странице через SPCaptcha.render()
1. Добавьте контейнер
Вставьте пустой контейнер в место страницы, где должна появиться капча:
<div id="signup-captcha"></div>
2. Напишите функцию инициализации
Создайте функцию инициализации — для примера назовём её initCaptcha(). Внутри вы:
-
подготовите опции виджета;
-
создадите виджет через
SPCaptcha.render(); -
при необходимости добавите функции для обработки результата, ошибок и истечения токена;
-
сможете использовать методы управления виджетом;
-
при необходимости подпишетесь на события виджета.
Общая структура функции будет выглядеть так:
function initCaptcha() {
let widget;
const options = {
// Опции виджета
};
widget = SPCaptcha.render("#signup-captcha", options);
// Здесь можно подписаться на события виджета
}
Добавьте вызов SPCaptcha.render()
Для создания виджета вызовите внутри initCaptcha() метод:
SPCaptcha.render(container, options);
Метод принимает два аргумента:
-
container— контейнер, внутри которого появится капча; -
options— объект с опциями виджета.
Контейнер можно передать как CSS-селектор:
"#signup-captcha"
Или как DOM-элемент:
document.querySelector("#signup-captcha")
Например:
function initCaptcha() {
const widget = SPCaptcha.render("#signup-captcha", options);
}
Метод создаст капчу внутри контейнера и вернёт объект виджета.
Подготовьте объект с опциями
Передайте вторым аргументом SPCaptcha.render() объект с нужными опциями.
| Опция | Значение | Что делает | Обязательна |
|---|---|---|---|
|
Значение |
Передаёт публичный ключ виджета. По этому ключу Servicepipe определяет, к какой интеграции относится виджет и какие настройки капчи нужно применить. |
Да |
|
По умолчанию: |
Задаёт язык интерфейса капчи. Доступны два значения: Если опция не указана, капча будет на русском. |
Нет |
|
Ваша функция, принимающая токен |
Задаёт функцию, которую SDK вызовет, если капча пройдена успешно. В эту функцию SDK передаст токен. Функцию вы напишете далее. |
Нет. Но токен всё равно должен быть получен. Сделать это можно одним из способов: через опцию |
|
Ваша функция, принимающая объект ошибки |
Задаёт функцию, которую SDK вызовет, если при работе виджета возникнет ошибка в браузере. В эту функцию SDK передаст объект с Функцию вы напишете далее. |
Нет |
|
Ваша функция без аргументов |
Задаёт функцию, которую SDK вызовет, когда срок действия уже полученного токена истечёт. Функцию вы напишете далее. |
Нет |
|
Ваша функция без аргументов |
Задаёт функцию, которую SDK вызовет после создания виджета и его перехода в состояние готовности. Функцию вы напишете далее. |
Нет |
|
Ваша функция без аргументов |
Задаёт функцию, которую SDK вызовет, когда задание капчи станет видно пользователю. Функцию вы напишете далее. |
Нет |
|
Ваша функция без аргументов |
Задаёт функцию, которую SDK вызовет при скрытии задания капчи: например, после успешного прохождения, ошибки или закрытия модального окна пользователем. Функцию вы напишете далее. |
Нет |
|
|
Создаёт скрытое поле для токена внутри HTML-элемента виджета. Если пользователь успешно пройдёт капчу, SDK запишет токен в это поле. |
Нет. Но токен всё равно должен быть получен. Сделать это можно одним из способов: через опцию |
|
Имя поля, например По умолчанию: |
Задаёт имя скрытого поля с токеном, которое вы включили через Если опция не указана, SDK создаст поле с именем по умолчанию — |
Нет |
Например, внутри initCaptcha() можно подготовить такой объект:
function initCaptcha() {
const options = {
siteKey: "<SITE_KEY>",
language: "ru",
responseField: true,
responseFieldName: "sp-captcha-token"
};
const widget = SPCaptcha.render("#signup-captcha", options);
}
В этом объекте вы:
-
передали публичный ключ виджета через
siteKey; -
выбрали русский язык через
language; -
включили создание скрытого поля через
responseField— в него SDK запишет токен, если пользователь успешно пройдёт капчу; -
задали этому полю имя
sp-captcha-tokenчерезresponseFieldName.
Добавьте функции, которые вы указали в опциях
В качестве значения callback, onError, onExpired или другой callback-опции вы передали функцию. Её можно написать прямо внутри объекта options:
const options = {
siteKey: "<SITE_KEY>",
onExpired() {
submitButton.disabled = true;
status.textContent = "Пройдите проверку ещё раз.";
}
};
Другой вариант — объявить функцию отдельно внутри initCaptcha() и передать ссылку на неё:
function handleExpired() {
submitButton.disabled = true;
status.textContent = "Пройдите проверку ещё раз.";
}
const options = {
siteKey: "<SITE_KEY>",
onExpired: handleExpired
};
|
Здесь handleExpired — функция, которую SDK вызовет после истечения срока действия токена. |
Внутри функций, переданных в options, можно использовать методы управления виджетом, предусмотренные SDK. Для этого сохраните объект, который вернул SPCaptcha.render():
let widget;
widget = SPCaptcha.render("#signup-captcha", options);
В свойстве widget.id находится идентификатор созданного виджета:
const widgetId = widget.id;
Передавайте этот идентификатор методам управления, чтобы SDK понимал, с каким виджетом выполнить действие.
|
Если у вас на странице всего одна капча, эти методы можно вызывать без аргумента — SDK и так поймёт, что вы обращаетесь к единственному виджету. |
| Метод | Что делает | Когда пригодится |
|---|---|---|
|
Возвращает текущий токен. Если токен ещё не получен либо уже истёк, вернёт пустую строку. |
Когда токен нужно прочитать позднее, а не обрабатывать сразу через callback или событие. |
|
Очищает токен и возвращает виджет в исходное состояние. Важно: после истечения срока действия токена SDK очищает его автоматически. Дополнительно вызывать |
Когда пользователь начинает новое защищаемое действие или предыдущий сценарий нужно запустить заново. |
|
Удаляет содержимое, обработчики и таймеры виджета. Сам внешний контейнер остаётся на странице. |
При удалении компонента со страницы, переходе между экранами SPA или полной замене виджета. |
Например, передадим в опцию onError функцию handleError. Если при работе капчи возникнет ошибка, эта функция удалит текущий виджет через SPCaptcha.destroy() и покажет пользователю кнопку для повторной загрузки виджета:
function initCaptcha() {
const status = document.querySelector("#captcha-status");
const retryButton = document.querySelector("#captcha-retry");
let widget;
function handleError(error) {
console.error("CAPTCHA error:", error.code, error.message);
if (widget) {
SPCaptcha.destroy(widget.id);
widget = undefined;
}
status.textContent =
"Не удалось загрузить антибот-проверку. Нажмите «Повторить».";
retryButton.hidden = false;
}
const options = {
siteKey: "<SITE_KEY>",
onError: handleError
};
function renderCaptcha() {
widget = SPCaptcha.render("#signup-captcha", options);
}
retryButton.addEventListener("click", function() {
retryButton.hidden = true;
status.textContent = "";
renderCaptcha();
});
renderCaptcha();
}
В этом примере:
-
handleErrorуказана как значение опцииonError; -
SDK вызывает
handleError, если при работе виджета возникает ошибка; -
внутри
handleErrorметодSPCaptcha.destroy()удаляет текущий виджет по идентификаторуwidget.id; -
после удаления виджета функция показывает сообщение и кнопку «Повторить»;
-
обработчик кнопки скрывает её, очищает сообщение и повторно вызывает
renderCaptcha(); -
renderCaptcha()создаёт новый виджет в том же контейнере.
Подпишитесь на события виджета (опционально)
Сначала создайте виджет и получите его объект. Затем вызовите метод subscribe():
const widget = SPCaptcha.render("#signup-captcha", options);
const unsubscribe = widget.subscribe(eventName, handler);
Передайте методу два аргумента:
-
eventName— название события; -
handler— функция, которую SDK вызовет при наступлении события.
Метод вернёт функцию unsubscribe. Вызовите её, когда подписка больше не нужна.
Доступны следующие события:
| Событие | Когда возникает | Что получает обработчик |
|---|---|---|
|
Виджет создан и готов к работе. Событие отправляется асинхронно после |
Без данных |
|
Задание капчи стало видно пользователю. |
Без данных |
|
Задание начинает скрываться после успешной проверки, ошибки или отмены. |
Без данных |
|
SDK получил токен, записал его в скрытое поле, если оно включено, и запустил отсчёт срока действия токена. |
Объект с |
|
Срок действия токена истёк. Перед отправкой события SDK очищает токен. |
Без данных |
|
При работе виджета или iframe произошла ошибка. |
Объект с |
|
Модальное окно полностью закрылось. Событие возникает после |
Без данных |
|
Для виджета вызван |
Без данных |
|
Для виджета вызван |
Без данных |
Например, так можно отправить событие об успешно пройденной капче в аналитику:
const widget = SPCaptcha.render("#signup-captcha", options);
const unsubscribeSuccess = widget.subscribe(
"success",
function(event) {
window.analytics?.track("captcha_success");
}
);
|
Если вы уже обрабатываете состояние через |
Выберите момент создания виджета
Если капча должна появиться сразу после готовности SDK, вызовите функцию создания виджета внутри initCaptcha():
function initCaptcha() {
function renderCaptcha() {
widget = SPCaptcha.render("#signup-captcha", options);
}
renderCaptcha();
}
Если капча должна появиться после действия пользователя, вызовите renderCaptcha() в обработчике этого действия:
function initCaptcha() {
const showButton = document.querySelector("#show-captcha");
function renderCaptcha() {
widget = SPCaptcha.render("#signup-captcha", options);
}
showButton.addEventListener("click", renderCaptcha);
}
Пример полной функции инициализации
Ниже показана функция initCaptcha(), которая объединяет описанные выше действия. В примере капча появляется сразу после готовности SDK. Также настроены обработка ошибок, истечение токена, повторное создание виджета и необязательная подписка на события.
function initCaptcha() {
const submitButton = document.querySelector("#signup-submit");
const status = document.querySelector("#captcha-status");
const retryButton = document.querySelector("#captcha-retry");
let widget;
let subscriptions = [];
function removeSubscriptions() {
subscriptions.forEach(function(unsubscribe) {
unsubscribe();
});
subscriptions = [];
}
function handleError(error) {
console.error("CAPTCHA error:", error.code, error.message);
if (widget) {
removeSubscriptions();
SPCaptcha.destroy(widget.id);
widget = undefined;
}
submitButton.disabled = true;
status.textContent =
"Не удалось загрузить антибот-проверку. Нажмите «Повторить».";
retryButton.hidden = false;
}
function handleExpired() {
submitButton.disabled = true;
status.textContent = "Пройдите проверку ещё раз.";
}
const options = {
siteKey: "<SITE_KEY>",
language: "ru",
responseField: true,
responseFieldName: "sp-captcha-token",
onError: handleError,
onExpired: handleExpired
};
function subscribeToEvents(currentWidget) {
subscriptions = [
currentWidget.subscribe("success", function() {
submitButton.disabled = false;
status.textContent = "";
retryButton.hidden = true;
window.analytics?.track("captcha_success");
}),
currentWidget.subscribe("error", function(event) {
window.analytics?.track("captcha_error", {
code: event.code
});
}),
currentWidget.subscribe("expired", function() {
window.analytics?.track("captcha_expired");
})
];
}
function renderCaptcha() {
widget = SPCaptcha.render("#signup-captcha", options);
subscribeToEvents(widget);
}
function retryCaptcha() {
retryButton.hidden = true;
status.textContent = "";
if (widget) {
removeSubscriptions();
SPCaptcha.destroy(widget.id);
widget = undefined;
}
renderCaptcha();
}
retryButton.addEventListener("click", retryCaptcha);
renderCaptcha();
}
В этом примере:
-
initCaptcha()получает элементы интерфейса и создаёт переменные для хранения виджета и подписок; -
объект
optionsзадаёт ключ, язык, скрытое поле и функции обработки; -
handleError()иhandleExpired()передаются в SDK через опцииonErrorиonExpired; -
renderCaptcha()создаёт виджет черезSPCaptcha.render(), сохраняет его объект в переменнойwidgetи добавляет подписки; -
если возникает ошибка,
handleError()отменяет подписки, удаляет текущий виджет черезSPCaptcha.destroy(), отключает отправку формы и показывает кнопку «Повторить»; -
subscribeToEvents()подписывается на событияsuccess,errorиexpired; -
после успешной проверки обработчик события
successвключает кнопку отправки формы; -
retryButton.addEventListener()связывает кнопку «Повторить» с функциейretryCaptcha(); -
после нажатия «Повторить» функция скрывает кнопку, очищает сообщение, удаляет оставшийся виджет, если он ещё существует, и вызывает
renderCaptcha()повторно; -
новый виджет создаётся в том же контейнере. Контейнер и остальные элементы формы не перезагружаются, поэтому введённые пользователем данные сохраняются;
-
последний вызов
renderCaptcha()создаёт первый виджет сразу после выполненияinitCaptcha().
3. Свяжите функцию инициализации со скриптом
Используйте вариант, который соответствует способу подключения скрипта, выбранному вами на шаге 2.
Если SDK должен сам вызвать функцию инициализации, сделайте её глобальной:
window.initCaptcha = initCaptcha;
Имя initCaptcha должно совпадать со значением параметра onload в URL скрипта.
Если код приложения подключён отдельным defer-скриптом после SDK, вызовите в этом файле SPCaptcha.ready(). Метод дождётся готовности SDK и DOM, а затем вызовет функцию инициализации:
SPCaptcha.ready(initCaptcha);
Сценарий 2. Открыть капчу в модальном окне через SPCaptcha.execute()
1. Подготовьте опции
Метод SPCaptcha.execute() открывает модальное окно с капчей и возвращает Promise. После успешного прохождения капчи результатом Promise будет токен:
const token = await SPCaptcha.execute(options);
Метод принимает следующие опции:
| Опция | Значение | Что делает | Обязательная |
|---|---|---|---|
|
Значение |
Передаёт публичный ключ виджета. По нему Servicepipe определяет интеграцию и настройки капчи. |
Да |
|
По умолчанию: |
Задаёт язык интерфейса капчи. Доступны два значения: Если опция не указана, капча будет на русском. |
Нет |
|
Ваша функция, принимающая токен |
Вызывается после успешного прохождения капчи и получает токен. Её можно использовать вместо результата |
Нет |
Например:
const options = {
siteKey: "<SITE_KEY>",
language: "ru"
};
2. Создайте функцию инициализации
Создайте функцию инициализации — для примера назовём её initCaptcha(). Внутри найдите нужные элементы страницы и добавьте обработчик действия, после которого должна открыться капча.
Например, чтобы запускать проверку при отправке формы, можно написать такую функцию:
function initCaptcha() {
const form = document.querySelector("#signup-form");
form.addEventListener("submit", async function(event) {
event.preventDefault();
const token = await SPCaptcha.execute(options);
});
}
Обработчик останавливает стандартную отправку формы и вызывает SPCaptcha.execute().
3. Обработайте результат проверки
При использовании await поместите вызов SPCaptcha.execute() в try…catch:
try {
const token = await SPCaptcha.execute(options);
// Добавьте токен в запрос к своему бекэнду.
} catch (error) {
// Обработайте отмену или ошибку проверки.
}
Если пользователь успешно пройдёт капчу, токен будет сохранён в переменной token.
Если пользователь закроет модальное окно, Promise будет отклонён с ошибкой execution-cancelled. Другие ошибки также попадут в блок catch.
Полный список ошибок виджета в браузере
| Код ошибки | Сообщение |
|---|---|
|
Контейнер CAPTCHA не найден. |
|
|
|
Не удалось определить адрес поставщика из URL SDK-скрипта. |
|
CAPTCHA сообщила об ошибке. |
|
Не удалось загрузить iframe CAPTCHA. |
|
Не удалось загрузить iframe CAPTCHA за отведённое время. |
|
Срок действия токена CAPTCHA истёк. |
|
Проверка CAPTCHA была отменена: пользователь закрыл модальное окно, оно закрылось автоматически или был вызван |
|
Виджет был уничтожен. Например, вызвали |
|
Нет доступного виджета CAPTCHA для выполнения проверки. Например, вызвали |
Если вы используете опцию callback, SDK передаст токен в эту функцию.
|
Не обрабатывайте один и тот же результат одновременно через |
4. Добавьте возможность повторить проверку (опционально)
Если пользователь закрыл модальное окно или при проверке произошла ошибка, можно показать кнопку «Повторить». Её обработчик должен повторно вызвать функцию, внутри которой выполняется SPCaptcha.execute().
Страницу при этом перезагружать не нужно, поэтому введённые пользователем данные сохранятся.
5. Свяжите функцию инициализации со скриптом
Используйте вариант, который соответствует способу подключения скрипта, выбранному вами на шаге 2.
Если SDK должен сам вызвать функцию инициализации, сделайте её глобальной:
window.initCaptcha = initCaptcha;
Если код приложения подключён отдельным defer-скриптом после SDK, вызовите в этом файле SPCaptcha.ready(). Метод дождётся готовности SDK и DOM, а затем вызовет функцию инициализации:
SPCaptcha.ready(initCaptcha);
Пример полного подключения через SPCaptcha.execute()
Ниже показан весь процесс на примере формы регистрации. Пример включает защиту от повторного запуска проверки, обработку отмены и ошибок, кнопку повторной попытки и отправку токена на бекэнд.
Добавляем форму:
<form id="signup-form" action="/signup" method="post">
<input type="email" name="email">
<input type="password" name="password">
<button id="signup-submit" type="submit">
Зарегистрироваться
</button>
<p id="captcha-status"></p>
<button id="captcha-retry" type="button" hidden>
Повторить
</button>
</form>
Создаём функцию инициализации:
function initCaptcha() {
const form = document.querySelector("#signup-form");
const submitButton = document.querySelector("#signup-submit");
const status = document.querySelector("#captcha-status");
const retryButton = document.querySelector("#captcha-retry");
const options = {
siteKey: "<SITE_KEY>",
language: "ru"
};
let isChecking = false;
async function submitWithCaptcha() {
if (isChecking) {
return;
}
isChecking = true;
submitButton.disabled = true;
retryButton.hidden = true;
status.textContent = "Проверяем, что вы не бот...";
try {
let token;
try {
token = await SPCaptcha.execute(options);
} catch (error) {
retryButton.hidden = false;
if (error.code === "execution-cancelled") {
status.textContent =
"Проверка отменена. Нажмите «Повторить», чтобы продолжить.";
return;
}
console.error("CAPTCHA error:", error.code, error.message);
status.textContent =
"Не удалось пройти проверку. Нажмите «Повторить».";
return;
}
status.textContent = "Отправляем данные...";
const formData = new FormData(form);
formData.set("sp-captcha-token", token);
const response = await fetch(form.action, {
method: form.method,
body: formData
});
if (!response.ok) {
throw new Error(
`Form submission failed with status ${response.status}`
);
}
status.textContent = "";
} catch (error) {
console.error("Form submission error:", error);
status.textContent =
"Не удалось отправить форму. Нажмите «Зарегистрироваться» ещё раз.";
} finally {
isChecking = false;
submitButton.disabled = false;
}
}
form.addEventListener("submit", function(event) {
event.preventDefault();
submitWithCaptcha();
});
retryButton.addEventListener("click", submitWithCaptcha);
}
Связываем функцию со скриптом одним из способов:
window.initCaptcha = initCaptcha;
Или:
SPCaptcha.ready(initCaptcha);
В этом примере:
-
Обработчик
submitостанавливает стандартную отправку формы и вызываетsubmitWithCaptcha(). -
Переменная
isCheckingне позволяет одновременно запустить несколько проверок. -
SPCaptcha.execute()открывает модальное окно и ожидает прохождения капчи. -
После успешной проверки
awaitсохраняет полученный токен в переменнойtoken. -
Код добавляет токен в
FormDataпод именемsp-captcha-tokenи отправляет форму на бекэнд. -
Если пользователь закрыл модальное окно или произошла ошибка, код показывает сообщение и кнопку «Повторить».
-
После нажатия «Повторить» функция
submitWithCaptcha()запускается снова. Страница не перезагружается, поэтому введённые данные сохраняются. -
Ошибки отправки формы обрабатываются отдельно от ошибок капчи.
-
Блок
finallyзавершает текущую попытку и снова включает кнопку отправки.
4. Отправьте токен на бэкенд
|
Это обязательный шаг. Получив токен на бэкенде, далее вы проверите, действительно ли:
Такая проверка защищает от злоумышленников, чьи боты пытаются обойти защиту, отправляя запросы со старыми токенами или подставляя вместо токена произвольное значение в надежде, что бэкенд проверяет только его наличие. |
После успешного прохождения капчи отправьте токен на бекэнд вместе с данными защищаемого действия.
Если вы создали виджет через SPCaptcha.render(), получить и передать токен можно несколькими способами:
-
Если включена опция
responseField, SDK запишет токен в скрытое поле. Когда контейнер виджета находится внутри формы, это поле попадёт в данные формы при отправке. Имя поля задаётся черезresponseFieldName. По умолчанию используется имяcaptcha-token. -
Если токен получен через
callbackили событиеsuccess, добавьте его в запрос самостоятельно. -
Чтобы получить текущий токен позднее, вызовите
SPCaptcha.getResponse(widgetId). Метод вернёт токен либо пустую строку, если токен ещё не получен или уже истёк.
Если вы открыли капчу через SPCaptcha.execute(), добавьте в запрос токен, который метод вернул через await или передал в callback.
Настройте бекэнд на получение поля, в котором вы передаёте токен. Например, если токен отправляется в поле sp-captcha-token, бекэнд должен считывать значение поля с этим именем.
5. Проверьте токен через серверный API
Чтобы проверить токен, отправьте с бекэнда такой запрос:
curl -H "X-Api-Key: <API_KEY>" \
"https://captcha.servicepipe.tech/<SITE_KEY>/verify?jwt=<TOKEN>"
Замените значения:
-
<API_KEY>— на приватный ключ, который мы передали вам на шаге 1; -
<SITE_KEY>— на публичный ключ виджета, который мы передали вам на шаге 1; -
<TOKEN>— на токен, который получил ваш бекэнд.
Если ваш бекэнд может определить IP пользователя, также передайте его в параметре ip:
curl -H "X-Api-Key: <API_KEY>" \
"https://captcha.servicepipe.tech/<SITE_KEY>/verify?jwt=<TOKEN>&ip=<USER_IP>"
Параметр ip необязательный, но рекомендуем передавать его, если это возможно. Если капчу прошли в одном окружении, а токен используют в другом (так часто работают фермы по прохождению капчи), параметр IP поможет это выявить. В этом случае наша система покажет, что проверка токена провалена, и вы не допустите злоумышленника до защищаемого действия.
6. Обработайте ответ проверки
Если токен прошёл проверку, Servicepipe вернёт ответ с success: true:
{
"success": true,
"request_id": "...",
"site_key": "<SITE_KEY>"
}
Это значит, всё в порядке — капчу правда решил человек. В этом случае продолжайте обработку защищаемого действия. Например, если капча защищала страницу входа в ваш сервис, можно дать пользователю войти.
Если токен не прошёл проверку, Servicepipe вернёт success: false и поле error — объяснение, что было не так. Также может вернуть дополнительные диагностические поля, например, validation_check — информацию, истёк срок действия токена или ещё нет на момент проверки.
Пример такого ответа:
{
"success": false,
"error": "invalid_jwt",
"validation_check": "expired"
}
Список возможных значений error
Значение поля error |
Описание |
|---|---|
|
Отсутствуют обязательные параметры. Например, не передан |
|
Токен не прошёл проверку. Например, токен повреждён, просрочен, уже использован повторно или содержит некорректные |
|
В JWT отсутствует или пустой |
|
В JWT отсутствует или пустой |
|
|
|
Временная ошибка серверного хранилища. |
При success: false, не выполняйте защищаемое действие автоматически.
Если токен повреждён, просрочен, уже использован или содержит некорректные iat или exp, попросите пользователя пройти капчу повторно и отправьте новый токен на проверку.
Ошибки missing_required_params, invalid_jwt_request_id, invalid_jwt_site_key и path_mismatch могут указывать на неправильную настройку интеграции или некорректно сформированный запрос. Повторное прохождение капчи обычно их не устранит. Запишите ошибку в журнал и проверьте обязательные параметры, передаваемый токен и соответствие SiteKey в URL и токене.
Отдельный случай: результат проверки не удалось получить из-за временной ошибки Servicepipe. К таким ситуациям относятся storage_error, недоступность API, тайм-аут, сетевая ошибка или ответ HTTP 5xx. Повторное прохождение капчи не устранит причину ошибки. В этом случае можно использовать один из двух подходов:
-
Fail-closed: не выполнять защищаемое действие, пока токен не удастся проверить. Этот подход обеспечивает более строгую защиту и подходит для атакуемых или дорогостоящих операций, например отправки SMS или регистрации аккаунта.
-
Fail-open: разрешить защищаемое действие без подтверждённого результата проверки, если API временно недоступен. Этот подход сохраняет доступность сервиса, но снижает защиту от ботов. Используйте его только там, где такой риск допустим.
7. Проверьте интеграцию
Настройка закончена. Теперь рекомендуем пройти весь сценарий на тестовой странице:
-
Откройте страницу, где подключён SDK.
-
Убедитесь, что функция инициализации была вызвана после готовности SDK.
-
Если вы используете
SPCaptcha.render(), проверьте, что виджет появился в нужном месте страницы.Если вы используете
SPCaptcha.execute(), выполните защищаемое действие и убедитесь, что модальное окно открылось в нужный момент. -
Пройдите капчу.
-
Выполните защищаемое действие.
-
Проверьте, что бекэнд получил токен.
-
Проверьте, что бекэнд отправил токен в Servicepipe и получил
success: true. -
Убедитесь, что защищаемое действие выполняется только после успешной серверной проверки.
-
Проверьте сценарий с закрытием модального окна или истечением токена. Защищаемое действие не должно выполняться без нового действующего токена.
|
Если виджет не появился или модальное окно не открылось, проверьте, что:
|