乐趣区

关于saprfc:使用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

要获取更多 Jerry 的原创文章,请关注公众号 ” 汪子熙 ”:

退出移动版