标签归档:soap

PHP函数参考 – Web服务 – SOAP

PHP的Web服务SOAP扩展需要libxml的支持,跟http://blog.ifeeline.com/1157.html这里描述的一样。这里不再重复。

PHP的SOAP扩展支持SOAP1.1和SOAP1.2,它们都可以以WSDL和NO WSDL方式运行。

要使用PHP的SOAP扩展,需要在编译PHP时需要加入–enable-soap参数。由于SOAP会向客户端传递一个描述文件(使用wsdl时),可以把描述文件缓存起来,相关的配置(以下是默认值):

soap.wsdl_cache_enabled	1	
soap.wsdl_cache_dir	/tmp	
soap.wsdl_cache_ttl	86400	
soap.wsdl_cache		1	
soap.wsdl_cache_limit	5

在测试时最好把soap.wsdl_cache_enabled设置为0。

PHP中的SOAP可分两部分,一部分是作为客户端是消费,一部分是作为服务端提供服务。本文主要探讨客户端:

$webservice_url = "http://******/services/order?wsdl";
$userToken = '******';

$client = new SoapClient($webservice_url);

print_r($client->__getFunctions());
print_r($client->__getTypes());

这里拿了个现成的例子测试,看看都有哪些函数和类型:

/usr/local/php-5.5.15/bin/php soap.php 
Array
(
    [0] => deleteOrderResponse deleteOrder(string $userToken, long $orderId)
    [1] => auditOrderResponse auditOrder(string $userToken, long $orderId)
    [2] => createOrderResponse createOrder(string $userToken, createOrderRequest $createOrderRequest)
    [3] => createOrderResponse createAndAuditOrder(string $userToken, createOrderRequest $createOrderRequest)
    [4] => getTransportWayListResponse getTransportWayList(string $userToken)
)
Array(......)

这里看到服务端提供了哪些API以及如何调用这些API,还有这些API要发送的数据结构和返回的数据结构也有清晰定义。这个是如何做到的?

实际上,__getFunctions()和__getTypes()函数只是解析从服务端返回的XML文件(WSDL)而已。服务端的程序需要构建这个XML文档并定义对应的可调用的方法。参看下图:

在构建SoapClient对象时就可以传递服务地址(wsdl),也可以调用SoapClient::__setLocation指定;通过调用SoapClient::__setCookie设置随SOAP请求一起发送的cookie;通过调用SoapClient::__setSoapHeaders设置SOAP头部信息,注意这个不是请求的头部信息,是Soap的头部,在发起请求时,实际传递一个XML字符串,PHP SOAP扩展提供了一个专门的SoapHeader类,可以自定义一些信息作为XML字符串的一部分发送:

$client = new SoapClient($webservice_url,array('trace' => 1));
$header = new SoapHeader('http://soapinterop.org/echoheader/', 
                            'echoMeStringRequest',
                            'hello world');
$client->__setSoapHeaders($header);

echo $client->__getLastRequest();

这个会输出:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://service.hop.service.ws.hlt.com/" xmlns:ns2="http://soapinterop.org/echoheader/"><SOAP-ENV:Header><ns2:echoMeStringRequest>hello world</ns2:echoMeStringRequest></SOAP-ENV:Header><SOAP-ENV:Body><ns1:getTransportWayList><userToken>2a924b2173d845dab94054223a110339</userToken></ns1:getTransportWayList></SOAP-ENV:Body></SOAP-ENV:Envelope>

注意看这里的SOAP-ENV:Header标签,跟SOAP-ENV:Body并列。具体需要参看SoapHeader类。

继续看如下例子:

$webservice_url = "http://******/services/order?wsdl";
$userToken = '******';

$client = new SoapClient($webservice_url,array('trace' => 1));
$something = $client->getTransportWayList($userToken);

echo "\n----\n".$client->__getLastRequestHeaders();
echo "\n----\n".$client->__getLastRequest();
echo "\n----\n".$client->__getLastResponseHeaders();
echo "\n----\n".$client->__getLastResponse();

这里的四个函数主要是查看请求头部和请求内容 和 响应头部和响应内容,需要注意的是如果要使用这四个方法有效,必须在建立SoapClient对象时,它的第二参数的数组有trace为true,比如array((‘trace’ => 1))。

输出:

----
POST /xms/services/order HTTP/1.1
Host: ****:8086
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.5.15
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 326


----
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://service.hop.service.ws.hlt.com/"><SOAP-ENV:Body><ns1:getTransportWayList><userToken>*****5dab9******</userToken></ns1:getTransportWayList></SOAP-ENV:Body></SOAP-ENV:Envelope>

----
HTTP/1.1 200 OK
Server: nginx/1.4.4
Date: Mon, 11 Aug 2014 10:41:55 GMT
Content-Type: text/xml;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: JSESSIONID=6AF7237052D518B02B37D45CF9F84120; Path=/xms/; HttpOnly

----
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns1:getTransportWayListResponse xmlns:ns1="http://service.hop.service.ws.hlt.com/"><return><success>true</success>......

头部输出没有什么特别的,就是HTTP的请求和响应头,不过要注意Content-Type,它是text/xml。请求体是一个XML字符串,里面包含了需要调用的方法和方法的参数。响应体也是一个XML,里面包含了响应的数据。实际我们在调用方法时,SOAP扩展会把请求转换成XML请求体,而服务端收到后把XML进行解析,然后调用对应方法,而返回的XML数据在客户端收到后也进行了对应的转换。

下面谈一下具体的方法调用。

以上代码有:

$client->getTransportWayList($userToken);

实际上,SoapClient()类并没有getTransportWayList()方法,这个方法是来自服务端的,通过调用SoapClient::__getFunctions方法可以看到这个方法,这里这个方法的调用告诉我们,通过wsdl文件暴露的方法,都可以通过SoapClient类对象直接调用,这个调用内部会转换成一个发送XML的HTTP请求。getTransportWayList()这类来自服务端的方法也可以通过调用SoapClient::__soapCall来间接调用。

SoapClient最后需要了解的方法是SoapClient::__doRequest,自己的类可以继承SoapClient然后重写这个方法,那么就可以实现自定义发送请求的操作,默认是自动的(调用方法就开始)。

客户端在调用方法时如果发生了错误该如何捕获?PHP SOAP提供了一个is_soap_fault()的方法,方法参数是调用的结果。需要首先知道的是,SOAP的调用如果发生错误,那么它将抛出一个SoapFault对象的异常,但是如果在创建SoapClient对象时如果第二参数的数组指定了exception为false,比如array(‘exceptions’ => 0),那么当SOAP的调用发生错误时直接返回SoapFault对象,它封装了相关的错误信息。以下官方的例子:

<?php
$client = new SoapClient("some.wsdl", array('exceptions' => 0));
$result = $client->SomeFunction();
if (is_soap_fault($result)) {
    trigger_error("SOAP Fault: (faultcode: {$result->faultcode}, faultstring: {$result->faultstring})", E_USER_ERROR);
}
?>

#################################
<?php
try {
    $client = new SoapClient("some.wsdl");
    $result = $client->SomeFunction(/* ... */);
} catch (SoapFault $fault) {
    trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_USER_ERROR);
}
?>

SOAP的服务器端部分如果使用WSDL,主要是这个文件的编写,鉴于PHP习惯用来作为SOAP的客户端,所以这里不探讨PHP SOAP的服务端的内容了,附上一篇之前写的文章作为参考:PHP Web服务 SOAP 快速入门

原创文章,转载务必保留出处。
永久链接:http://blog.ifeeline.com/1159.html

Magento 1.7.x 获取获取全部API

$client = new SoapClient('http://magento.vfeelit.com/api/v2_soap/?wsdl');
	
$session = $client->login('vfeelit', '1234567890');
$result = $client->resources($session);
print_r($result);

数组打印:

Array
(
    [0] => stdClass Object
        (
            [title] => Store API
            [name] => core_store
            [aliases] => Array
                (
                    [0] => store
                )

            [methods] => Array
                (
                    [0] => stdClass Object
                        (
                            [title] => Retrieve store list
                            [path] => core_store.list
                            [name] => list
                            [aliases] => Array
                                (
                                    [0] => store.list
                                )

                        )

                    [1] => stdClass Object
                        (
                            [title] => Retrieve store data
                            [path] => core_store.info
                            [name] => info
                            [aliases] => Array
                                (
                                    [0] => store.info
                                )

                        )

                )

        )

    [1] => stdClass Object

输出的数组元素都是一个stdClass。看看和V1的差别:

$client = new SoapClient('http://magento.vfeelit.com/api/soap/?wsdl');
	
$session = $client->login('vfeelit', '1234567890');
$result = $client->resources($session);
print_r($result);

数组打印:

Array
(
    [0] => Array
        (
            [title] => Store API
            [description] => 
            [name] => core_store
            [aliases] => Array
                (
                    [0] => store
                )

            [methods] => Array
                (
                    [0] => Array
                        (
                            [title] => Retrieve store list
                            [description] => 
                            [path] => core_store.list
                            [name] => list
                            [aliases] => Array
                                (
                                    [0] => store.list
                                )

                        )

                    [1] => Array
                        (
                            [title] => Retrieve store data
                            [description] => 
                            [path] => core_store.info
                            [name] => info
                            [aliases] => Array
                                (
                                    [0] => store.info
                                )

                        )

                )

        )

    [1] => Array

v1 API输出全部使用数组组织,v2 API是使用stdClass包装,说明版本1 和 2不兼容。

永久链接:http://blog.ifeeline.com/560.html
原创文章,转载务必保留出处。

Magento API 使用

到后台建立API用户,System->Web Services->SOAP XMP-RPC/Roles和Users。

内容来自:http://www.magentocommerce.com/api/soap/introduction.html

Introduction
The Magento SOAP v1 API provides you with the ability to manage your eCommerce stores by providing calls for working with resources such as customers, categories, products, and sales orders. It also allows you to manage shopping carts and inventory.

A SOAP v2 API version has been available since Magento 1.3, and a WS-I compliant version has been available since Magento 1.6. 从Magento 1.3开始,SOAP v2 API可用,从Magento1.6版本开始WS-I兼容版本可用。

Supported Types 支持的类型

The Magento API supports SOAP and XML-RPC, where SOAP is the default protocol. 支持SOAP和XML-RPC,SOAP作为默认的协议。

>SOAP

To connect to Magento SOAP web services, load the WSDL into your SOAP client from either of these URLs: 把WSDL加载到客户端以链接上Magento SOAP Web服务:

http://domain.com/api/soap/?wsdl
//由于默认使用soap,所以也可以使用如下链接
http://domain.com/api/?wsdl

As of v1.3, you may also use the following URL to access the Magento API v2, which has been added to improve compatibility with Java and .NET: Magento 1.3以后,可以使用如下URL使用Magento API v2:

http://magentohost/api/v2_soap?wsdl=1

>XML-RPC
To use XML-RPC, load the following URL into your XML-RPC client:

http://magentohost/api/xmlrpc/

The following PHP example shows how to make XML-RPC calls:例子

$client = new Zend_XmlRpc_Client('http://magentohost/api/xmlrpc/');

// If somestuff requires api authentification,
// we should get session token
$session = $client->call('login', array('apiUser', 'apiKey'));

$client->call('call', array($session, 'somestuff.method', array('arg1', 'arg2', 'arg3')));
$client->call('call', array($session, 'somestuff.method', 'arg1'));
$client->call('call', array($session, 'somestuff.method'));
$client->call('multiCall', array($session,
     array(
        array('somestuff.method', 'arg1'),
        array('somestuff.method', array('arg1', 'arg2')),
        array('somestuff.method')
     )
));

// If you don't need the session anymore
$client->call('endSession', array($session));

The XML-RPC only supports the version 1 of the Magento API. XML-RPC只支持 Magento API 版本1(说明未来主要是SOAP)

API Methods

The following table contains the API methods that can be called from your SOAP or XML-RPC client on the Magento v1 API.

Method Description Return Value
startSession() Start the API session and return session ID. string
endSession(sessionId) End the API session. boolean
login(apiUser, apiKey) Start the API session, return the session ID, and authorize the API user. string
call(sessionId, resourcePath,array arguments) Call the API resource that is allowed in the current session. See Note below. mixed
multiCall(sessionId, array calls,array options) Call the API resource’s methods that are allowed for current session. See Notes below. array
resources(sessionId) Return a list of available API resources and methods allowed for the current session. array
globalFaults(sessionId) Return a list of fault messages and their codes that do not depend on any resource. array
resourceFaults(sessionId, resourceName) Return a list of the specified resource fault messages, if this resource is allowed in the current session. array

The Magento SOAP API v2 does not support the call() and multiCall() methods, and instead provides a separate method for each API resource. SOAP API 版本2不支持call()和mutiCall()方法(这些方法非常不优雅,版本2提供了一种优雅的方法)

Global API Faults

Fault Code Fault Message
0 Unknown Error
1 Internal Error. Please see log for details.
2 Access denied.
3 Invalid api path.
4 Resource path is not callable.

SOAP API Version v2
Since Magento 1.3, version v2 of the SOAP API has also been available. The main difference between v1 and v2 is that instead of using methods call and multiCall, it has separate methods for each action. 主要不同是不使用call和muticall:

// SOAP  v1
$params = array(array(
    'status'=>array('eq'=>'pending'),
    'customer_is_guest'=>array('eq'=>'1'))
));
$result = $client->call($sessionId, 'sales_order.list', $params);

// v2
$params = array('filter' => array(
    array('key' => 'status', 'value' => 'pending'),
    array('key' => 'customer_is_guest', 'value' => '1')
));
$result = $client->salesOrderList($sessionId, $params);

Note that the WSDL for SOAP v1 and SOAP v2 are different. Note that in SOAP v1, customizing the API did not involve changing the WSDL. In SOAP v2, changes to the WSDL are required. 针对SOAP v1 and SOAP v2的WSDL是不同的。

You can configure the SOAP v2 API to be WS-I compliant in the system configuration menu. To do this, set Services > Magento Core API > WS-I Compliance to Yes. 可以在后台配置WS-I兼容。

Note that the WSDL for the SOAP v2 API is different when in WS-I compliant mode.

Using the WS-I compliant SOAP v2 API WSDL, it is easy to automatically generate client classes for Java, .NET, and other languages using standard libraries. 启用了WS-I兼容可以为Jave .NET等自动创建客户端类。

永久链接:http://blog.ifeeline.com/556.html

PHP Web服务 SOAP 快速入门

PHP中的SOAP扩展支持SOAP1.1和SOAP1.2和WSDL 1.1。

这个扩展需要需要libxml,表示需要使用enable-libxml来启用,不过默认是开启的。如果要开启SOAP的支持,需要使用enable-soap选项来编译PHP。

SOAP配置选项:

soap.wsdl_cache_enabled	        1	是否开启WSDL缓存
soap.wsdl_cache_dir		/tmp	WSDL缓存目录
soap.wsdl_cache_ttl		86400	WSDL缓存过期时间
soap.wsdl_cache			1	WSDL缓存类型 1表示磁盘 2表示内存
soap.wsdl_cache_limit		5	在内存缓存的文件最大数

SoapClient类
SoapClient类提供了一个使用了SOAP 1.1、SOAP1.2服务器的客户端。可以使用WSDL和non-WSDL模式。

实例化一个SoapClient:

$soap = new SoapClient(null,array('location'=>'http://localhost/soap/Server.php','uri'=>'server_namespace'));

要发送SOAP请求,必须先实例化一个新的SOAPClient对象,并向构造函数传递相应Web服务的WSDL地址。WSDL(Web Services Description Language, Web服务描述语言)是一个XML词汇表,它可以让实现者创建一个定义它的Web服务都支持哪些方法和变量的文件。这个文件会放在Web服务器上供其他程序调用。

当让SOAP扩展指向一个WSDL文件时,这个扩展会自动地为相应的Web服务创建一个对象,而你可以像操作PHP类一样来操作这个对象。这个对象甚至能够知道每个方法都带什么参数,以及每个参数的类型。之所以这一点很重要,是因为SOAP与PHP不同,它是严格类型的。WSDL允许SOAP扩展把PHP变量强制转换成适当的类型。

如果需要向一个没有提供WSDL文件的服务器发送一个SOAP请求,必须自己指定必要的信息。像WSDL文件参数的位置传递一个null值,而主要的服务设置(如位置和名称空间URI)则以一个选项数组提供。

入门例子:

// 定义一个类 Calculate.php
class Calculate{
	 public function getResult($base = ''){
		
		for($i  = 1; $i<=100; $i++){
			$r += $i;
		}
		return (int)$base+$r;
	}
}

// 实现服务端 Server.php
require_once("Calculate.php");

$s = new SoapServer(null, array('uri'=>'Server_Namespace'));

$s->setClass("Calculate");
$s->handle();

// 客户端 Client.php
try{
	$soap = new SoapClient(null,array('location'=>'http://localhost/soap/Server.php','uri'=>'Server_Namespace'));
	
	echo $soap->getResult();
	echo "<br />";
	echo $soap->__soapCall('getResult',array());
	
	echo "<br /><br />";

	echo $soap->getResult(100);
	echo "<br />";
	echo $soap->__soapCall('getResult',array(100));

}catch(SoapFault $e){
	echo $e->getMessage();
}catch(Exception $e){
	echo $e->getMessage();	
}

输出:

5050
5050

5150
5150 

更多内容可以参考:http://www.php.net/manual/zh/book.soap.php

永久链接:http://blog.ifeeline.com/554.html
原创文章,转载务必保留出处。