Интеграция интернет-магазина с 1С: REST API, вебхуки, синхронизация
  • Funktor

Интеграция интернет-магазина с 1С: REST API, вебхуки, синхронизация

Введение: Почему ручной ввод данных убивает рентабельность интернет-магазина

Типичная картина в малом и среднем интернет-магазине: менеджер получает заказ на сайте, заходит в 1С, вручную создаёт документ, распечатывает накладную, относит на склад. Кладовщик собирает заказ, возвращает менеджеру, тот отмечает в 1С как отгруженный, затем заходит на сайт и меняет статус заказа. На каждый заказ уходит 10-15 минут рабочего времени, плюс риск ошибок: перепутал артикул, не туда отправил, забыл обновить остатки.

При 50 заказах в день это 8-12 часов ручной работы. Месяц — 160-240 часов. Год — 2000-3000 часов. Это полная ставка сотрудника, который только и делает, что перекладывает данные из одной системы в другую. И это без учёта ошибок, которые приводят к отправке не того товара, двойной продаже одного и того же, рассинхронизации остатков.

Автоматическая интеграция сайта с 1С решает все эти проблемы. Но не ту интеграцию, которая предлагают большинство разработчиков («раз в час выгружаем CSV-файл»), а реальную синхронизацию в реальном времени через API.

В этой статье мы разберём, как построить такую интеграцию: от архитектуры обмена данными до обработки исключительных ситуаций. Мы будем использовать современные подходы: REST API, очереди сообщений, idempotency keys, компенсирующие транзакции.

Часть 1: Архитектура интеграции: от файлового обмена к real-time API

Эволюция интеграционных подходов

Уровень 0: Ручной ввод — всё делается руками. Время на заказ: 15 минут. Ошибки: 5-10%.

Уровень 1: Файловый обмен (CSV/XML) — раз в час/день сайт выгружает файл с заказами, 1С забирает, обрабатывает. Время: 5-10 минут с задержкой. Ошибки: 2-5%.

Уровень 2: Веб-сервисы (SOAP) — 1С предоставляет SOAP-сервис, сайт вызывает методы. Время: 1-2 минуты. Ошибки: 1-2%.

Уровень 3: REST API — современный подход, двусторонняя связь в реальном времени. Время: секунды. Ошибки: 0.1-0.5%.

Почему REST API, а не SOAP или файлы

1. Real-time синхронизация: Заказ сразу попадает в 1С, сразу резервируется товар.

2. Двусторонняя связь: Не только сайт → 1С, но и 1С → сайт (остатки, цены, статусы).

3. Надёжность: Подтверждение получения, повторные попытки при ошибках.

4. Масштабируемость: Легко добавить новые типы данных (заказы, клиенты, товары).

5. Стандартизация: REST — современный стандарт, с которым работают все разработчики.

Архитектурная схема

┌─────────────────┐      REST API       ┌─────────────────┐
│                 │  ┌───────────────►  │                 │
│   Интернет-     │  │   Заказы,       │       1С        │
│     магазин     │  │   Клиенты       │                 │
│   (Django)      │  │                 │   (через HTTP-  │
│                 │  │   Остатки,      │   сервисы или   │
│                 │  │   Цены,         │   внешние       │
│                 │  │   Статусы ◄─────┘   обработки)    │
└─────────────────┘                      └─────────────────┘
         │                                            │
         │                                            │
         ▼                                            ▼
┌─────────────────┐                      ┌─────────────────┐
│   Очередь       │                      │   База данных   │
│   сообщений     │                      │     1С          │
│   (RabbitMQ/    │                      │                 │
│    Redis)       │                      │                 │
└─────────────────┘                      └─────────────────┘

Часть 2: Настройка 1С для работы с REST API

Создание HTTP-сервиса в 1С

В 1С 8.3.10+ появилась возможность создавать полноценные REST API через механизм HTTP-сервисов. Вот пошаговая инструкция:

Шаг 1: Создаём обработку «Внешний обработчик HTTP-сервисов»

// В конфигураторе 1С создаём новую обработку
// Называем её, например, "ИнтеграцияССайтом"

Перем Лог;

Процедура ПриСозданииНаСервере()
    Лог = Новый ЛогФайл;
    Лог.Открыть("C:\\Logs\\1C_Integration.log", "UTF-8");
КонецПроцедуры

// Основной метод, который будет вызываться при HTTP-запросе
Функция ОбработатьВызов(Запрос, Ответ, ПараметрыЗапроса) Экспорт
    
    // Логируем запрос
    Лог.ЗаписатьСтроку("Получен запрос: " + Запрос.Метод + " " + Запрос.АдресРесурса);
    
    // Определяем метод и путь
    Если Запрос.Метод = "POST" И Запрос.АдресРесурса = "/api/orders" Тогда
        Возврат ОбработатьСозданиеЗаказа(Запрос, Ответ);
    ИначеЕсли Запрос.Метод = "GET" И Запрос.АдресРесурса = "/api/products" Тогда
        Возврат ОбработатьПолучениеТоваров(Запрос, Ответ);
    ИначеЕсли Запрос.Метод = "PUT" И Запрос.АдресРесурса НачинаетсяС("/api/orders/") Тогда
        Возврат ОбработатьОбновлениеЗаказа(Запрос, Ответ);
    КонецЕсли;
    
    // Если маршрут не найден
    Ответ.УстановитьТелоИзСтроки("{\"error\": \"Not found\"}");
    Ответ.КодСостояния = 404;
    
    Возврат Истина;
    
КонецФункции

Шаг 2: Реализуем метод создания заказа

Функция ОбработатьСозданиеЗаказа(Запрос, Ответ)
    
    Попытка
        // Читаем тело запроса (JSON)
        ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку("UTF-8");
        Лог.ЗаписатьСтроку("Тело запроса: " + ТелоЗапроса);
        
        // Парсим JSON
        ПарсерJSON = Новый ПарсерJSON;
        ДанныеЗаказа = ПарсерJSON.Прочитать(ТелоЗапроса);
        
        // Проверяем обязательные поля
        Если Не ДанныеЗаказа.Свойство("id")
            Или Не ДанныеЗаказа.Свойство("items") Тогда
            
            Ответ.УстановитьТелоИзСтроки("{\"error\": \"Missing required fields\"}");
            Ответ.КодСостояния = 400;
            Возврат Истина;
        КонецЕсли;
        
        // Проверяем, не создан ли уже заказ с таким ID (idempotency)
        ПоискЗаказа = Документы.ЗаказыПокупателей.НайтиПоНавигационнойСсылке(
            ДанныеЗаказа.id
        );
        
        Если Не ПоискЗаказа.Пустой() Тогда
            // Заказ уже существует, возвращаем его данные
            СуществующийЗаказ = ПоискЗаказа.Получить();
            ОтветJSON = СформироватьОтветПоЗаказу(СуществующийЗаказ);
            Ответ.УстановитьТелоИзСтроки(ОтветJSON);
            Ответ.КодСостояния = 200;
            Возврат Истина;
        КонецЕсли;
        
        // Создаём новый заказ
        НовыйЗаказ = Документы.ЗаказыПокупателей.СоздатьДокумент();
        НовыйЗаказ.Номер = ДанныеЗаказа.id;
        НовыйЗаказ.Дата = ТекущаяДата();
        
        // Заполняем контрагента
        Если ДанныеЗаказа.Свойство("customer") Тогда
            Контрагент = НайтиИлиСоздатьКонтрагента(ДанныеЗаказа.customer);
            НовыйЗаказ.Контрагент = Контрагент;
        КонецЕсли;
        
        // Добавляем товары
        Для Каждого ЭлементЗаказа Из ДанныеЗаказа.items Цикл
            СтрокаЗаказа = НовыйЗаказ.Товары.Добавить();
            
            Номенклатура = Справочники.Номенклатура.НайтиПоКоду(
                ЭлементЗаказа.sku
            );
            
            Если Не Номенклатура.Пустой() Тогда
                СтрокаЗаказа.Номенклатура = Номенклатура.Получить();
                СтрокаЗаказа.Количество = ЭлементЗаказа.quantity;
                СтрокаЗаказа.Цена = ЭлементЗаказа.price;
            КонецЕсли;
        КонецЦикла;
        
        // Проверяем наличие товаров
        Если Не ПроверитьНаличиеТоваров(НовыйЗаказ) Тогда
            Ответ.УстановитьТелоИзСтроки("{\"error\": \"Insufficient stock\"}");
            Ответ.КодСостояния = 409; // Conflict
            Возврат Истина;
        КонецЕсли;
        
        // Проводим заказ
        НовыйЗаказ.Записать();
        НовыйЗаказ.Провести();
        
        // Формируем ответ
        ОтветJSON = СформироватьОтветПоЗаказу(НовыйЗаказ);
        Ответ.УстановитьТелоИзСтроки(ОтветJSON);
        Ответ.КодСостояния = 201; // Created
        
        Лог.ЗаписатьСтроку("Заказ успешно создан: " + НовыйЗаказ.Номер);
        
    Исключение
        // Обработка ошибок
        Лог.ЗаписатьСтроку("Ошибка при создании заказа: " + ОписаниеОшибки());
        Ответ.УстановитьТелоИзСтроки("{\"error\": \"Internal server error\"}");
        Ответ.КодСостояния = 500;
    КонецПопытки;
    
    Возврат Истина;
    
КонецФункции

Настройка публикации HTTP-сервиса

  1. В конфигураторе: Сервис → Публикация веб-сервисов на веб-сервере
  2. Добавляем новую публикацию
  3. Указываем путь, например: /api/integration
  4. Выбираем созданную обработку
  5. Настраиваем аутентификацию (Basic Auth или токены)
  6. Публикуем

Теперь 1С доступна по адресу: http://1c-server.example.com/api/integration

Часть 3: Реализация клиента на стороне Django

Модель для синхронизации

class OneCSyncStatus(models.TextChoices):
    PENDING = 'pending', 'Ожидает синхронизации'
    SYNCING = 'syncing', 'Синхронизируется'
    SUCCESS = 'success', 'Успешно синхронизировано'
    ERROR = 'error', 'Ошибка синхронизации'
    RETRY = 'retry', 'Повторная попытка'

class OneCSyncLog(models.Model):
                            

Читайте также

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

Как онлайн-магазину победить гигантов вроде Ozon: стратегия персонализации

Полное руководство по созданию персонализированного опыта в интернет-магазине. AI-рекомендации, личный кабинет, напоминания о брошенных корзинах …

  • Funktor

Contact

Обсудим ваш проект?

Мы специализируемся на комплексной разработке сайтов, внедрении систем искусственного интеллекта (AI) и настройке CRM-систем. Мы создаём не просто инструменты, а связанную экосистему для роста вашего бизнеса.