Каталог решений - Web-сервисы из 1С в PHP или грабли, на которые я наступил.

Web-сервисы из 1С в PHP или грабли, на которые я наступил.

Web-сервисы из 1С в PHP или грабли, на которые я наступил.

В наличии

Наверное ни для кого не секрет, что 1С может создавать свои или использовать сторонние web-сервисы, но как она это делает? И что надо сделать, чтобы оно заработало? Информация к размышлению.

Категория:

Описание

Как это должно быть в 1С (подключение не буду описывать, там надо всего-навсего указать wsdl-файл):

Прокси = WSСсылки.Перл.СоздатьWSПрокси("http://it.selenia.ru/", "AWK", "AWK");
Результат = Прокси.pregMatch(Строка, Шаблон);

И написал я такой нехитрый PHP-код:

class AWKService {
  function pregMatch($str, $tmpl) {
                $res_str = "";
                preg_match($tmpl, $str, $res);
                foreach( $res as $line ) {
                        $res_str .= "" . $line . "";
                }
                $res_str .= "";
                return $res_str;
  }
}
$server = new SoapServer("./services.wsdl");
$server->setClass("AWKService");
$server->handle();
?>

И wsdl:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmln
<wsdl:types>
<xsd:schema targetNamespace="urn:pregwsdl">
 <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
 <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="pregMatchRequest">
  <wsdl:part name="str" type="xsd:string"/>
  <wsdl:part name="tmpl" type="xsd:sring"/></message>
<wsdl:message name="pregMatchResponse">
  <wsdl:part name="return" type="xsd:string"/></message>
<wsdl:portType name="pregwsdlPortType">
  <wsdl:operation name="pregMatch">
    <wsdl:documentation>see preg_Match</documentation>
    <wsdl:input message="tns:pregMatchRequest"/>
    <wsdl:output message="tns:pregMatchResponse"/>
  </wsdl:operation>
</wsdl:portType>
<wsdl:binding name="pregwsdlBinding" type="tns:pregwsdlPortType">
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
  <wsdl:operation name="pregMatch">
    <soap:operation soapAction="urn:pregwsdl#pregMatch" style="rpc"/>
    <wsdl:input><soap:body use="encoded" namespace="urn:pregwsdl" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/><
    <wsdl:output><soap:body use="encoded" namespace="urn:pregwsdl" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </wsdl:operation>
</binding>
<wsdl:service name="pregwsdl">
  <wsdl:port name="pregwsdlPort" binding="tns:pregwsdlBinding">
    <soap:address location="http://it.selenia.ru/services.php"/>
  </wsdl:port>
</wsdl:service>
</wsdl:definitions>

И получил от 1С при подключении: «Неверный формат», хотя на http://soapclient.com/SoapTest.html  и формат прочитали и запрос выполнили. И пошел я другим путем. Воспользовался nuSOAP (мало ли я wsdl писать не умею):

// Подключаем код NuSOAP
require_once('lib/nusoap.php');
// Создаем экземпляр сервера
$server = new soap_server();
$server->configureWSDL('AWK','http://it.selenia.ru');
$server->register('pregMatch',
    array('str' => 'xsd:string', 'tmpl' => 'xsd:string'),
    array('result' => 'xsd:string'),
    'http://it.selenia.ru',
    'http://it.selenia.ru#pregMatch',
    'rpc',
    'encoded',
    'Уфф...');
// Определяем метод как функцию PHP
function pregMatch($str, $tmpl) {

                $res_str = "";
                preg_match($tmpl, $str, $res);
                foreach( $res as $line ) {
                        $res_str .= "" . $line . "";
                }
                $res_str .= "";
                return $res_str;
}
// Используем HTTP-запрос чтобы вызвать сервис
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

Но опять, при подключении http://it.selenia.ru/services.php?wsdl — «Неверный формат».

Не буду вас долго мучить и приведу работающий код:

// Подключаем код NuSOAP
require_once('lib/nusoap.php');
// Создаем экземпляр сервера
$server = new soap_server();
$server->configureWSDL('AWK','http://it.selenia.ru');
$server->wsdl->addComplexType(
        'ArrayOfString',
        'complexType',
        'array',
        'all',
        '',
        array(
        'dn' => array('name' => 'dn', 'type' => 'xsd:string',
        'minOccurs' => '0', 'maxOccurs' => 'unbounded')
        )
);
$server->register('pregMatch',
    array('str' => 'xsd:string', 'tmpl' => 'xsd:string'),
    array('result' => 'tns:ArrayOfString'),
    'http://it.selenia.ru',
    'http://it.selenia.ru#pregMatch',
    'rpc',
    'encoded',
    'Уфф...');
// Определяем метод как функцию PHP
function pregMatch($str, $tmpl) {

        preg_match($tmpl, $str, $res);

        return $res;
}
// Используем HTTP-запрос чтобы вызвать сервис
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);

?>

А теперь можно поразмыслить на тему: «Где еще, кроме SQL, напортачил 1С?»

P.S. По мотивам комментариев.

Если вы думаете, что после этого удалось нормально пользоваться web-сервисом, то вы ошибаетесь. Были и еще пляски с бубном.
И огромную благодарность я выражаю всем, кто принял участие в тестировании. Отдельная благодарность Трактор и dushelov за их помощь в получении конечного положительного результата.

Итак, код, который можно нормально использовать:

<?php
// Подключаем код NuSOAP
require_once('lib/nusoap.php');
// Создаем экземпляр сервера
$server = new soap_server();


// Вместо document можно использовать rpc, но у меня не прошло

$server->configureWSDL('AWK','[url]http://it.selenia.ru[/url]','','document');
$server->decode_utf8 = false;
$server->soap_defencoding = 'UTF-8';

//Определяем массив
$server->wsdl->addComplexType(
        'ArrayOfString',
        'complexType',
        'array',
        '',
        'SOAP-ENC:Array',
        array(),
        array(
            array('ref'=>'SOAP-ENC:Array',
                'wsdl:arrayType' => 'SOAP-ENC:string[]',
                'arrayType' => 'SOAP-ENC:string[]',
                'nillable'=>'true'
        )),
        'SOAP-ENC:string'
);
// Регистрируем метод
$server->register('pregMatch',
    array('str' => 'xsd:string', 'tmpl' => 'xsd:string'),
    array('return' => 'tns:ArrayOfString'),
    '',
    '',
    'document',
    'literal');
// Определяем метод как функцию PHP
function pregMatch($str, $tmpl) {
        if (preg_match('@^(.).*\1.?$@i',$tmpl) == 0) {
            return new soap_fault('SERVER', '', 'bad template',$tmpl);
        }
        else {
                preg_match($tmpl, $str, $res);
        }
        return $res;
}
// Используем HTTP-запрос чтобы вызвать сервис
$HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
$server->service($HTTP_RAW_POST_DATA);
?>

Баги есть в релизе 8.2.9.356 — в 8.2.10.73 они исправлены.

И еще. Если вы при подключении получите 407 ошибку, то скорее всего в этом виноват прокси-сервер. Я из-за него долго не мог получить результат, так как 1С просто вылетала. Спасибо Visual Studio — оно дало и описание ошибки и направление его исправления. Если у вас стоит SQUID, то лечится это добавлением сторочки в squid.conf (ignore_expect_100 on). На этом вроде бы все.

has been added to your cart:
Оформление заказа