Consume standard C4C OData service via ABAP code
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
Wonderful blog Jerry. Thanks for sharing.
Hi Jerry,
Great blog ! Thanks 🙂
In the above code, how do I conver the Authorization - User:password into base64encoded value ? In POSTMAN we mention the User & password under Authorization tab & it automatically adds the base64encoded value under header.
Can you please advice ?
Thanks & Regards
Suchita
Hi Suchita,
In case you just would like to hard code the encoded value in your code, you can use many tool to get the encoded value, for example this website: https://www.base64encode.org/
Or you can search by keyword "*BASE64*" in your ABAP system using tcode SE37, there are lots of function modules available to achieve it.
Best regards,
Jerry
Thanks Jerry. So to encode, I pass values as user:password right ? or is it user/password ?
Many thanks in Advance.
Regards
Suchita
Hi Suchita,
Should be username:password. You can find more detail about basic authentication in wikipedia: https://en.wikipedia.org/wiki/Basic_access_authentication
Best regards,
Jerry
Thank you so much Jerry !!
Good day Jerry,
Very heIpful blog! thanks for sharing. I am totally new with OData. I need to integrate a web form of customer site with Sales Cloud to update / consult / create contacts, corporate accounts and opportunities. How is the authentication definition for OData in Sales Cloud? I can not find a way to generate a technical user like I used to do with the SOAP service. I refer to this link https://help.sap.com/viewer/1364b70b9cbb417ea5e2d80e966d4f49/1805/en-US/6c0a463cc9ca450cbd01a9a5057ce682.html but in the communication agreement I do not know how to relate my OData URL.
Can you give me a guide?
Thank you and best regards.
Monica
Hi Jerry,
This post was very useful.But unfortunately, I have to read some data from C4C using the URL: https://<myhostname>/sap/c4c/odata/v1/c4codataapi/ServiceRequestCollection('UUID'). I am getting the values using this URL in ODATA Console. But when I tried to write the corresponding code in ABAP, i failed. Could you please share me or let me know how can I write the corresponding ABAP code for reading data from C4C using this link.
Thanks and Regards,
Subina E S
Hi Jerry,
I would like to call OData service for Last Mile Adaptor in ABAP program, due to its $batch processing file shared by functional, there are multiple entities in our file at a single time.
Can we use Macro "Insert_line" to set the file as body with multiple entities and then send it ?
Regards,
Yahui Zhang