8.х WEB Работа с Webсервисом опубликованном на веб сервере

Тема в разделе ""1C:Web-Сервер"", создана пользователем bajiepka, 22 июл 2015.

  1. TopicStarter Overlay
    bajiepka
    Offline

    bajiepka Опытный в 1С

    Регистрация:
    26 сен 2014
    Сообщения:
    329
    Симпатии:
    23
    Баллы:
    29
    Доброго времени суток! Server 2012, IIS, платформа 8.3.6.2100 (самая свежая), БП 3.0 (3.0.40.36), тип базы: файловый. По многочисленным примерам из интернета создал Web-сервис, целью которого есть:
    - получить из интернета запрос с ИНН контрагента и номером договора;
    - отправить обратно сумму остатка по этому договору;

    Написал обработку для обкатки сего дела с таким кодом:

    Код:
    &НаСервере
    Процедура ПолучитьСальдоНаСервере()
      
        Определения = Новый WSОпределения("http://xxx.xxx.xxx.xxx:10000/public/ws/wsSumma.1cws?WSDL", "admin", "123");
        //Определения = Новый WSОпределения("http://192.168.1.20:80/public/ws/wsSumma.1cws?WSDL", "admin", "123");
          
        ВебСервис = Новый WSПрокси(Определения, "http://www.mysite.ru", "ExchangeWEB1CService", "ExchangeWEB1CServiceSoap");
      
        ВебСервис.Пользователь = "admin";
        ВебСервис.Пароль = "123";
      
            ТипWSПараметра = ВебСервис.ФабрикаXDTO.Пакеты.Получить("http://www.mysite.ru").Получить("ContractorBalance");
      
            WSПараметр       = ВебСервис.ФабрикаXDTO.Создать(ТипWSПараметра);
            WSПараметр.INN    = ИНН;
            WSПараметр.ContractNumber    = НомерДоговора;
            WSПараметр.Balance    = 0;
            БалансКонтрагента = ВебСервис.GetBalance(ИНН, НомерДоговора);
      
            Если БалансКонтрагента = Неопределено Тогда
                Сальдо = 0;
                Возврат;  
            КонецЕсли;
          
            Сальдо = БалансКонтрагента.Balance;
            Успех = ВебСервис.WriteSales(ИНН, НомерДоговора, Сальдо);
            Сообщить("Успех: " + Успех);
          
    КонецПроцедуры
    
    ContractorData - XDTO-пакет с предсозданной с типом объекта СontractorBalance

    Когда я обращаюсь по локальной сети к этому веб-сервису, то мне возвращает нормальный результат БалансКонтрагента.Balance.
    Код:
        Определения = Новый WSОпределения("http://192.168.1.20:80/public/ws/wsSumma.1cws?WSDL", "admin", "123");
    Когда же я обращаюсь по инет айпишнику (белый), то вылетает ошибка связи...
    Код:
        Определения = Новый WSОпределения("http://xxx.xxx.xxx.xxx:10000/public/ws/wsSumma.1cws?WSDL", "admin", "123");
    Ошибка такого содержания:
    Код:
    {Форма.Форма.Форма(5)}: Ошибка при вызове конструктора (WSОпределения)
        Определения = Новый WSОпределения("http://ххх.ххх.ххх.ххх:10000/public/ws/wsSumma.1cws?WSDL", "admin", "123");
    по причине:
    При создании описания сервиса произошла ошибка. http://admin:xxxxxxx@xxx.xxx.xxx.xxx:10000/public/ws/wsSumma.1cws?WSDL
    по причине:
    Ошибка работы с Интернет:   Не могу установить соединение
    Порты пробрасывали с сисадмином (с 80 на 10000). Если напрямую зайти на
    Код:
    http://admin:xxxxxxx@xxx.xxx.xxx.xxx:10000/public/ws/wsSumma.1cws?WSDL
    то меня спрашивает логин, пароль (admin,123) и выдает текст xml файла, где вроде все мои параметры...

    В интернете прочитал, что это "приколы" файлового варианта базы, мол существуют какие-то особенности клиент-серверного варианта базы... но это же нонсенс!!!!

    Также, меня настораживает содержимое этого xml файла:
    Код:
    ...
    <service name="ExchangeWEB1CService">
    <port name="ExchangeWEB1CServiceSoap" binding="tns:ExchangeWEB1CServiceSoapBinding">
    <documentation>
    <wsi:Claim conformsTo="http://ws-i.org/profiles/basic/1.1"/>
    </documentation>
    <soapbind:address location="http://ххх.ххх.ххх.ххх/public/ws/wsSumma.1cws"/>
    </port>
    <port name="ExchangeWEB1CServiceSoap12" binding="tns:ExchangeWEB1CServiceSoap12Binding">
    <soap12bind:address location="http://xxx.xxx.xxx.xxx/Public/ws/wsSumma.1cws"/>
    </port>
    </service>
    </definitions>
    Нигде не упоминается порт 10000...

    Подскажите пожалуйста, в какую сторону копать???
  2. nomad_irk
    Offline

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    7.581
    Симпатии:
    717
    Баллы:
    204
    Порт не виден, т.к. используется стандартный порт. Стандартный - 80.
    Порт 10000 нужно в настройках IIS указывать, тогда он должен быть виден.

    доступ в интернет машины с IIS каким образом организован?
    Последнее редактирование: 22 июл 2015
  3. TopicStarter Overlay
    bajiepka
    Offline

    bajiepka Опытный в 1С

    Регистрация:
    26 сен 2014
    Сообщения:
    329
    Симпатии:
    23
    Баллы:
    29
    через роутер с пробросом порта. к сожалению я там не админю, поэтому более конкретно сказать не могу.
  4. nomad_irk
    Offline

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    7.581
    Симпатии:
    717
    Баллы:
    204
    Если внутри локальной сети все работает, а из вне доступа нет, то проблема исключительно в маршрутизации.
    Настраивайте маршрутизатор.

    Например, мой домашний Web-сервис: nomadirk.us.to:81/buh_asap/ws/replicator.1cws?wsdl
    bajiepka нравится это.
  5. TODD22
    Offline

    TODD22 Профессионал в 1С Команда форума

    Регистрация:
    23 фев 2009
    Сообщения:
    4.759
    Симпатии:
    147
    Баллы:
    104
    У всех я смотрю похожие задачи :) Мне как раз то же нужно 1ску связать со сторонним сервисом и сделать что то типа биллинга. Что бы можно было отключать от услуг клиентов с задолженностями.
    Только мне надо на http сервис отправлять данные из 1ски.
  6. nomad_irk
    Offline

    nomad_irk Гуру в 1С

    Регистрация:
    20 окт 2008
    Сообщения:
    7.581
    Симпатии:
    717
    Баллы:
    204
    Да собственно разницы нет, куда и чего отправлять. Как напишешь,так и будет работать.
    Для работы с HTTP в 1С есть методы Получить()(GET)/Записать()(PUT)/ОтправитьДляОбработки()(POST c последующим GET результата) у объекта HTTPСоединение.
  7. TopicStarter Overlay
    bajiepka
    Offline

    bajiepka Опытный в 1С

    Регистрация:
    26 сен 2014
    Сообщения:
    329
    Симпатии:
    23
    Баллы:
    29
    разобрались вроде с пробросом портов на сервере. перенастроили IIS с 80-го на 10000, и пробрасываем с маршрутизатора на сервер 10000 на 10000. Всё вроде ок работало, но всё завернули. Soap оказался заказчику не нужен, попросил переделать на rest. TODD22 видимо смоим постом это всё спровоцировал :) Да еще и JSON нужно возвращать после GET'a.
    Помогите пожалуйста советом теперь с этой лабудой... уже бьюсь-бьюсь, ничего не выходит..
    Сделал http-сервис, создал шаблон /query/{number} (номер ИНН), создал метод GET и обработчик для него.
    Обработчик выглядит где-то так:
    Код:
    Функция СтрокиGET(Запрос)
          
        НомерИНН         = Запрос.ПараметрыURL["number"];
          
        НужныйКонтрагент= Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", НомерИНН);
      
        Если НужныйКонтрагент= Неопределено ИЛИ НужныйКонтрагент.Пустая() Тогда
            Ответ = Новый HTTPСервисОтвет(404);
            Возврат Ответ;
        КонецЕсли;
      
        // создаем новый JSON массив
        ЗаписьJSON = Новый ЗаписьJSON;
      
        ЗаписьJSON.ПроверятьСтруктуру = Истина;
        ПараметрыЗаписиJSON = Новый ПараметрыЗаписиJSON(,Символы.Таб);
        ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписиJSON);
      
        // создаем массив для параметров
        ЗаписьJSON.ЗаписатьНачалоМассива();
        // записываем в элементы массива ИмяКОнтрагента, ИНН, КПП, ОКПО, ТипЮрФизЛица
        ЗаписьJSON.ЗаписатьЗначение(Строка(НужныйДокумент.Наименование));
        ЗаписьJSON.ЗаписатьЗначение(Строка(НужныйДокумент.ИНН));
        ЗаписьJSON.ЗаписатьЗначение(Строка(НужныйДокумент.КПП));
        ЗаписьJSON.ЗаписатьЗначение(Строка(НужныйДокумент.КодПоОКПО));
        Если НужныйДокумент.ЮридическоеФизическоеЛицо = Перечисления.ЮридическоеФизическоеЛицо.ЮридическоеЛицо Тогда
            ЗаписьJSON.ЗаписатьЗначение("legal");
        ИначеЕсли НужныйДокумент.ЮридическоеФизическоеЛицо = Перечисления.ЮридическоеФизическоеЛицо.ЮридическоеЛицо Тогда
            ЗаписьJSON.ЗаписатьЗначение("person");
        КонецЕсли;
    
        // получаем список договоров контрагента
        ЗапросДоговоров = Новый Запрос;
        ЗапросДоговоров.УстановитьПараметр("ИНН", НужныйДокумент.ИНН);
        ЗапросДоговоров.Текст =
        "ВЫБРАТЬ
        |    ДоговорыКонтрагентов.Владелец             КАК Владелец,
        |    ДоговорыКонтрагентов.Наименование        КАК Наименование,
        |    ДоговорыКонтрагентов.Организация        КАК Контрагент,
        |    ДоговорыКонтрагентов.ТипЦен                КАК ТипЦен,
        |    ДоговорыКонтрагентов.Дата                КАК Дата,
        |    ДоговорыКонтрагентов.Номер                КАК Номер
        |ИЗ
        |    Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
        |ГДЕ
        |    ДоговорыКонтрагентов.Владелец = &ИНН";
      
        РезультатЗапроса = ЗапросДоговоров.Выполнить().Выбрать();
      
        Пока РезультатЗапроса.Следующий() Цикл
            // создаем для каждого договора отдельный объект в массиве JSONа
            ЗаписьJSON.ЗаписатьНачалоОбъекта();
          
            ЗаписьJSON.ЗаписатьИмяСвойства("ConName");
            ЗаписьJSON.ЗаписатьЗначение(Строка(РезультатЗапроса.Наименование));
            ЗаписьJSON.ЗаписатьИмяСвойства("ConDate");
            ЗаписьJSON.ЗаписатьЗначение(Строка(РезультатЗапроса.Дата));
            ЗаписьJSON.ЗаписатьИмяСвойства("ConPrices");
            ЗаписьJSON.ЗаписатьЗначение(Строка(РезультатЗапроса.ТипЦен));
            ЗаписьJSON.ЗаписатьИмяСвойства("ConOwner");
            ЗаписьJSON.ЗаписатьЗначение(Строка(РезультатЗапроса.Контрагент));
          
            ЗаписьJSON.ЗаписатьКонецОбъекта();
          
        КонецЦикла;
    
        ЗаписьJSON.ЗаписатьКонецМассива();
        ЗаписьJSON.Закрыть();
      
        РезультатСтрока = "у нас всё получилось!";
      
        Ответ = Новый HTTPСервисОтвет(200);
        Ответ.УстановитьТелоИзСтроки(ЗаписьJSON, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
      
        Возврат Ответ;
      
    КонецФункции
    
    Тут я создаю JSON для возврата. В его массив кидаю параметры контрагента, а в объекты текущие договоры по нему. JSON формируется вроде правильно, но передать его почему-то не могу. Возвращается у меня как и должен 200 ответ, а к нему я цепляю свой JSON.

    Пытаюсь принять его обработкой:
    Код:
    &НаСервере
    Процедура ПолучитьИнфуОКонтрагентах()
      
        HTTPСоединение     = Новый HTTPСоединение("localhost", 9000, "remote", "123");
      
        ТекстЗапроса     = "public/hs/order/query/" + ИНН;
        HTTPЗапрос         = Новый HTTPЗапрос(ТекстЗапроса);
        HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
          
        // сюда будем сохранять результаты запроса
        ФайлРезультата = ПолучитьИмяВременногоФайла();
      
        HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос, ФайлРезультата);
       
        КодСостояния = HTTPОтвет.КодСостояния;
        responseText = HTTPОтвет.ПолучитьТелоКакСтроку(ФайлРезультата);
      
    КонецПроцедуры
    
    По идее мне responseText должен вернуть мой JSON, но он Неопределен...

    А если посмотреть HTTPОтвет.Заголовки то вот такая фигня
    Значение элемента Тип элемента Ключ Значение
    КлючИЗначение КлючИЗначение "Date" "Fri, 24 Jul 2015 07:48:55 GMT"
    КлючИЗначение КлючИЗначение "Keep-Alive" "timeout=5, max=100"
    КлючИЗначение КлючИЗначение "Content-Type" "text/plain"
    КлючИЗначение КлючИЗначение "Connection" "Keep-Alive"
    КлючИЗначение КлючИЗначение "Content-Length" "19"
    КлючИЗначение КлючИЗначение "Server" "Apache/2.2.25 (Win32)"

    Если у кого-то есть рабочий пример работы с JSONом по http-сервису, поделитесь пожалуйста..
  8. TODD22
    Offline

    TODD22 Профессионал в 1С Команда форума

    Регистрация:
    23 фев 2009
    Сообщения:
    4.759
    Симпатии:
    147
    Баллы:
    104
    Это как это я смог "спровоцировать"?
  9. shurikvz
    Offline

    shurikvz Модераторы Команда форума Модератор

    Регистрация:
    1 окт 2009
    Сообщения:
    8.410
    Симпатии:
    316
    Баллы:
    104
    У вас в синтаксисе в обработке что-то не то. ПолучитьТелоКакСтроку возвращает данные только если не установлен временный файл. Таким образом
    Код:
    &НаСервере
    Процедура ПолучитьИнфуОКонтрагентах()
    
        HTTPСоединение     = Новый HTTPСоединение("localhost", 9000, "remote", "123");
    
        ТекстЗапроса     = "public/hs/order/query/" + ИНН;
    
       
    ЗаголовкиЗапроса = Новый Соответствие();
    ЗаголовкиЗапроса.Вставить("Content-Type", "application/json");
    
        HTTPЗапрос         = Новый HTTPЗапрос(ТекстЗапроса, ЗаголовкиЗапроса);
    
    Попытка
        HTTPОтвет = HTTPСоединение.Получить(HTTPЗапрос);
     
        КодСостояния = HTTPОтвет.КодСостояния;
        responseText = HTTPОтвет.ПолучитьТелоКакСтроку();
    Исключение
    //Здесь сделайте что-нибудь чтобы сообщить о причине ошибки
    КонецПопытки;
    
    КонецПроцедуры
    как-то так наверно.
  10. TopicStarter Overlay
    bajiepka
    Offline

    bajiepka Опытный в 1С

    Регистрация:
    26 сен 2014
    Сообщения:
    329
    Симпатии:
    23
    Баллы:
    29
    даже не знаю... мистика какая-то -Android- клиенты резко отказались от soap, мол говорят нам только rest нужен... по времени совпало :)
  11. TopicStarter Overlay
    bajiepka
    Offline

    bajiepka Опытный в 1С

    Регистрация:
    26 сен 2014
    Сообщения:
    329
    Симпатии:
    23
    Баллы:
    29
    разобрался. мой косяк. при формировании JSONа на сервере я не формировал его строковое представление, а просто как бэ записывал
    с помощью ЗаписьJSON.Закрыть(); Сам по себе JSON жирный и в тело HTTP ответа не пролазит. Поэтому его нужно запихивать в ответ в виде строки.
    Для возврата представления JSON в виде строки у него есть аналогичный метод закрыть но только с определением переменной этой строки, например: СтроковыйJSON = ЗаписьJSON.Закрыть();
    Это строковое представление комфортно ложится в тело HTTPОтвета, возвращаемого сервером. Потом уже из тела ответа формируется строка ответа и JSON читается... Интересно то, что если закрыть запись ЗаписьJSON.Закрыть(), то потом её нельзя уже преобразовать в строку вот так СтроковыйJSON = ЗаписьJSON.Закрыть(), ведь она уже закрыта... вобщем как-то так, сейчас всё работает аки надо
    TODD22 нравится это.

Поделиться этой страницей