# Инструкция для 1С-разработчиков: интеграция с Cert4U

## Подключение

| Параметр | Значение |
|----------|----------|
| **Базовый URL** | `https://cert4u.ru/api.php` (метод задаётся параметром `action`; в настройках обработки: адрес `cert4u.ru`, путь `/api.php`) |
| **Авторизация** | Заголовок `X-Api-Key: КЛЮЧ` (рекомендуется). Поддерживаются также `Authorization: Bearer КЛЮЧ` и — для обратной совместимости — GET-параметр `api_key` (не рекомендуется: ключ попадает в логи) |
| **Ключ** | Личный кабинет → Настройки → API-ключи. Ключ принадлежит одному аккаунту: все методы видят только документы и клиентов этого аккаунта |
| **Формат** | Ответ — JSON (UTF-8). Тело POST — JSON (`Content-Type: application/json`), форма или `multipart/form-data` (для файлов) |
| **Лимиты** | 60 запросов/мин с IP и 60/мин на ключ (превышение — 429) + лимиты тарифа (402 / 429) |
| **Идемпотентность** | Заголовок `Idempotency-Key: <ключ>` на `api_1c_upload`, `api_1c_upload_signed`, `api_1c_send_document`, `api_1c_pep_send`, `api_1c_pep_bulk` — повтор с тем же ключом (24 ч) не создаёт дубль и не шлёт повторную SMS |
| **Песочница** | Заголовок `X-Cert4U-Sandbox: 1` (или `sandbox=1`, или флаг на ключе) — без реальной отправки SMS/email, код ПЭП `000000`, лимиты не списываются |

> В примерах ниже указан только путь и `action`; ключ передаётся заголовком `X-Api-Key`.

## Самый простой путь: отправка одним запросом

Загрузить файл и сразу отправить получателю на подпись — клиента заранее создавать не нужно.

```
POST /api.php?action=api_1c_send_document
X-Api-Key: КЛЮЧ
Idempotency-Key: 1c-doc-000123          (необязательно, но рекомендуется)
Content-Type: multipart/form-data

Поля:
  document     — файл (pdf, doc, docx, txt, rtf, odt, xls, xlsx, png, jpg, jpeg)   обязательно
  client_name  — ФИО / наименование получателя                                   обязательно
  client_phone — телефон получателя      } нужен хотя бы один
  client_email — email получателя        }
  sign_type    — "pep_only", "ukep_only" или пусто (на выбор получателя)
  doc_name     — название (по умолчанию имя файла)
  description, company, inn — необязательно

Ответ:
{
  "success": true,
  "document_id": "3f9615873bf58c77",
  "document": {...},
  "sign_url": "https://cert4u.ru/client.html?token=...",
  "sign_token": "...",
  "pep_code": "533441",
  "client": {"id": "...", "name": "...", "phone": "...", "email": "..."},
  "sandbox": false,
  "notifications": {...}
}
```

Получатель ищется среди контактов **вашего аккаунта** по телефону/email (`8 900…`, `+7 (900)…`
и `900…` из 10 цифр — один номер); если не найден — создаётся скрытый контакт (в списке клиентов
и в `api_1c_clients` не виден). Документ сразу получает статус `sent`, без подписи отправителя.
Повторно получить ссылку — `api_1c_pep_status` (поле `sign_url`).

## Полный цикл подписания документа (пошагово)

### Шаг 1: Загрузка документа
```
POST /api.php?action=api_1c_upload
Content-Type: multipart/form-data

Поля:
  document — файл (PDF, DOCX, XLSX и др.)
  doc_name — название документа (необязательно, по умолчанию «Без названия»)
  description — описание (необязательно)
  client_id — ID клиента (необязательно, можно указать при отправке)

Ответ:
  {"success": true, "document": {"id": "abc123...", "status": "new", ...}}
```

### Шаг 2: Подпись отправителя

> **Вариант А (`api_1c_sign_admin`) ОТКЛЮЧЁН — отвечает HTTP 410:** серверная подпись не является УКЭП. Используйте вариант с вашей УКЭП: подпишите файл в 1С (`МенеджерКриптографии.НачатьПодписаниеДанныхCAdES(…, ТипПодписиCAdES.BES, Отсоединенная)`: `Ложь` → прикреплённая, `Истина` → открепленная; формат из `GET api_1c_settings` → `sig_attached`) и загрузите документ + .sig методом `api_1c_upload_signed`. Подробно — api-docs.html, «Как сделать прикреплённую или открепленную подпись».

Вариант А — техническая серверная подпись (отключён):
```
POST /api.php?action=api_1c_sign_admin
Content-Type: application/json

Тело: {"doc_id": "abc123..."}

Ответ:
  {"success": true, "document": {"status": "signed_admin", "admin_sign_method": "openssl", ...}}
```

Вариант Б — УКЭП вашей организации (вместо шагов 1–2): подпишите файл в 1С
(`МенеджерКриптографии`) и загрузите вместе с подписью через `api_1c_upload_signed`
(см. «УКЭП из 1С» ниже). Документ сразу получит статус `signed_admin`.

### Шаг 3: Отправка клиенту
```
POST /api.php?action=api_1c_send
Content-Type: application/json

Тело (клиент по ID):
{
  "doc_id": "abc123...",
  "client_id": "client456...",    // ID клиента вашего аккаунта
  "sign_type": "ukep_only"        // "ukep_only", "pep_only" или "" (оба)
}

Тело (получатель напрямую, без создания клиента):
{
  "doc_id": "abc123...",
  "client_name": "Петров Пётр Петрович",
  "client_phone": "89001234567",  // и/или "client_email"
  "sign_type": "pep_only"
}

Ответ:
{
  "success": true,
  "document": {...},
  "sign_url": "https://cert4u.ru/client.html?token=...",
  "pep_code": "384729",
  "sandbox": false,
  "message": "Документ отправлен клиенту",
  "notifications": {...}
}

Документ должен быть в статусе signed_admin. Клиент получает SMS/email со ссылкой sign_url.
```

### Шаг 4: Проверка статуса
```
GET /api.php?action=api_1c_pep_status&doc_id=abc123...

Ответ:
{
  "success": true,
  "document_id": "abc123...",
  "status": "sent",          // new / signed_admin / sent / completed / rejected / revoked
  "sign_type": "pep_only",
  "pep_code": "384729",
  "client": {"id": "...", "name": "Иванов И.И.", "email": "...", "phone": "..."},
  "sent_at": "...",
  "signed_at": null,
  "client_sign_type": null,
  "sign_url": "https://cert4u.ru/client.html?token=..."   // только пока статус sent, иначе null
}
```
Вместо опроса можно настроить вебхук (см. ниже).

### Шаг 5: Проверка подписей
```
GET /api.php?action=api_1c_verify&id=abc123...

Ответ:
{
  "success": true,
  "document_id": "abc123...",
  "status": "completed",
  "admin_signature": {
    "type": "CAdES-BES (УКЭП)",
    "valid": true,
    "crypto_verify": true,
    "crypto_method": "CryptoPro CSP 5.0 (cryptcp)",
    "sig_format": "attached",
    "stored_cert_info": {
      "subject_cn": "ООО Ваша Компания",
      "subject_inn": "7701234567",
      "subject_snils": "12345678901",
      "subject_ogrn": "1027700000001",
      "subject_title": "ГЕНЕРАЛЬНЫЙ ДИРЕКТОР",
      "issuer_cn": "Удостоверяющий центр",
      "serial": "0123456789ABCDEF..."
    }
  },
  "client_signature": {
    "type": "CAdES-BES (УКЭП)",
    "valid": true,
    "crypto_verify": true,
    "sig_format": "detached",
    "stored_cert_info": {...},
    "cert_validation": {"legal_status": "UKEP_OK", ...}
  },
  "cosigned_signature": {                 // только если есть совместная подпись
    "sig_format": "attached",
    "signers": 2,
    "crypto_verify": true,
    "content_mismatch": false
  },
  "download_zip_url": "https://cert4u.ru/api.php?action=api_1c_download_zip&api_key=...&id=..."
}
```
`sig_format`: `detached` (открепленная) или `attached` (прикреплённая, документ внутри .sig).
Для прикреплённой сервер сверяет вложенный документ с документом в системе; расхождение —
`crypto_verify=false`, `content_mismatch=true`. `download_zip_url` содержит API-ключ —
не передавайте её третьим лицам.

### Шаг 6: Скачивание ZIP-архива
```
GET /api.php?action=api_1c_download_zip&id=abc123...

Ответ: ZIP-файл (Content-Type: application/zip), имя <документ>_signed.zip

Содержимое:
  - Документ.pdf — оригинал (имя как при загрузке)
  - protocol.pdf — PDF-протокол со штампом «Подписано ЭП» (реквизиты сертификатов, SHA-256)
  - Документ.pdf.sig — СОВМЕСТНАЯ подпись: один прикреплённый файл, внутри документ и подписи
    всех сторон. Есть, если подпись отправителя прикреплённая и клиент подписал УКЭП; тогда
    отдельных _server.sig / _client.sig нет. В api_1c_verify — блок "cosigned_signature".
  - иначе: Документ_server.sig (подпись отправителя: УКЭП или серверная OpenSSL)
    и Документ_client.sig (подпись клиента, УКЭП)
  - Документ_client.pep.txt — подтверждение ПЭП (если клиент подписал ПЭП)
```
Сертификат сервера и текстовый протокол в архив не входят.

## Быстрые операции

### ПЭП за один запрос (загрузка + отправка)
```
POST /api.php?action=api_1c_pep_send
Idempotency-Key: 1c-pep-000123
Content-Type: multipart/form-data

Поля:
  client_id — ID клиента вашего аккаунта (обязательно)
  document — файл   ИЛИ   doc_id — существующий документ в статусе new
  doc_name, description — необязательно

Ответ: document, sign_url, pep_code, sandbox, pep_send_results, notifications
```
Подпись отправителя не ставится: документ сразу переходит в `sent` с `sign_type = pep_only`,
клиенту уходит SMS с кодом. Получателя без `client_id` — через `api_1c_send_document`.

### Массовая ПЭП-рассылка
```
POST /api.php?action=api_1c_pep_bulk
Content-Type: application/json

Тело:
{
  "doc_id": "abc123...",
  "client_ids": ["client1", "client2", "client3"]    // или строка через запятую
}

Ответ: results — для каждого клиента client_id, client_name, doc_id, sign_url, pep_code, sandbox
       (или client_id + error, если клиент не найден)
```
Для каждого клиента создаётся отдельная копия документа; каждая — одна отправка по тарифу.

### Переотправка ПЭП-кода
```
POST /api.php?action=api_1c_pep_send_code
Content-Type: application/json

Тело: {"doc_id": "abc123...", "method": "sms"}   // sms, email, both

Ответ: новый pep_code (прежний перестаёт действовать), send_results
```
Документ должен быть в статусе `sent`. Песочница на этот метод не распространяется.

## Справочники

### Список документов
```
GET /api.php?action=api_1c_documents&limit=50&offset=0

limit — по умолчанию 50, максимум 200. Ответ: documents, total, limit, offset.
У каждого документа есть legal_status (UKEP_OK | UKEP_SUSPECT | UNEP | null) и has_manual_review.
Статусы: new → signed_admin → sent → completed (или rejected / revoked)
```

### Один документ
```
GET /api.php?action=api_1c_document&id=abc123...
Ответ содержит полный cert_validation (63-ФЗ).
```

### Клиенты
```
GET  /api.php?action=api_1c_clients        — клиенты вашего аккаунта (скрытые контакты не показываются)

POST /api.php?action=api_1c_clients        — создать клиента
Content-Type: application/json
Тело: {"name": "Петров Пётр Петрович", "phone": "+79001234567", "email": "petrov@example.ru",
       "inn": "770000000001"}
       // обязательно name и phone или email; дополнительно: company, ogrn, kpp, address,
       // contact_person, position

Ответ: {"success": true, "client": {"id": "...", ...}, "existed": false, "message": "Клиент создан"}
```
Если в вашем аккаунте уже есть клиент с таким телефоном или email — возвращается он
(`"existed": true`), дубль не создаётся. Телефоны `8…`, `+7…` и 10 цифр считаются одним номером.

## Дополнительные методы

### Отзыв документа
```
POST /api.php?action=api_1c_revoke
Тело: {"doc_id": "abc123...", "reason": "Ошибка в документе"}

Ссылка подписания становится недействительной. Подписанный (completed) документ отозвать нельзя.
```

### УКЭП из 1С и формат подписи
```
GET  api_1c_settings           — формат УКЭП вашего аккаунта:
                                 {"sig_attached": true, "sig_format": "attached"}
POST api_1c_upload_signed      — загрузить документ с УКЭП отправителя (multipart):
                                 document, signature (.sig CAdES-BES — открепленная ИЛИ
                                 прикреплённая; DER или base64 — сервер определяет сам),
                                 doc_name (обязательно), description, client_id, cert_info
POST api_1c_upload_container   — сохранить на сервере контейнер ключа, зашифрованный PIN
                                 (pin + container или container_base64)
POST api_1c_delete_container   — удалить контейнер
```
1С формирует CAdES-BES подпись штатным `МенеджерКриптографии` и отправляет её в
`api_1c_upload_signed`; документ получает статус `signed_admin`, дальше — `api_1c_send`.
Формат (открепленная/прикреплённая) берите из `api_1c_settings` → `sig_attached`
(в кабинете: Настройки → «Формат подписи УКЭП»; для `НачатьПодписаниеДанныхCAdES`
параметр «Отсоединенная» = `Не sig_attached`). Реквизиты подписанта сервер берёт только
из самой подписи; `cert_info` дополняет лишь должность и email.

Ответ `api_1c_upload_signed`: `document`, `crypto_verify`, `crypto_method`, `sig_format`;
при ошибке проверки — `crypto_error` и (для прикреплённой с другим документом внутри)
`content_mismatch: true`. Документ сохраняется в любом случае — проверяйте `crypto_verify`.

**Совместная подпись.** Если подпись отправителя прикреплённая и клиент подписывает УКЭП,
формируется один `.sig` с документом и подписями всех сторон — его можно проверить целиком
в Контур.Крипто. В ZIP он называется `Документ.pdf.sig`.

Контейнер, загруженный через `api_1c_upload_container`, методом `api_1c_sign_admin` сейчас
не используется (там техническая подпись OpenSSL).

### Вебхуки (уведомления о статусах вместо опроса)
```
POST api_1c_webhook_set     Тело: {"url": "https://...", "events": ["document.signed", "document.completed"]}
                            url — только https; events — необязательно (по умолчанию все).
                            Ответ содержит secret (генерируется сервером при первой установке).
GET  api_1c_webhook_get      — текущая настройка (url, events, active, secret_last6)
POST api_1c_webhook_delete   — удалить вебхук
```
События: `document.sent`, `document.signed`, `document.completed`, `document.rejected`,
`document.revoked`. Cert4U присылает POST на ваш URL с заголовком
`X-Cert4U-Signature: sha256=<hex>` — HMAC-SHA256 тела с вашим `secret`; сверяйте его перед
обработкой. В песочнице вебхуки об отправке не шлются.

## Коды ошибок

| HTTP | Сообщение | Причина |
|------|-----------|---------|
| 400 | Не указан doc_id / Документ уже подписан или имеет некорректный статус | Нет параметра или операция недопустима в текущем статусе; файл не прошёл антивирус |
| 401 | Не указан API ключ / Неверный API ключ | Нет ключа в `X-Api-Key` / `Authorization: Bearer` / `api_key` или ключ неверный |
| 402 | API 1С доступен с тарифа Бизнес / Лимит отправок исчерпан / Тестовый период истёк | Тариф без API или закончились отправки |
| 403 | API для 1С отключен / API ключ деактивирован / API ключ истёк | Также: метод недоступен этому ключу, email не подтверждён на тестовом тарифе |
| 404 | Документ не найден | Неправильный doc_id или документ другого аккаунта |
| 429 | Превышен лимит / Дневной лимит API исчерпан | >60 запросов/мин (IP или ключ) либо дневной лимит тарифа |

## Данные из сертификата (УКЭП)

При проверке подписи (api_1c_verify) в `stored_cert_info` доступны:

| Поле | Описание |
|------|----------|
| subject_cn | ФИО / Наименование |
| subject_inn | ИНН |
| subject_snils | СНИЛС |
| subject_ogrn | ОГРН |
| subject_ogrnip | ОГРНИП |
| subject_org | Организация |
| subject_title | Должность |
| subject_email | Email |
| issuer_cn | Удостоверяющий центр |
| issuer_inn | ИНН УЦ |
| serial | Серийный номер сертификата |
| thumbprint | Отпечаток SHA1 |
| valid_from / valid_to | Срок действия |
| algorithm_name | Алгоритм (ГОСТ Р 34.10-2012) |

## Примечания

1. `api_1c_sign_admin` — ОТКЛЮЧЁН (HTTP 410), бывшая техническая серверная подпись OpenSSL. Для УКЭП организации — подпись в веб-интерфейсе (КриптоПро Browser Plugin) либо прямо из 1С через `api_1c_upload_signed`.
2. Проверка УКЭП — криптографическая, через КриптоПро CSP 5.0 на сервере (ГОСТ Р 34.10-2012), плюс проверка по 63-ФЗ (`cert_validation`).
3. SMS и письма клиентам отправляются автоматически (кроме песочницы).
4. Полная документация API: https://cert4u.ru/api-docs.html, обзор REST API: https://cert4u.ru/rest-api.html
