PHP SOAP的使用总结

发表于:2018-08-23 14:23:39,已有4396次阅读

PHP使用SOAP协议调用接口,需要安装soap模块插件,在使用之前使用phpinfo()方法输出判断安装的PHP是否已安装了该插件。
php soap插件
确认安装了后,下面来介绍几种常见的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

评论

暂无评论

您还可输入120个字