Простая интеграция сайта и 1С

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


    Тяпки, грабли и лопаты


    Не очень большой магазин (номенклатура порядка 5000 товаров).
    Обыкновенная, файловая 1С 8 УТ. Конфигурация стоит на полной поддержке, и снимать с поддержки нельзя.
    База лежит на одной из десктопных машин, которая в свою очередь используется для работы одним из сотрудников.
    Достаточно выгружать минимум информации: название, описание, фото, несколько видов цен.
    Ломать уже устоявшуюся экосистему было так же крайне не желательно.
    Под сайт выделен обыкновенный виртуальный хостинг, а значит нужно учесть ограниченность ресурсов такового.
    Выгрузка может происходить не часто, достаточно 1 раза в 3 часа.
    Впоследствии, стало необходимо добавить выгрузку прайс-листа в xls.
    Скромный бюджет для реализации проекта.

    Машина, выполняющая роль «сервера» была и без того не быстрой, а наличие постоянных подключений к базе 1С, только усугубляло ситуацию. Но, заказчика это устраивало, а значит, кучи денег на покупку отдельного сервера и перевооружение остального парка не было.
    В связи с ограничениями бюджета, вариант с Битриксом и его типовой интеграцией отпал сразу. Да и интерес был скорее спортивный, реализовать всё самостоятельно. Было решено использовать уже использовавшийся ранее каркас для каталога товаров. Каркас был сделан на CodeIgniter, поэтому добавить небольшой модуль труда не составляло. Решено.

    Лет'с старт


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

    Вот основные ключи, которые будут использоваться:
    "Путь к 1С" enterprise  /F"Путь к базе" /N"Логин" /P"Пароль" /Execute"Внешняя обработка" /C"Параметр" /DisableStartupMessages


    Теперь осталось настроить запуск этой конструкции по расписанию. Планировщик Windows? Настраиваем, проверяем… работает!
    Но есть один серьёзный недочёт. Когда планировщик запускает по расписанию 1С, то, разумеется, она открывается сверху над всеми приложениями и если в это время работает кто-то за компьютером, то это, во-первых, будет его отвлекать, а во-вторых, он может и закрыть это новое окно. Не порядок… Что же делать? Начинаем копать в сторону запуска под другой учётной записью. Спасибо гуглу, достаточно быстро находим возможность пакетного запуска под другим пользователем. Создаём нового пользователя Windows, разрешаем в политиках безопасности пакетный запуск, перенастраиваем планировщик, проверяем… вуаля! Всё сработало, при этом мы не увидели никаких раздражающих окон! Отлично, значит, такой вариант нам подходит… теперь переходим к собственно выгрузке самих данных.

    Выгрузка


    Первым делом, конечно, я стал смотреть в сторону CommerceML, но ознакомившись с документацией, стало ясно, что для нашей, достаточно элементарной выгрузки городить весь этот огород — слишком долго, а бюджет не резиновый. Значит, будем искать альтернативный способ. Почему бы просто не выгружать текстовую информацию в xml, а картинки выгружать в отдельную директорию? Решено, так и делаем. Получаем достаточно простую структуру xml-файла: внутри сначала идут записи для групп, а потом сами номенклатурные единицы.

    Так выглядят группы:
    	<group>
    		<Code>код</Code> /*Код-элемента из 1С*/
    		<Name>наименование</Name> /* Собственно, наименование группы*/
    		<ParentCode>код родителя</ParentCode> /* Если не пусто, значит группа является вложенной*/
    	</group>
    


    А так товары:
    	<item>
    		<Code>код</Code> /* Код-элемента из 1С */
    		<ParentCode>код родителя</ParentCode> /* Код группы, к которой принадлежит товар */
    		<Name>наименование</Name>
    		<Descr>Описание</Descr>
    		<Article>Артикул</Article>
    		<TypePrice>Тип цены</TypePrice>
    		<Price>Цена</Price>
    		<Сurrency>валюта</Сurrency>
    		<Remains>Остатки</Remains>
    		<Unit>шт/кг/литры</Unit>
    		<Img>img_dae5eacd-7d88-11de-8856-0024213f1c89.jpg</Img> /* Все изображения содержат в названии уникальный идентификатор элемента в базе 1С */
    	</item>
    


    Не хитрым запросом получаем информацию по всем товарным группам и товарам, далее формируем xml-ку. Также делаем отдельную выборку и вытаскиваем информацию для прайс-листа, а затем сохраняем полученную информацию в xls.
    После этого переходим к выгрузке изображений. В связи с ограничениями хостинг-площадки, обрабатывать изображения на стороне хостинга показалось не самым рациональным, поэтому было решено делать обработку изображений + создание превью на этапе формирования выгрузки. 1С — это конечно комбайн, но вот возможности обработать пачку фотографий я не нашёл. Но ведь у нас есть ImageMagick? Отличный, кроссплатформенный набор всего необходимого нам для обработки изображений… качаем, распаковываем… осталось лишь написать bat'ник, который произведёт необходимые манипуляции:

    cd c:\
    set thePATH= Здесь указываем путь к изображениям
    FOR /R "%thePATH%" %%a IN (*.jpg) DO ImageMagick-6.7.0-10\convert.exe %%a -resize ШИРИНАxВЫСОТА^> -quality 70 %%a
    FOR /R "%thePATH%" %%a IN (*.jpg) DO ImageMagick-6.7.0-10\convert.exe %%a -resize ШИРИНАxВЫСОТА^> -gravity center -extent ШИРИНАxВЫСОТА -quality 70 %thePATH%mini\%%~nxa
    


    Запускаем из нашей обработки этот bat'ник и получаем результат.

    Вся информация выгружена, осталось всё аккуратно упаковать в zip и загрузить по фтп на сервер, с чем отлично справляется 1С штатными средствами.

    На первый взгляд всё, но… Неужели мы каждый раз будем вытаскивать всю номенклатуру, со всеми картинками и всю эту махину грузить на сервер? Нет уж, это картина не для слабонервных… И что же делать? Делать флаги и отмечать, какая номенклатурная единица изменилась? Нет, мы же не можем править конфигурацию… Но ведь есть же планы обмена? Кто нам запрещал использовать их? Никто! Создаём план обмена, настраиваем. Дальше модифицируем нашу выгрузку, теперь во время выгрузки создаём новое сообщение в плане обмена, выгружаем только изменённые с момента последнего сообщения единицы… Отлично!

    Серверная часть


    Тут всё ещё прозрачнее. Вешаем запуск скрипта по крону. В скрипте смотрим в нужную директорию, ищем по маске нужный архив. Если таковой имеется, то распаковываем, парсим xml, пишем информацию в БД. Картинки у нас внутри ещё одним архивом, его тоже распаковываем, прямо поверх директории с уже имеющимися картинками. Если такая картинка уже есть, переписываем её новой. xls-файл копируем с заменой в нужную директорию. Пишем в базу информацию, о том, что произвели такое-то обновление, тогда-то, с таким-то номером, а затем чистим за собой временные файлы. Всё.

    Соломка от сбоев


    Если в процессе выгрузки информации, обработке изображений, архивировании, загрузке на удалённый фтп произойдут ошибки, то мы можем потерять часть обновлений, и в итоге информация на сайте и в базе 1С будет рассинхронизирована. Ниже я описал основные острые углы, для которых понадобилось подстелить соломки:

    1. Итак, что же будет, если например, в момент загрузки по фтп, оборвётся связь?
    Если мы уже записали сообщение в план обмена, то получается, что 1С, считает, что успешно выгрузила эти изменения и теперь уже собирает новые, но на сайт-то они не попали! Правильно, поэтому заканчиваем запись в план обмена только после успешного завершения всех этапов выгрузки, включая загрузку файлов по фтп! А если же в процессе выгрузки происходит исключительная ситуация, то мы прерываем запись сообщения в плане обмена и пишем ошибку в error-log.

    2. А что, если наш скрипт на сервере начнёт обрабатывать ещё не догруженный архив?
    Мы сначала даём ему одно имя (например, export.zip_), а лишь по завершении переименовываем его и даём имя, которое будет искать скрипт на сервере.

    3. А что если на сервере будет сбой и скрипт не успеет обработать наш архив, 1С затрёт его новым?
    Нет, для этого каждый архив содержит в названии номер сообщения из плана обмена (например, export_1.zip). Скрипт на сервере в свою очередь при обнаружении нескольких архивов обрабатывает их в порядке возрастания номеров.

    4. А логи не переполнятся?
    Т.к. при выгрузке в лог пишется подробно информация о результатах каждого действия, то логи достаточно быстро растут, поэтому не забываем при каждой выгрузке контролировать их размер и при необходимости удалять старые.

    5. А что если 1С не успеет произвести выгрузку, а в это время стартует процесс для новой выгрузки?
    В настройках планировщика настраиваем так, чтобы новое задание не выполнялось, если предыдущее не завершено.

    P.S.


    Итак, таким вот нехитрым способом за достаточно короткий срок была реализована выгрузка номенклатуры/цен/остатков на сайт. Разумеется, данный вариант имеет ряд недостатков и не претендует на лавры единственно-верного, но при этом нам удалось полностью вписаться в ограничения установленные экосистемой заказчика. Вся эта конструкция работает на слабых машинах, не требует постоянно запущенной копии 1С, работает на самом обыкновенном виртуальном-хостинге, абсолютно не отвлекает сотрудников на себя и главное, позволяет беспрепятственно обслуживать 1С. Подстеленной соломки оказалось достаточно, и за уже почти год, к счастью, ни одного нашего вмешательства в работу системы не потребовалось.
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 41
    • +1
      Я всё сделал примерно так же, выгружал из 1с в XLS, парсером-плагином для wordpress собирал его. Всё на виртуальном хостинге, прототип работает нормально.
      На похапе есть PHPexcelReader2

      * A class for reading Microsoft Excel (97/2003) Spreadsheets.
      * Version 2.22
      * Enhanced and maintained by Alex Frenkel < excell2@frenkel-online.com >
      * Maintained at code.google.com/p/php-excel-reader2/
      • 0
        Т.е. на стороне сайта парсится именно xls?
        • 0
          Ну да, эксель файл можно сразу класть как «Скачать прайс» или посмотреть что нужно онлайн. Объемы небольшие, время работы скрипта 0.1с для 100кб файла.
          • 0
            В моём случае в xls было не достаточно информации для обновления каталога, он вообще был лишь побочным продуктом и добавлялся уже после того как был разработан прототип.
            И ещё такой недостаток: в xls отсутствовал уникальный код/идентификатор для каждого товара, а значит, что обновлять было бы уже нельзя. Как скрипту установить соответствие между товаром в каталоге и обновлённом xls? По названию? Ну, во-первых, название может вдруг оказаться не уникальным, а во-вторых, оно ведь может и измениться. Поэтому пришлось бы, разве что, каждый раз затирать весь каталог и писать его заново, что мне кажется, было бы не совсем гладким решением. Поэтому и выгружал всё именно xml.
            • 0
              Я не спорю. В эксель выгружается название, количество и цена. Номенклатура небольшая.
              Сам буду на xml переделывать, если прототип одобрят.
              • 0
                А почему сразу не сделать с использованием xml?
                • 0
                  Начал путь по другому, попросил сделать мне выгрузку остатков из 1с для тестов. Получил xls файл, полез в гугл, нашел phpexcelreader, сделал такой вариант. Затем узнал что 1с умеет делать выгрузки в другие форматы, задумался :)
                  Весь процесс был для души побыдлокодить на похапе.
      • 0
        если уж планы обмена, то надо бы сделать на сайте счетчик полученных сообщений и в ответ 1су класть файлик с номером последнего загруженного из 1 с сообщения (его, естесственно, в xml надо добавить). тогда если при загрузке скриптом на сервере произошла ошибка (мало ли, память кончилась, или еще чего) — 1с просто выгрузит эти данные еще раз + новые изменившиеся. Да и в таком случае видно будет, что загрузка не производилась долгое время — пора бить в бубен тревогу.

        А вообще — для не онлайн обмена — вполне вариант. еще картинки можно (допустим) в base64 пихнуть внутрь XML, чтобы файл один был (меньше файлов — крепче спим ИМХО)
        • 0
          На сайте и есть счётчик сообщений, и в админке видна полная статистика, вплоть до того сколько и когда изменилось.
          Если скрипт рухнет в момент обработки, то он не удалит архив с сообщением и при следующем запуске попробует вновь, т.е. данные утеряны не будут.
          Складывать в xml картинки смысла было мало. Боюсь, что php-скрипт, который вытаскивает их из xml и сохраняет поштучно, будет работать медленнее, нежели вызываемая внешняя утиль, специально заточенная под подобные операции. Но соглашусь с вами, действительно как вариант это можно иметь ввиду. Спасибо.
        • +1
          Я делал такой проект для знакомых.
          Выгрузка в csv из 1C -> парсинг и заливка уже средствами PHP.
          Экспорт в xls тоже уже на стороне сайта.
          Наверное до сих пор работает (URL не даю — зачем хабраэффект маленькому вебмагазину?)
          • +1
            Да, думаю URL нам знать не обязательно, а вот услышать рассказ о подробностях создания всего механизма было бы очень интересно ;)
            • 0
              схема была такая:
              1. Программист 1С сделал выгрузку в определенную папку csv файла заранее определенного формата.
              (выгрузка была не по расписанию, а по кнопке из программы- так просил заказчик)
              Затем следом в эту же папку записывался другой файл с оговоренным именем.
              2. Программка nnCron следила за появлением файла и запускала скрипт загружающий данные в базу на хостинге. Следом в конце записывалось в базу значение флага конца загрузки и текущую дату актуальности прайса.
              3. Скрипт на стороне сервера смотрел в базу и если появлялись новые данные перемещал их из временной таблицы в действующую.
              4. Из тонкостей было одно: данные в 1С хранились в виде древовидного массива с двумя ключами (parent_id и element_id).

              Короче программу «слабал» за пару вечеров.
          • 0
            Чтобы сделать на сервере универсальное решение, не только под 1С, реализовывал чезе Soap (MSSoap.SoapClient30). Встроенные средства для работы с Soap в восьмерке глючили, поэтому не стал их использовать. Да и код получился почти одинаковый для 7.7 и 8.х.
            • 0
              так ведь выгрузка в XML тоже является «универсальным» решением — оговорен формат, можно дополнительно закрепить его в XSD. Нам не важно, что выгружеат данные с клиента, лишь бы в оговоренном формате, нам не важно, что загружает эти выгруженные данные — хоть 1с, хоть php, хоть аксапта с сапом.
              • 0
                Дело не в одинаковости кода, а в независимости от ПО, которое делает этот самый обмен.
              • 0
                А зачем усложнять то, что можно сделать проще?
                • 0
                  Впринипе верно, мне просто нудна была двухсторонняя связь во время обмена.
              • 0
                Хорошая статья, а заказы как обратно? А зачем xls, если есть точный порядок, то можно в csv завернуть, имхо и в разы быстрее будет обрабатывать. Подход запуска из командной строки подойдет только для 1с 8, в 7 не будет работать. Для большей надежности советую еще делить транспортный файл на куски.
                • 0
                  XML, а не эксель. да и задачи про обратную выгрузку может и нет — просто сайт-витрина.
                  • 0
                    Ага xml, меджиком можно еще ватермарк на изображения наложить для красоты. 5000 товаров это приличный магазин, руками заказы обрабатывать уже напряжно. Так же можно выгрузить характеристики, если они есть. Синхронизировать покупателей и т.д. Всегда будет хотеться большего :)
                    • 0
                      Да, ImageMagick вообще очень мощная библиотека, которая уже выручала не раз, да и сколько ещё раз выручит!

                      Думаю, что скоро будет проект, где как раз и будет синхронизация покупателей, выгрузка скидок, заказов, детали обработки заказов и тд.
                  • 0
                    Заказы обратно выгружать не захотел сам заказчик, по своим личным причинам. Но если бы уж и потребовалась обработка заказов, то её бы я реализовал наверное так:
                    1С стучится, по указанному URL, где выводится список новых, необработанных заказов. Далее парсим 1С'кой информацию о новых заказах, пишем её в базу, при успехе отправляем запрос на сайт, подтверждающий успешную обработку заказа. После чего данный заказ пропадает из списка необработанных.
                    • 0
                      А почему бы тогда уж не использовать планы обмена полностью? тогда и получение заказов с ответным пакетом и обновление статусов в выгрузке на сайт — всё в одном месте
                    • 0
                      Да, но по условию была именно 8-ка, поэтому можно было пользоваться всеми её преимуществами.

                      Да, сначала я тоже задумывался о делении на части, но потом несколько раз попробовал сделать полную, начальную выгрузку. Всё выгрузилось и обработалось на сервере без сбоев. А уж частичное обновление и подавно работает.
                      Но, да, при больших размерах обмена, действительно стоило бы делить данные на части. Спасибо, за замечание.
                    • 0
                      Тоже изобретаю под себя похожий велосипед. Т.к. в 1С ни бум-бум, строки "Создаём план обмена, настраиваем. Дальше модифицируем нашу выгрузку, теперь во время выгрузки создаём новое сообщение в плане обмена, выгружаем только изменённые с момента последнего сообщения единицы… " стали откровением. Теперь хоть знаю в какую сторону копать. Большое человеческое спасибо!
                      • +1
                        Попросить 1с-ника настроить планировщик выгрузок с удобным для тебя форматом и порядком данных.
                        • 0
                          Мне самому интересно научиться :-)
                          • 0
                            рекомендую начать с v8.1c.ru/metod/books/book.jsp?id=187
                              • 0
                                Спасибо, книжками уже затарился
                              • 0
                                Оно понятно, что можно самому научиться, но невозможно охватить всё. Проще разделить труд.
                                ИМХО нужно добавлять? )
                                • 0
                                  Я готов сам подписаться под этими словами. Но такова ситуация на данный момент.
                                  • +1
                                    Понятно, сам занимался всем. Утомляет.
                                    • 0
                                      Утомляет, очень, но зато позволяет узнать все тонкости и потенциально узкие места системы.
                                  • 0
                                    Знаете, вынужден с вами не согласиться. Да, хорошо огородиться и каждому барахтаться в своей песочнице. Но кто-то ведь должен всё это контролировать, искать правильные архитектурные решения, а для этого необходимо знать, как минимум основы всех частей системы.
                                    • 0
                                      Так я первым комментарием написал, что недавно делал всё то же самое, но только чтобы побыдлокодить.
                            • 0
                              > Первым делом, конечно, я стал смотреть в сторону CommerceML, но ознакомившись с документацией, стало ясно, что для нашей, достаточно элементарной выгрузки городить весь этот огород — слишком долго, а бюджет не резиновый.

                              Это оно в документации страшно выглядит, а на деле за полдня у меня получилось сделать полную синхронизацию — заказы в обе стороны, товары, картинки и характеристики товаров.
                              Плюс большие объёмы 1С раскидывает на части, так что не страшны ограничения сервера на время работы скрипта.
                              • 0
                                CommerceML в 8.2 кроме УТ отсутствует в виде готовой обработки для связи с ИМ, счастливым владельцам придется писать велосиды или использовать другие форматы или готовые обработчики не от битрикса. Зачем так сделали не знаю, но есть и другие аналоги, не использующие этот формат, но поддерживающие такие конфигурации и локализации.
                                • 0
                                  Думаю это далеко не последний проект. Так что ещё обязательно будет и близкое знакомство с CommerceML ;)
                                • 0
                                  В общем, как обычно: «Посмотрел чужие костыли — не понравились — сделал свои, родные».

                                  Теперь по-делу:
                                  1. Скрипт генерации превьювок надо доработать. Я свой писал, проверяющим время изменения исходного файла картинки и срабатывающего, если превьювки ещё нет или её дата изменения меньше даты изменения исходного файла. Очень экономит ресурсы и нервы особенно для генерации превью для номенклатур OVER 9000 позиций. особенно в вашем случае, кгда это всё запускается на клиентской машине.

                                  Пример скрипта на sh
                                  #!/bin/sh
                                  
                                  dir="/usr/home/www/site"
                                  src="/upload/images"
                                  prevDst="/httpdocs/catalog/prev"
                                  imgDst="/httpdocs/catalog/img"
                                  
                                  cmd="/usr/local/bin/convert"
                                  
                                  preview(){
                                    ${cmd} ${dir}${src}/$1 -auto-level -resize 170x105 -quality 70 -background white -gravity center -extent 170x105  ${dir}${prevDst}/$1
                                    ${cmd} ${dir}${src}/$1 -auto-level -resize 280x180 -quality 90  ${dir}${imgDst}/$1
                                  }
                                  
                                  cd ${dir}${src}
                                  for f in *.jpg
                                  do
                                  
                                    if test -f $dir$prevDst/$f
                                    then
                                  
                                      if test `stat -f %c $dir$src/$f` -gt `stat -f %c $dir$prevDst/$f` 
                                      then 
                                        preview $f
                                      fi
                                  
                                    else
                                      preview $f
                                    fi
                                  
                                  done


                                  1.1. Image Magic по мимо ресайза позволяет ещё накладывать водяные знаки.

                                  2. Зачем запускать выгрузку на стороне 1С и на стороне хостинга по планировшику? Что мешает после окончания формирования файла выгрузки, генерации картинок и заливки по FTP дёрнуть CGI-скрипт на стороне хостинга, чтобы инициировать обработку? Сразу отпадут некоторые «подстилки», которые фиксят вопрос «А что если соединение разорвётся?». Если разорвётся — скрипт не будет вызван.
                                  • 0
                                    dbfb

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