Есть ли такая битва? Простой клиент SOAP, который поставляется с PHP, не понимает многочастных сообщений. Заранее спасибо.
SoapClient
класс PHP SoapClient
не поддерживает SoapClient
сообщения (и сильно ограничен во всех вопросах WS- *), и я также думаю, что ни PHP-письменные библиотеки NuSOAP, ни Zend_Soap не могут обрабатывать подобные сообщения SOAP.
Я могу думать о двух решениях:
SoapClient
класс SoapClient
и перезапишите метод SoapClient::__doRequest()
чтобы получить фактическую строку ответа, которую вы можете проанализировать по своей прихоти.
class MySoapClient extends SoapClient { public function __doRequest($request, $location, $action, $version, $one_way = 0) { $response = parent::__doRequest($request, $location, $action, $version, $one_way); // parse $response, extract the multipart messages and so on } }
Это может быть несколько сложно, но стоит попробовать.
используйте более сложную клиентскую библиотеку SOAP для PHP. Первым и единственным, что приходит мне в голову, является WSO2 WSF / PHP, в котором реализованы SOAP MTOM, WS-Addressing, WS-Security, WS-SecurityPolicy, WS-Secure и WS-ReliableMessaging за счет необходимости установки собственного PHP расширение.
Использование второй идеи С. Герига работало здесь очень хорошо.
В большинстве случаев у вас есть только одно сообщение, упакованное в сообщение MIME MultiPart. В таких случаях исключение SoapFault: [Client] выглядит так, как будто у нас нет XML-документа, генерируется исключение . Здесь следующий класс должен делать только отлично:
class MySoapClient extends SoapClient { public function __doRequest($request, $location, $action, $version, $one_way = 0) { $response = parent::__doRequest($request, $location, $action, $version, $one_way); // strip away everything but the xml. $response = preg_replace('#^.*(<\?xml.*>)[^>]*$#s', '$1', $response); return $response; } }
Следуйте советам rafinskipg из документации PHP:
Поддержка MTOM добавляет этот код в ваш проект:
<?php class MySoapClient extends SoapClient { public function __doRequest($request, $location, $action, $version, $one_way = 0) { $response = parent::__doRequest($request, $location, $action, $version, $one_way); // parse $response, extract the multipart messages and so on //this part removes stuff $start=strpos($response,'<?xml'); $end=strrpos($response,'>'); $response_string=substr($response,$start,$end-$start+1); return($response_string); } } ?>
Тогда вы можете сделать это
<?php new MySoapClient($wsdl_url); ?>
Просто добавьте больше света к предыдущим предложенным шагам. Вы должны получать ответ в следующем формате
--uuid:eca72cdf-4e96-4ba9-xxxxxxxxxx+id=108 Content-ID: <http://tempuri.org/0> Content-Transfer-Encoding: 8bit Content-Type: application/xop+xml;charset=utf-8;type="text/xml" <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body> content goes here </s:Body></s:Envelope> --uuid:c19585dd-6a5a-4c08-xxxxxxxxx+id=108--
Просто используйте следующий код (я не так хорошо справляюсь с регулярным выражением, используя строковые функции)
public function __doRequest($request, $location, $action, $version, $one_way = 0) { $response = parent::__doRequest($request, $location, $action, $version, $one_way); // strip away everything but the xml. $response = stristr(stristr($response, "<s:"), "</s:Envelope>", true) . "</s:Envelope>"; return $response; }
Несмотря на то, что этот ответ уже здесь дан много, я собрал общие решения, которые имеют в виду, что XML может прийти без оболочки.
class SoapClientExtended extends SoapClient { /** * Sends SOAP request using a predefined XML * * Overwrites the default method SoapClient::__doRequest() to make it work * with multipart responses. * * @param string $request The XML content to send * @param string $location The URL to request. * @param string $action The SOAP action. [optional] default='' * @param int $version The SOAP version. [optional] default=1 * @param int $one_way [optional] ( If one_way is set to 1, this method * returns nothing. Use this where a response is * not expected. ) * * @return string The XML SOAP response. */ public function __doRequest( $request, $location, $action, $version, $one_way = 0 ) { $result = parent::__doRequest($request, $location, $action, $version, $one_way); $headers = $this->__getLastResponseHeaders(); // Do we have a multipart request? if (preg_match('#^Content-Type:.*multipart\/.*#mi', $headers) !== 0) { // Make all line breaks even. $result = str_replace("\r\n", "\n", $result); // Split between headers and content. list(, $content) = preg_split("#\n\n#", $result); // Split again for multipart boundary. list($result, ) = preg_split("#\n--#", $content); } return $result; } }
Это работает, только если вы инициализируете SoapClientExtended
с помощью опции trace => true
.
Код просто работал для меня с опцией «trace => true».
Спасибо, что поделился!