分享

SAP Cloud for Customer 里如何通过 ABSL 二次开发方式消费 SAP S4HANA 系统的 API

 汪子熙 2024-03-22 发布于上海

最近有朋友咨询本文标题这个问题,其实笔者之前写过一篇文章介绍过,本文将之前发布过的内容做了一些调整,重新发布出来。

本文介绍如何在 SAP Cloud for Customer 系统里通过二次开发的方式,使用 Cloud Application Studio 创建自定义增强,调用 SAP S/4HANA 的 API,完成两个 SAP 系统间的交互。

两个系统交互的场景是:在 SAP Cloud for Customer(下文简称 C4C) 系统的 Sales Order 明细页面里,创建一个新的自定义按钮 "Trigger Delivery", 点击之后,该按钮调用 SAP SAP S/4HANA 暴露出来的一个 API,在 SAP S/4HANA 系统端触发交货流程。

下面是具体的实现步骤。

(1) 首先在 S/4HANA 里开发一个 API,逻辑是接收从 SAP Cloud for Customer 传过来的 Sales Order ID,读出其包含的行项目,然后调用 SAP S/4HANA 的交货单创建函数,为这些行项目创建交货单。

用关键字 S/4HANA Outbound Delivery,一下子就搜索到了对应的 BAPI 名称:BAPI_OUTB_DELIVERY_CREATE_SLS.

使用这个 BAPI 编写一个测试用的 ABAP 报表:

REPORT zcreate_dn.
DATA:lv_ship_point TYPE bapidlvcreateheader-ship_point VALUE '0001',
lv_due_date TYPE datum VALUE '20181205',
lv_delivery TYPE bapishpdelivnumb-deliv_numb,
lt_so_items LIKE TABLE OF bapidlvreftosalesorder,
ls_so_items LIKE LINE OF lt_so_items,
lt_return TYPE TABLE OF bapiret2,
ls_read TYPE order_view,
lt_item TYPE TABLE OF bapisdit,
lt_order_headers_out TYPE TABLE OF bapisdhd,
lt_header TYPE TABLE OF sales_key,
lt_bapisdtehd TYPE TABLE OF bapisdtehd,
lt_bapitextli TYPE TABLE OF bapitextli,
lt_bapiret2 LIKE bapiret2 OCCURS 0 WITH HEADER LINE.
APPEND INITIAL LINE TO lt_header ASSIGNING FIELD-SYMBOL(<header>).
ls_read-item = 'X'.
<header>-vbeln = '0000000376'.
CALL FUNCTION 'BAPISDORDER_GETDETAILEDLIST'
EXPORTING
i_bapi_view = ls_read
TABLES
sales_documents = lt_header
order_items_out = lt_item.
LOOP AT lt_item ASSIGNING FIELD-SYMBOL(<item>).
APPEND INITIAL LINE TO lt_so_items ASSIGNING FIELD-SYMBOL(<fill>).
<fill>-ref_doc = <item>-doc_number.
<fill>-ref_item = <item>-itm_number.
<fill>-dlv_qty = <item>-req_qty.
<fill>-sales_unit = 'EA'.
ENDLOOP.
CALL FUNCTION 'BAPI_OUTB_DELIVERY_CREATE_SLS'
EXPORTING
ship_point = lv_ship_point
due_date = lv_due_date
IMPORTING
delivery = lv_delivery
TABLES
sales_order_items = lt_so_items
return = lt_return.
LOOP AT lt_return ASSIGNING FIELD-SYMBOL(<return>).
WRITE:/ | Type: { <return>-type }: { <return>-message } | COLOR COL_NEGATIVE.
ENDLOOP.
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = 'X'
IMPORTING
return = lt_bapiret2.
LOOP AT lt_bapiret2 ASSIGNING <return>.
WRITE:/ 'Message:', <return>-message COLOR COL_POSITIVE.
ENDLOOP.

第21行硬编码了一个 SAP Cloud for Customer 的销售订单 ID,测试后发现没什么问题,于是将这个报表的源代码拷贝到一个新的 ABAP Class 里,稍作修改,将硬编码去掉,替换成从 SAP Cloud for Customer 传过来的销售订单 ID 即可。

在 SAP S/4HANA 里新建一个 SICF 服务节点,其实现 Class 指定成刚刚建好的包含了调用 BAPI_OUTB_DELIVERY_CREATE_SLS 的 ABAP Class.

每个 ABAP SICF 节点会自动生成一个 url,从而将其节点分配的 SICF ABAP Class 的业务逻辑,通过 HTTP 的方式暴露给外界。

关于 ABAP SICF 的更多介绍,请参考笔者之前的文章:从 ABAP Netweaver 的 SICF 到 SAP Kyma 的 Lambda Function.

笔者当时完成的这个集成场景的 POC,选择的 SAP S/4HANA 服务器,其 url 可以直接被外网访问,所以省去了使用 SAP Cloud Connector 将其暴露给外网这一步。毕竟是 POC,追求的是在最短的时间内完成集成场景交付。

如果是用于生产用途,比如想要将常规的 SAP ABAP On-Premises 平台上开发的 HTTP Service url,暴露给外网使用,那么请参考笔者这篇文章:

使用 Java + SAP 云平台 + SAP Cloud Connector 调用 ABAP On-Premise 系统里的函数

(2) 回到 SAP C4C,打开 Cloud Application Studio,对标准的 Sales Order BO 进行扩展,增添一个新的 Action.

这里 BO 的 Technical Name 应该是 CustomerQuote,因为根据 SAP C4C 帮助文档介绍,Sales Order 和 Sales Quote 共用同一个 BO 模型,即 CustomerQuote. 通过模型字段 Type Code 的不同值来区分。

对 BO CustomerQuote 进行扩展,创建一个新的 Action triggerOutboundDelivery:

这个 Action 的实现逻辑,当然就是调用前一步骤里创建好的,SAP S/4HANA 通过 SICF 暴露出来的 API.

在动手实现 Action 之前,我们还需要在 SAP C4C 里创建一些消费 S/4HANA API 所需要的模型。

Cloud Application Studio 里新建一个 External Web Service Integration:

Web Service 名称取为 JerryExternal,类型为 REST.

URL 字段值,填充成 S/4HANA API 的 url.

这个 Web Service 模型的创建,会同时自动创建一个 Communication Scenario,名称为 JerryExternalService:

于该 Communication Scenario 创建一个新的 Communication Arrangement:

通过上图右键菜单中的菜单项,打开 Communication Arrangement 的维护 UI:

将访问 S/4HANA API 所需的用户名和密码,维护到新建的 Communication Arrangement 里去:

最后,实现 CustomerQuote BO 扩展出来的 Action,在里面通过 C4C 标准的工具库函数 WebServiceUtilities.ExecuteRESTService,消费 S/4HANA API:

/*
Add your SAP Business ByDesign scripting language implementation for:
Business Object: CustomerQuote
Node: Root
Action: triggerOutboundDeliveru
Note:
- To access the elements of the business object node,
use path expressions, for example, this.<element name>.
- To use code completion, press CTRL+J.
*/
import ABSL;
if( this.OutboundDeliveryID.IsInitial() == false){
raise already_delivered.Create("E");
return;
}
var HttpMethod = "GET";
var HttpResource = ""; // not required
var ContentType = ""; // not required
var Body = ""; // not required
var HeaderParameter : collectionof NameAndValue; // not required
var URLParameter : collectionof NameAndValue;
var URLParameterEntry : NameAndValue;
URLParameterEntry.Name = "SoID";
URLParameterEntry.Value = this.ID.content;
URLParameter.Add(URLParameterEntry);
var response = WebServiceUtilities.ExecuteRESTService("JerryExternalService", "JerryExternal", HttpMethod, HttpResource,
URLParameter, HeaderParameter,ContentType, Body);
this.OutboundDeliveryID = response.Content;
raise delivery_message.Create("S", this.OutboundDeliveryID);

从上图 ABSL 实现代码,我们也能体会到 SAP 引入 Communication Scenario & Arrangement 这些模型带来的好处,即 Code Over Configuration is better than Code Over Code - 基于配置编程优于硬编码。

如果 SAP S/4HANA API url 或者用户名和密码发生变化,我们只需修改 C4C 里 Communication Scenario 和 Arrangement 对应的配置即可,而无需重新编译 ABSL 代码本身。

最后,在 SAP C4C UI 上点击 Trigger Delivery 按钮后,触发我们在 BO 上自定义的 action,在 Cloud Application Studio 的调试器里能清楚的观察到代码的执行。

上图是 SAP C4C ABSL 代码的单步调试,点击 Continue 之后,设置在 SAP S/4HANA SICF 实现类里的 ABAP 断点触发,调试器里能看到 SAP C4C Sales Order ID 已经成功传递到 SAP S/4HANA 端了。

本文介绍了 SAP C4C 如何通过定制开发,实现消费第三方系统 API 的需求。这里的第三方系统 API,可以是 SAP S/4HANA,SAP Business Technology Platform 或者其他任何系统的 API. 这是一种比较轻量级的 SAP 系统之间的交互实现方式,希望对大家有所帮助。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章