Есть ли такая битва? Простой SOAP-клиент, который поставляется с PHP, не понимает многочастных сообщений. Спасибо заранее.
Клиент PHP SOAP, который понимает многочастные сообщения?
Ответ 1
Собственный класс PHP SoapClient
не поддерживает многостраничные сообщения (и сильно ограничен во всех вопросах WS- *), и я также я что ни PHP письменные библиотеки NuSOAP, ни Zend_Soap может обрабатывать подобные сообщения SOAP.
Я могу думать о двух решениях:
-
расширяем класс
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 Conversation и WS-ReliableMessaging за счет необходимости установки собственного расширения PHP.
Ответ 2
Использование второй идеи С. Герига работало здесь очень хорошо.
В большинстве случаев у вас есть только одно сообщение, упакованное в сообщение 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;
}
}
Ответ 3
Следуйте советам 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);
?>
Ответ 4
Просто добавьте больше света к предыдущим предложенным шагам. Вы должны получать ответ в следующем формате
--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;
}
Ответ 5
Несмотря на то, что этот ответ уже дан здесь, я собрал общие решения, которые имеют в виду, что 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
.
Ответ 6
Код просто работал у меня с опцией "trace = > true".
Спасибо за обмен!