Я пытаюсь вызвать метод SOAP с помощью PHP.
Вот код, который у меня есть:
$data = array('Acquirer' => array( 'Id' => 'MyId', 'UserId' => 'MyUserId', 'Password' => 'MyPassword' )); $method = 'Echo'; $client = new SoapClient(NULL, array('location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler', 'uri' => 'http://example.com/wsdl', 'trace' => 1)); $result = $client->$method($data);
Вот запрос, который он создает:
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns1:Echo> <param0 xsi:type="ns2:Map"> <item> <key xsi:type="xsd:string">Acquirer</key> <value xsi:type="ns2:Map"> <item> <key xsi:type="xsd:string">Id</key> <value xsi:type="xsd:string">mcp</value> </item> <item> <key xsi:type="xsd:string">UserId</key> <value xsi:type="xsd:string">tst001</value> </item> <item> <key xsi:type="xsd:string">Password</key> <value xsi:type="xsd:string">test</value> </item> </value> </item> </param0> </ns1:Echo> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
И вот что я хочу, чтобы запрос выглядел так:
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <Echo> <Acquirer> <Id>MyId</Id> <UserId>MyUserId</UserId> <Password>MyPassword</Password> </Acquirer> </Echo> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Есть несколько способов решить эту проблему. Самое малое и самое то, что вы хотите:
$client = new SoapClient( null, array( 'location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler', 'uri' => 'http://example.com/wsdl', 'trace' => 1, 'use' => SOAP_LITERAL, ) ); $params = new \SoapVar("<Acquirer><Id>MyId</Id><UserId>MyUserId</UserId><Password>MyPassword</Password></Acquirer>", XSD_ANYXML); $result = $client->Echo($params);
Это дает вам следующий XML:
<?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com/wsdl"> <SOAP-ENV:Body> <ns1:Echo> <Acquirer> <Id>MyId</Id> <UserId>MyUserId</UserId> <Password>MyPassword</Password> </Acquirer> </ns1:Echo> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Это почти то, что вы хотите, за исключением пространства имен в имени метода. Я не знаю, если это проблема. Если это так, вы можете взломать его еще больше. Вы можете поместить <Echo>
в строку XML вручную и заставить SoapClient не устанавливать метод, добавив 'style' => SOAP_DOCUMENT,
в массив параметров следующим образом:
$client = new SoapClient( null, array( 'location' => 'https://example.com/ExampleWebServiceDL/services/ExampleHandler', 'uri' => 'http://example.com/wsdl', 'trace' => 1, 'use' => SOAP_LITERAL, 'style' => SOAP_DOCUMENT, ) ); $params = new \SoapVar("<Echo><Acquirer><Id>MyId</Id><UserId>MyUserId</UserId><Password>MyPassword</Password></Acquirer></Echo>", XSD_ANYXML); $result = $client->MethodNameIsIgnored($params);
Это приводит к следующему запросу XML:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <Echo> <Acquirer> <Id>MyId</Id> <UserId>MyUserId</UserId> <Password>MyPassword</Password> </Acquirer> </Echo> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Наконец, если вы хотите поиграть с объектами SoapVar и SoapParam, вы можете найти хорошую ссылку в этом комментарии в руководстве по PHP: http://www.php.net/manual/en/soapvar.soapvar.php#104065 . Если вы получите это на работу, пожалуйста, дайте мне знать, я потерпел неудачу.
Прежде всего, вы должны указать, что хотите использовать стиль Document Literal:
$client = new SoapClient(NULL, array( 'location' => 'https://example.com/path/to/service', 'uri' => 'http://example.com/wsdl', 'trace' => 1, 'use' => SOAP_LITERAL) );
Затем вам необходимо преобразовать данные в SoapVar; Я написал простую функцию преобразования:
function soapify(array $data) { foreach ($data as &$value) { if (is_array($value)) { $value = soapify($value); } } return new SoapVar($data, SOAP_ENC_OBJECT); }
Затем вы применяете эту функцию преобразования к своим данным:
$data = soapify(array( 'Acquirer' => array( 'Id' => 'MyId', 'UserId' => 'MyUserId', 'Password' => 'MyPassword', ), ));
Наконец, вы вызываете службу, передающую параметр Data:
$method = 'Echo'; $result = $client->$method(new SoapParam($data, 'Data'));