2010-11-30 14 views
5

Lo he intentado por un tiempo, pero no puedo entender cómo usar PHP SoapCLient en combinación con un WSDL para formar un encabezado complejo (es decir, más complejo que cualquier tutorial I podría encontrar). El sobre que tengo que enviar el siguiente aspecto:PHP SoapClient y un encabezado complejo

(001) <?xml version='1.0' encoding='UTF-8'?> 

(002) <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xlink="http://www.w3.org/1999/xlink"> 

(003) <SOAP-ENV:Header> 

(004) <eb:MessageHeader xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" eb:version="2.0" SOAP-ENV:mustUnderstand="1"> 

(005) <eb:From> 

(006) <eb:PartyId>webservices.example.com</eb:PartyId> 

(007) </eb:From> 

(008) <eb:To> 

(009) <eb:PartyId>clientURL</eb:PartyId> 

(010) </eb:To> 

(011) <eb:CPAId>IPCC</eb:CPAId> 

(012) <eb:ConversationId>[email protected]</eb:ConversationId> 

(013) <eb:Service eb:type="XML">Session</eb:Service> 

(014) <eb:Action>SessionCreateRS</eb:Action> 

(015) <eb:MessageData> 

(016) <eb:MessageId>mid:[email protected]</eb:MessageId> 

(017) <eb:Timestamp>2001-02-15T11:25:12Z</eb:Timestamp> 

(018) </eb:MessageData> 

(019) <RefToMessageId>mid:[email protected]</RefToMessageId> 

(020) </eb:MessageHeader> 

(021) <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext"> 

(022) <wsse:BinarySecurityToken xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/12/utility" wsu:Id="SabreSecurityToken" valueType="String" EncodingType="wsse:Base64Binary">Shared/IDL:IceSess\/SessMgr:1\.0.IDL/Common/!ICESMS\/RESC!ICESMSLB\/RES.LB!-4954987477210575357!252506!0</wsse:BinarySecurityToken> 

(023) </wsse:Security> 

(024) </SOAP-ENV:Header> 

(025) <SOAP-ENV:Body> 

(026) <eb:Manifest xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" eb:version="2.0"> 

(027) <eb:Reference eb:id="SessionCreateRS" xlink:type="simple" xlink:href="cid:SessionCreateRS" 

(028) <eb:Description xml:lang="en-US">Response Message</eb:Description>"/> 

(029) </eb:Reference> 

(030) </eb:Manifest> 

(031) </SOAP-ENV:Body> 

(032) </SOAP-ENV:Envelope> 

Traté de hacer que el uso de __setSoapHeaders() y utilizando SoapVar(). Sin embargo, no puedo obtener la salida correcta. A partir de ejemplos supe que sería bueno utilizar una clase para llenar los parámetros en el XML, así que hice una clase como esta:

class EbXmlMessage{ 
public $From = array('PartyId' => '[email protected]'); 
public $To = array('PartyId' => 'example.com'); 
public $CPAId = 'XXXX'; 
public $ConversationId = '[email protected]'; 
public $Service = 'Session'; 
public $Action = 'SessionCreateRQ'; 
public $MessageData = array('MessageId' => "mid:[email protected]",'Timestamp' => '2010-11-26T08:19:00Z'); 
} 

que yo utilizo:

$eb_params = new SoapVar($eb,SOAP_ENC_OBJECT); 
$header = new SoapHeader($ns,"header", $eb_params,true); 

embargo, la solicitud no ni siquiera un poco empezar a parecerse a lo que tiene que:

<?xml version="1.0" encoding="UTF-8"?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.opentravel.org/OTA/2002/11" xmlns:ns2="https://cert.webservices.sabre.com/cert"> 
<SOAP-ENV:Header> 
    <ns2:header SOAP-ENV:mustUnderstand="1"> 
    <From> 
    <item> 
    <key>PartyId</key> 
    <value>[email protected]</value> 
    </item> 
    </From> 
    <To> 
    <item> 
    <key>PartyId</key> 
    <value>webservices.sabre.com</value> 
    </item> 
    </To> 
    <CPAId>XXX</CPAId> 
    <ConversationId>[email protected]</ConversationId> 
    <Service>Session</Service> 
    <Action>SessionCreateRQ</Action> 
    <MessageData> 
    <item> 
    <key>MessageId</key> 
    <value>mid:[email protected]</value> 
    </item> 
    <item> 
    <key>Timestamp</key> 
    <value>2010-11-26T08:19:00Z</value> 
    </item> 
    </MessageData> 
    </ns2:header> 
</SOAP-ENV:Header> 
<SOAP-ENV:Body> 
    <ns1:SessionCreateRQ> 
    <ns1:POS> 
    <ns1:Source PseudoCityCode="XXXX"/> 
    </ns1:POS> 
    </ns1:SessionCreateRQ> 
    <param1/> 
</SOAP-ENV:Body> 
</SOAP-ENV:Envelope 

los principales problemas en lo que va a encontrar las etiquetas correctas en el XML en el lugar correcto, y yo no sé cómo puedo conseguir "EB": y espacio de nombres "wsse:" en la etiqueta s. Espero utilizar la clase SoapClientI() pero no estoy seguro de si puede manejar un XML más complejo como el que necesito, si no debería usar Curl o algo similar y tratar el XML como una cadena.

+0

no es recomendable manipular la cadena manualmente ya que se vuelve difícil de mantener. Si puede lograr que el cliente trabaje correctamente en contra del wsdl, incluso en consideración de problemas extraños en el espacio de nombres, entonces probablemente valga la pena el tiempo. – zanlok

Respuesta

10

Tuve problemas con esto también al implementar wsse. Aquí estaba mi enfoque. Sí, esto es bastante específico de wsse; sin embargo, también debería funcionar en su contexto. Tenga en cuenta especialmente cómo está el parámetro de espacio de nombres 'wsse' en la llamada al new SoapHeader(). Simplemente reemplace eso con 'eb' para su caso.

$header_part = ' 
    <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext" SOAP-ENV:mustUnderstand="1"> 
     <wsse:UsernameToken> 
      <wsse:Username>'."USERNAME".'</wsse:Username> 
      <wsse:Password>'."PASSWORD".'</wsse:Password> 
     </wsse:UsernameToken> 
    </wsse:Security> 
'; 
$soap_var_header = new SoapVar($header_part, XSD_ANYXML, null, null, null); 
$soap_header = new SoapHeader('http://your-target-service.com', 'wsse', $soap_var_header); 
$soap_client->__setSoapHeaders($soap_header); 

Otra solución consiste en destrozar el XML después de la subclasificación de la SoapClient, pero sólo haría esto como último recurso.

class My_SoapClient extends SoapClient { 
    protected $_response = null; 
    public function __doRequest($request, $location, $action, $version, $one_way=null) { 
     // insert big bad mangling code here 
     $this->_response = parent::__doRequest($this->_request, $location, $action, $version, $one_way); 
     return $this->_response; 
    } 
} 
0

Una posible manera de hacer esto es sobrescribir la función __doRequest usando curl. Hay un ejemplo here que muestra cómo desactivar KeepAlive.

Cuestiones relacionadas