При реализации интеграции между мобильным приложением и основной базой 1С через веб-сервисы разработчики часто сталкиваются с ситуацией, когда код веб-сервиса отказывается «видеть» методы общих модулей. Это сопровождается неочевидными ошибками типа «Метод объекта не обнаружен» или «Ошибка SOAP сервера: Неизвестная ошибка». В данной статье мы подробно разберем, как правильно настроить среду выполнения, сконфигурировать общие модули и написать отказоустойчивый код для создания документов.
Для начала проанализируем, в каких условиях выполняется код веб-сервиса. Когда внешняя система (например, мобильное приложение) обращается к веб-сервису 1С, на стороне сервера создается специальный сеанс. Важно понимать следующие особенности этого сеанса:
Предупреждение() или ОткрытьФорму().COM-соединение или Внешнее соединение.rphost).Выясним причину, по которой метод общего модуля может быть «не обнаружен». Основная ошибка кроется в неправильной расстановке флагов в свойствах общего модуля. Рассмотрим, какие настройки должны быть установлены для модуля, к которому обращается веб-сервис:
1. Флаг «Сервер»: Должен быть включен обязательно, так как веб-сервис — это серверная операция.
2. Флаг «Внешнее соединение»: Это критически важный момент. Поскольку сеанс веб-сервиса часто идентифицируется платформой аналогично внешнему соединению, отсутствие этого флага сделает модуль недоступным для вызова из модуля веб-сервиса.
3. Флаг «Вызов сервера»: Многие ошибочно включают этот флаг, пытаясь «достучаться» до модуля. Однако Вызов сервера нужен только для обращения из клиентского модуля (формы) к серверному общему модулю. В случае с веб-сервисом этот флаг не требуется и иногда может мешать, если комбинируется с другими клиентскими флагами.
Рассмотрим рекомендации по разделению модулей. Если ваш общий модуль предназначен для работы и в обычном интерфейсе, и через веб-сервис, лучше всего разделить логику или убедиться, что у модуля стоят только флаги «Сервер» и «Внешнее соединение».
Проанализируем использование директив типа &НаСервере или &НаКлиенте внутри общего модуля. Это одна из распространенных ошибок начинающих разработчиков. Директивы компиляции предназначены для модулей форм и команд. В общих модулях они не работают так, как ожидается, и могут привести к тому, что компилятор просто «вырежет» кусок кода из области видимости веб-сервиса.
Правило: В общем модуле, предназначенном для работы с веб-сервисом, не должно быть никаких директив &НаСервере. Код должен быть чистым, а доступность процедур регулируется только ключевым словом Экспорт.
Разберем типичную ошибку при работе с данными. Часто разработчики пытаются обратиться к табличной части через менеджер документа, что вызывает ошибку «Поле объекта не обнаружено». Посмотрим на неправильный пример:
// ОШИБОЧНЫЙ КОД
ТЧ = Документы.ЗаказПокупателя.ТЧНоменклатура; // Это обращение к метаданным, так делать нельзя!
Для работы с данными документа необходимо сначала создать экземпляр объекта. Рассмотрим правильный алгоритм создания документа ЗаказПокупателя на основе структуры данных, полученной из мобильного приложения:
Процедура СоздатьЗаказИзМобильногоПриложения(СтруктураДанных) Экспорт
// Создаем новый объект документа
НовыйДокумент = Документы.ЗаказПокупателя.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Партнер = СтруктураДанных.Контрагент;
// Заполняем остальные реквизиты шапки...
// Переходим к заполнению табличной части
// Предположим, что данные пришли в виде массивов внутри структуры
Для Каждого ЭлементНоменклатуры Из СтруктураДанных.СписокНоменклатуры Цикл
// Добавляем новую строку в ТЧ конкретного ОБЪЕКТА
НоваяСтрока = НовыйДокумент.ТЧНоменклатура.Добавить();
НоваяСтрока.Номенклатура = ЭлементНоменклатуры;
// Если комментарии передаются отдельным массивом (важно соблюдать индексы!)
// Но лучше передавать массив структур, где номенклатура и комментарий связаны
КонецЦикла;
Попытка
НовыйДокумент.Записать(РежимЗаписиДокумента.Запись);
Исключение
ЗаписьЖурналаРегистрации("ОшибкаВебСервиса", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
ВызватьИсключение "Не удалось создать документ: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Выясним, как лучше передавать данные табличных частей. В сообщениях форума предлагалось использовать метод ЗагрузитьКолонку(). Рассмотрим этот метод: он удобен, но опасен. Если в одном массиве данных будет больше, чем в другом, информация в строках «съедет», и комментарий от одного товара прикрепится к другому.
Рекомендация: Передавайте данные в виде единого массива структур. Каждая структура должна представлять собой законченную строку документа. Например:
// Пример структуры данных строки
СтрокаТЧ = Новый Структура;
СтрокаТЧ.Вставить("Номенклатура", СсылкаНаТовар);
СтрокаТЧ.Вставить("Количество", 10);
СтрокаТЧ.Вставить("Комментарий", "Срочная доставка");
В этом случае при обходе массива в цикле вы гарантированно получите связанные данные для каждой строки НовыйДокумент.ТЧНоменклатура.Добавить().
Поскольку веб-сервисы сложно отлаживать в режиме реального времени (обычная точка останова может не сработать без специальной настройки сервера), используем следующие методы:
ЗаписьЖурналаРегистрации() внутри блока Попытка...Исключение. Это позволит вам увидеть реальный текст ошибки, даже если веб-сервис вернул клиенту стандартное сообщение об ошибке SOAP.Подводя итог, можно сказать: для успешного вызова общего модуля из веб-сервиса необходимо обеспечить его доступность через флаги «Сервер» и «Внешнее соединение», убрать лишние директивы компиляции и работать с документами через создание Объекта, а не через менеджер метаданных.