php SOAP-ERROR:编码:违反编码规则?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1309477/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 01:58:37  来源:igfitidea点击:

SOAP-ERROR: Encoding: Violation of encoding rules?

phpxmlsoap

提问by Jakub

Guys, I'm stuck, banging my head off the desk for the past few hours.

伙计们,我被困住了,在过去的几个小时里我的头从桌子上摔下来。

I am trying to consume a service, and I have 8 other functions that I call that are almost IDENTICAL in nature to this one, but this one, results in a 'SOAP-ERROR: Encoding: Violation of encoding rules' error.

我正在尝试使用一项服务,并且我调用了其他 8 个函数,它们本质上与这个函数几乎相同,但是这个函数会导致“SOAP-ERROR: Encoding: Violation of encoding rules”错误。

Heres the function call (wsdl omitted for security):

下面是函数调用(出于安全考虑,省略了 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;
    }

}

Ok so this function, connects to a webservice, the required elements are: username, password, prod, mdn, all 4 of which I supply as part of the $params array. Username/Pass are defined earlier, and do work fine, as the other 8 functions consume the web service without any problems.

好的,这个函数连接到一个网络服务,所需的元素是:用户名、密码、prod、mdn,我提供的所有 4 个元素都作为 $params 数组的一部分提供。用户名/通行证定义较早,并且工作正常,因为其他 8 个函数使用 Web 服务没有任何问题。

The $data[] array (that I pass to the function), contains: $data['productid'] $data['mdn'] nothing else is used.

$data[] 数组(我传递给函数的)包含: $data['productid'] $data['mdn'] 没有使用其他任何东西。

I am getting

我正进入(状态

SOAP-ERROR: Encoding: Violation of encoding rules

for some unexplained reason, and Googling this error gets me nowhere. Anyone else run into this? Running PHP 5.2.9-2. The strange thing is this is identical to this function which works 100%:

出于某种无法解释的原因,谷歌搜索这个错误让我无处可去。还有人遇到这个吗?运行 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;
}

Here is the WSDL (should have posted this first):

这是 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>

回答by Henrik Opel

It looks like you have a type mismatch somewhere, either while assembling your request (one of the parameters is not of type string), or the server returns something other than an int (violating the WSDL response definition and thus causing the client to consider the response invalid, as it expects something else).

看起来您在某处有类型不匹配,要么在组装请求时(其中一个参数不是字符串类型),要么服务器返回 int 以外的其他内容(违反 WSDL 响应定义,从而导致客户端考虑响应无效,因为它期待别的)。

  • To test the first case, ensure casting all parameters to string first
  • To test the second case, create your SoapClient with the traceoption set to true in order to gain access to the actual XML answer from the server via $client->__getLastResponse() afterwards (You can use this for request debugging also via __getLastRequest()).
  • 要测试第一种情况,请确保首先将所有参数转换为字符串
  • 要测试第二种情况,请创建您的 SoapClient,并将trace选项设置为 true,以便之后通过 $client->__getLastResponse() 从服务器获得对实际 XML 答案的访问(您也可以通过 __getLastRequest() 将其用于请求调试) ))。

Some additional observations/questions:

一些额外的意见/问题:

  • According to the posted WSDL, the 'CanLoadProductRequest' has a fifth param 'esn', which you do not supply in your function call.
  • Any reason why you use $client->__soapCall("CanLoadProduct", $params)instead of $client->CanLoadProduct($username, $password, etc.)? (The first version is a lower level variation which is intended to be used for non_WSDL scenarios. The second version might give you a more detailed error/exception)
  • Can you test the SOAP Call to CanLoadProductRequest by some other means? The error could be on the server side, trying to return a result type that does not fit the WSDL definition.
  • 根据发布的 WSDL,“CanLoadProductRequest”有第五个参数“esn”,您在函数调用中没有提供。
  • $client->__soapCall("CanLoadProduct", $params)$client->CanLoadProduct($username, $password, etc.)什么理由使用而不是?(第一个版本是一个较低级别的变体,旨在用于非 WSDL 场景。第二个版本可能会为您提供更详细的错误/异常)
  • 您可以通过其他方式测试对 CanLoadProductRequest 的 SOAP 调用吗?错误可能在服务器端,试图返回不符合 WSDL 定义的结果类型。

回答by Atlos

I had the same problem.

我有同样的问题。

In soapUI preferences I checked the option Preferences → Editor Settings → Validate Responses and I received this information:

在soapUI首选项中,我检查了选项首选项→编辑器设置→验证响应,我收到了以下信息:

line 3027: Invalid decimal value: unexpected char '44'.

第 3027 行:无效的十进制值:意外的字符“44”。

This solved my problem. Field contained wrong type value.

这解决了我的问题。字段包含错误的类型值。

回答by Shane

I had the same problem when trying to pass XML as a parameter to one of my webservices. Wrapping the XML data in <![CDATA[ ... ]]>got rid of the SOAP-ERROR: Encoding: Violation of encoding rulesand everything worked fine.

Other details:
1. The parameter was defined as xsd:string as well.
2. WSDL was document/literal.
3. Using built in SOAP class with php 5.2.10.

尝试将 XML 作为参数传递给我的 Web 服务之一时,我遇到了同样的问题。包装 XML 数据<![CDATA[ ... ]]>摆脱了SOAP-ERROR: Encoding: Violation of encoding rules并且一切正常。

其他细节:
1. 该参数也被定义为 xsd:string。
2. WSDL 是文档/文字。
3. 在 php 5.2.10 中使用内置的 SOAP 类。

回答by Patrick Ingle

I was getting this error using the SoapUI tool, until I reformatted the response with real test data and not just '?'. Also with SoapUI, the response may be more than expected and may have to shorten to the expected response by removing several optional response parameters. Hope this helps?

我使用 SoapUI 工具收到此错误,直到我用真实的测试数据重新格式化响应,而不仅仅是“?”。同样使用 SoapUI,响应可能比预期的要多,并且可能必须通过删除几个可选的响应参数来缩短到预期的响应。希望这可以帮助?

回答by sanchoo

<![CDATA[<?xml version="1.0"
encoding="utf-8"?>
<CONTENTXML></CONTENTXML]]></xmlCallString>]]>

回答by Cristiana

I had the same problem and I resolved using this syntax for __soapCall:

我遇到了同样的问题,我使用以下语法解决了__soapCall

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

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

Instead of

代替

__soapCall('methodName', array($params)

回答by mdekrijger

There's also a kind of bug in PHP where a wrong type leaves no room for giving a proper SOAPfault back to the client.

PHP 中还有一种错误,即错误的类型没有空间将正确的 SOAPfault 返回给客户端。

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

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

回答by Fiach Reid

I had the same problem, and managed to fix it by correcting the WSDL, which was assuming the server would send an integer for a particular value, but was actually sending a string. Perhaps modifying the WSDL from:

我遇到了同样的问题,并设法通过更正 WSDL 来修复它,这是假设服务器将发送一个特定值的整数,但实际上发送的是一个字符串。也许从以下位置修改 WSDL:

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

to

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

May solve your issue, here is some information on the particular case I was facing: https://blog.dotnetframework.org/2016/12/06/uncaught-soapfault-exception-sender-soap-error-encoding-violation-of-encoding-rules/

可能会解决您的问题,以下是有关我面临的特定案例的一些信息:https: //blog.dotnetframework.org/2016/12/06/uncaught-soapfault-exception-sender-soap-error-encoding-violation-of -编码规则/

回答by bezz

I had this issue in PhpStorm when doing unit tests. I disabled the wsdl cache and it worked:

在进行单元测试时,我在 PhpStorm 中遇到了这个问题。我禁用了 wsdl 缓存并且它起作用了:

ini_set("soap.wsdl_cache_enabled", "0");

回答by Shane N

Similar to @bezz, my issue was also caused by the WSDL being cached in a temp directory.

与@bezz 类似,我的问题也是由缓存在临时目录中的 WSDL 引起的。

I cleared out the wsdl-* files in /tmp and it worked.

我清除了 /tmp 中的 wsdl-* 文件并且它起作用了。