Python + 1С: микросервис на FastAPI для интеграции с 1С
Python + 1С: микросервис на FastAPI для интеграции с 1С
Видео: Python + 1С: микросервис на FastAPI для интеграции с 1С

PYTHON 1C. МИКРОСЕРВИС НА FASTAPI

Типичная ситуация: 1С нужно отдать данные во внешнюю систему или, наоборот, принять запрос снаружи, а встроенный HTTP-сервис 1С для этого неудобен — нет валидации входящих данных «из коробки», сложно обрабатывать долгие операции асинхронно, тяжело логировать и покрывать тестами. В итоге логику обвязки либо городят прямо в конфигурации 1С, либо тратят часы на ручную проверку каждого входящего JSON.

В этой статье соберём рабочий микросервис на Python и FastAPI, который принимает POST-запросы от 1С, автоматически валидирует тело запроса через Pydantic, возвращает предсказуемый ответ и поднимается в Docker одной командой. Дополнительно разберём защиту эндпоинта токеном, обработку ошибок на стороне 1С и сравним подход с аналогичным сервисом на Node.js.

Что вы узнаете

  • Как поднять минимальный сервис на FastAPI и подключить автоматическую валидацию через Pydantic v2
  • Как вызвать этот сервис из 1С через HTTPСоединение и корректно обработать ошибку
  • Как защитить эндпоинт токеном, чтобы к нему не мог обратиться кто угодно из интернета
  • Как упаковать микросервис в Docker и запустить его через docker-compose
  • Чем FastAPI отличается от аналогичного решения на Node.js/Express
  • Какие ошибки чаще всего допускают при интеграции 1С и Python

Зачем выносить логику из 1С в отдельный микросервис

Привет, на связи Илья Низамов. Периодически прилетают вопросы про интеграцию 1С и Python — и почти всегда за ними стоит одна из двух задач: либо нужно дёрнуть внешний API (LLM, платёжный шлюз, стороннюю CRM) из 1С, либо, наоборот, принять данные снаружи и что-то с ними сделать до того, как они попадут в базу.

Отдельная причина выносить логику наружу — защита кода. Часть разработчиков просит спрятать логику конфигурации или расширения от конечного пользователя. Городить обфускацию средствами 1С — плохая идея: тот, кому действительно надо, всё равно разберётся, а порядочным клиентам это только создаёт проблемы с обновлениями. Рабочий вариант — вынести чувствительную часть логики в микросервис на Python, скомпилировать его отдельно и разместить в облаке или на своём сервере. 1С в этом случае обращается к сервису по HTTP и не видит исходный код.

Быстрый старт: FastAPI + Pydantic

Ставим сам фреймворк:

pip install fastapi

И ASGI-сервер, на котором FastAPI будет работать — uvicorn:

pip install uvicorn

Создаём файл main.py. Импортируем сам FastAPI и BaseModel из pydantic — он отвечает за автоматическую валидацию входящих данных без единой строчки ручных проверок:

from fastapi import FastAPI, Header, HTTPException, status
from pydantic import BaseModel, Field

Создаём экземпляр приложения:

app = FastAPI(title="1C Integration Service")

Описываем схему данных, которые ждём от 1С. В Pydantic v2 это обычный класс-наследник BaseModel с типизированными полями — если 1С пришлёт не строку в name или вообще забудет это поле, FastAPI сам вернёт 422 с понятным описанием ошибки, до вашего кода дело не дойдёт:

class OnesData(BaseModel):
    # min_length защищает от пустых строк, которые 1С иногда шлёт вместо NULL
    name: str = Field(..., min_length=1, description="Значение, полученное из 1С")

Для реальной интеграции эндпоинт без авторизации — плохая идея: сервис торчит наружу, и запрос в него может отправить кто угодно. Добавляем простую проверку токена через заголовок запроса. Для продакшена токен читаем из переменной окружения, а не хардкодим в коде:

import os

API_TOKEN = os.environ.get("ONES_API_TOKEN", "dev-only-token")


def verify_token(x_api_key: str = Header(...)) -> None:
    # сравнение через == тут допустимо: токен не секрет уровня платёжной подписи,
    # для боевого продакшена лучше secrets.compare_digest
    if x_api_key != API_TOKEN:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Неверный токен")

Теперь сам эндпоинт. Обратите внимание на model_dump() — в Pydantic v1 использовался .dict(), в актуальной v2 это устаревший алиас, правильный вызов именно model_dump():

from fastapi import Depends


@app.post("/", status_code=201, dependencies=[Depends(verify_token)])
async def process_data(payload: OnesData):
    ones_data = payload.model_dump()  # Pydantic v2: .dict() устарел, используем model_dump()
    print(ones_data["name"])
    return {"newdata": ones_data["name"]}

Отдельно стоит добавить health-check — он не завязан на токен и нужен, чтобы Docker/оркестратор мог проверять, что сервис живой, не дёргая бизнес-логику:

@app.get("/health")
async def health_check():
    return {"status": "ok"}

Итоговый main.py

Собираем всё вместе — это уже полностью рабочий сервис с валидацией, авторизацией и health-check:

import os

from fastapi import Depends, FastAPI, Header, HTTPException, status
from pydantic import BaseModel, Field

app = FastAPI(title="1C Integration Service")

API_TOKEN = os.environ.get("ONES_API_TOKEN", "dev-only-token")


class OnesData(BaseModel):
    name: str = Field(..., min_length=1, description="Значение, полученное из 1С")


def verify_token(x_api_key: str = Header(...)) -> None:
    if x_api_key != API_TOKEN:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Неверный токен")


@app.get("/health")
async def health_check():
    return {"status": "ok"}


@app.post("/", status_code=201, dependencies=[Depends(verify_token)])
async def process_data(payload: OnesData):
    ones_data = payload.model_dump()
    print(ones_data["name"])
    return {"newdata": ones_data["name"]}

Запуск и проверка

Запускаем сервер в режиме автоперезагрузки и сразу открываем автосгенерированную документацию — в ней можно отправить тестовый запрос прямо из браузера:

uvicorn main:app --reload

Документация доступна по адресу http://127.0.0.1:8000/docs. Когда сервис готов, фиксируем зависимости:

pip freeze > requirements.txt

Упаковываем микросервис в Docker

Dockerfile — используем актуальный slim-образ Python вместо устаревшего buster:

FROM python:3.12-slim

ENV PYTHONUNBUFFERED=1

WORKDIR /app

COPY ./requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

docker-compose.yml для локального запуска. Токен передаём через переменную окружения, а не через код:

services:
  python:
    container_name: ones-micro
    build: ./
    environment:
      ONES_API_TOKEN: ${ONES_API_TOKEN}
    restart: always
    ports:
      - "8000:8000"

.dockerignore — чтобы в образ не попадали виртуальное окружение, кеш и локальные настройки IDE:

__pycache__/
*.pyc
.venv/
venv/
.env
.git
.idea
Dockerfile
docker-compose.yml

Собираем образ и поднимаем контейнер:

docker-compose build
docker-compose up -d

Вызов микросервиса из 1С

На стороне 1С — обычный HTTPСоединение с таймаутом и заголовком авторизации. Ниже пример с комментариями по каждому шагу:

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура ЗапросКСервису(Команда)
	ОтветОтСервера = ЗапросКСервисуНаСервере(ТестоваяСтрока);
КонецПроцедуры

#КонецОбласти

#Область Сериализация

&НаСервереБезКонтекста
Функция СформироватьJSON(Знач Данные)

	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку();

	ЗаписатьJSON(ЗаписьJSON, Данные);

	Возврат ЗаписьJSON.Закрыть();
КонецФункции

#КонецОбласти

#Область HTTPЗапрос

&НаСервереБезКонтекста
Функция ЗапросКСервисуНаСервере(Знач name)
	Попытка
		// 30 секунд — таймаут соединения, без него зависший сервис повесит и 1С
		HTTPСоединение = Новый HTTPСоединение("127.0.0.1", 8000,,,, 30);

		Заголовки = Новый Соответствие;
		Заголовки.Вставить("Content-Type", "application/json");
		// токен должен совпадать с ONES_API_TOKEN на стороне сервиса,
		// иначе FastAPI вернёт 401 ещё до вызова process_data
		Заголовки.Вставить("X-Api-Key", "секрет-из-настроек-1с");

		HTTPЗапрос = Новый HTTPЗапрос("/", Заголовки);

		Данные = Новый Соответствие;
		Данные.Вставить("name", name);

		ДанныеJSON = СформироватьJSON(Данные);

		HTTPЗапрос.УстановитьТелоИзСтроки(ДанныеJSON, КодировкаТекста.UTF8);

		HTTPОтветОтСервера = HTTPСоединение.ВызватьHTTPМетод("POST", HTTPЗапрос);

		// код ответа стоит проверять отдельно: 401 (токен), 422 (валидация)
		// и 5xx (сервис упал) требуют разной реакции у вызывающего кода
		Если HTTPОтветОтСервера.КодСостояния <> 201 Тогда
			ЗаписьЖурналаРегистрации("FastAPI", УровеньЖурналаРегистрации.Предупреждение,,,
				"Код ответа: " + HTTPОтветОтСервера.КодСостояния);
		КонецЕсли;

		Возврат HTTPОтветОтСервера.ПолучитьТелоКакСтроку();
	Исключение
		ЗаписьЖурналаРегистрации("FastAPI", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
	КонецПопытки;

	Возврат Неопределено;
КонецФункции

#КонецОбласти 

FastAPI vs Node.js/Express: что выбрать для интеграции с 1С

Оба стека одинаково хорошо справляются с ролью «принять HTTP-запрос от 1С и что-то с ним сделать». Разница — в деталях, которые важны именно для интеграций с 1С:

КритерийFastAPI (Python)Node.js / Express
Валидация входящих данныхИз коробки через Pydantic — схема одновременно и валидирует, и документирует APIНужна отдельная библиотека (Zod, Joi) и ручная привязка к роутам
Документация APIАвтогенерация Swagger UI на /docs без дополнительной настройкиНужен отдельный пакет (swagger-jsdoc и подобные) и описание вручную
Экосистема для работы с 1СБольшинство существующих скриптов обмена, парсеров выгрузок 1С и ML/LLM-библиотек — на PythonСильнее в реалтайме (WebSocket, SSE) и там, где фронтенд и бэкенд на одном языке
Порог входа для разработчика 1ССинтаксис ближе к тому, что 1С-разработчик уже видел в скриптах на PythonНужно параллельно разбираться с npm-экосистемой и async/await в JS

Практический вывод: если микросервис — это в первую очередь приём/валидация данных от 1С и дальнейшая передача в Python-экосистему (пандас, LLM, ML-модели), берите FastAPI. Если сервис — часть более крупного Node.js-бэкенда или нужен постоянный канал (WebSocket) с фронтендом, разумнее остаться на Node.js/Express. Подробнее про интеграцию 1С с JavaScript и Node.js — в статье «1С и JavaScript/Node.js».

Частые ошибки при интеграции 1С и Python

  • Отсутствие таймаута в HTTPСоединение на стороне 1С — зависший микросервис повесит и сеанс 1С.
  • Синхронный блокирующий код внутри async def — обращение к БД или файлу без await блокирует весь event loop FastAPI, а не только один запрос.
  • Отсутствие авторизации на эндпоинте, который смотрит в интернет напрямую, без reverse-proxy и firewall-правил.
  • Игнорирование кода ответа на стороне 1С: 401 и 422 требуют разной реакции, чем 5xx, но часто в 1С просто проверяют «тело не пустое».
  • Хардкод токенов и паролей в коде микросервиса вместо переменных окружения — при коммите в git это моментально становится технической проблемой.

Похожие статьи

Полный курс по Python + 1С

Если хотите не просто повторить один пример, а системно разобраться в интеграции 1С и Python — от HTTP-сервисов 1С до защищённого прокси-сервера на Python и OAuth 2 — приходите на курс «Python + 1С: защищённый OAuth 2 сервер». Разбираем архитектуру интеграции, безопасность и типовые ошибки на реальных кейсах.

Если тема ближе к ИИ-интеграциям — LLM, RAG, MCP-серверы для 1С — на эту задачу отвечает курс «ИИ-агент для 1С: LangChain, RAG и MCP-серверы», где похожий микросервис на FastAPI используется как шлюз между 1С и языковой моделью.