PHP SoapClient和复杂头部

5

我一直在尝试使用PHP SoapClient和WSDL结合起来形成一个复杂的头部(比我能找到的任何教程都要复杂),但是我一直没有成功。我需要发送的信封看起来像这样:

(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>ABC123@clientURL.com</eb:ConversationId> 

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

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

(015) <eb:MessageData>

(016) <eb:MessageId>mid:20030707-12545-1369@webservices.sabre.com</eb:MessageId> 

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

(018) </eb:MessageData>

(019) <RefToMessageId>mid:20001209-133003-2333@clientURL</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>

我尝试使用__setSoapHeaders()和SoapVar()来实现它。但是我无法得到正确的输出结果。从例子中我学到最好使用一个类来填充XML中的参数,因此我创建了这样一个类:

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

比我使用的:

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

但是这个请求看起来与实际需求相去甚远:
<?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>www.example.com@example.com</value>
    </item>
   </From>
   <To>
    <item>
     <key>PartyId</key>
     <value>webservices.sabre.com</value>
    </item>
   </To>
   <CPAId>XXX</CPAId>
   <ConversationId>12345@example.com</ConversationId>
   <Service>Session</Service>
   <Action>SessionCreateRQ</Action>
   <MessageData>
    <item>
     <key>MessageId</key>
     <value>mid:12345@www.example.com</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

目前主要问题在于将正确的标签放置到XML的正确位置上,并且我不知道如何在标签中添加“eb:”和“wsse:”名称空间。我希望使用SoapClientI()类,但我不确定它是否能够处理像我需要的更复杂的XML。如果不能,也许我应该使用Curl或类似的东西并将XML作为字符串进行处理?


手动操纵字符串不可取,因为难以维护。如果您可以让客户端正确地针对WSDL工作,即使考虑到奇怪的命名空间问题,那么这将很可能值得一试。 - zanlok
2个回答

10

当我实施 wsse 时也遇到了问题。这是我的方法。是的,这非常特定于 wsse;但是,在您的情况下也应该适用。特别注意在调用 new SoapHeader() 时有 'wsse' 命名空间参数。只需将其替换为您的情况下的 'eb'。

$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);

另一个解决方案是在子类化 SoapClient 之后篡改 XML,但我只会把这个方案作为最后的手段。

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
一种可能的方法是使用curl覆盖__doRequest函数。这里有一个示例here,展示了如何关闭KeepAlive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接