使用ABAP代码消费SAP Cloud for Customer的OData服务
In this blog, I will demonstrate how to create a new Opportunity by consuming C4C standard OData service via ABAP code. The related OData service for Opportunity with detailed explanation on its entity types could be found from SAP help:
I will use a HTTP POST request to finish the creation. A example about how to organize post body could be found from C4C OData development guideline, where ServiceRequest is used for demonstration. I just make minor changes to make it also works on Opportunity. First I test it in postman to ensure the successful creation:
I paste my http request body text here for your reference:
--batch_1
Content-Type: multipart/mixed; boundary=changeset_1
--changeset_1
Content-Type: application/http
Content-Transfer-Encoding: binary
POST OpportunityCollection HTTP/1.1
Content-Length: 5000
Accept: application/json
Content-Type: application/json
{
"AccountID": "8000018122",
"OwnerID": "8000018122",
"Name": {"content": "Testing ticket creation via OData Jerry1"}
}
--changeset_1--
--batch_1--
And a new opportunity could successfully be created in postman:
Now all I need to do is just to translate the activities I have done in postman into ABAP code.
I wrote an ABAP report to create Opportunity by consuming OData service:
zcl_odata_tool=>get_csrf_token_and_cookie( IMPORTING et_cookies = DATA(lt_cookie)
ev_token = DATA(lv_token) ).
zcl_odata_tool=>create_opp( iv_token = lv_token it_cookies = lt_cookie ).
Execute the report, new opportunity could be created and found in system:
Source code for ZCL_ODATA_TOOL:
CLASS zcl_odata_tool DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
CLASS-METHODS get_csrf_token_and_cookie
EXPORTING
!et_cookies TYPE tihttpcki
!ev_token TYPE string .
CLASS-METHODS create_opp
IMPORTING
!iv_token TYPE string
!it_cookies TYPE tihttpcki .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZCL_ODATA_TOOL IMPLEMENTATION.
METHOD create_opp.
DEFINE insert_line.
lv_body = lv_body && &1.
lv_body = lv_body && cl_abap_char_utilities=>newline.
END-OF-DEFINITION.
DATA:lo_http_client TYPE REF TO if_http_client,
lv_status TYPE i,
lt_fields TYPE tihttpnvp,
lv_sysubrc TYPE sysubrc.
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = 'https://<your C4C host>/sap/c4c/odata/v1/c4codata/$batch'
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
ASSERT sy-subrc = 0.
lo_http_client->propertytype_accept_cookie = if_http_client=>co_enabled.
CALL METHOD lo_http_client->request->set_method( if_http_request=>co_request_method_post ).
lo_http_client->request->set_header_field( name = 'Content-Type' value = 'multipart/mixed; boundary=batch_1' ).
lo_http_client->request->set_header_field( name = 'x-csrf-token' value = iv_token ).
lo_http_client->request->set_header_field( name = 'Authorization' value = 'your basic authentication code' ).
LOOP AT it_cookies ASSIGNING FIELD-SYMBOL(<cookie>).
lo_http_client->request->set_cookie( name = <cookie>-name
value = <cookie>-value ).
ENDLOOP.
DATA: lv_body TYPE string.
insert_line '--batch_1'.
insert_line 'Content-Type: multipart/mixed; boundary=changeset_1'.
lv_body = lv_body && cl_abap_char_utilities=>cr_lf.
*
insert_line '--changeset_1'.
insert_line 'Content-Type: application/http'.
insert_line 'Content-Transfer-Encoding: binary'.
lv_body = lv_body && cl_abap_char_utilities=>cr_lf.
insert_line 'POST OpportunityCollection HTTP/1.1'.
insert_line 'Content-Length: 5000'.
insert_line 'Accept: application/json'.
insert_line 'Content-Type: application/json'.
lv_body = lv_body && cl_abap_char_utilities=>cr_lf.
insert_line '{'.
insert_line '"AccountID": "8000018122",'.
insert_line '"OwnerID": "8000018122",'.
insert_line `"Name": {"content": "Testing ticket creation via OData Jerry1"}`.
insert_line '}'.
insert_line '--changeset_1--'.
lv_body = lv_body && cl_abap_char_utilities=>cr_lf.
insert_line '--batch_1--'.
lo_http_client->request->set_cdata( data = lv_body ).
CALL METHOD lo_http_client->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3.
ASSERT sy-subrc = 0.
CALL METHOD lo_http_client->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3.
IF sy-subrc <> 0.
CALL METHOD lo_http_client->get_last_error
IMPORTING
code = lv_sysubrc
message = DATA(ev_message).
WRITE: / 'error occurred during receive data' COLOR COL_NEGATIVE.
RETURN.
ENDIF.
DATA(lv_json) = lo_http_client->response->get_cdata( ).
WRITE:/ lv_json.
ENDMETHOD.
METHOD get_csrf_token_and_cookie.
DATA: lo_http_client TYPE REF TO if_http_client,
lv_status TYPE i,
lt_fields TYPE tihttpnvp,
lv_sysubrc TYPE sysubrc.
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = 'https://<your C4C host>/sap/c4c/odata/v1/c4codata/'
IMPORTING
client = lo_http_client
EXCEPTIONS
argument_not_found = 1
plugin_not_active = 2
internal_error = 3
OTHERS = 4.
ASSERT sy-subrc = 0.
lo_http_client->propertytype_accept_cookie = if_http_client=>co_enabled.
CALL METHOD lo_http_client->request->set_method( if_http_request=>co_request_method_get ).
lo_http_client->request->set_header_field( name = 'x-csrf-token' value = 'Fetch' ).
lo_http_client->request->set_header_field( name = 'Accept' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Content-Type' value = 'application/json' ).
lo_http_client->request->set_header_field( name = 'Authorization' value = 'Your basic authentication' ).
CALL METHOD lo_http_client->send
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3.
ASSERT sy-subrc = 0.
CALL METHOD lo_http_client->receive
EXCEPTIONS
http_communication_failure = 1
http_invalid_state = 2
http_processing_failed = 3.
IF sy-subrc <> 0.
CALL METHOD lo_http_client->get_last_error
IMPORTING
code = lv_sysubrc
message = DATA(ev_message).
WRITE: / 'Error when getting token:', ev_message.
RETURN.
ENDIF.
lo_http_client->response->get_header_fields( CHANGING fields = lt_fields ).
READ TABLE lt_fields ASSIGNING FIELD-SYMBOL(<field>) WITH KEY name = 'x-csrf-token'.
ev_token = <field>-value.
lo_http_client->response->get_cookies( CHANGING cookies = et_cookies ).
lo_http_client->close( ).
ENDMETHOD.
ENDCLASS.
Further reading
You can find a list of all other blogs related to OData written by Jerry.
- Consume standard C4C OData service via ABAP code
- Leverage C4C Odata notification to monitor C4C Opportunity change in CRM system
- OData Service backend implementation in C4C, CRM and S4 HANA
- JMeter beginner – how to use JMeter to measure performance of OData service accessed parallelly
- Regarding cookie manipulation in CL_HTTP_CLIENT to avoid CSRF token validation failure issue
- 删除链表中的重复元素
- Single Number and Single Number II
- 前端限制上传文件的类型
- JavaSript模块规范 - AMD规范与CMD规范介绍
- [大数据之Sqoop] —— Sqoop初探
- [大数据之Sqoop] —— 什么是Sqoop?
- Node.js包管理器Yarn的入门介绍与安装
- static_cast ,reinterpret_cast
- NodeJS使用formidable实现文件上传
- 签下北方最大港口,聚焦无人驾驶卡车技术的主线科技朝商业化又进一步
- 对缓存的思考——提高命中率
- 实用手册:130+ 提高开发效率的 vim 常用命令
- Sqoop切分数据的思想概况
- 设计模式分类
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Django+Vue开发生鲜电商平台之10.购物车、订单管理和支付功能
- 嵌入式linux之go语言开发(七)protobuf的使用
- 动手写简单的嵌入式操作系统一
- LeetCode 92 | 大公司常考的面试题,翻转链表当中指定部分
- 快速学习-Apollo从入门到精通
- dotnet 使用 SourceLink 将 NuGet 链接源代码到 GitHub 等仓库
- 嵌入式linux之go语言开发(八)存储模块的封装(一)
- QGIS制图中面积小的区域不显示注记
- linux 编译 c或cpp 文件为动态库 so 文件(最简单直观的模板)
- 满眼只有React和Vue,却对前端数据层几乎一无所知
- 嵌入式linux之go语言开发(八)存储模块的封装(二)
- 招商银行校招题二
- 小程序工程化系列(一):文件依赖分析
- ucgui在windows上的移植,及为go语言打造简易跨平台GUI的想法
- React setState 是异步执行还是同步执行?