PHP SOAP实践
我现在公司里的系统都是SOA/面向服务架构的,用Java编写的Web Service,理论上Web Service支持异构语言的,我想测试一下用PHP来调用Java的Web Service是否方便。
首先用Java建立一个Web Service服务端(用CXF,JAX-WS实现),下面是公布出来的WSDL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="SampleWebService" targetNamespace="http://www.abc.net/WS/2008" xmlns:ns1="http://webservice.passport.abc.net/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.abc.net/WS/2008" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:import location="http://192.168.19.42:8080/sample/service/SampleWebService?wsdl=SampleWebService.wsdl" namespace="http://webservice.passport.abc.net/"> </wsdl:import> <wsdl:message name="helloUser"> <wsdl:part element="ns1:helloUser" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:message name="helloUserResponse"> <wsdl:part element="ns1:helloUserResponse" name="parameters"> </wsdl:part> </wsdl:message> <wsdl:binding name="SampleWebServiceSoapBinding" type="ns1:SampleWebService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="helloUser"> <soap:operation soapAction="" style="document" /> <wsdl:input name="helloUser"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="helloUserResponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="SampleWebService"> <wsdl:port binding="tns:SampleWebServiceSoapBinding" name="SampleWebServicePort"> <soap:address location="http://192.168.19.42:8080/sample/service/SampleWebService" /> </wsdl:port> </wsdl:service> </wsdl:definitions> |
这个Web Service有个“helloUser”方法,传入一个参数,它返回一段文本“Hello 参数!”,
PHP5之后已经加入了SOAP的支持,我最开始用PHP5的SOAP函数来调用,下面是代码
1 2 | $client = new SoapClient('http://192.168.19.42:8080/sample/service/SampleWebService?wsdl'); var_dump($client->__getFunctions()); |
但报错Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: <message> ‘helloUser’ already defined in …,我搜了PHP网站上的相关文档也没找到答案,没办法,我只能找其他SOAP的组件,找到了NuSOAP,它最近发布的版本是0.7.3,是在2007年发布的,现在已经2009了,用用试试吧,参考nusoap的例子,写好自己代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | require_once('nusoap.php'); $client = new nusoap_client('http://192.168.19.42:8080/sample/service/SampleWebService?wsdl', 'wsdl'); $err = $client->getError(); if ($err) { echo '<h2>Constructor error</h2><p>' . $err . '</p>'; } $param = array('arg0'=>'laoer'); $result = $client->call('helloUser', array('parameters' => $param),"http://webservice.passport.abc.net/",'', false, false,"document","literal"); if ($client->fault) { echo '<h2>Fault</h2><p>'; print_r($result); echo '</p>'; } else { // Check for errors $err = $client->getError(); if ($err) { // Display the error echo '<h2>Error</h2><p>' . $err . '</p>'; } else { // Display the result echo '<h2>Result</h2><p>'; //print_r($result); echo $result["return"]; echo '</p>'; } } echo '<h2>Request</h2><p>' . htmlspecialchars($client->request, ENT_QUOTES) . '</p>'; echo '<h2>Response</h2><p>' . htmlspecialchars($client->response, ENT_QUOTES) . '</p>'; |
执行结果
Result
Hello laoer!
Request
POST /sample/service/SampleWebService HTTP/1.0
Host: 192.168.19.42:8080
User-Agent: NuSOAP/0.7.3 (1.114)
Content-Type: text/xml; charset=UTF-8
SOAPAction: “”
Content-Length: 436
我们可以看到Request的SOAP文本
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope 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:ns1="http://webservice.passport.abc.net/"> <SOAP-ENV:Body> <helloUser xmlns=""> <arg0 xmlns="">laoer</arg0> </helloUser> </SOAP-ENV:Body> </SOAP-ENV:Envelope> |
Response
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
SOAPAction: “”
Content-Type: text/xml;charset=UTF-8
Content-Length: 237
Date: Fri, 27 Mar 2009 04:27:11 GMT
Connection: close
Response的SOAP文本
1 2 3 4 5 6 7 | <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:helloUserResponse xmlns:ns2="http://webservice.passport.abc.net/"> <return>Hello laoer!</return> </ns2:helloUserResponse> </soap:Body> </soap:Envelope> |
碰到一个小问题就是PHP给方法传参数,看是我不知道怎么填,后来我用soapUI,做了一个SOAP Request的例子,发现参数的Name是arg0,如果是多个参数,则arg0、arg1、arg2…以此类推,所以我们定义的参数是$param = array(‘arg0’=>’laoer’),还有就是nusoap里对返回信息的编码有点问题,如果你Web Service放回的编码是UTF-8,则nusoap多转换了一次,在nusoap.php文件nusoap_client类里把$decode_utf8置为false就可以了。