这段客户端soap请求和服务端回复,怎么写php的soap服务端?

vicallee 2012-07-20 04:59:46
客户端请求:
POST /onvif/device_service HTTP/1.1
Host: 192.168.0.218
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 299

<?xml version="1.0" encoding="utf-8"?><s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><GetDeviceInformation xmlns="http://www.onvif.org/ver10/device/wsdl"/></s:Body></s:Envelope>


服务端正确回复:
HTTP/1.1 200 Data follows
Server: gSOAP/2.7
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 2083
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:wsrf_bf="http://tempuri.org/wsrf_bf.xsd" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf_r="http://tempuri.org/wsrf_r.xsd" xmlns:event="http://www.onvif.org/ver10/events/wsdl/EventBinding" xmlns:nc="http://www.onvif.org/ver10/events/wsdl/NotificationConsumerBinding" xmlns:np="http://www.onvif.org/ver10/events/wsdl/NotificationProducerBinding" xmlns:pps="http://www.onvif.org/ver10/events/wsdl/PullPointSubscriptionBinding" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:psm="http://www.onvif.org/ver10/events/wsdl/PausableSubscriptionManagerBinding" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:tns1="http://www.onvif.org/ver10/topics"><SOAP-ENV:Body><tds:GetDeviceInformationResponse><tds:Manufacturer>manufacture</tds:Manufacturer><tds:Model>IPCAM-A5</tds:Model><tds:FirmwareVersion>Jul--9-2012</tds:FirmwareVersion><tds:SerialNumber></tds:SerialNumber><tds:HardwareId>20100523-0001-0001-0001-122334455667</tds:HardwareId></tds:GetDeviceInformationResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>


我写的服务端:但没办法做到正确回复,总是提示找不到方法 ???

function GetDeviceInformation ()
{
return array (
'Manufacturer'=>'manufacture',
'Model'=>'IPCAM-A5',
'FirmwareVersion'=>'M-A5.222',
'SerialNumber'=>'54545454',
'HardwareId'=>'333333333333333');
}

header ("Content-Type: application/soap+xml; charset=utf-8");

$s = new SoapServer (null, '怎么写?');
$s->addFunction ("GetDeviceInformation");
$s->handler ();
...全文
1778 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
gfdsagfdsa382 2013-03-19
  • 打赏
  • 举报
回复
结了,找到了。php真他娘的弱,在远程服务器端调用天气预报接口成功,同样的写法调用股票接口却错误频出,新手无耐,只能啃书,书海茫茫,毫无头绪,不是不下功夫,只是搜索范围太广,不知如何是好,还好,运气来了,原来WEB调用真的很简单,想要的东西出来了,原来只有三四行脚本,但苦了我很多日子。找到WSDL,然后用语句$client = new SoapClient 加载它,这是关键的一步,接下来就是引用其中的方法了,我走了很多弯路,导致我以为自己走的路全错了。如:$param = array('theCityName'=>"南阳"); $result = $client->__soapCall('getWeatherbyCityName',array('paramters'=>$param)); 成功,但换成股票接口WSDL,引用其中方法,正确传参后,失败,反复试验,终于找到解决方法,原来是数组问题,不应用以上写法,换一种写法传参就很顺利拿到东西了
gfdsagfdsa382 2013-03-19
  • 打赏
  • 举报
回复
php真他娘的弱,在远程服务器端调用天气预报接口成功,同样的写法调用股票接口却错误频出,新手无耐,只能啃书,书海茫茫,毫无头绪,不是不下功夫,只是搜索范围太广,不知如何是好,还好,运气来了,原来WEB调用真的很简单,想要的东西出来了,原来只有三四行脚本,但苦了我很多日子。找到WSDL,然后用语句$client = new SoapClient 加载它,这是关键的一步,接下来就是引用其中的方法了,我走了很多弯路,导致我以为自己走的路全错了。如:$param = array('theCityName'=>"南阳"); $result = $client->__soapCall('getWeatherbyCityName',array('paramters'=>$param)); 成功,但换成股票接口WSDL,引用其中方法,正确传参后,失败,反复试验,终于找到解决方法,原来是数组问题,不应用以上写法,换一种写法传参就很顺利拿到东西了。
xuzuning 2012-07-22
  • 打赏
  • 举报
回复
你不是有 wsdl 吗?,那么无论是传入还是传出,都要遵守 wsdl 的约定。
对于不受 wsdl 约束的情况,你就按你们私下约定的去做了

总之,遵守协议是第一位的
vicallee 2012-07-22
  • 打赏
  • 举报
回复
尝试了一下,使用non-wsdl模式下,函数返回单个参数时可以用new soapparam('value', 'type')是可以的,但当要返回多个参数时,输出的xml就总是不对了,这种情况不知怎么处理?

返回单个时
function xx () { return new soapparam('value', 'ns1:type');}
它输出的XML如下,这是对的:【用type描述value】
<ns1:xxResponse env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"><rpc:result>ns1:type</rpc:result><ns1:type xsi:type="xsd:string">value</ns1:type></ns1:xxResponse>

返回多个时试过如下,不行
return array (new SoapParam('value1', 'ns1:type1'), new SoapParam('value2', 'ns1:type2'));
输出错误的xml是:不同之处是多了return和item,还有把param_name和param_value分开描述了。
<ns1:xxResponse env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"><rpc:result>return</rpc:result><return enc:itemType="enc:Struct" enc:arraySize="2" xsi:type="enc:Array"><item xsi:type="enc:Struct"><param_name xsi:type="xsd:string">ns1:type1</param_name><param_data xsi:type="xsd:string">value1</param_data></item><item xsi:type="enc:Struct"><param_name xsi:type="xsd:string">ns1:type2</param_name><param_data xsi:type="xsd:string">value2</param_data></item></return></ns1:xxResponse>

不知道 non-wsdl下怎么处理多返回值 ?
vicallee 2012-07-22
  • 打赏
  • 举报
回复
再等等看还有没高人高见。非常想知道解决办法。

现在是折衷点的处理办法
根据现有十来个wsdl,分析其中import,如果是远程的就下载,再改写成连接到本地。
再分析binding节,加上service/port节
对新下来的xsd/wsdl也同样这样处理。
再压缩1.08M至130K放到设备上,在设备启动时再解压至内存目录。。。

这样就是有wsdl了。。。。这时可以直接return array('key1'=>'val1', 'key2'=>'val2');
vicallee 2012-07-22
  • 打赏
  • 举报
回复
是啊,还有一个纠结,如果自己解析请求,再组织回复也可以,但工程量太大。

多希望php的soap灵活多一点、实例多一点啊。
现在都不知该怎么弄它。google了两天没解决。
也有人问题差不多的问题,是non-wsdl时客户端请求多参数,不过那人直接用class解决了,但我用class返回还是一样出错。。
qq120848369 2012-07-22
  • 打赏
  • 举报
回复
楼主是因为机器不能联网所以无法下载WSDL内的import外链,如果外链也拉到本地存储结果存不下。

那纠结了
vicallee 2012-07-22
  • 打赏
  • 举报
回复
所以在两个值时,期望输出是:
<ns1:xxResponse env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"><ns1:type1 xsi:type="xsd:string">value1</ns1:type1><ns1:type2 xsi:type="xsd:string">value2</ns1:type2></ns1:xxResponse>
即还是type直接描述value,但就不知怎么控制return才能这样输出了
vicallee 2012-07-22
  • 打赏
  • 举报
回复
是有wsdl ,在互联网上,但有两方面原因不能使用它,一是不允许连互联网取,二存在设备里1M太大了不能保存。这就要求服务端non-wsdl

客户端服务端都遵从这个wsdl,服务端开发时是有WSDL做参考的,可以知道其参数和值类型,我是打算返回的数据客户端能解析,而客户端只需要知道wsdl就能解析了
vicallee 2012-07-21
  • 打赏
  • 举报
回复
现有的问题解决了,原因是服务端里的wsdl里有import外部文件连接,而服务端本身是没有连接外网的条件的。所以总是超时。

所以现在只有途径:
要么把所有wsdl/xsd都下载回来,并改为本地import,但试了一下发现体积超过1M,不合适
要么不用wsdl,这时有两个问题,
如果用soapserver,那么怎么才能它能handle到客户端的方法请求?
如果不用soapserver,自己写DOM,解析请求,组织回复,那好像搞得太复杂了


另外有一个问题是onvif的wsdl文档里都没有service节,php在new soapclient或者soapserver时总是异常,这问题通常怎么解决的?
qq120848369 2012-07-21
  • 打赏
  • 举报
回复
用zend studio可视化的生成WDSL,在WDSL中有函数的说明以及接口URL的说明。

之后soapclient就可以获取WDSL文件,然后直接调用其中的方法即可。而soapserver就是WSDL中接口URL,它接受soapclient的请求调用对应的函数并将结果返回到soapclient。

这个东西很简单,你直接去php.net里看看soap的评论内容就会了,不简单就不叫soap(Simple Object Access Protocol)了。

4,251

社区成员

发帖
与我相关
我的任务
社区描述
国内外优秀PHP框架讨论学习
社区管理员
  • Framework
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧