SOAP-ERROR: Кодировка: Нарушение правил кодирования? - PullRequest
10 голосов
/ 21 августа 2009

Ребята, я застрял, стуча головой по столу последние несколько часов.

Я пытаюсь использовать службу, и у меня есть 8 других функций, которые я вызываю и которые почти идентичны этой, но эта приводит к ошибке «SOAP-ERROR: Encoding: Нарушение правил кодирования» .

Вот вызов функции (wsdl опущен для безопасности):

    function CanLoadProduct($data){

    $client = new SoapClient('wsdl-url');

    $params = array('username'   => $this->username,
                    'password'  => $this->password,
                    'prod'      => $data['productid'],
                    'mdn'       => $data['mdn']);

    try {
        $reply = $client->__soapCall("CanLoadProduct", $params);
    } catch (Exception $e) {
        echo 'Error: ',  $e->getMessage(), "\n";
        print_r($params);
        die();
    }

    if( $reply['result'] == 1 ){
        return TRUE;        // 1 = true
    } else {
        return FALSE;
    }

}

Хорошо, поэтому эта функция подключается к веб-сервису. Необходимые элементы: имя пользователя, пароль, prod, mdn, все 4 из которых я предоставляю как часть массива $ params. Имя пользователя / пароль определены ранее и работают нормально, так как остальные 8 функций без проблем используют веб-сервис.

Массив $ data [] (который я передаю функции) содержит: $ данных [ 'ProductID'] $ данных [ 'MDN'] больше ничего не используется.

Я получаю

SOAP-ERROR: Encoding: Violation of encoding rules

по какой-то необъяснимой причине, и поиск в Google этой ошибки ни к чему не приведет. Кто-нибудь еще сталкивался с этим? Запуск PHP 5.2.9-2. Странно то, что это идентично этой функции, которая работает на 100%:

    function GetPIN($productid){

    $client = new SoapClient('wsdl-url');

    $params = array('username'  => $this->username,
                    'password'  => $this->password,
                    'prod'      => $productid);

    try {
        $reply = $client->__soapCall("GetPIN", $params);
    } catch (Exception $e) {
        echo 'Error: ',  $e->getMessage(), "\n";
        die();
    }
        return $reply;
}

Вот 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="ready:test" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="ready:test">
<types>
<xsd:schema targetNamespace="ready:test"
>
 <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
 <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
</xsd:schema>
</types>
<message name="CanLoadProductRequest">
  <part name="username" type="xsd:string" />
  <part name="password" type="xsd:string" />
  <part name="prod" type="xsd:string" />    
  <part name="mdn" type="xsd:string" />
  <part name="esn" type="xsd:string" /></message>
<message name="CanLoadProductResponse">
  <part name="result" type="xsd:int" /></message>
<portType name="CanLoadProductPortType">
  <operation name="CanLoadProduct">
    <input message="tns:CanLoadProductRequest"/>
    <output message="tns:CanLoadProductResponse"/>
  </operation>
</portType>

<binding name="CanLoadProductBinding" type="tns:CanLoadProductPortType">
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
  <operation name="CanLoadProduct">
    <soap:operation soapAction="{url-removed}" style="rpc"/>
    <input>
        <soap:body use="encoded" namespace="" 
           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </input>
    <output>
        <soap:body use="encoded" namespace="" 
            encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
    </output>
  </operation>
</binding>
<service name="CanLoadProduct">
  <port name="CanLoadProductPort" binding="tns:CanLoadProductBinding">

    <soap:address location="{url-removed}"/>
  </port>
</service>
</definitions>

Ответы [ 9 ]

16 голосов
/ 21 августа 2009

Похоже, что у вас где-то есть несоответствие типов, либо при сборке вашего запроса (один из параметров не является строкой типа), либо сервер возвращает что-то отличное от int (нарушая определение ответа WSDL и, таким образом, вызывая клиента считать ответ недействительным, так как он ожидает чего-то другого).

  • Чтобы проверить первый случай, убедитесь, что все параметры приведены к первой строке
  • Чтобы протестировать второй случай, создайте свой SoapClient с параметром trace , установленным в значение true, чтобы впоследствии получить доступ к фактическому XML-ответу от сервера через $ client -> __ getLastResponse () используйте это для отладки запросов также через __getLastRequest ()).

Некоторые дополнительные замечания / вопросы:

  • Согласно опубликованному WSDL, CanLoadProductRequest имеет пятый параметр esn, который вы не указываете при вызове функции.
  • Есть ли причина, по которой вы используете $client->__soapCall("CanLoadProduct", $params) вместо $client->CanLoadProduct($username, $password, etc.)? (Первая версия - это вариант более низкого уровня, который предназначен для использования в сценариях не-WSDL. Вторая версия может дать вам более подробную ошибку / исключение)
  • Можете ли вы проверить SOAP-вызов в CanLoadProductRequest другими способами? Ошибка может быть на стороне сервера при попытке вернуть тип результата, который не соответствует определению WSDL.
6 голосов
/ 29 августа 2012

У меня была такая же проблема.

В настройках soapUI я выбрал опцию Настройки → Настройки редактора → Проверить ответы и получил эту информацию:

строка 3027: недопустимое десятичное значение: неожиданный символ '44'.

Это решило мою проблему. Поле содержит неверное значение типа.

2 голосов
/ 27 апреля 2012

У меня была такая же проблема, и я решил использовать этот синтаксис для __soapCall:

...
$params = new SoapParam($data, 'parameters');

$response = $this->__soapCall('methodName', 
    array(new SoapVar($data, XSD_ANYTYPE, 'parameters'))
  );        
...

Вместо

__soapCall('methodName', array($params)
2 голосов
/ 16 апреля 2010

Я получал эту ошибку, используя инструмент SoapUI, пока я не переформатировал ответ с реальными тестовыми данными, а не просто «?». Также с SoapUI, ответ может быть больше, чем ожидалось, и, возможно, придется сократить до ожидаемого ответа, удалив несколько необязательных параметров ответа. Надеюсь, это поможет?

2 голосов
/ 11 декабря 2009

У меня была такая же проблема при попытке передать XML в качестве параметра одному из моих веб-сервисов. Обтекание XML-данных в <![CDATA[ ... ]]> избавило от SOAP-ERROR: Кодировка: Нарушение правил кодирования и все работало нормально.

Другие детали:
1. Параметр также был определен как xsd: string.
2. WSDL был документальным / буквальным.
3. Использование встроенного класса SOAP с php 5.2.10.

1 голос
/ 30 мая 2011
<![CDATA[<?xml version="1.0"
encoding="utf-8"?>
<CONTENTXML></CONTENTXML]]></xmlCallString>]]>
1 голос
/ 24 февраля 2011

В PHP также есть ошибка, из-за которой неправильный тип не оставляет места для правильного возврата SOAP-ошибки клиенту.

http://bugs.php.net/bug.php?id=50547

0 голосов
/ 29 марта 2017

У меня была эта проблема в PhpStorm при выполнении юнит-тестов. Я отключил кэш wsdl, и он работал: ini_set ("soap.wsdl_cache_enabled", "0");

0 голосов
/ 06 декабря 2016

У меня была та же проблема, и мне удалось ее исправить, исправив WSDL, который предполагал, что сервер будет отправлять целое число для определенного значения, но фактически отправлял строку. Возможно изменение WSDL из:

<part name="result" type="xsd:int" /></message>

до

<part name="result" type="xsd:string" /></message>

Может решить вашу проблему, вот некоторая информация о конкретном случае, с которым я столкнулся: https://blog.dotnetframework.org/2016/12/06/uncaught-soapfault-exception-sender-soap-error-encoding-violation-of-encoding-rules/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...