当前位置: 首页 > 工具软件 > wsdl2php > 使用案例 >

php生成的wsdl调用地址,PHP 生成WSDL 以及 提供SOAP服务

轩辕阳焱
2023-12-01

近期项目需要与Java对接, 为 Java方提供 SOAP服务,

我们知道SOAP服务  分为 有WSDL与没有WSDL的两种.

我们实现了较为复杂的有WSDL的这种

1.注意要点: PHP环境中 php.ini 中always_populate_raw_post_data 必须设置为 -1  (默认不是)

否则会出现 各种错误.

2.网上找了SoapDiscovery.class.php ,使用后,只有一点不太好用, 就是 location地址不合适,我对这个类进行了改造,代码下附

/**

* 生成WSDL的SOAP类,修改版

**/

class soapDiscovery

{

/**

* 构造方法检查PHP.INI设置

* soapDiscovery constructor.

*/

public function __construct()

{

if(ini_get('always_populate_raw_post_data')!=-1){

throw new Exception('php.ini setting always_populate_raw_post_data must be -1');

}

}

/**

* 生成 k="v" ... 的属性串

* @param $array array 属性键值数组

* @return string 属性串

*/

private function kvs(array $array)

{

$ret = '';

foreach ($array as $k => $v) {

$ret .= ' ' . $k . '="' . $v . '"';

}

return $ret;

}

/**

* 生成一个标签

* @param $name string 标签名称

* @param $open bool 是否开放标签(闭合标签自带/>)

* @param array $properties 属性键值数组

* @return string 标签的字符串表达

*/

private function tag($name, $open, array $properties)

{

return 'kvs($properties) . ($open ? '' : '/') . '>' . "\n";

}

/**

* 生成WSDL

* @param string $class_name 服务类名

* @param string $service_name 服务名称

* @param string $location 提供服务的地址

* @return string

* @throws

**/

public function getWSDL($class_name, $service_name, $location)

{

//对处理响应的类 反射

$class = new ReflectionClass($class_name);

if (!$class->isInstantiable()) {

throw new Exception('Class is not instantiable.');

}

//换行符

$n = "\n";

$schemas = 'http://schemas.xmlsoap.org/';

//头部空间定义

$headerWSDL = '' . $n;

$headerWSDL .= $this->tag('definitions', true, [

'name' => $service_name,

'targetNamespace' => 'urn:' . $service_name,

'xmlns:wsdl' => $schemas . 'wsdl/',

'xmlns:soap' => $schemas . 'wsdl/soap/',

'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',

'xmlns:soap-ENC' => $schemas . 'soap/encoding',

'xmlns' => $schemas . 'wsdl/'

]);

$headerWSDL .= $this->tag('types', false, ['xmlns' => $schemas . 'wsdl/']);

$portTypeWSDL = $this->tag('portType', true, ['name' => $service_name . 'Port']);

$bindingWSDL = $this->tag('binding', true, [

'name' => $service_name . 'Binding',

'type' => 'tns:' . $service_name . 'Port'

]) . $this->tag('soap:binding', false, [

'style' => 'rpc',

'transport' => $schemas . 'soap/http'

]);

$serviceWSDL = $this->tag('service', true, ['name' => $service_name])

. $this->tag('documentation', false, [])

. $this->tag('port', true, [

'name' => $service_name . 'Port',

'binding' => 'tns:' . $service_name . 'Binding'

]) . $this->tag('soap:address', false, ['location' => $location])

. '' . $n

. '' . $n;

$body = $this->tag('soap:body', false, [

'use' => 'encoded',

'namespace' => 'urn:' . $service_name,

'encodingStyle' => $schemas . 'soap/encoding/'

]);

$messageWSDL = '';

$methods = $class->getMethods();

foreach ($methods as $method) {

if (!$method->isPublic() or $method->isConstructor()) continue;

$methodName = $method->getName();

$portTypeWSDL .= $this->tag('operation', true, ['name' => $methodName])

. $this->tag('input', false, ['message' => 'tns:' . $methodName . 'Request'])

. $this->tag('output', false, ['message' => 'tns:' . $methodName . 'Response'])

. '' . $n;

$bindingWSDL .= $this->tag('operation', true, ['name' => $methodName])

. $this->tag('soap:operation', false, ['soapAction' => 'urn:' . $service_name . '#' . $class_name . '#' . $methodName])

. '' . $n

. $body

. '' . $n

. '' . $n

. $body

. '' . $n

. '' . $n;

$messageWSDL .= $this->tag('message', true, ['name' => $methodName.'Request']);

$parameters = $method->getParameters();

foreach ($parameters as $parameter) {

$messageWSDL .= $this->tag('part', false, [

'name' => $parameter->getName(),

'type' => 'xsd:string'

]);

}

$messageWSDL .= '' . $n

. $this->tag('message', true, ['name' => $methodName . 'Response'])

. $this->tag('part', false, ['name' => $methodName, 'type' => 'xsd:string'])

. "" . $n;

}

$portTypeWSDL .= "".$n;

$bindingWSDL .= "".$n;

return sprintf('%s%s%s%s%s%s', $headerWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, $messageWSDL, '');

}

}

3. 服务端 生成WSDL的代码如下

$soap = new soapDiscovery();

header("Content-type:text/xml");

//此处需要根据SAOP服务器地址进行修改

echo $soap->getWSDL('MSupervise', 'cmdService','http://www.tgj.com/supervise/process');

这里 的参数1, 是 你用来处理SOAP请求的类的名称,请事先加载类

参数2. 是 一个 服务名称的标识,请自行定义, 只要在服务端与客户端保持一致即可

参数3.  是处理SOAP请求的地址(服务端)

生成WSDL后,显示在浏览器上,  如果需要保存成文件 ,注意: 查看源代码后再复制保存.否则 会 丢失第一行XML定义

4.客户端 调用示例如下

public function test(){

ini_set("soap.wsdl_cache_enabled",0);

ini_set('soap.wsdl_cache_ttl',0);

$wsdl='http://www.tgj.com/wsdl/supervise.wsdl?wsdl';

$soap=new SSoapClient($wsdl,[

'uri'=>'cmdService',

'trace'=>1,

"style" => SOAP_RPC,

"use" => SOAP_ENCODED

]);

try{

$ret=$soap->command();

dump($ret);

}catch(Exception $e){

dump($e);

}

}  其中 两行ini_set在开发调试时使用,上线时去除.

$wsdl是一个可以访问到 服务端保存的那个WSDL文件 的地址

uri是服务标识符,要与服务端那个标识符保持一致

5.如果程序运行不通, 调试会比较麻烦

我查找 网上资料后得到 一个方法,扩展了 SOAPClient类

/**

* 扩展SOAPClient类,以便加调试代码

* User: 蓝冰

* Date: 2017/5/25

* Time: 11:44

*/

class SSoapClient extends SoapClient

{

public function __doRequest($request, $location, $action, $version, $one_way = 0)

{

$request = parent::__doRequest($request, $location, $action, $version, $one_way);

//dump($request);exit;

return $request;

}

}     在调用时,使用这个子类, 即可在这个扩展类中加入打印等调试语句

 类似资料: