XML-RPC Web服务(XML-RPC Web Services)

XML-RPC 是一个著名的Web服务. Web 服务是一个工具,它可以再现有的网络基础设施上面设置分布式的应用程序。这些应用程序使用一种传输层的网络但是并不提供直接通过浏览器的人机界面。可扩展标记语言(XML)提供了描述远程过程调用(RPC)的词汇表,RPC是使用超文本传输协议(HTTP) 在计算机之间传输。实际上,RPC让各开发者自行定义网络调用中的接口。这些接口可以是很简单的一个函数调用也可以像大型API那样复杂.

XML-RPC 允许在两台或者更多运行不同操作系统和不同语言程序的计算机之间协同处理。比如,一个JAVA应用可以和一个Perl应用会谈,一个Perl应用可以同一个同ASP会谈的PYTHON应用会谈,等等。系统集成商往往在不同系统之间建立自己的连接,创建它们自己定义的格式的协议来进行通信,但是这造成了大量的不常使用的协议。RPC方法的程序员无需了解底层的协议、网络以及各种实施细则.

XML-RPC 可以同 Python, Java, Perl, PHP, C, C++, Ruby, Microsoft’s .NET 以及许多其他的编程语言来一起使用。它的实现被广泛用于 Unix, Linux, Windows 和 Macintosh 的平台.

一个 XML-RPC 调用实在双方之间进行的,客户端(调用程序)和服务器(被调用过程)。服务时提供在一个特定的URL上的,比如 (such as http://example.org:8080/rpcserv/).

上面我们只是接触了 XML-RPC 的表面. 我推荐 O’Reilly’s “Programming Web Service with XML-RPC” 进行进一步的学习。还可以阅读以下几个环节:

接口(InterFaces)

XML-RPC

XML-RPC 架构

OpenERP 基于C/S体系结构。服务器和客户端之间的通信使用XML-RPC协议。XML-RPC是一个非常简单的协议,它允许客户端进行远程过程调用。被调用的函数,它的参数,调用结果通过XML编码并且使用HTTP进行传输。欲了解更多的关于XML-RPC的详尽信息,请参阅: http://www.xml-rpc.com.

架构(Architecture)

下面的图标综合了OpenERP的客户端和服务器结构。OpenERP的服务器和客户端通信使用 XML-RPC.

/doc_static/6.0/_images/tech_arch.png

客户端

OpenERP 的逻辑实在服务器一段配置的。客户端是很简单的,它是仅用于POST的数据(forms, lists, trees)并且把结果发回服务器。新功能的更新和加入并不需要客户端的升级,这使得OpenERP更容易维护.

客户端并不明白POST的内容。即使像点击打印图标的行动时发送到服务器并且询问如何作出反应.

客户端的操作时很简单的,当客户发出一个动作(保存一个表格、打开一个目录、打印…)它发送动作到服务器。然后服务器执行客户端的请求并将结果发送回来.

下面是三种行为;

  • Open a window (form or tree)

  • Print a document

  • Execute a wizard

Python

通过 xml-rpc 获取数据

代码示例
  • 创建一个合伙人和他的地址
  1. import xmlrpclib
  2. username = 'admin' #the user
  3. pwd = 'admin' #the password of the user
  4. dbname = 'terp' #the database
  5. # Get the uid
  6. sock_common = xmlrpclib.ServerProxy ('http://localhost:8069/xmlrpc/common')
  7. uid = sock_common.login(dbname, username, pwd)
  8. #replace localhost with the address of the server
  9. sock = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/object')
  10. partner = {
  11. 'name': 'Fabien Pinckaers',
  12. 'lang': 'fr_FR',
  13. }
  14. partner_id = sock.execute(dbname, uid, pwd, 'res.partner', 'create', partner)
  15. address = {
  16. 'partner_id': partner_id,
  17. 'type' : 'default',
  18. 'street': 'Chaussée de Namur 40',
  19. 'zip': '1367',
  20. 'city': 'Grand-Rosière',
  21. 'phone': '+3281813700',
  22. 'fax': '+3281733501',
  23. }
  24. address_id = sock.execute(dbname, uid, pwd, 'res.partner.address', 'create', address)
  • 查询业务伙伴

    1. args = [('vat', '=', 'ZZZZZZ')] #query clause
    2. ids = sock.execute(dbname, uid, pwd, 'res.partner', 'search', args)
  • 读取业务伙伴数据

    1. fields = ['name', 'active', 'vat', 'ref'] #fields to read
    2. data = sock.execute(dbname, uid, pwd, 'res.partner', 'read', ids, fields) #ids is a list of id
  • 更新业务伙伴数据

    1. values = {'vat': 'ZZ1ZZZ'} #data to update
    2. result = sock.execute(dbname, uid, pwd, 'res.partner', 'write', ids, values)
  • 删除业务伙伴

    1. # ids : list of id
    2. result = sock.execute(dbname, uid, pwd, 'res.partner', 'unlink', ids)

PHP

JAVA

Download the XML-RPC framework for PHP

下载 XML-RPC PHP Library

windows / linux: download the xml-rpc framework for php from http://phpxmlrpc.sourceforge.net/ The latest stable release is version 2.2 released on February 25, 2007

配置 PHP XML-RPC Library

Download the xml-rpc framework for java from http://ws.apache.org/xmlrpc/ The latest stable release is version 3.1 released on August 12, 2007. All OpenERP errors throw exceptions because the framework allows only an int as the error code where OpenERP returns a string.

  • 获取OpenERP帐套列表
  1. function connect() {
  2. var $user = 'admin';
  3. var $password = 'admin';
  4. var $dbname = 'db_name';
  5. var $server_url = 'http://localhost:8069/xmlrpc/';
  6. if(isset($_COOKIE["user_id"]) == true) {
  7. if($_COOKIE["user_id"]>0) {
  8. return $_COOKIE["user_id"];
  9. }
  10. }
  11. $sock = new xmlrpc_client($server_url.'common');
  12. $msg = new xmlrpcmsg('login');
  13. $msg->addParam(new xmlrpcval($dbname, "string"));
  14. $msg->addParam(new xmlrpcval($user, "string"));
  15. $msg->addParam(new xmlrpcval($password, "string"));
  16. $resp = $sock->send($msg);
  17. $val = $resp->value();
  18. $id = $val->scalarval();
  19. setcookie("user_id",$id,time()+3600);
  20. if($id > 0) {
  21. return $id;
  22. }else{
  23. return -1;
  24. }
  25. }
  • 登陆OpenERP
  1. /**
  2. * $client = xml-rpc handler
  3. * $relation = name of the relation ex: res.partner
  4. * $attribute = name of the attribute ex:code
  5. * $operator = search term operator ex: ilike, =, !=
  6. * $key=search for
  7. */
  8. function search($client,$relation,$attribute,$operator,$keys) {
  9. var $user = 'admin';
  10. var $password = 'admin';
  11. var $userId = -1;
  12. var $dbname = 'db_name';
  13. var $server_url = 'http://localhost:8069/xmlrpc/';
  14. $key = array(new xmlrpcval(array(new xmlrpcval($attribute , "string"),
  15. new xmlrpcval($operator,"string"),
  16. new xmlrpcval($keys,"string")),"array"),
  17. );
  18. if($userId<=0) {
  19. connect();
  20. }
  21. $msg = new xmlrpcmsg('execute');
  22. $msg->addParam(new xmlrpcval($dbname, "string"));
  23. $msg->addParam(new xmlrpcval($userId, "int"));
  24. $msg->addParam(new xmlrpcval($password, "string"));
  25. $msg->addParam(new xmlrpcval($relation, "string"));
  26. $msg->addParam(new xmlrpcval("search", "string"));
  27. $msg->addParam(new xmlrpcval($key, "array"));
  28. $resp = $client->send($msg);
  29. $val = $resp->value();
  30. $ids = $val->scalarval();
  31. return $ids;
  32. }
  • 查询业务伙伴
  1. <?
  2. include('xmlrpc.inc');
  3. $arrayVal = array(
  4. 'name'=>new xmlrpcval('Fabien Pinckaers', "string") ,
  5. 'vat'=>new xmlrpcval('BE477472701' , "string")
  6. );
  7. $client = new xmlrpc_client("http://localhost:8069/xmlrpc/object");
  8. $msg = new xmlrpcmsg('execute');
  9. $msg->addParam(new xmlrpcval("dbname", "string"));
  10. $msg->addParam(new xmlrpcval("3", "int"));
  11. $msg->addParam(new xmlrpcval("demo", "string"));
  12. $msg->addParam(new xmlrpcval("res.partner", "string"));
  13. $msg->addParam(new xmlrpcval("create", "string"));
  14. $msg->addParam(new xmlrpcval($arrayVal, "struct"));
  15. $resp = $client->send($msg);
  16. if ($resp->faultCode())
  17. echo 'Error: '.$resp->faultString();
  18. else
  19. echo 'Partner '.$resp->value()->scalarval().' created !';
  20. ?>
  • 创建业务伙伴
  1. /**
  2. * $client = xml-rpc handler
  3. * $relation = name of the relation ex: res.partner
  4. * $attribute = name of the attribute ex:code
  5. * $operator = search term operator ex: ilike, =, !=
  6. * $id = id of the record to be updated
  7. * $data = data to be updated
  8. */
  9. function write($client,$relation,$attribute,$operator,$data,$id) {
  10. var $user = 'admin';
  11. var $password = 'admin';
  12. var $userId = -1;
  13. var $dbname = 'db_name';
  14. var $server_url = 'http://localhost:8069/xmlrpc/';
  15. $id_val = array();
  16. $id_val[0] = new xmlrpcval($id, "int");
  17. if($userId<=0) {
  18. connect();
  19. }
  20. $msg = new xmlrpcmsg('execute');
  21. $msg->addParam(new xmlrpcval($dbname, "string"));
  22. $msg->addParam(new xmlrpcval($userId, "int"));
  23. $msg->addParam(new xmlrpcval($password, "string"));
  24. $msg->addParam(new xmlrpcval($relation, "string"));
  25. $msg->addParam(new xmlrpcval("write", "string"));
  26. $msg->addParam(new xmlrpcval($id, "array"));
  27. $msg->addParam(new xmlrpcval($data, "struct"));
  28. $resp = $client->send($msg);
  29. $val = $resp->value();
  30. $record = $val->scalarval();
  31. return $record;
  32. }

更新业务伙伴数据

JAVA

Download the apache XML-RPC framework for JAVA

下载 JAVA XML-RPC Library

Download the xml-rpc framework for java from http://ws.apache.org/xmlrpc/ The latest stable release is version 3.1 released on August 12, 2007. All OpenERP errors throw exceptions because the framework allows only an int as the error code where OpenERP returns a string.

  • 代码示例
  1. import java.net.URL;
  2. import java.util.Vector;
  3. import org.apache.commons.lang.StringUtils;
  4. import org.apache.xmlrpc.XmlRpcException;
  5. import org.apache.xmlrpc.client.XmlRpcClient;
  6. import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
  7. public Vector<String> getDatabaseList(String host, int port)
  8. {
  9. XmlRpcClient xmlrpcDb = new XmlRpcClient();
  10. XmlRpcClientConfigImpl xmlrpcConfigDb = new XmlRpcClientConfigImpl();
  11. xmlrpcConfigDb.setEnabledForExtensions(true);
  12. xmlrpcConfigDb.setServerURL(new URL("http",host,port,"/xmlrpc/db"));
  13. xmlrpcDb.setConfig(xmlrpcConfigDb);
  14. try {
  15. //Retrieve databases
  16. Vector<Object> params = new Vector<Object>();
  17. Object result = xmlrpcDb.execute("list", params);
  18. Object[] a = (Object[]) result;
  19. Vector<String> res = new Vector<String>();
  20. for (int i = 0; i < a.length; i++) {
  21. if (a[i] instanceof String)
  22. {
  23. res.addElement((String)a[i]);
  24. }
  25. }
  26. catch (XmlRpcException e) {
  27. logger.warn("XmlException Error while retrieving OpenERP Databases: ",e);
  28. return -2;
  29. }
  30. catch (Exception e)
  31. {
  32. logger.warn("Error while retrieving OpenERP Databases: ",e);
  33. return -3;
  34. }
  35. }
  • 获取OpenERP帐套列表
  1. import java.net.URL;
  2. import org.apache.commons.lang.StringUtils;
  3. import org.apache.xmlrpc.XmlRpcException;
  4. import org.apache.xmlrpc.client.XmlRpcClient;
  5. import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
  6. public int Connect(String host, int port, String tinydb, String login, String password)
  7. {
  8. XmlRpcClient xmlrpcLogin = new XmlRpcClient();
  9. XmlRpcClientConfigImpl xmlrpcConfigLogin = new XmlRpcClientConfigImpl();
  10. xmlrpcConfigLogin.setEnabledForExtensions(true);
  11. xmlrpcConfigLogin.setServerURL(new URL("http",host,port,"/xmlrpc/common"));
  12. xmlrpcLogin.setConfig(xmlrpcConfigLogin);
  13. try {
  14. //Connect
  15. params = new Object[] {tinydb,login,password};
  16. Object id = xmlrpcLogin.execute("login", params);
  17. if (id instanceof Integer)
  18. return (Integer)id;
  19. return -1;
  20. }
  21. catch (XmlRpcException e) {
  22. logger.warn("XmlException Error while logging to OpenERP: ",e);
  23. return -2;
  24. }
  25. catch (Exception e)
  26. {
  27. logger.warn("Error while logging to OpenERP: ",e);
  28. return -3;
  29. }
  30. }
  • 登陆

    1. TODO
  • 查询业务伙伴

    1. TODO
  • 创建业务伙伴

    1. TODO

更新业务伙伴

Python 代码示例

  1. import xmlrpclib
  2. sock = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/object')
  3. uid = 1
  4. pwd = 'demo'
  5. partner = {
  6. 'title': 'Monsieur',
  7. 'name': 'Fabien Pinckaers',
  8. 'lang': 'fr',
  9. 'active': True,
  10. }
  11. partner_id = sock.execute(dbname, uid, pwd, 'res.partner', 'create', partner)
  12. address = {
  13. 'partner_id': partner_id,
  14. 'type': 'default',
  15. 'street': 'Rue du vieux chateau, 21',
  16. 'zip': '1457',
  17. 'city': 'Walhain',
  18. 'phone': '(+32)10.68.94.39',
  19. 'fax': '(+32)10.68.94.39',
  20. }
  21. sock.execute(dbname, uid, pwd, 'res.partner.address', 'create', address)

Example of creation of a partner and their address.

  1. sock = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/common')
  2. UID = sock.login('terp3', 'admin', 'admin')

To get the UID of a user, you can use the following script:

  1. """
  2. :The login function is under
  3. :: http://localhost:8069/xmlrpc/common
  4. :For object retrieval use:
  5. :: http://localhost:8069/xmlrpc/object
  6. """
  7. import xmlrpclib
  8. user = 'admin'
  9. pwd = 'admin'
  10. dbname = 'terp3'
  11. model = 'res.partner'
  12. sock = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/common')
  13. uid = sock.login(dbname ,user ,pwd)
  14. sock = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/object')
  15. # CREATE A PARTNER
  16. partner_data = {'name'.. code-block:: php:'Tiny', 'active':True, 'vat':'ZZZZZ'}
  17. partner_id = sock.execute(dbname, uid, pwd, model, 'create', partner_data)
  18. # The relation between res.partner and res.partner.category is of type many2many
  19. # To add categories to a partner use the following format:
  20. partner_data = {'name':'Provider2', 'category_id': [(6,0,[3, 2, 1])]}
  21. # Where [3, 2, 1] are id fields of lines in res.partner.category
  22. # SEARCH PARTNERS
  23. args = [('vat', '=', 'ZZZZZ'),]
  24. ids = sock.execute(dbname, uid, pwd, model, 'search', args)
  25. # READ PARTNER DATA
  26. fields = ['name', 'active', 'vat', 'ref']
  27. results = sock.execute(dbname, uid, pwd, model, 'read', ids, fields)
  28. print results
  29. # EDIT PARTNER DATA
  30. values = {'vat':'ZZ1ZZ'}
  31. results = sock.execute(dbname, uid, pwd, model, 'write', ids, values)
  32. # DELETE PARTNER DATA
  33. results = sock.execute(dbname, uid, pwd, model, 'unlink', ids)

CRUD(创建/读取/更新/删除)代码示例:

  1. PRINT(打印) 示例代码:

  2. PRINT INVOICE

  3. IDS is the invoice ID, as returned by:

  1. import time
  2. import base64
  3. printsock = xmlrpclib.ServerProxy('http://server:8069/xmlrpc/report')
  4. model = 'account.invoice'
  5. id_report = printsock.report(dbname, uid, pwd, model, ids, {'model': model, 'id': ids[0], 'report_type':'pdf'})
  6. time.sleep(5)
  7. state = False
  8. attempt = 0
  9. while not state:
  10. report = printsock.report_get(dbname, uid, pwd, id_report)
  11. state = report['state']
  12. if not state:
  13. time.sleep(1)
  14. attempt += 1
  15. if attempt>200:
  16. print 'Printing aborted, too long delay !'
  17. string_pdf = base64.decodestring(report['result'])
  18. file_pdf = open('/tmp/file.pdf','w')
  19. file_pdf.write(string_pdf)
  20. file_pdf.close()

PHP Example

This example shows how to insert a new partner using PHP. It uses the phpxmlrpc library, available on sourceforge.

  1. <?
  2. include('xmlrpc.inc');
  3. $arrayVal = array(
  4. 'name'=>new xmlrpcval('Fabien Pinckaers', "string") ,
  5. 'vat'=>new xmlrpcval('BE477472701' , "string")
  6. );
  7. $client = new xmlrpc_client("http://localhost:8069/xmlrpc/object");
  8. $msg = new xmlrpcmsg('execute');
  9. $msg->addParam(new xmlrpcval("dbname", "string"));
  10. $msg->addParam(new xmlrpcval("3", "int"));
  11. $msg->addParam(new xmlrpcval("demo", "string"));
  12. $msg->addParam(new xmlrpcval("res.partner", "string"));
  13. $msg->addParam(new xmlrpcval("create", "string"));
  14. $msg->addParam(new xmlrpcval($arrayVal, "struct"));
  15. $resp = $client->send($msg);
  16. if ($resp->faultCode())
  17. echo 'Error: '.$resp->faultString();
  18. else
  19. echo 'Partner '.$resp->value()->scalarval().' created !';
  20. ?>

Here is an example on how to insert a new partner using PHP. This example makes use the phpxmlrpc library, available on sourceforge.

Perl 代码示例

  1. #!c:/perl/bin/perl
  2. # 17-02-2010
  3. # OpenERP XML RPC communication example
  4. # Todor Todorov <todorov@hp.com> <tttodorov@yahoo.com>
  5. use strict;
  6. use Frontier::Client;
  7. use Data::Dumper;
  8. my($user) = 'admin';
  9. my($pw) = 'admin';
  10. my($db) = 'put_your_dbname_here';
  11. my($model) = 'res.partner';
  12. #login
  13. my $server_url = 'http://localhost:8069/xmlrpc/common';
  14. my $server = Frontier::Client->new('url' => $server_url);
  15. my $uid = $server->call('login',$db,$user,$pw);
  16. print Dumper($uid);
  17. my $server_url = 'http://localhost:8069/xmlrpc/object';
  18. my $server = Frontier::Client->new('url' => $server_url);
  19. print Dumper($server);
  20. #
  21. # CREATE A PARTNER
  22. #
  23. my $partner_data = {'name'=>'MyNewPartnerName',
  24. 'active'=> 'True',
  25. 'vat'=>'ZZZZZ'};
  26. my $partner_id = $server->call('execute',$db, $uid, $pw, $model, 'create', $partner_data);
  27. print Dumper($partner_id);
  28. #
  29. # SEARCH PARTNERS
  30. #
  31. my $query = [['vat', '=', 'ZZZZZ']];
  32. print Dumper($query);
  33. my $ids = $server->call('execute',$db, $uid, $pw, $model, 'search', $query);
  34. print Dumper($ids);
  35. #Here waiting for user input
  36. #OpenERP interface my be checked if partner is shown there
  37. print $/."Check OpenERP if partner is inserted. Press ENTER".$/;
  38. <STDIN>;
  39. #
  40. # DELETE PARTNER DATA
  41. #
  42. my $results = $server->call('execute',$db, $uid, $pw, $model, 'unlink', $ids);
  43. print Dumper($results);

Here is an example in Perl for creating, searching and deleting a partner.