2009-08-20 13 views
9

Ragazzi, sono bloccato, sbattendo la testa dalla scrivania per le ultime ore.SOAP-ERROR: Encoding: violazione delle regole di codifica?

Sto provando a consumare un servizio, e ho 8 altre funzioni che chiamo di natura quasi IDENTICA a questa, ma questa, risulta in un 'SOAP-ERROR: Encoding: Violazione di regole di codifica' errore.

Heres la chiamata di funzione (wsdl omesso per sicurezza):

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 quindi questa funzione, si connette ad un webservice, gli elementi necessari sono: username, password, prod, mdn, tutti e 4 di cui Fornisco come parte dell'array $ params. Username/Pass sono definiti in precedenza e funzionano bene, poiché le altre 8 funzioni consumano il servizio Web senza problemi.

L'array $ dati [] (che mi passa per la funzione), contiene: dati $ [ 'IDProdotto'] dati $ [ 'MDN'] nient'altro viene utilizzato.

sto ottenendo

SOAP-ERROR: Encoding: Violation of encoding rules 

per qualche motivo inspiegabile, e Googling questo errore mi porta da nessuna parte. Qualcun altro si imbatte in questo? Esecuzione di PHP 5.2.9-2. La cosa strana è questo è identica a questa funzione che funziona al 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; 
} 

Ecco il WSDL (dovrebbe avere postato questo primo):

<?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> 
+2

Se si trattasse di un client .NET, provare a codificare "prod" e "mdn" per conoscere valori validi e vedere cosa succede. Se funziona, rimuoverei i codici hardware uno alla volta per vedere qual è il problema. Poi guarderei il valore negativo per vedere se c'è qualcosa di speciale al riguardo. –

+0

Questo è stato anche il mio primo pensiero. –

+0

Ho provato a codificarlo, ma ottengo lo stesso risultato, è MOLTO strano. Non sono a conoscenza di nessun altro metodo per risolvere questo problema. – Jakub

risposta

14

Sembra che si dispone di un tipo non corrispondente da qualche parte , sia durante il montaggio della richiesta (uno dei parametri non è di tipo stringa), o il server restituisce qualcosa di diverso da un int (violando la definizione di risposta WSDL e quindi inducendo il client a considerare la risposta non valida, in quanto si aspetta qualcos'altro) .

  • Per testare il primo caso, garantire la fusione di tutti i parametri di stringa prima
  • Per verificare il secondo caso, crea il tuo SoapClient con la traccia opzione impostata su true al fine di ottenere l'accesso alla risposta XML reale dal server tramite $ client -> __ getLastResponse() in seguito (È possibile utilizzare questo per il debug delle richieste anche tramite __getLastRequest()).

Alcune ulteriori osservazioni/domande:

  • Secondo il WSDL pubblicato, il 'CanLoadProductRequest' ha un param quinta 'ESN', che non si fornisce nella vostra chiamata di funzione.
  • Qualsiasi motivo per cui si utilizza $client->__soapCall("CanLoadProduct", $params) anziché $client->CanLoadProduct($username, $password, etc.)? (La prima versione è una variazione di livello inferiore che deve essere utilizzata per scenari non_WSDL.La seconda versione potrebbe fornire un errore/eccezione più dettagliato)
  • Puoi testare la chiamata SOAP a CanLoadProductRequest con altri mezzi? L'errore potrebbe essere sul lato server, cercando di restituire un tipo di risultato che non si adatta alla definizione WSDL.
+0

L''esn' è opzionale, e questo modello di dati utente/pass/prod/mdn/esn è standard per la maggior parte delle altre 8 chiamate che uso, nessuna sembra fallire eccetto per questa. Ho provato $ client-> CanLoadProduct ($ params), ma risulta in: Array alla conversione stringa Avviso da PHP – Jakub

+0

Oups - scusa, se si utilizza la notazione $ client-> CanLoadProduct(), non si passa array di parametri, ma i singoli parametri come si farebbero con una chiamata di funzione standard (ad es. $ client-> CanLoadProduct ($ username, $ password, ecc.) ) –

+1

Un'altra cosa da provare sarebbe il cast esplicito dei parametri in stringa prima la chiamata (ad esempio il productid potrebbe essere passato come int qui) –

2

Ho avuto lo stesso problema quando cercavo di passare XML come parametro a uno dei miei servizi web.Il wrapping dei dati XML in <![CDATA[ ... ]]> ha eliminato lo SOAP-ERROR: Codifica: violazione delle regole di codifica e tutto ha funzionato correttamente.

Altri dettagli:
1. Il parametro è stato definito anche come xsd: string.
2. WSDL è stato documentato/letterale.
3. Utilizzo della classe SOAP integrata con php 5.2.10.

2

Stavo ricevendo questo errore utilizzando lo strumento SoapUI, fino a quando ho riformattato la risposta con dati di test reali e non solo "?". Anche con SoapUI, la risposta potrebbe essere più del previsto e potrebbe essere necessario abbreviare la risposta prevista rimuovendo diversi parametri di risposta opzionali. Spero che questo ti aiuti?

+0

Questo è anche il mio problema. Si aspettava un numero intero da restituire e ovviamente? non è un int. –

+0

come posso sapere quale valore si aspetta che venga restituito? –

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

Ho avuto lo stesso problema e ho risolto utilizzando questa sintassi per __soapCall:

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

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

Invece di

__soapCall('methodName', array($params) 
6

Ho avuto lo stesso problema.

Nelle preferenze SoapUI ho controllato l'opzione Preferenze → Impostazioni Editor → Convalida Risposte e ho ricevuto questa informazione:

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

Questo risolto il mio problema. Il campo conteneva un valore di tipo errato.

+0

Questo mi ha aiutato un sacco con il debug del mio wsdl. – Halfstop

+0

Le preferenze si trovano sotto "File", e puoi anche attivare "Convalida richieste" per scoprire se stai inviando il tipo sbagliato di dati negli esempi di test. – MatsLindh

0

Ho avuto lo stesso problema e sono riuscito a correggerlo correggendo il WSDL, che presupponeva che il server inviasse un intero per un valore particolare, ma in realtà stava inviando una stringa. Forse la modifica del WSDL da:

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

a

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

può risolvere il problema, ecco alcune informazioni sul caso particolare che stavo affrontando: https://blog.dotnetframework.org/2016/12/06/uncaught-soapfault-exception-sender-soap-error-encoding-violation-of-encoding-rules/

0

ho avuto questo problema in PhpStorm quando facendo test unitari. Ho disabilitato la cache wsdl e ha funzionato: ini_set ("soap.wsdl_cache_enabled", "0");