to be deleted
to be deleted
Преамбула: я где то год назад думал, что имплементация SOAP в Сапе - это кошмар на улице вязов, хуже которого ничего не бывает. Работая с вебсервисами в 1с, я начинаю понимать, что они друг друга стоят.
Собственно, вопрос.
Как в 1С преобразовать сложный тип к объектам языка?
Есть PHP class который использует nusoap для создания вебсервисов
<?php error_reporting(0); // Configuration require_once('../admin/config.php'); require_once(DIR_SYSTEM . 'startup.php'); require_once(DIR_SYSTEM . 'library/nusoap.php'); //$registry = new Registry(); date_default_timezone_set('Asia/Bangkok'); // Create SOAP Server $server = new soap_server(); $server->configureWSDL("test_service", "http://www.example.com/test_service"); // Example "hello" function function hello($username) { if ($username == 'admin') { return "Welcome back, Boss"; } else { return "Hello, $username"; } } $server->register("hello", array("username" => "xsd:string"), array("return" => "xsd:string"), "http://www.example.com", "", "", "", "say hi to the caller" ); // Example "intCount" function (return array) function int_count($from, $to) { $out = array(); for ($i = $from; $i <= $to; $i++) { $out[] = $i; } return $out; } function int_count_matrix($from, $to) { $out = array(); ////lets create a matrix ////x coordinate for ($x = $from; $x <= $to; $x++) { $out_x = array(); for ($y = $from; $y <= $to; $y++) { $out_x = x + y; } $out[] = $out_x; } return $out; } $server->wsdl->addComplexType( 'intArray', 'complexType', 'array', '', 'SOAP-ENC:Array', array(), array( array( 'ref' => 'SOAP-ENC:arrayType', 'wsdl:arrayType' => 'xsd:integer[]' ) ), 'xsd:integer' ); $server->register("int_count", array("from" => "xsd:integer", "to" => "xsd:integer"), array("return" => "tns:intArray"), "http://www.example.com", "", "", "", "count from 'from' to 'to'" ); // Example "getUserInfo" function (return struct and fault) function get_user_info($userId) { if ($userId == 1) { return array( 'id' => 1, 'username' => 'testuser', 'email' => 'testuser@example.com' ); } else { return new soap_fault('SOAP-ENV:Server', '', 'Requested user not found', ''); } } $server->wsdl->addComplexType( 'userInfo', 'complextType', 'struct', 'sequence', '', array( 'id' => array('name' => 'id', 'type' => 'xsd:integer'), 'username' => array('name' => 'username', 'type' => 'xsd:string'), 'email' => array('name' => 'email', 'type' => 'xsd:string') ) ); $server->register("get_user_info", array("userId" => "xsd:integer"), array("return" => "tns:userInfo"), "http://www.example.com", "", "", "", "get info for user" ); // Get our posted data if the service is being consumed // otherwise leave this data blank. $POST_DATA = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : ''; // pass our posted data (or nothing) to the soap service $server->service($POST_DATA); exit(); ?>
класс генерирует при обращении к нему вот такой WSDL
<?xml version="1.0" encoding="ISO-8859-1"?> <definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.example.com/test_service" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.example.com/test_service"> <types> <xsd:schema targetNamespace="http://www.example.com/test_service" > <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" /> <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" /> </xsd:schema> </types> <message name="helloRequest"> <part name="username" type="xsd:string" /></message> <message name="helloResponse"> <part name="return" type="xsd:string" /></message> <message name="get_user_infoRequest"> <part name="userId" type="xsd:integer" /></message> <message name="get_user_infoResponse"> <part name="return" type="tns:userInfo" /></message> <portType name="test_servicePortType"> <operation name="hello"> <documentation>say hi to the caller</documentation> <input message="tns:helloRequest"/> <output message="tns:helloResponse"/> </operation> <operation name="get_user_info"> <documentation>get info for user</documentation> <input message="tns:get_user_infoRequest"/> <output message="tns:get_user_infoResponse"/> </operation> </portType> <binding name="test_serviceBinding" type="tns:test_servicePortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="hello"> <soap:operation soapAction="http://localhost/shop3/export/webservices_test.php/hello" style="rpc"/> <input><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input> <output><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output> </operation> <operation name="get_user_info"> <soap:operation soapAction="http://localhost/shop3/export/webservices_test.php/get_user_info" style="rpc"/> <input><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input> <output><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output> </operation> </binding> <service name="test_service"> <port name="test_servicePort" binding="tns:test_serviceBinding"> <soap:address location="http://localhost/shop3/export/webservices_test.php"/> </port> </service> </definitions>
из WSDL был выковырян XSD
<xsd:schema xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.example.com/test_service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/test_service"> <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"></xsd:import> <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/"></xsd:import> <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/"></xsd:import> <xsd:complexType name="intArray"> <xsd:complexContent> <xsd:restriction base="SOAP-ENC:Array"> <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="xsd:integer[]"></xsd:attribute> </xsd:restriction> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="userInfo"> <xsd:sequence> <xsd:element name="id" type="xsd:integer"></xsd:element> <xsd:element name="username" type="xsd:string"></xsd:element> <xsd:element name="email" type="xsd:string"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:schema>
И WSDL и XSD были импортированы в конфигурацию.
Пытаюсь вызвать веб сервис вот таким кодом
Proxy = WSСсылки.WSСсылка1.СоздатьWSПрокси("http://www.example.com/test_service","test_service","test_servicePort"); Определения = WSСсылки.WSСсылка1.ПолучитьWSОпределения(); Answer = Proxy.int_count(1,5); МойСериализаторXDTO = новый СериализаторXDTO(Определения.ФабрикаXDTO); КакойТоРезультат = МойСериализаторXDTO.ПрочитатьXDTO(Answer);
Падаю на
{Форма.Форма.Форма(23)}: Ошибка при вызове метода контекста (ПрочитатьXDTO) КакойТоРезультат = МойСериализаторXDTO.ПрочитатьXDTO(Answer); по причине: Ошибка преобразования данных XDTO: НачалоСвойства: {http://www.example.com/test_service}intArray Форма: Элемент Тип: {http://www.example.com/test_service}intArray по причине: Ошибка отображения типов: Отсутствует отображение для типа '{http://www.example.com/test_service}intArray'
Когда пытаюсь вызвать вот таким кодом
Proxy = WSСсылки.WSСсылка1.СоздатьWSПрокси("http://www.example.com/test_service","test_service","test_servicePort"); Определения = WSСсылки.WSСсылка1.ПолучитьWSОпределения(); Answer = Proxy.int_count(1,5); КакойТоРезультат = СериализаторXDTO.ПрочитатьXDTO(Answer);
Ошибка становится другая - но все равно остается
{Форма.Форма.Форма(12)}: Ошибка при вызове метода контекста (ПрочитатьXDTO) КакойТоРезультат = СериализаторXDTO.ПрочитатьXDTO(Answer); по причине: Несоответствие типов XDTO: Тип '{http://www.example.com/test_service}intArray' не найден Тип принадлежит пакету, входящему в состав другой фабрики типов XDTO
И я остаюсь в полном непонимании - как сказать одинэске чтобы она преобразовала intArray в массив?
ЗлобнийМальчик из WSDL был выковырян XSD
каким образом?
(2) да, наверное я не тот WSDL запостил. Извиняюсь
<?xml version="1.0" encoding="ISO-8859-1"?> <definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://www.example.com/test_service" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.example.com/test_service"> <types> <xsd:schema targetNamespace="http://www.example.com/test_service" > <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" /> <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" /> <xsd:complexType name="intArray"> <xsd:complexContent> <xsd:restriction base="SOAP-ENC:Array"> <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="xsd:integer[]"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> <xsd:complexType name="userInfo"> <xsd:sequence> <xsd:element name="id" type="xsd:integer"/> <xsd:element name="username" type="xsd:string"/> <xsd:element name="email" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema> </types> <message name="helloRequest"> <part name="username" type="xsd:string" /></message> <message name="helloResponse"> <part name="return" type="xsd:string" /></message> <message name="int_countRequest"> <part name="from" type="xsd:integer" /> <part name="to" type="xsd:integer" /></message> <message name="int_countResponse"> <part name="return" type="tns:intArray" /></message> <message name="get_user_infoRequest"> <part name="userId" type="xsd:integer" /></message> <message name="get_user_infoResponse"> <part name="return" type="tns:userInfo" /></message> <portType name="test_servicePortType"> <operation name="hello"> <documentation>say hi to the caller</documentation> <input message="tns:helloRequest"/> <output message="tns:helloResponse"/> </operation> <operation name="int_count"> <documentation>count from 'from' to 'to'</documentation> <input message="tns:int_countRequest"/> <output message="tns:int_countResponse"/> </operation> <operation name="get_user_info"> <documentation>get info for user</documentation> <input message="tns:get_user_infoRequest"/> <output message="tns:get_user_infoResponse"/> </operation> </portType> <binding name="test_serviceBinding" type="tns:test_servicePortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="hello"> <soap:operation soapAction="http://localhost/shop3/test_1.php/hello" style="rpc"/> <input><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input> <output><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output> </operation> <operation name="int_count"> <soap:operation soapAction="http://localhost/shop3/test_1.php/int_count" style="rpc"/> <input><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input> <output><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output> </operation> <operation name="get_user_info"> <soap:operation soapAction="http://localhost/shop3/test_1.php/get_user_info" style="rpc"/> <input><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input> <output><soap:body use="encoded" namespace="http://www.example.com" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output> </operation> </binding> <service name="test_service"> <port name="test_servicePort" binding="tns:test_serviceBinding"> <soap:address location="http://localhost/shop3/test_1.php"/> </port> </service> </definitions>
xsd был выковырян xmlspy
Забил я короче на XDTO преобразования и воспользовался банальным кодом типа такого
Сервис = WSСсылки.Products.СоздатьWSПрокси("http://localhost/test_3.php?wsdl", "WSDLTST", "WSDLTSTPort"); // Ну и наконец-то вызовем наш метод value = Сервис.Method1(); For each element in value.list do Сообщить(element.index); Сообщить(element.size); enddo;
Для вот такого WSDL
<?xml version="1.0" encoding="ISO-8859-1"?> <definitions xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://localhost/soap/WSDLTST" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://localhost/soap/WSDLTST"> <types> <xsd:schema targetNamespace="http://localhost/soap/WSDLTST" > <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" /> <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" /> <xsd:complexType name="Product"> <xsd:all> <xsd:element name="index" type="xsd:int"/> <xsd:element name="size" type="xsd:string"/> </xsd:all> </xsd:complexType> <xsd:complexType name="ProductArray"> <xsd:complexContent> <xsd:restriction base="SOAP-ENC:Array"> <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="tns:Product[]"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:schema> </types> <message name="Method1Request"></message> <message name="Method1Response"> <part name="return" type="tns:ProductArray" /></message> <portType name="WSDLTSTPortType"> <operation name="Method1"> <documentation>bla bla bla</documentation> <input message="tns:Method1Request"/> <output message="tns:Method1Response"/> </operation> </portType> <binding name="WSDLTSTBinding" type="tns:WSDLTSTPortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="Method1"> <soap:operation soapAction="http://localhost/shop3/test_3.php/Method1" style="rpc"/> <input><soap:body use="encoded" namespace="http://localhost/api/tstserver.php" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input> <output><soap:body use="encoded" namespace="http://localhost/api/tstserver.php" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output> </operation> </binding> <service name="WSDLTST"> <port name="WSDLTSTPort" binding="tns:WSDLTSTBinding"> <soap:address location="http://localhost/shop3/test_3.php"/> </port> </service> </definitions>
PHP не нужен.
XML, XSLT, WDSL, XSD не нужны.
JSON, YAML, Tree и Rest сервисы рулят.
(6) слава богу! Вы напишите свой интернет с гейшами и шоколадом. "Наконец то ты пришел!"(с)
update:
с вебсервисами разобрался (более менее), теперь только один вопрос - есть ли какая то возможность изменять заголовки запроса (добавлять свои поля) при использовании одинэсовских вебсервисов или лучше пихать параметры ключ/SDA 512 хэш ключа в определение каждого веб сервиса?
(7) - ну я его сейчас и пишу. А я что, самоубийца, находить работу, где нужно копаться в говне WCF/SOAP/XDTO/.. и прочей [...]?
ЗлобнийМальчик и воспользовался банальным кодом типа такого
только хотел предложить подобное :)