php调用webservice

来源:互联网 发布:win7网络已存在 编辑:程序博客网 时间:2024/05/03 17:35
<span style="font-size:14px;">1.生成wsdl的文件类</span>
<pre name="code" class="php"><span style="font-size:14px;"><?phpclass Wsdl {    private $_operations;    private $_types;    private $_messages;    private $_namespace;    private $_serviceName;    public function generateWsdl($className, $serviceUrl, $encoding='UTF-8')    {        $this->_operations=array();        $this->_types=array();        $this->_messages=array();        $this->_serviceName=$className;        $this->_namespace="urn:{$className}wsdl";        $reflection=new ReflectionClass($className);        foreach($reflection->getMethods() as $method)        {            if($method->isPublic()){                $this->processMethod($method);            }        }        header("content-type: text/xml");        echo $this->buildDOM($serviceUrl,$encoding)->saveXML();    }    private function processMethod($method)    {        $comment = $method->getDocComment();        if(strpos($comment,'@soap')===false)            return;        $methodName = $method->getName();        $comment = preg_replace('/^\s*\**(\s*?$|\s*)/m','',$comment);        $params = $method->getParameters();        $message = array();        $n = preg_match_all('/^@param\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/im',$comment,$matches);        if($n>count($params))            $n = count($params);        for($i=0;$i<$n;++$i)            $message[$params[$i]->getName()] = array($this->processType($matches[1][$i]), trim($matches[3][$i])); // name => type, doc                            $this->_messages[$methodName.'Request'] = $message;        if(preg_match('/^@return\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/im',$comment,$matches))             $return = array($this->processType($matches[1]),trim($matches[3])); // type, doc        else            $return = null;        $this->_messages[$methodName.'Response'] = array('return'=>$return);        if(preg_match('/^\/\*+\s*([^@]*?)\n@/s',$comment,$matches))            $doc = trim($matches[1]);        else            $doc='';        $this->_operations[$methodName]=$doc;    }    private function processType($type)    {        static $typeMap=array(            'string'=>'xsd:string',            'str'=>'xsd:string',            'int'=>'xsd:int',            'integer'=>'xsd:integer',            'float'=>'xsd:float',            'double'=>'xsd:float',            'bool'=>'xsd:boolean',            'boolean'=>'xsd:boolean',            'date'=>'xsd:date',            'time'=>'xsd:time',            'datetime'=>'xsd:dateTime',            'array'=>'soap-enc:Array',            'object'=>'xsd:struct',            'mixed'=>'xsd:anyType',        );        if(isset($typeMap[$type]))            return $typeMap[$type];        else if(isset($this->_types[$type]))            return is_array($this->_types[$type]) ? 'tns:'.$type : $this->_types[$type];        else if(($pos=strpos($type,'[]'))!==false) // if it is an array        {            $type=substr($type,0,$pos);            if(isset($typeMap[$type]))                $this->_types[$type.'[]']='xsd:'.$type.'Array';            else            {                $this->_types[$type.'[]']='tns:'.$type.'Array';                $this->processType($type);            }            return $this->_types[$type.'[]'];        }        else // class type        {            $type=Yii::import($type,true);            $this->_types[$type]=array();            $class=new ReflectionClass($type);            foreach($class->getProperties() as $property)            {                $comment=$property->getDocComment();                if($property->isPublic() && strpos($comment,'@soap')!==false)                {                    if(preg_match('/@var\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/mi',$comment,$matches))                        $this->_types[$type][$property->getName()]=array($this->processType($matches[1]),trim($matches[3]));  // name => type, doc 1                }            }            return 'tns:'.$type;        }    }    private function buildDOM($serviceUrl,$encoding)    {        $xml="<?xml version=\"1.0\" encoding=\"$encoding\" ?>              <definitions name=\"{$this->_serviceName}\" targetNamespace=\"{$this->_namespace}\"              xmlns=\"http://schemas.xmlsoap.org/wsdl/\"              xmlns:tns=\"{$this->_namespace}\"              xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\"              xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"              xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\"              xmlns:soap-enc=\"http://schemas.xmlsoap.org/soap/encoding/\">              </definitions>";        $dom=new DOMDocument();        $dom->loadXml($xml);        $this->addTypes($dom);        $this->addMessages($dom);        $this->addPortTypes($dom);        $this->addBindings($dom);        $this->addService($dom,$serviceUrl);        return $dom;    }    private function addTypes($dom)    {        if($this->_types===array())            return;        $types=$dom->createElement('wsdl:types');        $schema=$dom->createElement('xsd:schema');        $schema->setAttribute('targetNamespace',$this->_namespace);        foreach($this->_types as $phpType=>$xmlType)        {            if(is_string($xmlType) && strrpos($xmlType,'Array')!==strlen($xmlType)-5)                continue;  // simple type            $complexType=$dom->createElement('xsd:complexType');            if(is_string($xmlType))            {                if(($pos=strpos($xmlType,'tns:'))!==false)                    $complexType->setAttribute('name',substr($xmlType,4));                else                    $complexType->setAttribute('name',$xmlType);                $complexContent=$dom->createElement('xsd:complexContent');                $restriction=$dom->createElement('xsd:restriction');                $restriction->setAttribute('base','soap-enc:Array');                $attribute=$dom->createElement('xsd:attribute');                $attribute->setAttribute('ref','soap-enc:arrayType');                $attribute->setAttribute('wsdl:arrayType',substr($xmlType,0,strlen($xmlType)-5).'[]');                $restriction->appendChild($attribute);                $complexContent->appendChild($restriction);                $complexType->appendChild($complexContent);            }            else if(is_array($xmlType))            {                $complexType->setAttribute('name',$phpType);                $all=$dom->createElement('xsd:all');                foreach($xmlType as $name=>$type)                {                    $element=$dom->createElement('xsd:element');                    $element->setAttribute('name',$name);                    $element->setAttribute('type',$type[0]);                    $all->appendChild($element);                }                $complexType->appendChild($all);            }            $schema->appendChild($complexType);            $types->appendChild($schema);        }        $dom->documentElement->appendChild($types);    }    private function addMessages($dom)    {        foreach($this->_messages as $name=>$message)        {            $element=$dom->createElement('wsdl:message');            $element->setAttribute('name',$name);            foreach($this->_messages[$name] as $partName=>$part)            {                if(is_array($part))                {                    $partElement=$dom->createElement('wsdl:part');                    $partElement->setAttribute('name',$partName);                    $partElement->setAttribute('type',$part[0]);                    $partElement->setAttribute('note',$part[1]);                    $element->appendChild($partElement);                }            }            $dom->documentElement->appendChild($element);        }    }    private function addPortTypes($dom)    {        $portType=$dom->createElement('wsdl:portType');        $portType->setAttribute('name',$this->_serviceName.'PortType');        $dom->documentElement->appendChild($portType);        foreach($this->_operations as $name=>$doc)            $portType->appendChild($this->createPortElement($dom,$name,$doc));    }    private function createPortElement($dom,$name,$doc)    {        $operation=$dom->createElement('wsdl:operation');        $operation->setAttribute('name',$name);        $input = $dom->createElement('wsdl:input');        $input->setAttribute('message', 'tns:'.$name.'Request');        $output = $dom->createElement('wsdl:output');        $output->setAttribute('message', 'tns:'.$name.'Response');        $operation->appendChild($dom->createElement('wsdl:documentation',$doc));        $operation->appendChild($input);        $operation->appendChild($output);        return $operation;    }    private function addBindings($dom)    {        $binding=$dom->createElement('wsdl:binding');        $binding->setAttribute('name',$this->_serviceName.'Binding');        $binding->setAttribute('type','tns:'.$this->_serviceName.'PortType');        $soapBinding=$dom->createElement('soap:binding');        $soapBinding->setAttribute('style','rpc');        $soapBinding->setAttribute('transport','http://schemas.xmlsoap.org/soap/http');        $binding->appendChild($soapBinding);        $dom->documentElement->appendChild($binding);        foreach($this->_operations as $name=>$doc)            $binding->appendChild($this->createOperationElement($dom,$name));    }    private function createOperationElement($dom,$name)    {        $operation=$dom->createElement('wsdl:operation');        $operation->setAttribute('name', $name);        $soapOperation = $dom->createElement('soap:operation');        $soapOperation->setAttribute('soapAction', $this->_namespace.'#'.$name);        $soapOperation->setAttribute('style','rpc');        $input = $dom->createElement('wsdl:input');        $output = $dom->createElement('wsdl:output');        $soapBody = $dom->createElement('soap:body');        $soapBody->setAttribute('use', 'encoded');        $soapBody->setAttribute('namespace', $this->_namespace);        $soapBody->setAttribute('encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/');        $input->appendChild($soapBody);        $output->appendChild(clone $soapBody);        $operation->appendChild($soapOperation);        $operation->appendChild($input);        $operation->appendChild($output);        return $operation;    }    private function addService($dom,$serviceUrl)    {        $service=$dom->createElement('wsdl:service');        $service->setAttribute('name', $this->_serviceName.'Service');        $port=$dom->createElement('wsdl:port');        $port->setAttribute('name', $this->_serviceName.'Port');        $port->setAttribute('binding', 'tns:'.$this->_serviceName.'Binding');        $soapAddress=$dom->createElement('soap:address');        $soapAddress->setAttribute('location',$serviceUrl);        $port->appendChild($soapAddress);        $service->appendChild($port);        $dom->documentElement->appendChild($service);    }} </span>

2.调用webservice的文件
<pre name="code" class="php"><span style="font-size:14px;">$host = $_SERVER ['HTTP_HOST'];$module = trim ( $_GET ['m'] );include __DIR__.'/'.$module.".class.php";if (isset($_GET ['ws']) && $_GET['ws']==1) {    $soap = new SoapServer ( "http://" . $host . "/wsdl/service.php?m={$module}", array('cache_wsdl'=>0) );   $soap->setClass ( $module);    $soap->handle ();} else {    include __DIR__ . '/WsdlModel.class.php';    $wsdl = new wsdl ();    $wsdl->generateWsdl ( $module, "http://" . $host . "/wsdl/service.php?m={$module}&ws=1" );    unset ( $wsdl );}</span>


<span style="font-size:14px;">3.定义一个类作为测试类</span>
<pre name="code" class="php"><span style="font-size:14px;">class Food{    /**      * function name: getFood     * @param string 食物     * @return string     * @soap     */    public function getFood($food){        $arr['food'] =   "我喜欢吃".$food;        return    json_encode($arr);    }        /**     * function name: getEat     * @return string     * @soap     */    public function getEat(){        return "food";    }}</span>

4.在客服端进行调用
<span style="font-size:14px;">1.通过php自带扩展soap调用</span>
<pre name="code" class="php"><span style="font-size:14px;">try {    $soap = new SoapClient ( "http://www.mytest.com/wsdl/service.php?m=Food", array ('cache_wsdl' => 0) );    $result = $soap->__soapCall ( "getFood", array("apple"));    echo $result;} catch ( SoapFault $e ) {    echo $e->getMessage ();    echo $e->getTraceAsString ();} catch ( Exception $e ) {    echo $e->getMessage ();}</span>

2.通过开源类nusoap调用
<pre name="code" class="php"><span style="font-size:14px;">include __DIR__ . "/Nusoap.class.php";$client = new nusoap_client ( 'http://www.mytest.com/wsdl/service.php?m=Food', 'wsdl' );$client->soap_defencoding = 'utf-8';$client->decode_utf8 = false;$client->xml_encoding = 'utf-8';$client->debugLevel = 2;$result = $client->call ( 'getFood', array ("苹果"));echo $result;</span>

3.通过java的axis2进行调用
<pre name="code" class="java"><span style="font-size:14px;">import javax.xml.namespace.QName;import org.apache.axis2.AxisFault;import org.apache.axis2.addressing.EndpointReference;import org.apache.axis2.client.Options;import org.apache.axis2.rpc.client.RPCServiceClient;import org.apache.axis2.transport.http.HTTPConstants;public class TestTwoSoap{public static void main(String[] args) throws AxisFault {// 使用RPC方式调用WebService         RPCServiceClient serviceClient = new RPCServiceClient(); Options options = serviceClient.getOptions(); options.setProperty(HTTPConstants.CHUNKED, "false");// 指定调用WebService的URL EndpointReference targetEPR = new EndpointReference( "http://www.mytest.com/wsdl/service.php?m=Food&ws=1"); options.setTo(targetEPR); // 指定方法的参数值 Object[] requestParam = new Object[] {"dd"}; // 指定方法返回值的数据类型的Class对象 Class[] responseParam = new Class[] {String.class}; // 指定要调用的getGreeting方法及WSDL文件的命名空间 QName requestMethod = new QName("http://www.mytest.com/wsdl/service.php?m=Food&ws=1", "getFood"); // 调用方法并输出该方法的返回值 try {System.out.println(serviceClient.invokeBlocking(requestMethod, requestParam, responseParam)[0]);} catch (AxisFault e) {e.printStackTrace();} } }</span>


                                             
0 0
原创粉丝点击