☰
OA统一待办中心Webservice接口对接:XFire服务调用与避坑指南
2026/10/20 14:06:32 网站建设 项目流程

简介:泛微E9统一集成待办中心接口文档是一份面向协同办公系统开发与集成人员的PDF技术资料,主要解决异构系统待办任务无法统一汇聚的问题。文档围绕webservice接口展开,详述了服务配置文件services.xml中的服务名称、命名空间与实现类等关键信息,帮助开发者快速定位接口路径;同时重点说明receiveTodoRequestByMap接收待办流程标准格式的方法,逐项解释syscode、flowid、requestname、pcurl、appurl、receiver、receivets等Map参数的业务含义与赋值规则,并给出可直接套用的SOAP请求XML示例,涵盖节点名称、流程标题、时间字段等完整报文结构。资源包仅含1份PDF文档,压缩包大小约1.6MB,内容紧凑、便于查阅,适合正在实施泛微E9统一待办中心对接项目的后端工程师、接口开发人员及企业系统集成顾问使用。目前已有4158人学习下载,文档中的配置步骤和请求示例可有效缩短接口联调周期,帮助规避参数漏传、时间戳冲突等常见问题。

1. 统一待办中心接口:一次对接,把散落的待办收拢到一个入口

做过多系统集成的开发应该都有同感:OA、ERP、项目管理系统各有一堆待办,用户每天要在三四个系统里来回点,漏掉一个就是事故。某协同 OA 的 E9 版本提供的「统一待办中心」,就是把这些异构系统的待办通过 webservice 接口聚到一处。这篇文档解决的核心问题只有一个:怎么用标准格式(Map 或 JSON)把外部系统的待办推给统一待办中心,以及怎么在流程处理完后同步状态。适合正在做 OA 与业务系统集成的实施工程师、后端开发,尤其是第一次接触 XFire 服务的老手——参数看着简单,真正调起来有不少隐含约定,后面会逐个拆。

2. 先看服务怎么暴露的:XFire 配置与 WSDL 定位

2.1 services.xml:写接口前先认准这三个类名

统一待办中心的服务端是 XFire 框架暴露的 webservice,配置文件固定放在/ecology/classbean/META-INF/xfire/services.xml。注意这个路径不是随便写的,它决定了服务是否能在容器启动时被正确加载。配置内容如下:

<service> <name>OfsTodoDataWebService</name> <namespace>webservices.ofs.weaver.com.cn</namespace> <serviceClass>weaver.ofs.webservices.OfsTodoDataWebService</serviceClass> <implementationClass>weaver.ofs.webservices.OfsTodoDataWebServiceImpl</implementationClass> </service>

配置逻辑不难:name是暴露给客户端看的服务名,namespace是 SOAP 报文里的命名空间,serviceClass是接口定义类,implementationClass是真正干活的实现类。我一般会建议先确认implementationClass在后端 jar 包里的路径是否一致,很多接口 500 错误其实就是这里类名写错或包没部署全。

namespace不是随便填的,它直接决定了 SOAP 请求里方法的xmlns属性。比如调用receiveTodoRequestByMap时,请求体里必须写xmlns="webservices.ofs.weaver.com.cn",写错命名空间,服务端直接抛SOAPFaultException,而且报错信息还不太直观。对接前可以把 WSDL 拉下来看一眼,确认命名空间、服务名、方法名三者的实际值,别只照着文档抄。

2.2 从 WSDL 到调用地址:把三个名字拼成完整 URL

XFire 的服务访问地址由两部分组成:服务发布的上下文路径 +services/+ 服务名。E9 默认的 webservice 访问路径一般是:

http://<服务器IP>:<端口>/services/OfsTodoDataWebService?wsdl

?wsdl是为了拿到 WSDL 文档,里面能看到所有可调用方法、参数类型和命名空间。用浏览器或 SoapUI 打开这个地址后,重点核对三件事:方法名是否以ByMap和ByJson结尾、传入参数的类型结构(Map 还是 String)、以及命名空间是不是webservices.ofs.weaver.com.cn。我在项目里经常碰到的情况是:开发环境能通,测试环境报404。原因绝大多数不是代码问题,而是测试环境的服务名没发布,或者services.xml没有随应用包一起更新。

还有一点值得说:这个服务走的是 SOAP 1.1,报文里soapenv:Envelope的命名空间必须是http://schemas.xmlsoap.org/soap/envelope/,写成 SOAP 1.2 的http://www.w3.org/2003/05/soap-envelope会直接被拒。XFire 对 SOAP 版本比较敏感,这个坑在客户端用 Java 内置javax.xml.soap时尤其常见。

3. 核心三接口拆解:待办接收、转已办、转办结的完整链路

3.1 receiveTodoRequestByMap:待办入库的标准写法

这个接口负责把异构系统的待办流程收进统一待办中心,方法签名是Map<String, String> receiveTodoRequestByMap(Map<String, String> dataMap)。参数是 Map,返回也是 Map,理解起来没有负担。下面是手动构造 SOAP 请求的 Python 示例,核心是拼报文,不依赖第三方 SOAP 库:

import requests body = """<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <receiveTodoRequestByMap xmlns="webservices.ofs.weaver.com.cn"> <in0> <entry> <key xsi:type="xsd:string">syscode</key> <value xsi:type="xsd:string">0001</value> </entry> <entry> <key xsi:type="xsd:string">flowid</key> <value xsi:type="xsd:string">A00000000007</value> </entry> <entry> <key xsi:type="xsd:string">requestname</key> <value xsi:type="xsd:string">员工请假流程_0001_-1_A00000000007_luffy</value> </entry> <entry> <key xsi:type="xsd:string">workflowname</key> <value xsi:type="xsd:string">员工请假流程</value> </entry> <entry> <key xsi:type="xsd:string">nodename</key> <value xsi:type="xsd:string">查看节点</value> </entry> <entry> <key xsi:type="xsd:string">pcurl</key> <value xsi:type="xsd:string">/showtask.aspx?id=A00000000007</value> </entry> <entry> <key xsi:type="xsd:string">appurl</key> <value xsi:type="xsd:string">/showtask.aspx?id=A00000000007</value> </entry> <entry> <key xsi:type="xsd:string">creator</key> <value xsi:type="xsd:string">wld</value> </entry> <entry> <key xsi:type="xsd:string">createdatetime</key> <value xsi:type="xsd:string">2016-03-09 10:10:10</value> </entry> <entry> <key xsi:type="xsd:string">receiver</key> <value xsi:type="xsd:string">luffy</value> </entry> <entry> <key xsi:type="xsd:string">receivedatetime</key> <value xsi:type="xsd:string">2016-03-10 10:10:10</value> </entry> </in0> </receiveTodoRequestByMap> </soapenv:Body> </soapenv:Envelope>""" resp = requests.post( "http://192.168.1.10/services/OfsTodoDataWebService", data=body.encode("utf-8"), headers={"Content-Type": "text/xml; charset=utf-8"}, ) print(resp.text)

这段代码的逻辑很直接:把所有业务参数以<entry>键值对形式塞进<in0>,一个 entry 对应一个参数。requests.post的 URL 不写?wsdl,直接打到服务地址。Content-Type必须带上charset=utf-8,否则中文参数可能出现乱码。

参数层面有几个需要留意的点。flowid是异构系统这边的流程实例 ID,统一待办中心靠syscode + flowid的组合来判断这条数据是新建还是更新,所以同一个流程的flowid必须保持稳定,不能每次推送都生成新值。requestname文档里给的样例是拼接串(流程名_标识_flowid_接收人),这是为了确保标题唯一,实际接入时如果业务系统有更好的唯一业务编号,可以替换,但建议保留可读性。pcurl和appurl是相对路径,拼接逻辑由前端处理,不需要传完整域名。

3.2 processDoneRequestByMap 与 processOverRequestByMap:状态流转的两个动作

待办处理完变成已办,调用processDoneRequestByMap;流程彻底结束变成办结,调用processOverRequestByMap。两个接口的参数结构几乎一样,只有syscode、flowid、requestname、workflowname、nodename、receiver、receivets这几个字段。SOAP 报文结构与 3.1 的示例相同,只需要把方法名替换掉,<in0>里的 entry 按需删除不需要的字段。

这里的隐性约定是:执行这两个接口时,服务端会用「syscode + flowid + receiver」去定位原有待办数据。如果这条待办之前没通过receiveTodoRequestByMap推过,返回值里operResult会是 0,message提示「流程数据不存在」。这不是接口报错,而是数据时序问题——必须先接收待办,再处理已办/办结,顺序反了会看到失败返回。

3.3 返回值的业务语义:不能只盯着 1 和 0

每次调用后,服务端返回一个包含五个键的 Map,如下表:

返回参数说明常见值
syscode本次操作的异构系统标识回显请求里的 syscode
dateType数据类型WfData / OtherSys / WfType / IsUse / SetParam
operType操作类型AutoNew / New / AutoEdit / Edit / Del / Check / Set
operResult操作结果1 成功,0 失败
message错误或状态描述例如「流程数据不存在」

operType=AutoNew加operResult=1表示数据不存在、自动创建成功;operType=AutoEdit加operResult=1表示数据已存在、自动更新成功。这两种都是正常情况。真正要警惕的是operResult=0且message是「流程数据【xxx】已存在」——这句话看起来像报错,实际上是因为receivets或关键字段没传,服务端走了检测逻辑后返回的存在提示。我在对接时踩过一次:把这种返回当失败重推,结果产生大量重复日志。

4. 异构系统与 JSON 通道:两种格式、四种状态

4.1 receiveRequestInfoByMap:带处理状态的异构流程接收

如果说 3.1 的三个接口是「待办专用」,那receiveRequestInfoByMap就是「通用流程接收」,它额外支持isremark和viewtype两个字段,可以表达待办的全生命周期状态:

参数名说明取值
isremark流程处理状态0 待办 / 2 已办 / 4 办结
viewtype流程查看状态0 未读 / 1 已读

这两个字段给了一个更灵活的路子:异构系统不需要分别调用三个方法,一个receiveRequestInfoByMap就能覆盖待办、已办、办结三种业务状态。viewtype控制的是待办中心里这条记录是否显示未读红点,一般在对接 Web 端消息推送时配合使用。

用这个接口时,参数里不仅要传receiver,还要保证createdatetime和receivedatetime的格式统一为yyyy-MM-dd HH:mm:ss。文档里的报文值都是这个格式,但是服务端对格式的容错能力有限,传2016/03/10 10:10:10这种斜杠格式,更新时间字段会直接落空。我一般是让上游 Java 端统一用SimpleDateFormat("yyyy-MM-dd HH:mm:ss")格式化后传参。

4.2 receiveTodoRequestByJson:不用 SOAP 的替代通道

如果外部系统用的是 Java 之外的栈,或者不想处理 SOAP 那层繁琐的 Envelope 结构,可以用receiveTodoRequestByJson(String json)。方法签名更简单,入参是 JSON 字符串,返回也是字符串。参考请求体如下:

{ "syscode": "0001", "flowid": "A00000000007", "requestname": "员工请假流程_0001_-1_A00000000007_luffy", "workflowname": "员工请假流程", "nodename": "查看节点", "pcurl": "/showtask.aspx?id=A00000000007", "appurl": "/showtask.aspx?id=A00000000007", "creator": "wld", "createdatetime": "2016-03-09 10:10:10", "receiver": "luffy", "receivedatetime": "2016-03-10 10:10:10" }

JSON 接口的好处是省掉了<entry>那套包裹结构,字段顺序无关紧要,解析也直接。注意命令和 SOAP 一样要求flowid和syscode必须存在,否则服务端无法判断是哪条数据,返回的字符串是一个 Map 结构序列化后的 JSON,解析时同样关注operResult和operType两个键。

JSON 格式也有自己的坑:字段值里的特殊字符必须转义。比如requestname里如果包含双引号或反斜杠,没转义会导致服务端解析 JSON 失败,返回的是解析异常信息而不是正常的 Map 返回结构。建议实现时先用一个 JSON 解析器验证一遍再发请求。

5. 避坑指南:统一待办中心对接的六个常见问题

5.1 返回 message 是乱码,看不出错误内容

现象:调用接口返回的message是&#27969;&#31243;这类实体编码,直接打印没法读。

原因:服务端返回的中文被转成了 XML 实体编码,这是 SOAP 传输的常见表现,不是接口故障。

解决:客户端解析时做一层反转义。Java 端用StringEscapeUtils.unescapeHtml4(),Python 端用html.unescape(),把message解码后再看,错误信息立刻可读。这个处理放在统一封装层,所有接口的返回值都过一遍,省得到处排查。

5.2 请求报错OperationNotSupportedException

现象:方法名正确,参数也对,但服务端返回不支持该操作。

原因:服务的实际发布版本里没有对应方法。通常是services.xml里的implementationClass指向了旧版本实现类,或应用包没更新。

解决:拉取?wsdl,对比 WSDL 里的方法列表与文档方法是否一致;同时检查后端services.xml中serviceClass与implementationClass的版本。遇到这种情况,先在后端服务器上grep -r "receiveTodoRequestByJson" /ecology/classbean/META-INF/xfire确认实现类存在。

5.3 待办重复推送,列表出现两条相同数据

现象:同一流程推送两次后,统一待办中心出现重复记录。

原因:syscode或flowid的取值不稳定。比如 flowid 用了数据库自增 ID,数据在不同库迁移后 ID 变了,服务端就把它当成新流程。

解决:flowid 必须用业务系统里稳定的唯一键,不能用行号或自增主键;如果业务上确有内容变更,要靠receivets字段来标记新版本,而不是换 flowid。我一般会让上游专门生成一个bizFlowId,规则是「系统代码-业务表名-业务主键」,对接期间保持不变。

5.4 明明调了已办接口,待办中心还显示待办

现象:processDoneRequestByMap返回operResult=1,但前端列表里这条数据还在待办区。

原因:数据异步同步延迟,或者前端列表有缓存。E9 的统一待办中心对已办数据的刷新存在秒级延迟,尤其是 PC 端列表,通常要等页面重新拉取。

解决:先不急着改代码,等待 10~15 秒后刷新页面再确认。如果仍然存在,检查调用时是否传了receiver——已办更新依赖receiver定位数据,不传或传错,服务端无法匹配原待办,更新等于没发生。

5.5 时间戳 receivets 没传,后发的请求把先发的覆盖了

现象:两个线程同时推送同一 flowid 的待办,数据状态与最后处理结果不一致。

原因:receivets字段的用途是解决并发乱序。文档里明确说「不传此字段会根据当前系统时间自动生成」,但多个线程的请求到达顺序可能与业务顺序不一致,导致旧数据覆盖新数据。

解决:客户端显式传receivets,取值为业务侧的数据变更时间戳(建议精确到毫秒)。服务端以此判断是否更新,后发的请求时间戳更旧会被忽略。这个字段是防覆盖的后悔药,并发量高的系统必须传。

5.6 中文字段被转成&#x67E5;后,pcurl 链接拼接地址错误

现象:nodename里中文正常显示,但pcurl拼接后 URL 里中文参数被编码,点开跳转 404。

原因:SOAP 传输过程中,中文被转义成 XML 实体,客户端拿到后忘记反转义就拼进 URL。

解决:对pcurl和appurl做两件事——先反转义还原中文,再对 URL 参数做URLEncoder编码。服务端收到相对路径后按原值存储,跳转时用的是编码结果。

6. 联调验证与幂等自查:上线前强制走一遍的五个动作

接口不是调通就算完,真正上线前我习惯用脚本做一轮「幂等 + 状态流转」的完整验证。下面这个 Python 脚本覆盖了最关键的验证场景:

import html import requests SOAP_URL = "http://192.168.1.10/services/OfsTodoDataWebService" NS = "webservices.ofs.weaver.com.cn" def call(method, params): entries = "".join( f"<entry><key xsi:type='xsd:string'>{k}</key>" f"<value xsi:type='xsd:string'>{v}</value></entry>" for k, v in params.items() ) body = f"""<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body><{method} xmlns="{NS}"><in0>{entries}</in0></{method}> </soapenv:Body></soapenv:Envelope>""" resp = requests.post(SOAP_URL, data=body.encode("utf-8"), headers={"Content-Type": "text/xml; charset=utf-8"}) return html.unescape(resp.text) # 第一次:AutoNew 创建 r1 = call("receiveTodoRequestByMap", { "syscode": "0001", "flowid": "T0001", "requestname": "测试流程_T0001", "workflowname": "测试流程", "nodename": "发起节点", "receiver": "zhangsan", "receivets": "20240101120000123" }) print(r1[:500]) # 第二次:同一 flowid 重复推送,应为 AutoEdit r2 = call("receiveTodoRequestByMap", { "syscode": "0001", "flowid": "T0001", "requestname": "测试流程_T0001", "workflowname": "测试流程", "nodename": "审批节点", "receiver": "zhangsan", "receivets": "20240101120000124" }) print(r2[:500])

脚本逻辑是:第一次推送验证自动创建,第二次推同一个flowid验证自动更新。重点看返回里的operType字段——第一次是AutoNew,第二次是AutoEdit,说明幂等逻辑生效。如果第二次还是AutoNew,说明syscode或flowid的传递有问题,服务端没识别出同一条数据。每轮验证后,再到 PC 端待办列表里人工确认状态和跳转链接。

上线前我还会强制走一遍这五个动作:查 WSDL 确认方法列表;用 SoapUI 跑一遍所有接口的样例报文;验证中文反转义;确认receivets在并发场景下生效;最后从待办中心点开pcurl确认跳转到达。这套流程跑完,对接类的返工能少掉大半。某次做某跨平台系统的待办接入,就是因为没做第三项反转义验证,上线后用户反馈节点名称全是转义符,页面一片&#x67E5;,从那以后每一次对接我都强制先验证一遍再交付。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询