SAP 集成钉钉 Webhook 实现方案
一、钉钉配置
钉钉提供了 AI 表格功能,其中包含自动化流程的 Webhook 接口。相比传统的机器人 API 连接,这种方式更为简单。
1. AI 表格创建
创建一个空白模板的 AI 表格,设置字段以存储从 SAP 传来的数据,类似于后台日志表。
2. 自动化流程设置
在表格中启用'自动化'功能,配置接收数据后的操作(如发送消息、待办等)。配置完成后,钉钉系统增加了一个可被调用的接口。
3. Webhook 接口参数
Webhook 相当于一个 API 接口,需要定义传输数据的参数字段。具体参数设置需参考钉钉官方文档。
二、SAP 开发
在 SAP 中封装接口调用钉钉 Webhook,类似连接其他 RESTful 接口。
1. 接口开发
核心在于参数结构设置。以下是 ABAP 代码示例,实现了 JSON 序列化、HTTP 客户端创建、请求发送及响应解析。
FUNCTION ZTEST_API.
*"----------------------------------------------------------------------
*"本地接口:
*" IMPORTING
*" REFERENCE(I_BUDAT) TYPE BUDAT
*" REFERENCE(I_TYPE) TYPE BAPI_MTYPE
*" EXPORTING
*" VALUE(E_MSEG) TYPE BAPI_MSG
*" VALUE(E_TYPE) TYPE BAPI_MTYPE
*" TABLES
*" T_TAB STRUCTURE ZTXX_WEBHOOK
*"-------------------------------------------------------------------
DATA: LV_ECS_JSON_REQ TYPE STRING, LV_ECS_JSON_RES TYPE STRING, LV_URL TYPE STRING, LV_RESPONSE TYPE STRING.
DATA: LO_HTTP_CLIENT TYPE REF TO IF_HTTP_CLIENT.
DATA: LO_EXCEPTION TYPE REF TO CX_ROOT.
DATA: LV_ERROR_TEXT TYPE STRING.
TYPES: TY_DETAILS TYPE STANDARD TABLE OF ZTXX_WEBHOOK WITH DEFAULT KEY.
TYPES: BEGIN OF TY_REQUEST, BUDAT TYPE BUDAT, TYPE1 TYPE BAPI_MTYPE, TAB TYPE TY_DETAILS, END OF TY_REQUEST.
TYPES: BEGIN OF TY_RESPONSE, DATA TYPE ABAP_BOOL, SUCCESS TYPE ABAP_BOOL, END OF TY_RESPONSE.
DATA: LS_REQUEST TYPE TY_REQUEST, LS_RESPONSE TYPE TY_RESPONSE.
* 1. 准备请求数据
LS_REQUEST = VALUE #( BUDAT = I_BUDAT TYPE1 = I_TYPE ).
APPEND LINES OF T_TAB[] TO LS_REQUEST-TAB.
* 2. 序列化请求数据
TRY.
LV_ECS_JSON_REQ = /UI2/CL_JSON=>SERIALIZE( DATA = LS_REQUEST PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-LOW_CASE ).
CATCH CX_ROOT INTO LO_EXCEPTION.
E_MSEG = 'JSON 序列化失败:' && LO_EXCEPTION->GET_TEXT( ).
E_TYPE = 'E'.
RETURN.
ENDTRY.
* 3. 设置 URL
LV_URL = 'webhook 地址'.
* 4. 创建 HTTP 客户端
TRY.
CALL METHOD CL_HTTP_CLIENT=>CREATE_BY_URL EXPORTING URL = LV_URL IMPORTING CLIENT = LO_HTTP_CLIENT EXCEPTIONS ARGUMENT_NOT_FOUND = 1 PLUGIN_NOT_ACTIVE = 2 INTERNAL_ERROR = 3 OTHERS = 4.
IF SY-SUBRC <> 0.
E_MSEG = '创建 HTTP 客户端失败'.
E_TYPE = 'E'.
RETURN.
ENDIF.
CATCH CX_ROOT INTO LO_EXCEPTION.
E_MSEG = '创建 HTTP 客户端异常:' && LO_EXCEPTION->GET_TEXT( ).
E_TYPE = 'E'.
RETURN.
ENDTRY.
* 5. 配置请求头
LO_HTTP_CLIENT->REQUEST->SET_METHOD( 'POST' ).
LO_HTTP_CLIENT->REQUEST->SET_CONTENT_TYPE( 'application/json' ).
LO_HTTP_CLIENT->REQUEST->SET_HEADER_FIELD( NAME = 'OperationCode' VALUE = 'xxxx.webhook' ).
LO_HTTP_CLIENT->REQUEST->SET_HEADER_FIELD( NAME = 'ClientId' VALUE = 'XXX' ).
* 设置请求数据
LO_HTTP_CLIENT->REQUEST->SET_CDATA( LV_ECS_JSON_REQ ).
* 6. 发送请求
TRY.
LO_HTTP_CLIENT->SEND( EXCEPTIONS HTTP_COMMUNICATION_FAILURE = 1 HTTP_INVALID_STATE = 2 OTHERS = 3 ).
IF SY-SUBRC <> 0.
LV_ERROR_TEXT = '发送请求失败'.
IF SY-SUBRC = 1. LV_ERROR_TEXT = 'HTTP 通信失败'.
ELSEIF SY-SUBRC = 2. LV_ERROR_TEXT = 'HTTP 状态无效'.
ENDIF.
E_MSEG = LV_ERROR_TEXT.
E_TYPE = 'E'.
LO_HTTP_CLIENT->CLOSE( ).
RETURN.
ENDIF.
CATCH CX_ROOT INTO LO_EXCEPTION.
E_MSEG = '发送请求异常:' && LO_EXCEPTION->GET_TEXT( ).
E_TYPE = 'E'.
LO_HTTP_CLIENT->CLOSE( ).
RETURN.
ENDTRY.
* 7. 接收响应
TRY.
LO_HTTP_CLIENT->RECEIVE( EXCEPTIONS HTTP_COMMUNICATION_FAILURE = 1 HTTP_INVALID_STATE = 2 OTHERS = 3 ).
IF SY-SUBRC <> 0.
LV_ERROR_TEXT = '接收响应失败'.
IF SY-SUBRC = 1. LV_ERROR_TEXT = 'HTTP 通信失败'.
ELSEIF SY-SUBRC = 2. LV_ERROR_TEXT = 'HTTP 状态无效'.
ENDIF.
E_MSEG = LV_ERROR_TEXT.
E_TYPE = 'E'.
LO_HTTP_CLIENT->CLOSE( ).
RETURN.
ENDIF.
CATCH CX_ROOT INTO LO_EXCEPTION.
E_MSEG = '接收响应异常:' && LO_EXCEPTION->GET_TEXT( ).
E_TYPE = 'E'.
LO_HTTP_CLIENT->CLOSE( ).
RETURN.
ENDTRY.
* 8. 获取响应数据
LV_RESPONSE = LO_HTTP_CLIENT->RESPONSE->GET_CDATA( ).
* 9. 关闭连接
LO_HTTP_CLIENT->CLOSE( ).
* 10. 解析响应数据
TRY.
/UI2/CL_JSON=>DESERIALIZE( EXPORTING JSON = LV_RESPONSE PRETTY_NAME = /UI2/CL_JSON=>PRETTY_MODE-LOW_CASE CHANGING DATA = LS_RESPONSE ).
CATCH CX_ROOT INTO LO_EXCEPTION.
E_MSEG = 'JSON 反序列化失败:' && LO_EXCEPTION->GET_TEXT( ).
E_TYPE = 'E'.
RETURN.
ENDTRY.
* 11. 处理响应结果
IF LS_RESPONSE-SUCCESS = ABAP_TRUE.
E_TYPE = 'S'.
E_MSEG = '接口调用成功'.
ELSE.
E_TYPE = 'E'.
E_MSEG = '接口调用失败'.
ENDIF.
ENDFUNCTION.


