提起php調用web service,在php4年代的人會立即想到用nusoap調用,這個nusoap是個好東東,不過年久未更新,恐其中會有眾多漏洞了,正好已經進入了php5年代了,調用web service用內建的擴充豈不快哉!
前提:開啟php5的web service擴充
環境需求:
This extension makes use of the GNOME xml library. Download and install this library. You will need at least libxml-2.5.4.
Linux下,
This extension is only available if PHP was configured with --enable-soap
Windows下:
php.ini檔案中 extension=php_soap.dll 去掉注釋即可
其次:調用實踐,以下是俺近期調用的算是一些總結吧
手冊摘錄:
SoapClient->__soapCall()
說明
class SoapClient {
mixed __soapCall ( string function_name, array arguments [, array options [, mixed input_headers [, array &output_headers]]] )
}
This is a low level API function that is used to make a SOAP call. Usually, in WSDL mode, you can simply call SOAP functions as SoapClient methods. This method useful in non-WSDL mode when soapaction is unknown, uri differs from the default or when sending and/or receiving SOAP Headers.
On error, a call to a SOAP function can cause PHP to throw exceptions or return a SoapFault object if exceptions are disabled. To check if the function call failed to catch the SoapFault exceptions, check the result with is_soap_fault().
傳回值
SOAP functions may return one, or multiple values. If only one value is returned by the SOAP function, the return value of __soapCall will be a simple value (e.g. an integer, a string, etc). If multiple values are returned, __soapCall will return an associative array of named output parameters.
範例
例 1. SoapClient->__soapCall() Examples
<?php
$client = new SoapClient("some.wsdl");
$client->SomeFunction($a, $b, $c);
$client->__soapCall("SomeFunction", array($a, $b, $c));
$client->__soapCall("SomeFunction", array($a, $b, $c), NULL,
new SoapHeader(), $output_headers);
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
'uri' => "http://test-uri/"));
$client->SomeFunction($a, $b, $c);
$client->__soapCall("SomeFunction", array($a, $b, $c));
$client->__soapCall("SomeFunction", array($a, $b, $c),
array('soapaction' => 'some_action',
'uri' => 'some_uri'));
?>
1.in WSDL mode,soapCall應用web service,例子用的是asp.net的web service,提供service.asmx頁面,調用及查看都比較簡單,手冊上的example也大多是這個類型,比較簡單
SOAP發送的協議:
POST /servicepath/service.asmx HTTP/1.1
Host: 211.186.1.4
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://211.186.5.15/Service/ServiceMethod"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ServiceMethod xmlns="http://211.186.5.15/Service">
<param1>string</param1>
<param2>string</param2>
<param3>string</param3>
</ServiceMethod>
</soap:Body>
</soap:Envelope>
調用方法:
$client = new SoapClient("http://www.xxx.com/service/service.asmx?WSDL");
//向SOAP服務方發送參數值
$param1 = "p1";
$param2 = "p2";
$param3 = "p3";
//serviceParam1,serviceParam2,serviceParam3為發送參數值所對應的參數名(或service端提供的欄位名)
$param = array('serviceParam1' => $param1,'serviceParam2' => $param2,'serviceParam3' => $param3);
//方法名為ServiceMethod,參數數組為$param,預設以parameters欄位標示傳遞的參數數組
$arr = $client->__soapCall('ServiceMethod',array('parameters' => $param));
print_r($arr);
2.in non-WSDL mode,這種情況下soapaction is unknown
SOAP發送協議
POST /services/SoapMethod?WSDL HTTP/1.1
Host: 220.211.1.12:8088
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.2.5
Content-Type: text/xml; charset=utf-8
SOAPAction: "urn:SoapMethod#ServiceMethod"
Content-Length: 1297
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:SoapMethod" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://220.211.1.12" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:ServiceMethod>
<ServiceMethodSection xsi:type="ns2:ServiceObjectType">
<param1 xsi:type="xsd:string">01019</param1>
<param2 xsi:type="xsd:long">10</param2>
<param3 xsi:type="xsd:long">0</param3>
<param4 xsi:type="xsd:long">11</param4>
</ServiceMethodSection>
</ns1:ServiceMethod>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
調用方法:
2.1傳遞一個參數:
try {
$client = new SoapClient(null,
array('location' => 'http://192.168.1.180:8088/services/SoapPage?WSDL','uri' => 'http://192.168.1.180:8088/services/'));
$result = $client->__soapCall('ServiceMethod', array('fieldName' => "data")); //以數組形式傳遞params
//$result = $client->__soapCall('ServiceMethod', array(new SoapParam("data", 'fieldName'))); //以構造服務端參數的形式構造參數傳遞給服務端
var_dump($result);
}
catch (Exception $e)
{
printf("Message = %s",$e->__toString());
}
附:手冊解釋
class SoapParam {
__construct ( mixed data, string name )
}
參數
data
The data to pass or return. You can pass this parameter directly as PHP value, but in this case it will be named as paramN and the SOAP Service may not understand it.
name
The parameter name
2.2傳遞多個參數:
如果服務端在non wsdl的情況下要求傳遞一個對象參數,該對象中包含多個屬性,則code如下
try {
$client = new SoapClient(null, array('location' => 'http://192.168.1.180:8088/services/SoapPage?WSDL','uri' => 'urn:SoapName')); //uri部分也可能是uri地址
class Obj{
public $param1 = '01019';
public $param2 = 10;
public $param3 = 0;
public $param4 = 11;
}
$struct = new Obj(); //建立服務端要求傳遞的對象
//如果服務端變態到傳遞的參數有的參數類型是你程式設計語言中沒有的資料類型,如本人用php,沒有Java的Long類型(一般做web service都要考慮到通用性,資料類型都是string或int型,而且我認為根本沒必要用Long類型。沒辦法服務端不改,只能我這邊改)就要將參數進行強制類型轉換處理,這樣的處理也只是在SOAP傳輸中將xml的參數類型替換成服務端所要求的類型名,並不是真實轉化傳遞的資料類型
$struct->param1 = iconv('gb2312','utf-8',$struct->param1);
$struct->param2 = new SoapVar($struct->param2,XSD_LONG);
$struct->param3 = new SoapVar($struct->param3,XSD_LONG);
$struct->param4 = new SoapVar($struct->param4,XSD_LONG);
//序列化對象中使用SoapVar的方法參考php手冊對SoapVar的解釋,每個參數都解釋的很清楚
$soapstruct = new SoapVar($struct, SOAP_ENC_OBJECT, "ServiceObjectType", "http://soapinterop.org/xsd"); //對象序列化,注意區分,SOAP對象的序列化不是用serialize
$result = $client-> ServiceMethod(new SoapParam($soapstruct, 'ServiceMethodSection'));
//$result = $client->__soapCall('ServiceMethod', array(new SoapParam($soapstruct, 'ServiceMethodSection')));
var_dump($result);
} catch (Exception $e) {
printf("Message = %s",$e->__toString());
}
附:PEAR Manual中找到的SoapVar的解釋
SoapVar
SoapVar -- Changes the Returntype of a variable
Description
new SoapVar (mixed variable, long type)
Warning
This function is EXPERIMENTAL. That means, that the behaviour of this function, the function name, in concreto ANYTHING documented here can change in a future release of this package WITHOUT NOTICE. Be warned, and use this function at your own risk.
You can change the return type of variable - so that it works better with non-PHP applications for example.
type should be one of the following
XSD_1999_TIMEINSTANT
XSD_STRING
XSD_BOOLEAN
XSD_DECIMAL
XSD_FLOAT
XSD_DOUBLE
XSD_DURATION
XSD_DATETIME
XSD_TIME
XSD_DATE
XSD_GYEARMONTH
XSD_GYEAR
XSD_GMONTHDAY
XSD_GDAY
XSD_GMONTH
XSD_HEXBINARY
XSD_BASE64BINARY
XSD_ANYURI
XSD_QNAME
XSD_NOTATION
XSD_NORMALIZEDSTRING
XSD_TOKEN
XSD_LANGUAGE
XSD_NMTOKEN
XSD_NAME
XSD_NCNAME
XSD_ID
XSD_IDREF
XSD_IDREFS
XSD_ENTITY
XSD_ENTITYS
XSD_INTEGER
XSD_NONPOSITIVEINTEGER
XSD_NEGATIVEINTEGER
XSD_LONG
XSD_INT
XSD_SHORT
XSD_BYTE
XSD_NONNEGATIVEINTEGER
XSD_UNSIGNEDLONG
XSD_UNSIGNEDINT
XSD_UNSIGNEDSHORT
XSD_UNSIGNEDBYTE
XSD_POSITIVEINTEGER
HTTP協議精解.rar
SOAP協議規範.rar