odoo12-webservice接口开发
Urllib模块
- 从指定的url获取数据
- 对URL字符串进行格式化处理
1.urllib.request(为打开url提供的可扩展类库)
urllib.request模块定义了方法和类,帮助打开url(主要是HTTP)在一个复杂的世界–基本和摘要式身份验证,重定向,cookies等等。
urllib.request模块定义了以下功能:
urllib.request.urlopen()
类urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None),这个类是一个抽象的URL请求。
2.函数urlopen(url, data=None, proxies=None)
(1)参数说明:
① url : 符合URL规范的字符串(包括http,ftp,gopher,local-file标准)
② data : 向指定的URL发送的数据字符串,GET和POST都可,但必须符合标准格式格式为key=value&key1=value1…
③ proxies : 代理服务器地址字典,如果未指定,在WINDOWS平台上则依据IE的设置不支持需要验证的代理服务器。例如:proxies = {‘http’: ‘http://www.someproxy.com:3128’},该例子表示一个http代理服务器http://www.someproxy.com:3128
(2)函数实现说明:
该函数使用类FancyURLopener从URLopener继承来的open方法执行具体的操作。
(3)返回值:
返回一个类似文件对象的对象(file_like) object,该对象拥有的方法为: read(),readline() , readlines() ,fileno() ,close() 。
以上方法同file object的类似方法的使用方法基本一致, info()返回从服务器传回的MIME标签头。 geturl()返回真实的URL,之所以称为真实,是因为对于某些重定向的URL,将返回被重定后的。
xml.etree.ElementTree模块
xml.etree.ElementTree模块实现了一个简单而高效的API用于解析和创建XML数据
1、XML tree and elements
XML是一种固有的分层数据格式,最自然的表示方法是使用树。ET有两个类为此目的—ElementTree表示整个XML文档为树,元素表示此树中的单个节点。与整个文档的交互(读取和写入文件)通常是在ElementTree级别上完成的。与单个XML元素及其子元素的交互是在元素级别上完成的。
2、解析XML文件
可以通过读取文件来导入这些数据
root有一个标签和一个属性字典,它也有子节点,我们可以迭代或者通过索引访问他的孩子节点,下面介绍几种访问元素和标签的方法。
① Element.findall(): 只找到带有标签的元素,该标签是当前元素的直接子元素。
② Element.find() :找到第一个带有特定标签的子元素。
③ Element.text:访问标签的内容
④ Element.get():访问标签的属性值
接口开发的整体流程
1.导入所需模块
import xml.etree.ElementTree as ET
import urllib
2.创建接口后台表
class ChinkAndChangeInterfaceWebservice(models.Model):
_name = 'check.and.change.interface.web.service'
_description = 'Check And Change Interface Web Service'
# 入住单id
check_in_id = fields.Many2one(comodel_name='cms.check.in')
# 变更单
change_id = fields.Many2one(comodel_name='cms.service.change.document')
# 返回的结果
result_id = fields.Integer()
# OA流程发起人id
creator_id = fields.Integer()
3.获取dict格式数据,业务取值部分可忽略不看
head_vals = {
'creator_id':creator_id,
'source_id':doc_id.id,
'source_type':'01' if model=='cms.check.in' else '02',
'company':doc_id.company_id.full_name,
'person':self.env.user.employee_ids[0].name,
'apply_time':fields.Datetime.now(),
'senior':doc_id.senior_id.senior_name,
'age':doc_id.age,
'condition':res['current_living_situation'][condition] if condition else '',
'guardian':guardian.emergency_contact_name if guardian else '',
'guardian_tel':guardian.mobile_phone if guardian else '',
'type':self.get_trans(doc_id.in_type,doc_id.in_type.name,'name'),
'bed':','.join(name_array),
'in_date':doc_id.expect_in_time if model == 'cms.check.in' else '',
'service_package':service_package.package_name,
'food_type':self.get_trans(food_type_id,food_type_id.name,'name'),
'lsspyj':','.join(opinion_str),
'note': note
}
4.拼接请求报文,根据对方提供的报文格式拼接。
head_message ='''
<WorkflowRequestInfo>
<requestName>%(doc_name)s</requestName>
<requestLevel>0</requestLevel>
<workflowBaseInfo>
<workflowId>%(workflow_id)s</workflowId>
</workflowBaseInfo>
<creatorId>%(creator_id)s</creatorId>
<canView>false</canView>
<canEdit>false</canEdit>
<mustInputRemark>false</mustInputRemark>
<needAffirmance>false</needAffirmance>
<workflowMainTableInfo>
<requestRecords>
<weaver.workflow.webservices.WorkflowRequestTableRecord>
<recordOrder>0</recordOrder>
<workflowRequestTableFields>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>source_id</fieldName>
<fieldValue>%(source_id)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>source_type</fieldName>
<fieldValue>%(source_type)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>company</fieldName>
<fieldValue>%(company)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>person</fieldName>
<fieldValue>%(person)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>apply_time</fieldName>
<fieldValue>%(apply_time)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>senior</fieldName>
<fieldValue>%(senior)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>age</fieldName>
<fieldValue>%(age)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>condition</fieldName>
<fieldValue>%(condition)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>guardian</fieldName>
<fieldValue>%(guardian)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>guardian_tel</fieldName>
<fieldValue>%(guardian_tel)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>assess_time</fieldName>
<fieldValue>%(assess_time)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>care_level</fieldName>
<fieldValue>%(care_level)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>cognitive_level</fieldName>
<fieldValue>%(cognitive_level)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>care_area</fieldName>
<fieldValue>%(care_area)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>type</fieldName>
<fieldValue>%(type)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>bed</fieldName>
<fieldValue>%(bed)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>in_date</fieldName>
<fieldValue>%(in_date)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>service_package</fieldName>
<fieldValue>%(service_package)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>food_type</fieldName>
<fieldValue>%(food_type)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>lsspyj</fieldName>
<fieldValue>%(lsspyj)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>note</fieldName>
<fieldValue>%(note)s</fieldValue>
<fieldOrder>1</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
</workflowRequestTableFields>
</weaver.workflow.webservices.WorkflowRequestTableRecord>
</requestRecords>
</workflowMainTableInfo>
'''
head_message = head_message.replace('%(doc_name)s', doc_name)
head_message = head_message.replace('%(workflow_id)s',str(107) if model == 'cms.check.in' else str(108))
head_message = head_message.replace('%(source_id)s', str(head_vals['source_id']))
head_message = head_message.replace('%(creator_id)s', str(head_vals['creator_id']))
head_message = head_message.replace('%(source_type)s', head_vals['source_type'])
head_message = head_message.replace('%(company)s', head_vals['company'])
head_message = head_message.replace('%(person)s', head_vals['person'])
head_message = head_message.replace('%(apply_time)s', datetime.strftime(head_vals['apply_time'],DEFAULT_SERVER_DATETIME_FORMAT))
head_message = head_message.replace('%(senior)s', head_vals['senior'])
head_message = head_message.replace('%(age)s', str(head_vals['age']))
head_message = head_message.replace('%(condition)s', head_vals['condition'])
head_message = head_message.replace('%(guardian)s', head_vals['guardian'])
head_message = head_message.replace('%(guardian_tel)s', head_vals['guardian_tel'])
head_message = head_message.replace('%(assess_time)s', datetime.strftime(head_vals['assess_time'],DEFAULT_SERVER_DATETIME_FORMAT) if head_vals['assess_time'] else '')
head_message = head_message.replace('%(care_level)s', head_vals['care_level'])
head_message = head_message.replace('%(cognitive_level)s', head_vals['cognitive_level'])
head_message = head_message.replace('%(care_area)s', head_vals['care_area'])
head_message = head_message.replace('%(type)s', head_vals['type'])
head_message = head_message.replace('%(bed)s', head_vals['bed'])
head_message = head_message.replace('%(in_date)s',datetime.strftime(head_vals['in_date'],DEFAULT_SERVER_DATETIME_FORMAT) if \
head_vals['in_date'] else '')
head_message = head_message.replace('%(service_package)s', head_vals['service_package'])
head_message = head_message.replace('%(food_type)s', head_vals['food_type'])
head_message = head_message.replace('%(lsspyj)s', head_vals['lsspyj'])
head_message = head_message.replace('%(note)s', head_vals['note'])
行数据拼接:
for line in doc_id.cms_charge_line_ids:
line_vals.append({
'head_id':doc_id.id,
'lastest_item':line.charge_item_id.item_name,
'lastest_list_price':str(line.price_list)+'/'+res['unit'][line.unit],
'lastest_base_price':str(line.headquarters_floor_price)+'/'+res['unit'][line.unit],
'lastest_actual_price':str(line.actual_price)+'/'+res['unit'][line.unit],
'formal_item': '',
'formal_list_price': '',
'formal_base_price': '',
'formal_actual_price': '',
})
报文拼接:
line_data = '''
'''
for l in line_vals:
line_data_message = '''
<weaver.workflow.webservices.WorkflowRequestTableRecord>
<recordOrder>0</recordOrder>
<workflowRequestTableFields>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>head_id</fieldName>
<fieldValue>%(head_id)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>formal_item</fieldName>
<fieldValue>%(formal_item)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>formal_list_price</fieldName>
<fieldValue>%(formal_list_price)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>formal_base_price</fieldName>
<fieldValue>%(formal_base_price)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>formal_actual_price</fieldName>
<fieldValue>%(formal_actual_price)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>lastest_item</fieldName>
<fieldValue>%(lastest_item)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>lastest_list_price</fieldName>
<fieldValue>%(lastest_list_price)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>lastest_base_price</fieldName>
<fieldValue>%(lastest_base_price)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
<weaver.workflow.webservices.WorkflowRequestTableField>
<fieldName>lastest_actual_price</fieldName>
<fieldValue>%(lastest_actual_price)s</fieldValue>
<fieldOrder>0</fieldOrder>
<isView>true</isView>
<isEdit>true</isEdit>
<isMand>false</isMand>
</weaver.workflow.webservices.WorkflowRequestTableField>
</workflowRequestTableFields>
</weaver.workflow.webservices.WorkflowRequestTableRecord>
'''
line_data_message = line_data_message.replace('%(head_id)s', str(l['head_id']))
line_data_message = line_data_message.replace('%(formal_item)s', l['formal_item'])
line_data_message = line_data_message.replace('%(formal_list_price)s', l['formal_list_price'])
line_data_message = line_data_message.replace('%(formal_base_price)s', l['formal_base_price'])
line_data_message = line_data_message.replace('%(formal_actual_price)s', l['formal_actual_price'])
line_data_message = line_data_message.replace('%(lastest_item)s', l['lastest_item'])
line_data_message = line_data_message.replace('%(lastest_list_price)s', l['lastest_list_price'])
line_data_message = line_data_message.replace('%(lastest_base_price)s', l['lastest_base_price'])
line_data_message = line_data_message.replace('%(lastest_actual_price)s', l['lastest_actual_price'])
line_data += line_data_message
头行报文拼接:
line_message = '''
<workflowDetailTableInfos>
<weaver.workflow.webservices.WorkflowDetailTableInfo>
<workflowRequestTableRecords>
''' + line_data + '''
</workflowRequestTableRecords>
</weaver.workflow.webservices.WorkflowDetailTableInfo>
</workflowDetailTableInfos>
</WorkflowRequestInfo>
'''
处理拼接报文请求头:
message = head_message + line_message
message = message.replace('<','<')
message = message.replace('>', '>')
texturl = 'http://123.56.238.154:8090/services/WorkflowServiceXml'
postcontent = '''<?xml version="1.0" encoding="utf-8"?>'''
postcontent += '''
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="webservices.services.weaver.com.cn" xmlns:web1="http://webservices.workflow.weaver">
'''
postcontent +="<soapenv:Header/> "
postcontent +="<soapenv:Body>"
postcontent +="<web:doCreateWorkflowRequest>"
postcontent +="<web:in0>" + message + "</web:in0>" # 参数
postcontent +="<web:in1>1</web:in1>"
postcontent +="</web:doCreateWorkflowRequest>"
postcontent +="</soapenv:Body>"
postcontent +="</soapenv:Envelope>"
发送请求,获取返回值,如果报错创建接口错误数据记录
req = urllib.request.Request(texturl, data=postcontent.encode('utf-8'), headers={'Content-Type': 'text/xml'})
response = urllib.request.urlopen(req)
result = response.read()
result_code = ET.fromstring(result).findall(".//{webservices.services.weaver.com.cn}out")
if result_code and result_code[0] != None:
result_code = result_code[0].text
else:
raise ValidationError("同步OA接口报错,请检查后重试。")
self.create({
'check_in_id':doc_id.id if model == 'cms.check.in' else None,
'change_id':doc_id.id if model != 'cms.check.in' else None,
'result_id':int(result_code) if result_code !=0 else None,
'creator_id':int(creator_id)
})
return int(result_code)
开发中遇到的问题:
在本地调试时,对方接口能顺利调通,并且请求完成后能顺利拿到对方返回信息,测试无误后部署到测试环境,却一直报错报文格式有误。同样的报文在本地调试没有问题,放到环境上却调试不同,在本地打断点已无法找到错误信息,只能在环境日志里print出请求报文,发现不管传输多少数据总是会丢失最后几行,尝试多次后发现,在环境上ping请求url,居然ping不通!原因是对方系统对请求方做了限制,让对方将测试ip加入白名单后,可顺利调通。