Интеграция Telegram Mini App с 1С:Управление торговлей через синхронизацию номенклатуры

07.10.25

Интеграция - Мессенджеры и боты

С ростом популярности Telegram как платформы для ведения бизнеса, все больше компаний задумываются о создании Mini Apps — встроенных веб-приложений, работающих непосредственно в мессенджере. Одной из ключевых задач при разработке таких решений становится интеграция с учетными системами, в частности с 1С:Управление торговлей. В данной статье мы рассмотрим подход к синхронизации каталога товаров между Telegram Mini App и 1С:УТ с использованием артикула в качестве ключевого идентификатора.

Система интеграции строится на следующих принципах:

  • Артикул — единый идентификатор товара в обеих системах
  • REST API — универсальный интерфейс обмена данными
  • Односторонняя синхронизация — 1С выступает источником данных (master), Mini App — получателем (slave)
  • Ручной запуск — выгрузка инициируется администратором через панель управления

 

Часть 1: Реализация на стороне 1С:УТ

 

Структура HTTP-сервиса

В 1С:УТ создаем HTTP-сервис для предоставления данных номенклатуры. Сервис публикует метод получения товаров с фильтрацией по дате изменения.

// HTTP-сервис "MiniAppAPI"
// URL шаблон метода: /nomenclature

Функция НоменклатураGET(Запрос)
    
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
    
    // Получаем параметры запроса
    ДатаИзменения = Запрос.ПараметрыЗапроса.Получить("modified_since");
    
    // Формируем запрос к базе
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |    Номенклатура.Ссылка КАК Ссылка,
    |    Номенклатура.Артикул КАК Артикул,
    |    Номенклатура.Наименование КАК Наименование,
    |    Номенклатура.ПолнОе Наименование КАК ПолноеНаименование,
    |    ЦеныНоменклатуры.Цена КАК Цена,
    |    Номенклатура.Описание КАК Описание,
    |    ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК ОстатокНаСкладе
    |ИЗ
    |    Справочник.Номенклатура КАК Номенклатура
    |    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних() КАК ЦеныНоменклатуры
    |        ПО Номенклатура.Ссылка = ЦеныНоменклатуры.Номенклатура
    |    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки() КАК Остатки
    |        ПО Номенклатура.Ссылка = Остатки.Номенклатура
    |ГДЕ
    |    НЕ Номенклатура.ПометкаУдаления
    |    И Номенклатура.Артикул <> """"
    |    И Номенклатура.ДатаИзменения >= &ДатаИзменения";
    
    Если ЗначениеЗаполнено(ДатаИзменения) Тогда
        Запрос.УстановитьПараметр("ДатаИзменения", XMLЗначение(Тип("Дата"), ДатаИзменения));
    Иначе
        Запрос.УстановитьПараметр("ДатаИзменения", Дата(1, 1, 1));
    КонецЕсли;
    
    Результат = Запрос.Выполнить();
    Выборка = Результат.Выбрать();
    
    // Формируем JSON
    МассивТоваров = Новый Массив;
    
    Пока Выборка.Следующий() Цикл
        Товар = Новый Структура;
        Товар.Вставить("article", Выборка.Артикул);
        Товар.Вставить("name", Выборка.Наименование);
        Товар.Вставить("full_name", Выборка.ПолноеНаименование);
        Товар.Вставить("price", Выборка.Цена);
        Товар.Вставить("description", Выборка.Описание);
        Товар.Вставить("stock_quantity", Выборка.ОстатокНаСкладе);
        
        МассивТоваров.Добавить(Товар);
    КонецЦикла;
    
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, МассивТоваров);
    
    Ответ.УстановитьТелоИзСтроки(ЗаписьJSON.Закрыть());
    
    Возврат Ответ;
    
КонецФункции

 

Авторизация запросов

Для обеспечения безопасности используем базовую аутентификацию или токен доступа:

Функция ПроверитьАвторизацию(Запрос)
    
    ЗаголовокАвторизации = Запрос.Заголовки.Получить("Authorization");
    
    Если ЗаголовокАвторизации = Неопределено Тогда
        Возврат Ложь;
    КонецЕсли;
    
    // Проверяем токен
    ОжидаемыйТокен = Константы.TokenДляMiniApp.Получить();
    Токен = СтрЗаменить(ЗаголовокАвторизации, "Bearer ", "");
    
    Возврат Токен = ОжидаемыйТокен;
    
КонецФункции

 

Обработка изображений товаров

Изображения товаров можно передавать как Base64 или предоставлять URL для скачивания:

Функция ПолучитьURLИзображенияТовара(СсылкаНоменклатура)
    
    // Получаем присоединенный файл
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |    ПрисоединенныеФайлы.Ссылка КАК Ссылка
    |ИЗ
    |    Справочник.НоменклатураПрисоединенныеФайлы КАК ПрисоединенныеФайлы
    |ГДЕ
    |    ПрисоединенныеФайлы.ВладелецФайла = &Номенклатура
    |    И ПрисоединенныеФайлы.ЭтоИзображение";
    
    Запрос.УстановитьПараметр("Номенклатура", СсылкаНоменклатура);
    
    Результат = Запрос.Выполнить();
    Если Результат.Пустой() Тогда
        Возврат "";
    КонецЕсли;
    
    Выборка = Результат.Выбрать();
    Выборка.Следующий();
    
    // Формируем публичную ссылку
    АдресСервера = Константы.АдресПубликацииИБ.Получить();
    URLИзображения = АдресСервера + "/images/" + Строка(Выборка.Ссылка.УникальныйИдентификатор());
    
    Возврат URLИзображения;
    
КонецФункции

 

Часть 2: Реализация на стороне Telegram Mini App

 

Backend API (Node.js/Express)

На стороне Mini App создаем эндпоинт для инициации синхронизации:

// routes/admin/sync.js
const express = require('express');
const router = express.Router();
const axios = require('axios');
const Product = require('../../models/Product');

// Эндпоинт для синхронизации номенклатуры
router.post('/sync-nomenclature', async (req, res) => {
  try {
    const { lastSyncDate } = req.body;
    
    // Запрос к 1С API
    const response = await axios.get(
      `${process.env.ONS_API_URL}/nomenclature`,
      {
        params: {
          modified_since: lastSyncDate || null
        },
        headers: {
          'Authorization': `Bearer ${process.env.ONS_API_TOKEN}`
        },
        timeout: 30000
      }
    );
    
    const products = response.data;
    let created = 0;
    let updated = 0;
    let errors = [];
    
    // Обработка полученных товаров
    for (const item of products) {
      try {
        // Ищем товар по артикулу
        let product = await Product.findOne({ article: item.article });
        
        if (product) {
          // Обновляем существующий товар
          product.name = item.name;
          product.fullName = item.full_name;
          product.price = item.price;
          product.description = item.description;
          product.stockQuantity = item.stock_quantity;
          product.lastSyncDate = new Date();
          
          await product.save();
          updated++;
        } else {
          // Создаем новый товар
          product = new Product({
            article: item.article,
            name: item.name,
            fullName: item.full_name,
            price: item.price,
            description: item.description,
            stockQuantity: item.stock_quantity,
            isActive: true,
            lastSyncDate: new Date()
          });
          
          await product.save();
          created++;
        }
      } catch (err) {
        errors.push({
          article: item.article,
          error: err.message
        });
      }
    }
    
    // Возвращаем результат синхронизации
    res.json({
      success: true,
      summary: {
        total: products.length,
        created,
        updated,
        errors: errors.length
      },
      errors: errors.length > 0 ? errors : undefined
    });
    
  } catch (error) {
    console.error('Sync error:', error);
    res.status(500).json({
      success: false,
      message: 'Ошибка при синхронизации с 1С',
      error: error.message
    });
  }
});

module.exports = router;

 

Модель данных товара (Mongoose)

// models/Product.js
const mongoose = require('mongoose');

const productSchema = new mongoose.Schema({
  article: {
    type: String,
    required: true,
    unique: true,
    index: true
  },
  name: {
    type: String,
    required: true
  },
  fullName: {
    type: String
  },
  price: {
    type: Number,
    required: true,
    min: 0
  },
  description: {
    type: String
  },
  imageUrl: {
    type: String
  },
  stockQuantity: {
    type: Number,
    default: 0
  },
  isActive: {
    type: Boolean,
    default: true
  },
  category: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category'
  },
  lastSyncDate: {
    type: Date
  }
}, {
  timestamps: true
});

module.exports = mongoose.model('Product', productSchema);

 

Административная панель (React)

Компонент кнопки синхронизации в админ-панели:

// components/Admin/SyncButton.jsx
import React, { useState } from 'react';
import axios from 'axios';

const SyncButton = () => {
  const [syncing, setSyncing] = useState(false);
  const [result, setResult] = useState(null);

  const handleSync = async () => {
    setSyncing(true);
    setResult(null);

    try {
      // Получаем дату последней синхронизации
      const lastSync = localStorage.getItem('lastNomenclatureSync');
      
      const response = await axios.post('/api/admin/sync-nomenclature', {
        lastSyncDate: lastSync
      });

      if (response.data.success) {
        // Сохраняем время синхронизации
        localStorage.setItem('lastNomenclatureSync', new Date().toISOString());
        
        setResult({
          type: 'success',
          message: `Синхронизация завершена успешно!
            Создано: ${response.data.summary.created}
            Обновлено: ${response.data.summary.updated}
            Ошибок: ${response.data.summary.errors}`
        });
      }
    } catch (error) {
      setResult({
        type: 'error',
        message: error.response?.data?.message || 'Ошибка синхронизации'
      });
    } finally {
      setSyncing(false);
    }
  };

  return (
    <div className="sync-container">
      <button 
        onClick={handleSync} 
        disabled={syncing}
        className="sync-button"
      >
        {syncing ? 'Синхронизация...' : 'Выгрузить номенклатуру из 1С'}
      </button>
      
      {result && (
        <div className={`sync-result ${result.type}`}>
          {result.message}
        </div>
      )}
    </div>
  );
};

export default SyncButton;

 

Обработка конфликтов и особые случаи

 

Деактивация удаленных товаров

В 1С товары редко удаляются физически — обычно ставится пометка удаления. Рекомендуется реализовать мягкое удаление:

// Проверка неактивных товаров
router.post('/deactivate-missing', async (req, res) => {
  const { activeArticles } = req.body;
  
  // Деактивируем товары, которых нет в актуальном списке
  const result = await Product.updateMany(
    { 
      article: { $nin: activeArticles },
      isActive: true 
    },
    { 
      $set: { isActive: false } 
    }
  );
  
  res.json({ deactivated: result.modifiedCount });
});

 

Логирование синхронизации

// models/SyncLog.js
const syncLogSchema = new mongoose.Schema({
  startTime: Date,
  endTime: Date,
  status: String, // 'success', 'partial', 'failed'
  productsCreated: Number,
  productsUpdated: Number,
  errors: [{ article: String, message: String }],
  initiatedBy: String
});

 

Настройка и запуск

 

Конфигурация 1С

  1. Опубликовать HTTP-сервис с внешним доступом
  2. Создать константу TokenДляMiniApp с уникальным токеном
  3. Настроить права доступа для веб-сервиса
  4. Проверить доступность эндпоинта через Postman

 

Конфигурация Mini App

Переменные окружения (.env):

ONS_API_URL=https://your-1c-server.com/your-base/hs/MiniAppAPI
ONS_API_TOKEN=your-secret-token-here
SYNC_TIMEOUT=30000

 

Заключение

Предложенное решение позволяет гибко интегрировать Telegram Mini App с 1С:УТ, обеспечивая актуальность каталога товаров. Использование артикула как единого идентификатора упрощает сопоставление данных и минимизирует вероятность дублирования.

Ключевые преимущества подхода:

  • Простота реализации — стандартные HTTP-сервисы 1С
  • Гибкость — легко расширить дополнительными полями
  • Контроль — ручной запуск синхронизации администратором
  • Безопасность — токен-based авторизация

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

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Мессенджеры и боты 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Платные (руб)

Интеграция мессенджера WhatsApp и 1С: УНФ, УТ, КА, ERP - отправка и получение сообщений, картинок, файлов и видео прямо в 1С. Расширение работает с сервисом GreenApi.

18000 руб.

23.06.2023    14793    53    24    

58

SALE! 50%

Мессенджеры и боты SMS рассылки Email рассылки Пользователь 1С v8.3 1C:Бухгалтерия 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Управленческий учет Платные (руб)

Расширение 1С с полным набором инструментов для качественных транзакционных, триггерных и маркетинговых рассылок Email, SMS, WhatsApp, Telegram. Даже простые уведомления об оплате счетов способны существенно упростить сбор дебиторской задолженности. Применение всех возможностей прямого маркетинга выводит коммуникацию с клиентами, уровень сервиса и лояльность на новый уровень.

6000 3000 руб.

07.04.2014    90498    68    200    

150

Мессенджеры и боты Системный администратор Программист Бизнес-аналитик Пользователь Руководитель проекта 1С v8.3 Платные (руб)

Развитие популярного решения для интеграции мессенджера Telegram с нашей любимой 1С - конструктор чат-ботов в Телеграм.

15000 руб.

18.06.2021    76927    321    273    

397

Мобильная разработка Мессенджеры и боты 1С v8.3 Платные (руб)

Теперь создать telegram-бота - элементарно. Достаточно просто нарисовать блок-схему телеграм-бота, и он сразу заработает. Это возможно при использовании Графического конструктора телеграм-ботов. Это единственный конструктор ботов для telegram, чье качество и функционал подтверждены фирмой 1С, есть сертификат 1С:Совместимо. Расширение в интерактивном режиме, с помощью блок-схем, позволяет с минимальными трудозатратами создать телеграм-ботов в любой конфигурации, работающей на платформе «1С:Предприятие 8.3».

13200 руб.

27.12.2021    46972    126    172    

222

Мессенджеры и боты Учет документов 1С v8.3 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия государственного учреждения 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление холдингом 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Платные (руб)

Расширение для согласования справочников и документов в основных типовых конфигурациях. Ролевая адресация, условная маршрутизация, чат-бот telegram, интеграция с n8n, последовательное и параллельное согласование, уведомление о новых задачах на почту, блокировка объектов в зависимости от статуса, запрет проведения в зависимости от статуса, автозапуск процессов согласования, отчеты по исполнительской дисциплине. Не требуется снятие конфигурации с поддержки. Настройка без программирования. Версия для 1cfresh.com. Сертификат 1С-Совместимо.

14900 руб.

15.11.2018    38987    42    55    

77

Мессенджеры и боты Учет документов 1С v8.3 1С:Документооборот Россия Платные (руб)

Сделайте взаимодействие сотрудников компании быстрым и удобным. В Личном кабинете в Телеграм сотрудники могут получать и выполнять задачи используя популярный мессенджер

11520 руб.

29.12.2022    8851    7    13    

13
Для отправки сообщения требуется регистрация/авторизация