测试
全部博文(931)
分类: 架构设计与优化
2019-08-29 10:46:54
Jerry在今年2月28日,SAP Customer Management for S/4HANA 1.0正式问世这个具有纪念意义的日子,同时发布了中英文版的博客进行介绍。
英文版发在SAP社区上,至今超过16000的阅读量:
而发布在微信公众号上的中文版,也有两千多的阅读量:
一转眼大半年就过去了,如今SAP S4CRM的标准开发,进行得怎么样了呢?在SAP社区上我写的那个英文博客里,有很多国外的partners在上面留言询问各种各样的问题。由于今年4月份起Jerry就离开了S4CRM开发团队,所以很多问题我没有办法回答,于是我邀请了SAP S4CRM的首席产品经理Frick Oliver在社区上回答大家提出的问题:
这是Oliver介绍S4CRM的视频,节选自SAP官方招聘公众号上的一篇文章。大家可以一睹这位德国老帅哥的风采。
今天这篇文章我邀请了SAP成 都研究院S4CRM团队的开发人员宋浩,由他介绍所在团队设计并开发的S4CRM里服务订单(Service Order)创建和更新的API。关于宋浩的背景介绍,大家可以参考他之前的文章:一个SAP顾问在美国的这些年。
在宋浩的文章里,Jerry也植入了一些关于SAP CRM中间件和SAP Cloud for Customer内容介绍,这些内容都和SAP基于Netweaver的系统集成这个主题相关,希望能对大家有所帮助。
为什么SAP要成立专门的团队来做API开发呢?最简单的4个字答案:系统集成。
Jerry的另一篇文章:SAP S4CRM vs C4C, 诸葛亮和周瑜? 曾经比较过这两个产品的方方面面,下图"系统集成"这一行,就是本文要详细阐述的内容。
如我上图中高亮强调的,SAP C4C和其他系统做集成,SAP推荐采用基于Netweaver的PI或者HCI作为中间件,而S4CRM同其他系统的集成方式,就由宋浩给大家做详细介绍。
下面是宋浩的正文。
大家好,我是宋浩,今年6月份刚加入SAP这个大家庭,平日里喜欢旅行,看恐 怖片,玩单机恐 怖游戏,从生化危机,零红蝶,再到恶灵附身,恐 怖元素一直是我闲暇时光的点缀,欢迎各位道友切磋指导。
S4CRM API是我在SAP经历的第一个项目,我们就从开发这个API的初衷说起吧。CRM市场这些年瞬息万变,百家争鸣。乱世必出英雄,我们新一代的产品S4CRM可以说是生于乱世,肩扛重任。
要实现一个企业的良好运营,一个高效且稳定的系统体系是必不可少的。而CRM便是这体系中重要的一员。如果一个已经采用SAP S4CRM的客户本身还有其他第三方系统,那么如何确保S4CRM与这些外部系统之间高效地运行与交互呢?我们的S4CRM API由此应运而生。
借助我们开发的服务订单领域相关的S4CRM API,外部系统可以同S4CRM进行一系列的服务流程操作,一个典型的场景就是,在外部系统调用S4CRM API,实现创建和修改服务订单或者服务确认(Service Confirmation)等需求。
如何找到我们11月份刚刚发布的这些API文档呢?
浏览器访问help.sap.com,看到这位美女后,输入关键字S/4HANA cloud进行搜索:
进入S/4HANA cloud的产品页面,输入service order - Create, Change, 即可打开我们的API帮助文档。
对于我输入的关键字S/4HANA cloud,大家不用觉得费解,因为对于这些API,S/4HANA On-Premise和Cloud共享同一套ABAP代码实现。
帮助文档里详细介绍了API请求和响应结构里每个字段的技术名称,长度和业务含义。对于SAP的老司机来说,拿到这份文档就可以开工了。
另外在SAP Best Practices Explorer网站上,对于这些API的使用有更详细的说明文档。
您可以直接通过下面的链接浏览这些文档。
文档里最有用的三部分:
(图太大了,一屏显示不完全)
因为Test script里包含了使用API的详细步骤,这里不再重复了,咱们来谈谈S4CRM API的实现细节。
在介绍S4CRM API之前,让我们先来回顾SAP CRM顾问都非常熟悉的SAP CRM中间件的消息流设计。
还是拿前面提到的例子来说明,假设外部系统通过CRM中间件触发CRM端的服务订单创建。那么从外部系统向CRM中间件发送消息,到我们能够在CRM的数据库表CRMD_ORDERADM_H里看到一条对应的服务订单抬头记录,主要经历了下图标注的三个步骤。
第一步: Inbound Adapter的字段映射
为什么需要这个字段映射呢?无论是老的CRM On-Premise还是新的S4CRM,只要涉及到服务订单的创建,最终必定会调用到函数CRM_ORDER_MAINTAIN。而下图中的Data Container,其数据格式同CRM_ORDER_MAINTAIN的输入参数个数截然不同,因此必须要经过Inbound Adapter做一个格式映射,这个思想和设计模式里的Adapter模式是一个道理。
因为CRM中间件里做格式转换的Inbound Adapter需要支持各种业务对象的数据同步,比如服务订单,物料主数据,产品主数据等等,因此Adapter用于接收Data Container的输入参数类型必然是一个通用类型:
第二步:Validation Service
一般情况下每一个CRM中间件数据同步对象都有一个对应的用于做校验的函数,在调用实际的创建/修改API之前,使用该校验函数执行错误检测,实现Fail Fast,Fail Early的目的。
Fail Fast, Fail Early是大神Jim Shore和Martin Fowler提出的一种软件开发实现理念,详细介绍参考Martin的著作。
例如下图中的COM_PRODUCT_MAT_VALIDATE就是物料主数据同步对象对应的数据校验函数,该截图来自事务码SMW01。
第三步:调用对应的CRM函数
如果是服务订单同步,意味着函数CRM_ORDER_MAINTAIN的调用;如果是物料主数据,就是COM_PRODUCT_MAINTAIN,以此类推。
从事基于ABAP Netweaver的SAP产品相关的二次开发的顾问们可以享受一个优势:很多作用相似的功能API,在不同的SAP产品中实现理念也类似,这种风格的相似性不容易用语言来描述,简单地说就是都带着一股“SAP味儿”。
比如我之前做过多年的SAP SD开发,创建销售订单用的是函数SD_SALESDOCUMENT_CREATE,而加入SAP S4CRM团队后使用函数CRM_ORDER_MAINTAIN创建CRM里的服务订单。当我浏览了后者的参数定义,试着写了一些测试代码之后,不由得发出感叹,“啊,一切都是熟悉的味道。”
同样,我们S4CRM API的实现思路,同刚刚回顾过的SAP CRM中间件思路一致,也是三大步骤。
1. Validation
2. Mapping
3. Business Processing
除了Validation和Mapping调换了顺序之外,整体思路和CRM中间件的三大步骤完全一致:
接下来我们看看在S4CRM里开发一个API的详细步骤。
1. 模型
首先需要的是建模,没有模型,API何从谈起?
工欲善其事必先利其器,所以我们第一步要做的就是根据具体的服务场景中的销售订单在SAP系统中建立我们的数据模型。
使用事务码SXMB_IFR,选择Enterprise Service Builder, 系统会在本机寻找Java运行环境,此项为必须项,所以在建模前务必要安装JRE。
模型是需要建在相对应的namespace下面的,我这里使用的是SAP S4CRM标准开发用的namespace:
建模有四大元素:
数据类型(data Type)
消息类型(Message Type)
错误消息类型(Fault Message Type)
服务接口(Service Interface)
首先要做的是创建基本数据类型,可以参考现有的global的基础数据元素,将API需要使用到的global数据元素从global namespace引入到我们自己的namespace里面来。
举个例子,下图是SalesArea这个复合字段,里面包含了“五朵金花”,大多数基于Netweaver的SAP产品里,对于SalesArea的建模都沿用了这一最佳实践:
实际我们这里是在做一个拼装工作,乐高(LEGO)大家一定听说过或者玩过吧。
如下图所示,我们像拼装乐高玩具那样,把各种数据类型拼装成一个结构,用于接收外部数据(也就是服务订单)。
业务模型的结构创建好之后,我们需要再拼装一个供Message Type引用的整体数据类型,其实就是将Message Header的信息引入进来,相信有经验的顾问们已经知道这个Message Header里维护什么信息了。是的,就是一些用来做传输的标识性信息。
我们可以回顾下SAP CRM中间件Inbound Adapter的输入参数,同样具有这个Message Header:一切都是熟悉的味道。
所有数据类型都就位后,我们可以组装最终的Service Interface模型了,这个模型才是最终开放给外部去调用的Webservice 对象。这里我们采用的是异步传输的方式,当然您也可以选择同步,取决于大家的实际需求和业务场景。
上图Service Interface的名称,ServiceOrderRequest_In, 就是出现在SAP帮助文档里的API技术名称。
这些模型创建好之后,再到事务码SPROXY里生成Proxy对象,实际上就是能够被ABAP代码访问到的ABAP DDIC结构。
2. 使用ABAP实现服务订单的创建和修改
前面已经提过,我们首先要做的是对外部接收进来的数据进行校验,以期在调用CRM_ORDER_MAINTAIN之前最大程度的保证数据的正确性。
在数据校验执行完并且没有抛出任何校验错误以后,我们需要将外部接进来的数据结构与SAP CRM_ORDER_MAINTAIN里的数据结构进行字段映射。
实际在CRM_ORDER_MAINTAIN里面相关数据字段是分散存储在对应的结构里的。比如抬头数据大部分是存放在ORDERADM_H中,行项目数据大部分是放在ORDERADM_I里,状态数据存放在STATUS里。
基于这种特性,您会很容易发现,变化的始终是模型,而CRM_ORDER_MAINTAIN这边相对来说是固定不变的。所以我们专门设计了一个类用于完成数据映射。在这个类的设计上,我们倾向于以固定不变的一边为主,每一个结构创建一个方法,这样有利于以后的复用和维护,设计也相对清晰和有层次感。
下图是这个数据映射类的方法列表:
我们以ORDERADM_H来举例说明,Inbound端我们将对应的外部数据映射到SAP CRM_ORDER_MAINTAIN对应的结构ORDERADM_H上面。
下图展示的是数据映射类如何将外部数据中包含的服务订单抬头字段里包含的ID,类型和描述信息映射给CRM_ORDER_MAINTAIN需要的输入参数格式。其中红色高亮的部分是订单ID这个字段的映射处理。
所有字段映射完成后,我们就可以进行业务的处理了,调用CRM_ORDER_MAINTAIN去创建或者更新服务订单。
如果是服务订单创建场景,订单的ID是在S4CRM系统自动生成的,创建完毕后需要将生成的服务订单数据读取出来,作为API响应发送给外部系统。
上图红色区域代表调用CRM_ORDER_MAINTAIN创建服务订单的代码,蓝色区域代表调用CRM_ORDER_READ将创建好的订单明细从内存中读取出来,准备进行Outbound处理,即字段映射和映射后的数据发送至外部系统。
发送响应之前的字段映射,将SAP内部结构上的数据映射到外部结构上的处理逻辑如下图:
字段映射完毕之后,调用函数/AIF/SEND_WITH_PROXY将映射好的结构发送出去。发送的目标系统通过Logical Port指定,其值包含在下图第15行高亮的变量里。
关于Logical Port在Web Service消费场景中的用途,Jerry已经在他的SAP博客中详细介绍过,这里不再重复:
而我们仔细观察Logical Port的获取,这个值是通过好几个参数共同决定的。
IF_CONF_API_SRO_CONSTANTS=>COMM-SCENARIO_ID:
这个字段是一个常量,值为SAP_COM_0424:
SAP_COM_0424代表的communication scenario的配置步骤,可以从我之前介绍的SAP Best Practices Explorer网站下载。
这个communication scenario就是SAP针对实际系统集成场景抽象出来的一种开箱即用的模型,通过少量简单的配置就能实现和其他系统做集成。
比如在SAP Cloud for Customer里同样存在communication scenario的概念,用法也类似:
最后,我模拟外部系统调用S4CRM API来创建服务订单,给大家一个更直观的感受。
我使用SOAP UI这个软件来发起请求。下图可以看到我们出发了一个请求,创建一个事务类型为SVO1的服务订单:
SOAP UI里成功调用Web Service之后,到S4CRM系统查看我们刚才创建的服务订单明细:
最后大家或许会好奇真正执行发送动作的函数/AIF/SEND_WITH_PROXY。
我们还是先来回忆SAP CRM中间件,比如CRM向ERP发送数据这个场景,最后实质是执行的RFC调用:
而S4CRM API使用的/AIF/SEND_WITH_PROXY,这个函数的前缀AIF代表Application Interface Framework, 是SAP Netweaver上的一个Addon,一个轻量级的数据集成中间件的解决方案。
关于AIF的更多介绍,大家可以阅读下面这篇SAP博客:
https://blogs.sap.com/2012/04/03/sap-aif-so-what-is-it-all-about/
我们成 都S4CRM团队负责开发的API还在不断的功能增强中,敬请期待。感谢大家的阅读。
相关阅读
要获取更多Jerry的原创文章,请关注公众号"汪子熙":