原 PHP SOAP的使用总结
PHP使用SOAP协议调用接口,需要安装soap模块插件,在使用之前使用phpinfo()
方法输出判断安装的PHP是否已安装了该插件。
确认安装了后,下面来介绍几种常见的soap调用形式。
普通调用
使用soap插件极大的方便了php的soap调用,如下使用腾讯开放的查询QQ号是否在线的普通的soap调用:
$url = "http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl";
$client = new SoapClient($url);
$params = array(
"qqCode"=> "8698053"
);
$result = $client->qqCheckOnline($params);
print_r($result);
执行的结果如下:
stdClass Object
(
[qqCheckOnlineResult] => Y
)
在使用过程中,你可以通过SoapClient
对象的__getTypes()
和__getFunctions()
这两个方法来查看对应WSDL文件中声明的方法名和参数类型定义,这样方便我们构建$params
。
如下执行这两个方法,查看QQ开放的这个WSDL文件中定义的类型与方法:
print_r($client->__getTypes());
print_r($client->__getFunctions());
执行结果:
Array
(
[0] => struct qqCheckOnline {
string qqCode;
}
[1] => struct qqCheckOnlineResponse {
string qqCheckOnlineResult;
}
)
Array
(
[0] => qqCheckOnlineResponse qqCheckOnline(qqCheckOnline $parameters)
[1] => qqCheckOnlineResponse qqCheckOnline(qqCheckOnline $parameters)
)
设置SOAP Headers
在安全性较高的接口中,有时候还需要加入SOAP Header头,用于校验调用方接口的身份权限,这时可以使用SoapHeader
类来进行设置,如下参考代码:
$client = new SoapClient($url);
$params = array(
"key"=> "value"
);
// 设置SOAP Header
$ns = 'http://WebXml.com.cn/'; // 命名空间
$headers = array();
$headers[] = new SOAPHeader($ns, $_header_name, $_header_value);
$headers[] = new SOAPHeader($ns, $_header_name, $_header_value);
$client->__setSoapHeaders($headers);
$result = $client->functionName($params);
也可以像官网中其他用户定义的那样的嵌套形式:
$client = new SoapClient(WSDL,array());
$auth = array(
'UserName'=>'USERNAME',
'Password'=>'PASSWORD',
'SystemId'=> array('_'=>'DATA','Param'=>'PARAM'),
);
$ns = 'http://WebXml.com.cn/'; // 命名空间
$header = new SoapHeader('NAMESPACE','Auth', $auth, false);
$client->__setSoapHeaders($header);
这时得到的XML如下:
<SOAP-ENV:Header>
<ns1:Auth>
<ns1:SystemId Param="PARAM">DATA</ns1:SystemId>
<ns1:UserName>USERNAME</ns1:UserName>
<ns1:Password>PASSWORD</ns1:Password>
</ns1:Auth>
</SOAP-ENV:Header>
设置HTTP Request Headers
由于SOAP协议本质上其实还是HTTP协议,只是改变了传输过程中的内容为XML形式,而在实际开发过程中,更有些接口对于请求的Http头也做一些校验限制,因此需要设置Http的请求头以适应需求。默认的SoapClient
类的构造方法,其实包含有两个参数,其中就可以设置HTTP的请求头,参见它的官方定义文档:
public SoapClient::__construct ( mixed $wsdl [, array $options ] )
这里的$options
选项可以控制SOAP类的属性配置,包括HTTP头的设置,如下示例,设置HTTP头接收GZIP压缩:
$mode = array (
//'soap_version' => SOAP_1_2, // SOAP版本,默认为1.0
'keep_alive' => true,
'trace' => true, // 跟踪异常信息,对下面的exceptions属性成对
'encoding' =>'UTF-8',
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE, // 压缩
'exceptions' => true, // 显示异常
'cache_wsdl' => WSDL_CACHE_NONE, // 是否缓存WSDL定义文件,这里设置不使用,接口稳定的情况下建议开启缓存加速
//'proxy_host' => "192.168.2.60", // 代理IP
//'proxy_port' => 8888, // 代理端口
'stream_context' => stream_context_create(array(
'http' => array('header' => 'Content-Encoding: gzip'), // HTTP请求头设置,多个使用'\r\n'分割
'ssl' => array( // 设置不验证HTTPS证书
'verify_peer' => false,
'verify_peer_name' => false
))
)
);
$client = new SoapClient($url, $mode);
上面的设置中在创建SoapClient
对象时就设置好了HTTP请求头,但如果需要实时的根据传入的参数来设置HTTP头,这时应该怎么做呢?为了实现这样的功能,我们需要创建一个基类,继承SoapClient
类来实现:
class BaseSoapClient extends SoapClient {
private $context;
function __construct($wsdl, $options = array()) {
$this->context = stream_context_create();
$options = array_merge($options, array('stream_context' => $this->context));
parent::SoapClient($wsdl, $options);
}
function __doRequest($request, $location, $action, $version, $one_way = 0) {
// 设置HTTP请求头
$headers = array(
'test'=> 'kkkk',
'kkkk'=> 'kkkk'
);
stream_context_set_option($this->context, array('http' => array('header' => $this->encodeRequestHeaders($headers))));
return parent::__doRequest($request, $location, $action, $version, $one_way);
}
private function encodeRequestHeaders($headers) {
$hader = "";
foreach($headers as $key => $value) {
$hader .= $key.": ". $value."\r\n";
}
return $hader;
}
}
对应测试如下:
$url = "http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl";
$client = new BaseSoapClient($url, array (
'trace' => true // 开启跟踪打印请求详情
));
$params = array(
"qqCode"=> "8698053"
);
$result = $client->qqCheckOnline($params);
print_r($client->__getLastRequestHeaders()); // 打印请求头,为了保证这里有输出,需开启trace为true
print_r($result);
执行的结果如下:
POST /webservices/qqOnlineWebService.asmx HTTP/1.1
Host: www.webxml.com.cn
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.5.12
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://WebXml.com.cn/qqCheckOnline"
Content-Length: 274
test: kkkk
kkkk: kkkk
stdClass Object
(
[qqCheckOnlineResult] => Y
)
在这里可以看到我们自定义的HTTP头被设置成功了。
更多关于php soap的高级应用可以参考官网中其他用户提交的使用案例:http://php.net/manual/en/soapclient.dorequest.php
暂无评论