致命错误:SOAP-ERROR:编码:违反PHP中的编码规则

时间:2016-06-14 14:52:12

标签: php soap

我正在尝试使用PHP连接到SOAP API,但不断收到以下错误:

Fatal error: SOAP-ERROR: Encoding: Violation of encoding rules

以下是Web服务的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="http://localhost/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://localhost/">
<types>
<xsd:schema targetNamespace="http://localhost/"
>
 <xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
 <xsd:import namespace="http://schemas.xmlsoap.org/wsdl/" />
 <xsd:complexType name="LoyaltySchemeSignUpPacket">
  <xsd:all>
   <xsd:element name="auth_id" type="xsd:string"/>
   <xsd:element name="member_id" type="xsd:string"/>
   <xsd:element name="email" type="xsd:string"/>
   <xsd:element name="customername" type="xsd:string"/>
   <xsd:element name="first_name" type="xsd:string"/>
   <xsd:element name="last_name" type="xsd:string"/>
   <xsd:element name="gender" type="xsd:string"/>
   <xsd:element name="date_of_birth" type="xsd:string"/>
   <xsd:element name="address1" type="xsd:string"/>
   <xsd:element name="address2" type="xsd:string"/>
   <xsd:element name="address3" type="xsd:string"/>
   <xsd:element name="address4" type="xsd:string"/>
   <xsd:element name="address5" type="xsd:string"/>
   <xsd:element name="address6" type="xsd:string"/>
   <xsd:element name="postcode" type="xsd:string"/>
   <xsd:element name="telephone" type="xsd:string"/>
   <xsd:element name="tsa_flag" type="xsd:string"/>
   <xsd:element name="nomail" type="xsd:string"/>
   <xsd:element name="climbers_flag" type="xsd:string"/>
   <xsd:element name="outdoor_flag" type="xsd:string"/>
   <xsd:element name="staff_referral_id" type="xsd:string"/>
   <xsd:element name="mountainerring" type="xsd:string"/>
   <xsd:element name="news" type="xsd:string"/>
   <xsd:element name="running" type="xsd:string"/>
   <xsd:element name="sale" type="xsd:string"/>
   <xsd:element name="skiing" type="xsd:string"/>
   <xsd:element name="snowboarding" type="xsd:string"/>
   <xsd:element name="travelling" type="xsd:string"/>
   <xsd:element name="trekking" type="xsd:string"/>
   <xsd:element name="cycling" type="xsd:string"/>
   <xsd:element name="camping" type="xsd:string"/>
   <xsd:element name="groupid" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeSignUpResponsePacket">
  <xsd:all>
   <xsd:element name="status" type="xsd:int"/>
   <xsd:element name="customer_id" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVouchPacket">
  <xsd:all>
   <xsd:element name="auth_id" type="xsd:string"/>
   <xsd:element name="disctype" type="xsd:string"/>
   <xsd:element name="amount" type="xsd:string"/>
   <xsd:element name="qnty" type="xsd:string"/>
   <xsd:element name="expiry" type="xsd:string"/>
   <xsd:element name="includeid" type="xsd:string"/>
   <xsd:element name="excludeid" type="xsd:string"/>
   <xsd:element name="minspend" type="xsd:decimal"/>
   <xsd:element name="description" type="xsd:string"/>
   <xsd:element name="maxdiscount" type="xsd:string"/>
   <xsd:element name="frequency" type="xsd:string"/>
   <xsd:element name="freq_qnty" type="xsd:string"/>
   <xsd:element name="vouchercap" type="xsd:string"/>
   <xsd:element name="groupid" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVouchResponsePacket">
  <xsd:all>
   <xsd:element name="Type_ID" type="xsd:int"/>
   <xsd:element name="Status" type="xsd:int"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVouchCodePacket">
  <xsd:all>
   <xsd:element name="auth_id" type="xsd:string"/>
   <xsd:element name="type_id" type="xsd:string"/>
   <xsd:element name="customerid" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVouchCodeResponsePacket">
  <xsd:all>
   <xsd:element name="Code_ID" type="xsd:string"/>
   <xsd:element name="Status" type="xsd:int"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVoucherCheckPacket">
  <xsd:all>
   <xsd:element name="auth_id" type="xsd:string"/>
   <xsd:element name="email_url" type="xsd:string"/>
   <xsd:element name="customer_id" type="xsd:string"/>
   <xsd:element name="voucher_code" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVoucherCheckResponse">
  <xsd:all>
   <xsd:element name="status" type="xsd:int"/>
   <xsd:element name="statustext" type="xsd:string"/>
   <xsd:element name="emailurl" type="xsd:string"/>
   <xsd:element name="customer_id" type="xsd:int"/>
   <xsd:element name="vouch_expires" type="xsd:string"/>
   <xsd:element name="disc_claimed" type="xsd:string"/>
   <xsd:element name="number_uses" type="xsd:string"/>
   <xsd:element name="transaction_cap" type="xsd:string"/>
   <xsd:element name="voucher_cap" type="xsd:string"/>
   <xsd:element name="voucherdetails" type="tns:LoyaltySchemeVouchPacket"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVoucherRedeemPacket">
  <xsd:all>
   <xsd:element name="auth_id" type="xsd:string"/>
   <xsd:element name="customer_id" type="xsd:string"/>
   <xsd:element name="customer_email" type="xsd:string"/>
   <xsd:element name="amount_disc" type="xsd:string"/>
   <xsd:element name="voucher_code" type="xsd:string"/>
   <xsd:element name="order_number" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemeVoucherRedeemResponse">
  <xsd:all>
   <xsd:element name="status" type="xsd:int"/>
   <xsd:element name="statustext" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemecustomerpacket">
  <xsd:all>
   <xsd:element name="auth_id" type="xsd:string"/>
   <xsd:element name="customerid" type="xsd:string"/>
   <xsd:element name="customer_email" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
 <xsd:complexType name="LoyaltySchemecustomerresponsepacket">
  <xsd:all>
   <xsd:element name="status" type="xsd:int"/>
   <xsd:element name="statustext" type="xsd:int"/>
   <xsd:element name="member_id" type="xsd:string"/>
   <xsd:element name="email" type="xsd:string"/>
   <xsd:element name="customername" type="xsd:string"/>
   <xsd:element name="firstname" type="xsd:string"/>
   <xsd:element name="surname" type="xsd:string"/>
   <xsd:element name="gender" type="xsd:string"/>
   <xsd:element name="date_of_birth" type="xsd:string"/>
   <xsd:element name="address1" type="xsd:string"/>
   <xsd:element name="address2" type="xsd:string"/>
   <xsd:element name="address3" type="xsd:string"/>
   <xsd:element name="address4" type="xsd:string"/>
   <xsd:element name="address5" type="xsd:string"/>
   <xsd:element name="address6" type="xsd:string"/>
   <xsd:element name="postcode" type="xsd:string"/>
   <xsd:element name="phone" type="xsd:string"/>
   <xsd:element name="member" type="xsd:string"/>
   <xsd:element name="tsa_flag" type="xsd:string"/>
   <xsd:element name="nomail" type="xsd:string"/>
   <xsd:element name="climbers_flag" type="xsd:string"/>
   <xsd:element name="outdoor_flag" type="xsd:string"/>
   <xsd:element name="staff_referral_id" type="xsd:string"/>
   <xsd:element name="mountainerring" type="xsd:string"/>
   <xsd:element name="news" type="xsd:string"/>
   <xsd:element name="running" type="xsd:string"/>
   <xsd:element name="sale" type="xsd:string"/>
   <xsd:element name="skiing" type="xsd:string"/>
   <xsd:element name="snowboarding" type="xsd:string"/>
   <xsd:element name="travelling" type="xsd:string"/>
   <xsd:element name="trekking" type="xsd:string"/>
   <xsd:element name="cycling" type="xsd:string"/>
   <xsd:element name="camping" type="xsd:string"/>
   <xsd:element name="groupid" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
</xsd:schema>
</types>
<message name="ws_loyalty_signupRequest">
  <part name="signuprec" type="tns:LoyaltySchemeSignUpPacket" /></message>
<message name="ws_loyalty_signupResponse">
  <part name="response" type="tns:LoyaltySchemeSignUpResponsePacket" /></message>
<message name="ws_loyalty_updateRequest">
  <part name="signuprec" type="tns:LoyaltySchemeSignUpPacket" /></message>
<message name="ws_loyalty_updateResponse">
  <part name="response" type="tns:LoyaltySchemeSignUpResponsePacket" /></message>
<message name="ws_voucher_typesRequest">
  <part name="vouchercre" type="tns:LoyaltySchemeVouchPacket" /></message>
<message name="ws_voucher_typesResponse">
  <part name="response" type="tns:LoyaltySchemeVouchResponsePacket" /></message>
<message name="ws_voucher_codesRequest">
  <part name="vouchercode" type="tns:LoyaltySchemeVouchCodePacket" /></message>
<message name="ws_voucher_codesResponse">
  <part name="response" type="tns:LoyaltySchemeVouchCodeResponsePacket" /></message>
<message name="ws_voucher_checkRequest">
  <part name="customervoucher" type="tns:LoyaltySchemeVoucherCheckPacket" /></message>
<message name="ws_voucher_checkResponse">
  <part name="response" type="tns:LoyaltySchemeVoucherCheckResponse" /></message>
<message name="ws_voucher_redeemRequest">
  <part name="customervoucher" type="tns:LoyaltySchemeVoucherRedeemPacket" /></message>
<message name="ws_voucher_redeemResponse">
  <part name="response" type="tns:LoyaltySchemeVoucherRedeemResponse" /></message>
<message name="ws_customer_infoRequest">
  <part name="customerpacket" type="tns:LoyaltySchemecustomerpacket" /></message>
<message name="ws_customer_infoResponse">
  <part name="response" type="tns:LoyaltySchemecustomerresponsepacket" /></message>
<portType name="LoyaltySchemePortType">
  <operation name="ws_loyalty_signup">
    <documentation>Pass signup details from customer and return existing ID if found or create new customer record and return new ID</documentation>
    <input message="tns:ws_loyalty_signupRequest"/>
    <output message="tns:ws_loyalty_signupResponse"/>
  </operation>
  <operation name="ws_loyalty_update">
    <documentation>Pass update details from customer and return update status and Member ID</documentation>
    <input message="tns:ws_loyalty_updateRequest"/>
    <output message="tns:ws_loyalty_updateResponse"/>
  </operation>
  <operation name="ws_voucher_types">
    <documentation>Generation of the Voucher Types</documentation>
    <input message="tns:ws_voucher_typesRequest"/>
    <output message="tns:ws_voucher_typesResponse"/>
  </operation>
  <operation name="ws_voucher_codes">
    <documentation>Generation of the Voucher Types</documentation>
    <input message="tns:ws_voucher_codesRequest"/>
    <output message="tns:ws_voucher_codesResponse"/>
  </operation>
  <operation name="ws_voucher_check">
    <documentation>Validate voucher code</documentation>
    <input message="tns:ws_voucher_checkRequest"/>
    <output message="tns:ws_voucher_checkResponse"/>
  </operation>
  <operation name="ws_voucher_redeem">
    <documentation>Redeem voucher by code</documentation>
    <input message="tns:ws_voucher_redeemRequest"/>
    <output message="tns:ws_voucher_redeemResponse"/>
  </operation>
  <operation name="ws_customer_info">
    <documentation>Get customer information </documentation>
    <input message="tns:ws_customer_infoRequest"/>
    <output message="tns:ws_customer_infoResponse"/>
  </operation>
</portType>
<binding name="LoyaltySchemeBinding" type="tns:LoyaltySchemePortType">
  <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
  <operation name="ws_loyalty_signup">
    <soap:operation soapAction="http://localhost/#ws_loyalty_signup" style="rpc"/>
    <input><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
    <output><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
  </operation>
  <operation name="ws_loyalty_update">
    <soap:operation soapAction="http://localhost/#ws_loyalty_update" style="rpc"/>
    <input><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
    <output><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
  </operation>
  <operation name="ws_voucher_types">
    <soap:operation soapAction="http://localhost/#ws_voucher_types" style="rpc"/>
    <input><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
    <output><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
  </operation>
  <operation name="ws_voucher_codes">
    <soap:operation soapAction="http://localhost/#ws_voucher_codes" style="rpc"/>
    <input><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
    <output><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
  </operation>
  <operation name="ws_voucher_check">
    <soap:operation soapAction="http://localhost/#ws_voucher_check" style="rpc"/>
    <input><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
    <output><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
  </operation>
  <operation name="ws_voucher_redeem">
    <soap:operation soapAction="http://localhost/#ws_voucher_redeem" style="rpc"/>
    <input><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
    <output><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
  </operation>
  <operation name="ws_customer_info">
    <soap:operation soapAction="http://localhost/#ws_customer_info" style="rpc"/>
    <input><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></input>
    <output><soap:body use="encoded" namespace="http://localhost/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/></output>
  </operation>
</binding>
<service name="LoyaltyScheme">
  <port name="LoyaltySchemePort" binding="tns:LoyaltySchemeBinding">
    <soap:address location="http://www.ellisbrigham-uk.com/loyaltyserver.php"/>
  </port>
</service>
</definitions>

我使用SOAP UI来测试服务,它在SOAP UI中运行良好。以下是SOAP UI发送的请求:

<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:loc="http://localhost/">
   <soapenv:Header/>
   <soapenv:Body>
      <loc:ws_customer_info soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <customerpacket xsi:type="loc:LoyaltySchemecustomerpacket">
            <auth_id xsi:type="xsd:string">auth-code-here</auth_id>
            <customerid xsi:type="xsd:string">0</customerid>
            <customer_email xsi:type="xsd:string">someone@gmail.com</customer_email>
         </customerpacket>
      </loc:ws_customer_info>
   </soapenv:Body>
</soapenv:Envelope>

以下是我使用的导致错误的代码:

<?php
$context = stream_context_create([
    'http'=> [
        'user_agent' => 'PHPSoapClient'
    ]
]);

$accent = new \SoapClient( 'http://domain.com/loyaltyserver.php?wsdl', [
    'stream_context' => $context,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'trace' => true
]);

$data = [
    'auth_id' => (string) 'my-auth-code',
    'customer_email' => (string) 'someone@gmail.com',
    'customerid' => (string) 0
];

$result = $accent->ws_customer_info($data);

我使用了__getLastRequest(),这是它发送的请求:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost/" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
    <ns1:ws_customer_info>
        <customerpacket xsi:type="ns1:LoyaltySchemecustomerpacket">
            <auth_id xsi:type="xsd:string">my-auth-code</auth_id>
            <customerid xsi:type="xsd:string">0</customerid>
            <customer_email xsi:type="xsd:string">someone@gmail.com</customer_email>
        </customerpacket>
    </ns1:ws_customer_info>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

正如您所看到的那样,通过比较这两个请求它们是不同的但我不太了解SOAP以了解它们为何不同或导致错误的原因。

更新

如果我捕获异常并使用__getLastResponse()输出最后一个响应,我可以看到返回的似乎是有效响应。以下是回复:

<?xml version="1.0" encoding="ISO-8859-1"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 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="http://localhost/">
<SOAP-ENV:Body>
    <ns1:ws_customer_infoResponse xmlns:ns1="http://localhost/">
        <response xsi:type="tns:LoyaltySchemecustomerresponsepacket">
            <status xsi:type="xsd:int">0</status>
            <statustext xsi:type="xsd:int">OK</statustext>
            <member_id xsi:nil="true" xsi:type="xsd:string"/>
            <email xsi:nil="true" xsi:type="xsd:string"/>
            <customername xsi:nil="true" xsi:type="xsd:string"/>
            <firstname xsi:nil="true" xsi:type="xsd:string"/>
            <surname xsi:nil="true" xsi:type="xsd:string"/>
            <gender xsi:nil="true" xsi:type="xsd:string"/>
            <date_of_birth xsi:nil="true" xsi:type="xsd:string"/>
            <address1 xsi:nil="true" xsi:type="xsd:string"/>
            <address2 xsi:nil="true" xsi:type="xsd:string"/>
            <address3 xsi:nil="true" xsi:type="xsd:string"/>
            <address4 xsi:nil="true" xsi:type="xsd:string"/>
            <address5 xsi:nil="true" xsi:type="xsd:string"/>
            <address6 xsi:nil="true" xsi:type="xsd:string"/>
            <postcode xsi:nil="true" xsi:type="xsd:string"/>
            <phone xsi:nil="true" xsi:type="xsd:string"/>
            <member xsi:nil="true" xsi:type="xsd:string"/>
            <tsa_flag xsi:nil="true" xsi:type="xsd:string"/>
            <nomail xsi:nil="true" xsi:type="xsd:string"/>
            <climbers_flag xsi:nil="true" xsi:type="xsd:string"/>
            <outdoor_flag xsi:nil="true" xsi:type="xsd:string"/>
            <staff_referral_id xsi:nil="true" xsi:type="xsd:string"/>
            <mountainerring xsi:nil="true" xsi:type="xsd:string"/>
            <news xsi:nil="true" xsi:type="xsd:string"/>
            <running xsi:nil="true" xsi:type="xsd:string"/>
            <sale xsi:nil="true" xsi:type="xsd:string"/>
            <skiing xsi:nil="true" xsi:type="xsd:string"/>
            <snowboarding xsi:nil="true" xsi:type="xsd:string"/>
            <travelling xsi:nil="true" xsi:type="xsd:string"/>
            <trekking xsi:nil="true" xsi:type="xsd:string"/>
            <cycling xsi:nil="true" xsi:type="xsd:string"/>
            <camping xsi:nil="true" xsi:type="xsd:string"/>
            <groupid xsi:nil="true" xsi:type="xsd:string"/>
        </response>
    </ns1:ws_customer_infoResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

1 个答案:

答案 0 :(得分:1)

问题出在服务器响应中。

XSD表示<statustext>标记类型为int,但是服务器返回字符串OK,从而中断了响应解析。