Skip to Content
Author's profile photo Jerry Wang

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 guidelinewhere 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.

Assigned tags

      9 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Harish Choudhary
      Harish Choudhary

      Wonderful blog Jerry. Thanks for sharing.

      Author's profile photo Suchita Phulkar
      Suchita Phulkar

      Hi Jerry,

      Great blog ! Thanks 🙂

       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' ).

       

      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

       

       

      Author's profile photo Jerry Wang
      Jerry Wang
      Blog Post Author

      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

      Author's profile photo Suchita Phulkar
      Suchita Phulkar

      Thanks Jerry. So to encode, I pass values as user:password right ? or is it user/password ?

      Many thanks in Advance.

      Regards

      Suchita

      Author's profile photo Jerry Wang
      Jerry Wang
      Blog Post Author

      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

       

      Author's profile photo Suchita Phulkar
      Suchita Phulkar

      Thank you so much Jerry !!

      Author's profile photo Monica Cotes
      Monica Cotes

      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

      Author's profile photo Subina E S
      Subina E S

      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

      Author's profile photo amy amy.zhang04
      amy amy.zhang04

      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