ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用友ERP二次开发实战:扩展字段与U8 OpenAPI接口联调复盘

用友ERP二次开发实战:扩展字段与U8 OpenAPI接口联调复盘 1. 那个夏天我为什么要写这篇复盘暑假实习结束那天mentor拍着我肩膀说了一句ERP二次开发这活儿会上手不算本事能讲明白才算。当时没太在意回家整理笔记才发现这两个月踩过的坑、啃过的文档、改废的代码如果就这么散在脑子里过半年基本全忘光。所以这篇总结与其说是交作业不如说是给自己留一份施工日志——顺便也给后面要进这个坑的同学省点弯路。用友ERP系统二次开发这个名词第一次听的时候我完全没概念。简单说用友是国产ERP里的老大哥U8、U9、NC、BIP这一串产品线覆盖了从小型制造企业到大型集团的不同规模。所谓二次开发就是标准产品交付给客户之后客户总有些自己的业务逻辑、报表格式、审批流程跟标准功能对不上这时候就需要在标准系统之上做定制——写插件、改接口、加字段、做单据联动本质上是在别人的地基上盖自己的房子。这篇内容适合谁看如果你是在校生正纠结暑假去软件公司实习能学到什么如果你是刚入行做ERP实施或开发被丢到项目上不知道从哪下手又或者你是业务部门的人好奇系统里那些自定义按钮到底是怎么冒出来的——那这篇东西大概能帮上点忙。我会从整体思路、核心技术点、实际动手过程、以及踩坑记录四个角度展开尽量把当时为什么这么做的思考过程也写出来而不只是列一堆结论。需要提前说明的是下面涉及的配置、接口、代码示例都是基于我实习期间接触到的常见实践整理具体项目环境不同版本不同细节会有出入。用友产品线版本差异极大U8和U9的扩展机制就不是一个路数动手前务必先确认清楚自己面对的是哪个版本。2. 先搞清楚自己在改什么用友ERP二次开发的整体地图很多人对ERP二次开发的想象是改源代码这其实是个误区。用友这类产品基本不会让你动核心代码而是通过一套预留的扩展机制来插入业务逻辑。理解这套机制的分层结构是后面所有工作的前提。2.1 从产品线切入U8、U9、NC、BIP到底差在哪我实习的项目组主要围绕U8和U9两个产品线。简单梳理一下我理解到的区别。U8是面向中小型企业的经典产品架构偏传统C/S和B/S混合数据库以SQL Server为主。它的二次开发主要靠**UAPU8应用平台**和一系列开放接口常见的做法是写外部程序通过API读写单据或者在UAP里做表单和报表的扩展。U8的生态很成熟网上资料多但正因为老祖传代码也多接手时经常需要先考古。U9现在的U9 cloud更现代化是纯B/S架构、基于.NET技术栈的产品主打多组织、多工厂的中大型制造企业。它的扩展能力明显更强尤其是公共扩展字段和实体扩展字段这两个概念——前者是多个业务对象都能挂载的通用扩展位后者是针对某个具体实体单独加的字段。这两个东西用好了很多需求不用写代码就能解决这也是我在项目里被反复强调的一点。NC和BIP就是更高端的产品线了面向大型集团、央企级别架构复杂度上一个台阶。实习期间只是远远看过文档没有实际动手这里就不班门弄斧。提醒选哪条技术路线取决于客户用什么产品。别看到用友二次开发就去搜教程先问清楚版本号U8和U9的解决方案基本不能互相套用。2.2 二次开发的四种典型形态摸了一圈之后我大概把ERP二次开发归纳成四类由浅到深。第一类是配置型扩展也就是不写代码通过系统的自定义字段、扩展字段、自定义档案、单据模板设计器来完成。U9里的公共扩展字段就属于这一类业务人员有时自己就能配。这类需求占实际项目的比例其实不低能配置解决就别写代码这是mentor一直强调的原则。第二类是接口型开发通过系统提供的API比如U8 OpenAPI、U9的WebAPI实现外部系统与ERP的数据交互。像益模与ERP系统对接方案这种需求就属于这一类让模具管理系统和ERP之间同步工单、物料、BOM数据。接口开发的门槛在于要理解ERP的数据模型知道一张单据背后关联了哪些表、哪些字段是必填、哪些状态有自己的状态机。第三类是插件型开发在标准业务流程的关键节点挂载自定义逻辑。比如单据保存前校验、审核后触发动作、打印时动态取数。这类开发要绑定到具体的业务事件上属于侵入式的定制。第四类是报表与外围程序常见的是做自定义报表、导数据工具、批量处理脚本。技术上相对独立但难点在于要准确理解业务的取数口径一个库存周转率的计算口径不同部门能吵三天。2.3 为什么先看能不能配置是铁律这点值得单独拎出来讲。我刚开始特别想写代码觉得配置太low结果第一次独立接需求就翻了车客户要一个合同金额超50万需副总审批的流程我吭哧吭哧研究插件怎么挂搞了两天mentor过来看了一眼说这不就是工作流里加个条件分支的事吗。后来的教训就是接到需求先做三件事一是翻系统标准功能里有没有现成的二是看扩展字段能不能满足三是再看工作流、模板、公式能不能解决。真的都不行了才考虑写代码。原因很现实——配置可维护代码是负债。你用配置做的东西客户自己的IT或后续实施顾问能看懂、能改你写的插件人走了就是黑盒。而且配置型方案升级时受影响小插件在版本升级时经常要重新适配这是长期成本。3. 我在实习里真正动手的核心技术点聊完框架说说实际动过手的东西。这一段尽量写细包括当时怎么想的、怎么试的、结果怎样。3.1 扩展字段这件事看似简单实则讲究U9里加字段有两条路公共扩展字段和实体扩展字段。我一开始没搞明白区别随便选了一个结果数据没地方存。通俗讲公共扩展字段像一个公共储物柜很多业务对象比如销售订单、采购订单、出入库单都能共享这批扩展位好处是通用、能跨单据引用坏处是数量有限而且语义上不够专一。实体扩展字段则是给某个房间专门加的柜子只挂在特定实体上语义清晰适合该业务对象独有的属性。实操中我的判断逻辑是这样的如果这个字段是某个单据独有的比如销售订单上的项目编号就用实体扩展字段如果这个字段多个单据都要用比如统一的渠道来源那就考虑公共扩展字段。具体操作路径以我当时的U9环境为例进入系统管理端的扩展字段配置界面选择目标实体新增字段时要填《字段编码、名称、数据类型、长度、是否必填、默认值。特别要注意字段编码一旦启用基本不能改因为底层已经生成了对应的数据库结构改编码会导致数据错位。数据类型也要想清楚选错了后面做报表取数会很痛苦比如你为了省事都选字符串结果金额字段没法直接做汇总运算。注意事项扩展字段加完不是立刻生效的需要在相关的单据模板里把这个字段放到界面上否则数据能存但用户看不到。我第一次加完字段用户说没看到啊找了半天才发现是模板没配。3.2 接口联调U8 OpenAPI的实际使用姿势U8这块我们用的是OpenAPI通过HTTP方式对接外部系统。整体流程是申请对应的API权限、拿到访问凭证、按文档拼接请求参数、调用、解析返回。结构上一次调用大体是这么几步先登录鉴权拿token然后构造业务数据的JSON或XML报文调用具体的接口比如销售订单新增、物料查询最后处理返回结果。返回里最重要的是成功标志和错误信息ERP接口的错误提示往往比较含蓄比如只告诉你保存失败具体哪个字段有问题得自己一点点试。我印象最深的是一个物料同步的需求外部系统推过来的物料十有八九失败排查下来原因五花八门有的缺计量单位有的物料分类编码对不上有的名称超长。后来我总结出一个笨办法但很管用——先把最小可用数据集跑通。就是只传最少的必填字段能成功保存再一个一个往上加字段加到哪个报错就知道是哪个字段的问题。这个二分排查法在接口联调里救了我无数次。{ code: M001, name: 测试物料, unit: PCS, category: CL01 }上面这种就是典型的最小数据集思路字段能少就少跑通了再加。3.3 用友u8api与u8 openapi的区别理解实习时文档里这两个词经常一起出现我一开始以为是同一个东西。后来才理清U8 openapi是面向外部系统集成的开放接口体系偏对外而u8api这一类更多是产品自身能力对外暴露的接口集合涵盖范围和使用场景有差异。对开发者来说看接口文档时先确认是哪一套鉴权方式、请求格式、返回结构可能都不同。我踩的坑就是拿了A文档的示例去调B接口字段名对不上白白耗了一下午。3.4 SQL层面的数据理解别怕看表ERP开发绕不开数据库。虽然不写核心逻辑但排查问题时查库是常态。我学到的经验是先从单据界面反查表结构。比如一张销售订单界面上有表头、表体对应数据库里通常就是主表加子表一对多关联字段一般是单据号或行号。看表的时候重点关注三件事主键、外键关联、状态字段。状态字段尤其重要ERP里单据有生命周期草稿、审核、关闭很多数据查不到的问题其实是状态过滤掉了。我有次查库存对不上死活找不到差异最后发现是过滤条件里漏了未审核的出入库单。4. 一次完整需求的实操全过程光讲技术点容易散用一个完整案例串起来会更清楚。我拿实习后期做的一个需求来讲——外部系统推送销售订单到U8并在订单上带一个自定义的渠道来源字段。4.1 需求拆解与前置确认拿到需求的第一反应不是写代码是先问清楚几件事外部系统推过来的字段清单是什么哪些必填渠道来源的值来自哪里、有没有字典订单是未审核状态进来还是要自动审核推送频率是实时还是批量这些问题看似废话实际上每一个都会影响方案。比如是否自动审核如果自动审核那就要考虑审核失败怎么回滚批量推送就要考虑并发和幂等同一条订单重复推送会不会生成两张单。需求确认不清代码写得再漂亮也是返工。我当时列了一张确认清单逐条找业务和外部系统的人对齐最后确定的方案是订单以未审核状态进入渠道来源通过实体扩展字段承载推送方式为HTTP单条推送需要幂等控制。4.2 扩展字段的落地配置第一步是把渠道来源这个字段建起来。进入U9或U8对应环境的扩展字段配置选定销售订单实体新增字段配置项取值说明字段编码cChannelSource一旦启用不建议修改字段名称渠道来源界面显示用数据类型字符串渠道是编码不做运算长度20留足余量是否必填否外部不传时允许为空配完之后要去销售订单的模板设计里把这个字段拖到界面合适的位置。这里有个细节模板修改后要确认影响到的是哪个组织、哪个账套多组织环境下模板可能分组织维护配错组织会导致另一家公司看不到。我第一次就没注意只给测试组织配了结果换了个组织去验证字段消失虚惊一场。4.3 接口调用的代码实现代码部分我用的是.NET通过HTTP调用接口。核心逻辑分三段鉴权、取token、构造报文并调用。// 1. 鉴权拿token示意 var loginResult await httpClient.PostAsync(loginUrl, loginContent); var token ParseToken(loginResult); // 2. 构造订单报文带上扩展字段 var order new { orderNo externalOrderNo, customerCode customerCode, lines new[] { new { itemCode M001, qty 10, unit PCS } }, cChannelSource ONLINE // 自定义扩展字段 }; // 3. 调用新增接口 httpClient.DefaultRequestHeaders.Add(Authorization, token); var saveResult await httpClient.PostAsync(saveUrl, ToJson(order));构造报文时有几个坑。一是日期格式ERP对日期格式要求很死常见是yyyy-MM-dd传成别的格式直接失败。二是数值精度数量、金额的小数位数要和系统设置匹配传了四位小数给只接受两位的字段会报错或被截断。三是编码对应外部系统用的物料编码必须是ERP里已有的、且在该组织可见的否则报物料不存在。这些我都实际撞过。调通的那一刻其实没什么激动因为前面失败太多次了但看到订单在系统里带着ONLINE这个渠道来源显示出来时还是有点小成就感。4.4 幂等与重复推送的处理这是需求里被特别强调的点。外部系统网络抖动时会重推如果不管一条订单就变两条。处理思路是以外部订单号作为唯一键做校验调用保存前先查询该单号是否已存在于ERP。SELECT order_no FROM sale_order WHERE external_order_no extNo AND status CLOSED存在就跳过返回已处理不存在才真正保存。这里注意状态过滤已经作废的单据其实可以允许重新推送所以判重时要带上状态条件。这个细节是踩过坑才想到的——最初没带状态结果一张作废的订单永远推不进来。更进一步如果并发量高光靠先查后插还有竞态风险那就需要在数据库层面对外部单号加唯一约束靠数据库来兜底。这是mentor提醒我的属于工程经验的范畴。5. 那些文档里不会写的踩坑记录技术方案网上都能搜到真正值钱的是踩坑经验。这一段我把自己实际遇到的整理出来希望能帮后来人少走点弯。5.1 环境搭建阶段的老问题装U8的时候在Win7上出现过IE Web Control组件装不上的情况后来查资料才知道是系统组件版本和安装包要求不匹配。这类环境问题特别磨人而且往往和业务逻辑无关纯粹是环境坑。我的应对办法是尽量用官方推荐的系统版本和数据库版本组合别图省事拿手边随便一台机器就装后期环境不一致带来的诡异问题排查成本远超当初省下的时间。数据库创建也是U8、NC这类产品安装时会要求先创建好数据库实例字符集、排序规则最好按文档来。我见过因为排序规则不对导致中文查询乱序的案例。5.2 接口调试的排查速查表下面这张表是我自己整理的后来组里新人都在用。现象可能原因排查方向保存失败无具体提示必填字段缺失对照最小数据集逐个补提示物料不存在编码错误或组织不可见确认编码和组织范围数量/金额报错精度或格式不符检查小数位和类型日期类报错格式不匹配统一为系统要求格式重复生成单据无幂等控制加唯一键校验权限拒绝token失效或无接口权限重新鉴权、确认授权这张表不是万能的但覆盖了大部分高频问题新手照这个顺序排查效率能提升不少。5.3 关于配置优先于代码的再次强调前面提过这里再补一个真实例子。项目里有个需求是采购订单金额超过某个值要走额外审批。有同事第一反应是写插件我按mentor教的思路先看工作流发现工作流本身支持按条件走不同分支配置了两个小时搞定没写一行代码。而隔壁用插件做的类似需求测试花了更久还留了个隐患——版本升级时要重新适配。不是说代码没用而是能用配置表达的就别用代码这是ERP这个领域的特殊之处。它的业务逻辑大多高度结构化产品早就把常见模式抽象成配置项了。心得判断一个需求该配置还是该开发有个简单标准——如果这个逻辑能被非程序员描述成规则大概率能配置如果逻辑里涉及复杂计算、跨系统协作、特殊算法才需要开发。6. 实习学到的比技术更重要的东西说实话两个月下来技术上我也就是刚入门能照着文档和前辈的指点做点小需求。但有几个认知上的转变我觉得比会写几个接口更值钱。第一个是对数据的敬畏。ERP是所有业务数据的汇聚地你改一个字段、写错一条逻辑影响的是真实的采购、库存、财务。实习期间 mentor 反复强调测试环境验证、生产变更要走流程一开始觉得繁琐后来理解了这就是这个行业的底线。第二个是沟通的价值被严重低估。技术方案再漂亮需求理解错了全白搭。我那个订单推送的需求光需求确认就花了三四天比写代码时间还长但正因为对齐清楚了后面开发反而顺。很多新手包括之前的我总想快点进入写代码环节其实是逃,避了最难的想清楚环节。第三个是文档和笔记的习惯。ERP的产品线太庞大没人能全记住。我养成了每做一个需求就记一份笔记的习惯记的是为什么这么选当时遇到什么坑而不是我做了什么。这份总结本身就是这个习惯的产物。最后分享一个小技巧。如果你也要做类似的接口对接建议先做一个最小的端到端跑通一个字段、一条数据、从外部发到ERP、能在界面看到先把这个闭环打通再往上堆业务。我见过太多人一上来就想做完整方案结果卡在环境、卡在鉴权、卡在某个必填字段上几天都没进展最后士气都没了。先把最小闭环跑起来那种通了的感觉会支撑你啃完后面所有细节。这个领域往后还能往深里挖比如插件开发、报表引擎、和多系统集成的复杂场景都是下一步可以继续折腾的方向。但暑假这一轮能把扩展字段、接口对接、需求拆解这几件事搞明白对我来说已经值回票价了。
返回列表