Подготавливаем страницу…
Подготавливаем страницу…
Самый надёжный способ интеграции: ключ sk_ остаётся на сервере, защита идёт через IP whitelist или HMAC. Подходит любому языку и любой инфраструктуре.
sk_ (secret, только server-side) forms_scope=[id1, id2, …] , и в каждом запросе передаёте form_id в body.Ключ создаёт менеджер 1ОПД и передаёт вам один раз. Все endpoints → API Reference
Прочитайте один раз: дальше в инструкции эти слова уже не будут пугать.
От этого зависит дальнейшая настройка.
Подходит: bare-metal сервер, VPS со статичным адресом, выделенный хостинг.
Ограничение: при смене сервера список надо обновлять. Для AWS Lambda, Cloud Run и kubernetes с динамическими адресами способ не подходит.
Подходит: контейнеры, serverless, кластеры, динамическая инфраструктура.
Ограничение: кода немного больше, каждый запрос нужно подписывать. Зато адрес отправителя роли не играет.
С выбранным типом защиты.
Зайдите в ЛК 1ОПД → «Интеграция» . Если ключа sk_ ещё нет, попросите менеджера его выпустить.
OPD_SECRET_B64, секрет в кодировке base64, показанный один раз.Не в код и не в git, только через ENV.
Никогда не записывайте sk_ и OPD_SECRET_B64 прямо в коде, держите их в ENV-переменных:
# В .env / /etc/environment / systemd Unit / docker-compose.yml
OPD_KEY=sk_abc12345678901234567890
# Для HMAC дополнительно:
OPD_SECRET_B64=base64encodedsecretXYZ== env[OPD_KEY]= либо getenv() из системного окружения.Ниже переключатель языка и опция HMAC.
Выберите язык (PHP, Node.js, Python) и отметьте «Подписывать HMAC», если работаете с этим типом защиты.
<?php
$body = json_encode([
"form_id" => 1, // ← form_id из ЛК 1ОПД
"hash_field" => $_POST["email"],
"fields" => [
["field" => "email", "value" => $_POST["email"]],
["field" => "name", "value" => $_POST["name"]],
["field" => "phone", "value" => $_POST["phone"]],
],
]);
$ch = curl_init("https://app.1opd.ru/api/v2/create-agreement");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => [
// sk_ + IP whitelist в ЛК ИЛИ sk_ + HMAC (переключите вкладку)
"API-KEY: sk_xxxxxxxxxxxxxxxxxxxx", // ← ваш sk_ ключ
"Content-Type: application/json",
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
$response = curl_exec($ch);
$data = json_decode($response, true);
curl_close($ch);
error_log("1ОПД hash: " . ($data["hash"] ?? "(error)")); form_id: 1 на свой номер формы из ЛК.fields к полям своей формы.OPD_KEY и, при HMAC, OPD_SECRET_B64 корректно читаются из ENV.Алгоритм нужен для отладки и для реализации на другом языке.
Подпись считают от конкатенации timestamp и тела запроса, разделённых переводом строки. Алгоритм HMAC-SHA256, результат в hex. Сам секрет лежит в base64: перед вычислением декодируйте его в байты.
API-SIGN = hex( HMAC-SHA256( ts + "\n" + body_bytes, base64_decode(secret) ) ) ts: unix-timestamp в секундах, строкой. Например 1731936000.body_bytes: точные байты отправляемого JSON. Сериализуйте его один раз и используйте и для подписи, и для отправки: любая разница в пробелах даёт неверную подпись. API-KEY + API-SIGN + API-TIMESTAMP .data=body, а не json=...: requests пересериализует JSON, и подпись не совпадёт. Сериализуйте через json.dumps(..., separators=(",", ":")), без лишних пробелов.Логи сервера и раздел «Согласия» в ЛК 1ОПД.
1ОПД hash: ABC123…. При ответе 202 hash не приходит: согласие принято в очередь, и его идентификатор отдаст GET /spool/status/<idempotency_key>.Самые частые проблемы и что с ними делать. Решает 95% случаев.
1. Сериализуйте JSON один раз: body = json.dumps(...), и используйте эту строку и для подписи, и для отправки.
2. В Python берите data=body, а не json=...: с json=... requests пересериализует тело, и подпись сломается.
3. Разделителем между ts и body служит именно \n (LF), а не CRLF.
4. Результат HMAC кодируйте в hex, а не в base64. В base64 приходит только сам секрет.
Синхронизируйте время через NTP: sudo timedatectl set-ntp true (Ubuntu, Debian).
Контейнер Docker наследует время хост-машины, поэтому проверяйте часы хоста.
Выполните на сервере curl ifconfig.me, узнайте текущий внешний адрес и добавьте его в ЛК 1ОПД → ключ → IP-whitelist.
Если у инфраструктуры несколько исходящих адресов (балансир, NAT-пул), внесите все.
Второй путь: перейти на HMAC, он от адреса не зависит.
1. Перезапустите сервис после изменения .env.
2. Для systemd добавьте в Unit-файл EnvironmentFile=/path/to/.env либо Environment="OPD_KEY=sk_...", затем systemctl daemon-reload и restart.
3. Для Docker проверьте, что переменная передана через docker-compose environment или --env-file.
4. На PaaS (Vercel, Railway, Render) внесите её в UI Environment Variables.
Выполните на сервере curl https://app.1opd.ru/healthz: ответом должен прийти JSON.
При timeout обратитесь к провайдеру и попросите открыть исходящий 443 для app.1opd.ru.
Чаще всего это встречается на дешёвых shared-хостингах.
Рекомендация: не блокируйте основную бизнес-логику. Оберните вызов 1ОПД в try/catch либо отправляйте его fire-and-forget, чтобы обработка формы шла как обычно.
Учтите и то, что 503 приходит редко: при недоступном бэкенде спул-шлюз отвечает 202 и доставляет согласие сам. 503 означает отказ и бэкенда, и очереди.
Для критичных потоков заводите локальную очередь (Redis, SQS, RabbitMQ) и повторяйте запись асинхронно: тогда согласие не потеряется и при одновременной недоступности обеих сторон.
Когда у каждого клиента отдельный тенант в 1ОПД со своим набором форм, у каждого свой ключ sk_. Храните в БД поля tenant.opd_api_key и tenant.opd_hmac_secret_b64.
Когда все клиенты пишут в один тенант 1ОПД (оператором персональных данных выступаете вы, а клиенты выступают субъектами), достаточно одного ключа sk_ и разных form_id через forms_scope.
Откройте ЛК → «Интеграция»: персональные snippet'ы + готовый HTML-чекбокс с авто-ссылками на согласие и политику + кнопка «IP-whitelist» для каждого ключа.
Открыть ЛК →Запросите тестовый доступ: выдаём ключ под ваш домен и помогаем подключиться.
Связаться →Все endpoints, коды ошибок, форматы HMAC/Origin/IP. Таблица «какую защиту выбрать».
Открыть →Успехом считаются и 200, и 202. Проверка «строго 200» отметит ошибкой согласие, которое 1ОПД принял и доставит.
В массиве fields передавайте любые из 28 полей ниже, имя поля стоит в столбце field. Обязательное одно: email, он же идентификатор субъекта (hash_field). Остальные 27 опциональны, незаполненное поле не передавайте. Все значения 1ОПД шифрует на своей стороне (AES-256-GCM). Актуальный список полей конкретной формы отдаёт POST /api/v2/get-fields.
| field | Название | Примечание |
|---|---|---|
email | Электронная почта | обязательное · идентификатор (hash_field) |
first_name | Имя | опциональное |
last_name | Фамилия | опциональное |
sur_name | Отчество | опциональное |
birth_date | Дата рождения | опциональное |
phone_number | Номер телефона | опциональное |
birth_place | Место рождения | опциональное |
registration_address | Адрес регистрации | опциональное |
delivery_address | Адрес доставки | опциональное |
passport_details | Паспортные данные | опциональное |
inn | ИНН | опциональное |
snils | СНИЛС | опциональное |
bank_details | Банковские реквизиты | опциональное |
account_vk | Аккаунт VK | опциональное |
account_telegram | Аккаунт Telegram | опциональное |
account_instagram | Аккаунт Instagram | опциональное |
account_facebook | Аккаунт Facebook | опциональное |
account_viber | Аккаунт Viber | опциональное |
account_ok | Аккаунт OK | опциональное |
account_whatsapp | Аккаунт WhatsApp | опциональное |
job_title | Должность | опциональное |
organization_name | Название организации | опциональное |
field_of_activity | Сфера деятельности | опциональное |
city | Город | опциональное |
mattermost_account | Аккаунт Mattermost | опциональное |
slack_account | Аккаунт Slack | опциональное |
ms_teams_account | Аккаунт MS Teams | опциональное |
sex | Пол | значения male / female · в карточках: «мужчина» / «женщина» |
Набор одинаков для всех способов интеграции (Tilda, WordPress, Bitrix, браузерный JS, server-side API). Каждое значение приходит строкой длиной до 5000 символов.