Управление 1С извне






Передача команд 1С на выполнение через ссылки в письме.

1С имеет один очень мощный инструмент, который для меня был темным лесом. Хотя, наверно, и сейчас таковым остаётся, но уже что-то начинает проясняться. Это Web-сервисы. На сайте 1С можно поверхностно понять что это такое и зачем вообще это нужно.

Итак, web-сервисы помогают интегрировать 1С с различными программами, делая её более гибкой. Статей в интеренете достаточно можно, но в основном там описывается выгрузка из 1С, обмен между двумя 1С или 1С и каким-то мощным программным продуктом написанным на C или других языках.

Для меня же была поставлена задача возможности управление 1С через браузер. Как пример: обрабатывать завершение задачи БП в 1С по ссылке в письме (примерно такого типа //infostart.ru/?user=000000001&bp=000000555, т.е. отсюда видно, что пользователь 000000001 хочет закрыть задачу 000000555), т.е. пользователь со своего смартфона не имеющего доступа к 1С как таковому, должен получить возможность управлять ею извне. Собственно, более сложной задачей можно поставить написание собственных web-форм, более легких и компактных, с произвольным дизайном для управления 1С.

Задача с точки зрения написания кода 1С очень легкая. Основная сложность заключалась в освоении HTML и JavaScript для управления извне. Начальные знаний по этому вопросу я подчерпнул из статьи Примеры пользования web сервисов 1С из браузера.

Настройка 1С

Для возможности использовать 1С в вебе необходимо:
1. Установить модуль расширения веб-сервера;

2. Настроить Windows: доустановить компоненты IIS и настроить проверку подлинности. Всё это можно прочитать в статье Настройка веб-клиента 1С:Предприятие 8.2 под Windows 7 x64 и IIS.

Программирование 1С

Теперь можно приступить к конфигурированию.

1. Создадим Web-сервис Input:
1.1. Input имеет операцию InputData которая принимает два параметра: User и Command, и возвращает параметр типа «boolean (http://www.w3.org/2001/XMLSchema)». Текст функции InputData:

Функция InputData(User, Command)

    обДанные = Справочники.Данные.СоздатьЭлемент();

    обДанные.Наименование = User + «:» + Command;

    обДанные.Записать();

    Возврат Истина;

КонецФункции

1.2. Устанавливаем для Input URI пространства имен = «//infostart.ru«. Здесь может быть любое уникальное имя, обычно это ссылка на сайт.

1.3. Устанавливаем для Input имя файла публикации = «input.1cws». Это имя web-сервиса к которому будем устанавливать соединение.

2. Для наглядности примера создадим справочник Данные, все параметры оставим по умолчанию.

3. Публикуем нашу конфигурацию и web-сервис: Администрирование -> Публикация на веб сервере…

На этом конфигурирование заканчивается, всё остальное сделает за нас 1С.

Разработка HTML страницы

Эта часть далась для меня тяжело, т.к. я ещё только делаю первые шаги в этой теме. Буду рад замачаниям и советам. А так, я постараюсь объяснить всё на пальцах тем, кто как и я знаком по большей части с 1С.

После установки ISS (я уже давал ссылку в начале статьи) на диске C появится каталог C:inetpubwwwroot, в этом каталоге располагается сайт. Для локальной машины (на которой установили ISS) он виден так http://localhost/, ну а для пользователей извне, как-то так //infostart.ru (по правде там немного сложнее, но не суть, мы сейчас не про это). Заглавная страница сайта будет грузиться из файла index.htm каталога C:inetpubwwwroot

 

Исходники файлов можно скачать здесь

Код файла index.htm попытаюсь объяснить как могу, т.к. сам некоторые моменты не понимаю:

[html xmlns=»http://www.w3.org/1999/xhtml»] // Неважно. Используется в XHTML для объявления пространства имен.
[head] // Предназначен для хранения других элементов, цель которых — помочь браузеру в работе с данными.

[meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ /] // Неважно.  Мета-теги используются для указания описания.

[title]Тест веб сервиса 1С[/title] // Неважно. Определяет заголовок документа, то что видит пользователь как текст вкладки.

[script type=»text/javascript» src=»../js/connect1c.js»] [/script] // Важно. Подключение JavaScript библиотек. В моём случае это мой модуль соединения с 1С.
[script type=»text/javascript» src=»../js/parameters.js»] [/script] // Важно. А это модуль обработки параметров строки браузера.

[/head]

[body] // Предназначен для хранения содержания веб-страницы (контента), отображаемого в окне браузера.
[p id=»response1C»][/p] // Важно. Метка response1C, куда вернёться ответ запроса 1С.
[/body]

[script type=»text/javascript»] // Важно. Начало основного скрипта, который выдёргивает из строки браузера всё что идёт дальше знака вопроса,
а дальше парсит по определенному алгоритму. В нашем случае будут искаться ключевые слова «user=» и «command=».

    user = GetParameter(«user»); // Важно. Находим значение user. Сам метод GetParameter находится в библиотеке parameters.js, о которой поговорим чуть позже.
   
command = GetParameter(«command»); // Важно. Находим значение command.

    Inquiry1C(user, command); // Важно. Запрос к 1С с найденными параметрами. Сам метод Inquiry1C находится в библиотеке connect1c.js

[/script]

[/html]

*дико извиняюсь, & lt; и & gt; не работают (точнее работают, но после пересохранения они исчезают). Заменил < на [, а > — ]

Рассмотрим библиотеку parameters.js, которая находится в папке C:inetpubwwwrootjs

function GetParameter(pName) { // Сам метод я нашёл на просторах интернета.

    search = window.location.search; // window.location — это по сути URL, метод search этого объекта возвращает часть адреса после символа «?», включая символ «?».

    begin = search.indexOf(pName) + pName.length + 1; // Вычисляем позицию начала строки значения параметра для вырезания. +1 — в нашем случае это знак «=».
Итого, для search = «?user=007» мы найдём позицию начала равной 6 (нумерация с нуля).
    end = search.indexOf(‘&’, begin); // Находим позицию конца выражения. В нашем случае, разделение параметров осуществляется знаком «&», и если мы его не найдём,
то позицией конца будет последний символ строки search (смотри дальше код).

    if (end == -1) {
        end = search.length;
    };

    return unescape(search.substring(begin, end)); // Метод unescape возвращает строку, содержащую данные типа charString (не знаю зачем это надо,
но видимо такое приведение типа здесь необходимо). Ну а метод substring — извлекает подстроку из строки.

}

Теперь рассмотрим библиотеку connect1c.js, которая также находится в папке C:inetpubwwwrootjs

function Inquiry1C(pUser, pCommand) { // Основной метод этой библиотеки. Запрос к 1С.

    XMLHTTP = CreateRequestObject(); // Создание XML HTTP запроса. Сам метод я узнал из википедии.

    XMLHTTP.open(‘POST’, ‘../TestWeb/ws/Input.1cws’, true, «Admin», «1»); // Создаём соединение типа POST, где второй параметр — адрес; параметр true — значит асинхронное,
то есть браузер не будет ждать ответа сервера, а продолжит работу; далее пользователь и пароль с правами на операцию InputData (этот тот метод, который мы написали в 1С),
саму операцию можно выполнять в привилегированном режиме, чтобы не мучиться с правами для пользователя Admin.

    XMLHTTP.onreadystatechange = function() {WhenAnswering1C(XMLHTTP)}; // Когда 1С отработает, автоматически сработает метод WhenAnswering (о нём чуть ниже по тексту этой библиотеки).

    XMLHTTP.send(»
        + ‘ ‘
        + ‘ ‘
        + »
        + pUser + ‘ ‘
        + »
        + pCommand + ‘ ‘
        + ‘ ‘); // Отправка XML запроса, где описывается метод к исполнению в 1С, с переданными параметрами из нашей строки URL.
// Строку запроса можно раскурить минут за 5:)

}

function CreateRequestObject() { // Чудо метод из википедии «Пример использования». По сути, ничего сложного.
   
if (typeof XMLHttpRequest === ‘undefined’) {
        XMLHttpRequest = function() {
            try { return new ActiveXObject(«Msxml2.XMLHTTP.6.0»); }
                catch(e) {}
            try { return new ActiveXObject(«Msxml2.XMLHTTP.3.0»); }
                catch(e) {}
            try { return new ActiveXObject(«Msxml2.XMLHTTP»); }
                catch(e) {}
            try { return new ActiveXObject(«Microsoft.XMLHTTP»); }
                catch(e) {}
            throw new Error(«This browser does not support XMLHttpRequest.»);
        };
    }
    return new XMLHttpRequest();
}

function WhenAnswering1C(pXMLHTTP) { // Метод, который срабатывает после обработки запроса 1С.

    status = StausRequest(pXMLHTTP); // Вычисляется статус для отправки сообщения пользователю (о нём чуть ниже).
   
document.getElementById(«response1C»).appendChild(document.createTextNode(status)); // Вывод на экран в помеченную область response1C (о ней я писал в основном файле).
Метод getElementById возвращает ссылку на узел документа.
Метод appendChild добавляет нод в конце списка дочерных нодов элемента, т.е. встраивает в нашу область нужный нам текст.

}

function StausRequest(pXMLHTTP) // Определение статуса.
{
    status = «»;
    if (pXMLHTTP.readyState == 4) { // Опять же, читая википедию можно понять, readyState — это текущее состояние объекта (0 — не инициализирован, 1 — открыт,
2 — отправка данных, 3 — получение данных и 4 — данные загружены).
        if (pXMLHTTP.status != 200) { // status — HTTP-статус в виде числа (404 — «Not Found», 200 — «OK» и т. д.)
           
status = «Запрос завершился неудачно. Ответ сервера: » + pXMLHTTP.responseText; // responseText -текст ответа на запрос.
Если состояние не 3 или 4, возвращает пустую строку.
        }
        else {
            if (RequestSuccessful(pXMLHTTP)) { // Проверка ответа от 1С (о нём чуть ниже).
               
status = «Запрос отработан.»;
            }
            else {
                status = «Запрос был отклонён.»;
            };

        };
    };

    return status;
}

function RequestSuccessful(pXMLHTTP) { // Проверка ответа от 1С. Здесь мы получим возвращаемое от 1С значение (в нашем случае 1С может вернуть тип булево).

    DOM = pXMLHTTP.responseXML.getElementsByTagName(«return»)[0]; // responseXML — Текст ответа на запрос в виде XML, который затем может быть обработан посредством DOM.
Если состояние не 4, возвращает null.
    response = DOM.childNodes[0].data; // Достаём данные из ответа.

    return response == «true»; // Если правда, то правда:) По правде, я не смог преобразовать сроку в булево, поэтому пришлось оставить так.

}

Проверка

Открываем браузер и вводим строку «localhost/?user=007&command=hello world!»:

После чего можно открыть 1С и убедиться что создался элемент справочника:

На этом пример ознакомления управления 1С извне можно считать законченным:)

51 Comments

  1. alexware

    Отличная статья! Только начинаю присматриваться к Web-сервисам — скоро, видимо, понадобится по работе. Очень хорошо написана, чудесные комментарии. Даже непосвященному всё понятно. Спасибо!

    Reply
  2. BorisMor

    Статья хорошая, но html и java-script не читаемые.

    Может просто код выделить тегом <pre> ?

    Reply
  3. las77

    добавлю в закладки. когда нибудь пригодится.

    Reply
  4. Vladimir87
    Задача с точки зрения написания кода 1С очень легкая. Основная сложность заключалась в освоении HTML и JavaScript для управления извне.

    А мне наоборот, web-программирование проще, чем 1с ). Но это так. А по статье — молодец. Ставлю плюс.

    Reply
  5. Soloist

    (2) BorisMor, что-то так сразу не получается. Но думаю сами файлы улучшат ситуацию http://yadi.sk/d/jmg8ydss07Dey

    Reply
  6. oly86

    (3) las77, +1, тоже в закладки, полезная вещь, надо начинать осваивать

    Reply
  7. ivs200999

    Любопытно, спасибо за статью.

    Reply
  8. DoctorRoza

    Плюс за содержание и оформление. Все бы так делали.

    Reply
  9. poyson

    Хорошая статья. подробная. спасибо.

    Reply
  10. sstar90

    Нормалек, спасибо за статью

    Reply
  11. NPMar

    Спасибо большое за статью! Очень хорошее и содержание и оформление. Даже «чайнику» всё понятно. Надеюсь, что пригодится в удаленной работе. Спасибо!

    Reply
  12. absolutblohin

    Как раз работаю над конфигурацией, в которой программисту ставятся задачи через письма. Попробую это как нибудь прикрутить. Автору спасибо.

    Reply
  13. Raminus

    Как ознакомление пойдет.

    Reply
  14. Gandalf Белый

    Большое спасибо! Очень интересная статья! думаю пригодиться. ))

    Reply
  15. Soloist

    (12) Yashazz, со стороны кодинга и установки 1С — всё просто. Но для человека не знающего JavaScript дальнейшая реализация — это новый мир. Я не скрываю, что он легок для тех кто знает его. Я просто показал как я к этому шёл, и поверьте я был бы рад, если бы для меня это написали раньше, когда я задавал подобный вопрос на Мисте http://www.forum.mista.ru/topic.php?id=614454

    Следующая статья будет более 1Сая.

    Reply
  16. lukoyanovas

    (0) Что-то я не заметил, а где мы указываем под каким пользователем логинимся в 1С?

    И еще, а что если полученную в результате ссылку мы нажмем 10000000 раз подряд (допустим в цикле)?

    Reply
  17. Soloist

    1. «XMLHTTP.open(‘POST’, ‘../TestWeb/ws/Input.1cws’, true, «Admin», «1»);» — здесь пользователь базы Admin с паролем 1;

    2. В моём примере будет столько записей сколько раз перейдут по ссылке. Но не сложно отработать подобную ситуацию в 1С и предусмотреть под это событие нужную ветку.

    Reply
  18. Soloist

    (17) lukoyanovas, ответил выше.

    Reply
  19. AlexO

    Я всегда знал, что 1С — навязана ИЗВНЕ.

    Ничего человеческого 🙂

    Reply
  20. alon
    саму операцию можно выполнять в привилегированном режиме

    А если еще в функции InputData использовать команду «Выполнить», то уже на следующий день можно увольняться. Хакеры камня на камне от базы не оставят.

    Reply
  21. Soloist

    (21) alon,

    …, чтобы не мучиться с правами для пользователя Admin

    настройте тоньше и будет счастье.

    Reply
  22. klel

    Самая что ни на несть отличная статья, даже не думал что такое можно сделать 🙂 Огромное спасибо за статью обязательно возьму себе на вооружение =) ОГРОМНЫЙ «+»

    Reply
  23. LelikOFF

    Интересная статья, нужно будет попробовать

    Reply
  24. UncleVader

    Я так понял данный метод будет работать только при условии удачного создания ActiveX-объекта, т.е. только на Win-платформе!?

    Reply
  25. Soloist

    (26) UncleVader, если я правильно понимаю код метода CreateRequestObject(), то в блок использования ActiveX исполняемый код попадёт, если typeof XMLHttpRequest === ‘undefined’, а это возможно для IE версии 6 и ниже. Для всех остальных случаев будет работать строка «return new XMLHttpRequest();»

    Reply
  26. kilokilo

    Очень опасно без предварительной авторизации через web-сервисы создавать контент в БД.. разгребать потом замучаетесь — кто, что и когда.

    На чтение — еще куда не шло, единственное — слишком частые запросы приведут к отказу от обслуживания (типа DDOS атаки).

    А так — плюс за обмен опытом.

    Reply
  27. Angry

    (12) Yashazz, Вы не правы, человек описал на простом языке основы веб сервисов, за это он заслужил огромный +.

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

    А по теме: Иван молодец, я раньше пытался узнать, что это за зверь такой Веб сервис, но не смог выделить достаточно времени, потому просто забил, теперь есть возможность попробовать снова, потому: Спасибо и +.

    Reply
  28. Трактор

    (29) Angry,

    Я думаю многие плюсовавшие будут благодарны и Вам если предоставите информацию, о том где есть информация о веб сервисах, доступная для программистов 1С.

    Уже 5 лет публикации http://infostart.ru/public/16001/ Она о том же что и эта.

    Reply
  29. Kuzja_R

    Заголовок «Передача команд 1С на выполнение через ссылки в письме.» совершенно не соответствует содержанию. Тонкий маркетинговый ход?

    Reply
  30. Soloist

    (30) Трактор, ваша статья мне очень помогла, для развитии этой идеи. Извиняюсь, что забыл добавить в публикацию. Исправил.

    Reply
  31. Soloist

    (31) Kuzja_R, нет

    Reply
  32. nataon

    Хорошая статья, спасибо

    Reply
  33. evrakylon

    Спасибо за статью. Осталось не ясным следующий момент. Вот строка HTTP запроса

    XMLHTTP.open(‘POST’, ‘../TestWeb/ws/Input.1cws’, true, «Admin», «1»);

    Веб сервис публикуется из 1С 8.2, значит файла Input.1cws нет, а данные об alias указываются в default.vrd, например в разделе <ws>. Что означает в данном случае путь (или адрес) ‘../TestWeb/ws/Input.1cws’? На скрине видна папка TestWeb — что в ней?

    Спасибо!

    Reply
  34. tolik_byr

    Интересно, но какие-либо мыслей по явному применению у кого-нибудь есть?

    Reply
  35. Soloist

    (35) evrakylon, я думаю что это адрес. В папке TestWeb два файла default.vrd и web.config. В файле default.vrd прописан наш web-сервис вот так:

    <ws>

    <point name=»Input»

    alias=»input.1cws»/>

    </ws>

    Reply
  36. evrakylon

    1. При вводе в браузер http://localhost/preved/ws/preved.1cws?wsdl открывается корректное описание

    2. При вводе http://localhost/preved запускается web-клиент 1С

    Тут корректно, мало того я подключаюсь к вебсервису из другой 1С.

    Далее, в папке C:inetpubwwwrootpreved есть файл default.vrd

    <ws>

    <point name=»preved»

    alias=»preved.1cws»/>

    </ws>

    Какой же путь тут должен быть XMLHTTP.open(‘POST’, ‘???’, true, «Admin», «1»);

    и где правильно расположить файлы HTM и JS?

    Reply
  37. Soloist

    (38) evrakylon,

    «Какой же путь тут должен быть XMLHTTP.open(‘POST’, ‘???’, true, «Admin», «1»); »

    я думаю ‘../preved/ws/preved.1cws’. Может зависит от платформы… у меня на одной из 8.3.1 точно не выполнялось (может даже есть одна 8.2 на которой не выполняется). Сейчас стоит 8.3.2.172 и IIS 8, путь такой, какой я написал.

    «и где правильно расположить файлы HTM и JS?»

    в принципе где угодно, важна ведь строчка подключения этой библиотеки. Путь к файлам js я прописывал в самом начале

    <script type=»text/javascript» src=»../js/parameters.js»> </script>

    Reply
  38. x2z7yy
    XMLHTTP.send(»

    + ‘ ‘

    + ‘ ‘

    + »

    + pUser + ‘ ‘

    + »

    + pCommand + ‘ ‘

    + ‘ ‘);

    Не пойму, так и надо чтоли писать? Или вместо пробелов что-то должно быть?

    Reply
  39. Soloist

    (40) x2z7yy, извиняюсь, это infostart пожрал код, возьмите его отсюда http://yadi.sk/d/jmg8ydss07Dey

    Reply
  40. x2z7yy

    (41) Soloist, спасибо, сейчас буду пробовать дальше.

    Reply
  41. sikuda

    Хорошая статья, но как из прошлой жизни:

    XMLHttpRequest = function() {

    try { return new ActiveXObject(«Msxml2.XMLHTTP.6.0»); }

    catch(e) {}

    try { return new ActiveXObject(«Msxml2.XMLHTTP.3.0»); }

    catch(e) {}

    try { return new ActiveXObject(«Msxml2.XMLHTTP»); }

    catch(e) {}

    try { return new ActiveXObject(«Microsoft.XMLHTTP»); }

    catch(e) {}

    throw new Error(«This browser does not support XMLHttpRequest.»);

    };

    Я развил эту идею http://infostart.ru/public/167093/

    Reply
  42. Soloist

    (43) sikuda, ценно

    Reply
  43. 300hp

    (41) Soloist, привет! где еще можно посмотреть что там за код съел infostart?

    Reply
  44. Soloist

    (45) 300hp, вот здесь все исходники http://yadi.sk/d/jmg8ydss07Dey. Сейчас статью обновлю

    Reply
  45. m.bolsun

    ставлю + т.к. люблю всякие вещи, такого рода. У самого есть пара прототипов работы с вебсервисами из самой 1с, но мне не подходит изменение конфигурации, поэтому использую HTTPСоединение.

    Тут однозначно необходимо решить вопросы с безопасностью и имхо, возможно стоит поменять направление запросов, т.е. к 1с никто не соединяется, а сама 1с цепляется через SSL соединение, к какому-нибудь доверенному безопасному серверу, где ее уже ждет очередь команд. Как то так.

    Reply
  46. Soloist

    (47) m.bolsun, спасибо

    Reply
  47. TitanLuchs

    Веб-сервисы и не на это способны на самом деле ) Но минус у них есть — при большом потоке запросов имеют свойство отваливаться…

    Reply
  48. mary61

    Большой +. В будущем пригодится

    Reply
  49. Ed111111

    Не понял, для чего это нужно?

    Reply
  50. Soloist

    (51) Ed111111, ради фана. Ну и приятно же не открывая 1С выполнить действие в базе, имея лишь исполняемую ссылку, которую тебе прислали.

    Reply
  51. mdSerg

    (30) Трактор, только её не скачать

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *