我已经尝试了一段时间,但我无法弄清楚如何将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获取正确的标签,我不知道如何获得&#34; eb:&#34;和&#34; wsse:&#34;标签中的命名空间。我希望使用SoapClientI()类,但我不确定它是否可以处理更复杂的XML,如果不是,我可能应该使用Curl或类似的东西,只需将XML视为一个字符串?
答案 0 :(得分:10)
在实施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;
}
}
答案 1 :(得分:0)
执行此操作的可能方法是使用__doRequest
覆盖curl
函数。有一个示例here,其中显示了如何关闭KeepAlive
。