cancel
Showing results for 
Search instead for 
Did you mean: 

API to POST to SAP | RAP | SEGW | if_http_extension~handle_request

Sathya_Gunasekaran
Active Participant
487

Hello experts,

We have a requirement for a non-SAP cloud system to POST a simple JSON paylod to SAP S/4 and the schema is something similar to

{
	"event": "initiated",
	"date": "2021-10-12T19:26:01Z",
	"data": {
		"id": "MMM12345678",
		"amount": "100",
		"currency": "GBP",
		"payment_method": {
			"type": "card"
		},
		"fields": {
			"reference": "REF-1234",
			"id": "123456789"
		},
		"payer": {
			"first_name": "TEST",
			"last_name": "TESTL",
			"email": "Test.Test@Test.com"
		}
	}
}

No GET needed. What is the best way to handle this? REST handler class or an ODATA  service using SEGW or ODATA service using RAP. If RAP is the reommended way, how to define the nested json structure as custom entity for the above payload please?

Thank you.

Sathya

 

 

Accepted Solutions (0)

Answers (6)

Answers (6)

jaroslav_hrbacek
Participant

Hello Sathya,

if you have such an RAP Webservice in your SAP, you can call it with POST request. Let say you have orders( root ) and its items( children) 

the http post request you can call it something like (curl...) :

 

curl --location --request POST 'https://<your_sap_system>/sap/opu/odata4/sap/zui_salesorder_srv/0001/$batch?sap-client=050

--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Basic <your_base64_encoded_credentials>' \
--data-raw '{
  "SalesOrderId": "1000000002",
  "Description": "Sales Order via curl",
  "to_Items": [
    {
      "ItemId": "000001",
      "ProductId": "MATERIAL01",
      "Quantity": 2.5
    },
    {
      "ItemId": "000002",
      "ProductId": "MATERIAL02",
      "Quantity": 8.0
    }
  ]
}'

to_items is your assotiation to children / items.....

Sathya_Gunasekaran
Active Participant
0 Kudos
The requirement is to accept a nested JSON structure Jaroslav ( Not an array of item).
jaroslav_hrbacek
Participant
0 Kudos
but so you can achieve it with next layer of children(grandchild), etc subitem, subsubitem etc..-> in this way you get nested structure ready to accept a nested JSON structure
jaroslav_hrbacek
Participant
0 Kudos
of course it always depends on your context and needs, SICF service with IF_HTTP_EXTENSION can be your choise if RAP is unknown to you
Sathya_Gunasekaran
Active Participant
0 Kudos
I think I am not explaining it properly. The cincoming payload doesn't have [ ]. Instead it has the structure { { } } - This is the bit that I don't understand how to handle in RAP
jaroslav_hrbacek
Participant
0 Kudos
in rap if it is [ ] or {{}} it is set through the assotiation between root->child{{ / children {[ ] ->/ grandchild {{ / grandchildren {[ ]. If the assotiation is [1..n] then it is an array like items and if the assotiation is [1..1] then it is your nested structure like child->grandchild.
jaroslav_hrbacek
Participant

Hello Sathya,

If you are going to use in your task RAP Object ( Root+Child etc..) as suggested, you can use unmanaged save. see docu: Integrating Unmanaged Save in Managed Business Objects 

Here you can use your BAPI in the class and its method 

save_modified

here you have all you need. Your JSON data are in the importing parameters, because you have defined your rap object root+ child and you can read data of it within  query.

Regards

Jarda

Sathya_Gunasekaran
Active Participant
0 Kudos
Thanks for taking time to respine Jarda. The problem is the nested JSON structure. If we define root and association, we get an array for the item. I am still not sure how to accept the above payload as is. Any ideas? Thanks again.
kyo_choi2
Participant
0 Kudos
I think you might want to try the SEGW OData using Deep Entity. With SAP Gateway client and ABAP implementation, it's generally easier to develop. RAP also is good but you will have to use tools like Postman to test which is not SAP.
junwu
SAP Champion
SAP Champion
0 Kudos

deep structure data doesn't mean you have to model the bo in that way(hierarchy).

that deep structure data is just the function call paramter

follow this one to implement action in rap which can take deep structure data as parameter

https://community.sap.com/t5/technology-blogs-by-members/implementing-deep-action-for-bulk-approval-...

for the BO, you can just define a dummy custom entity as your root and implement a action by following that blog.

junwu
SAP Champion
SAP Champion
if_http_extension~handle_request would be the easiest
Sathya_Gunasekaran
Active Participant
0 Kudos
the payload doesn't have any item ( no array [ ] ). But a nested structure 😞
jaroslav_hrbacek
Participant
0 Kudos

{{ or nested structure is no problem. The main thing to declare ABAP structure to map it. No matter if you user RAP or if_http_extension~handle_request

lets suppose you use SICF WebAPI with if_http_extension~handle_request

there in the handler class:

1. Define ABAP structures that mirror the JSON

You can define nested structures in a TYPE or TYPESblock. Example:

TYPES: BEGIN OF ty_payment_method,
         type TYPE string,
       END OF ty_payment_method.

TYPES: BEGIN OF ty_fields,
         reference TYPE string,
         id        TYPE string,
       END OF ty_fields.

TYPES: BEGIN OF ty_payer,
         first_name TYPE string,
         last_name  TYPE string,
         email      TYPE string,
       END OF ty_payer.

TYPES: BEGIN OF ty_data,
         id             TYPE string,
         amount         TYPE string,
         currency       TYPE string,
         payment_method TYPE ty_payment_method,
         fields         TYPE ty_fields,
         payer          TYPE ty_payer,
       END OF ty_data.

TYPES: BEGIN OF ty_json_root,
         event TYPE string,
         date  TYPE string,
         data  TYPE ty_data,
       END OF ty_json_root.

 2. Parse JSON using /ui2/cl_json or cl_trex_json_deserializer

DATA: lv_json_string TYPE string,
      ls_json_data   TYPE ty_json_root.

" Assuming you already received the JSON payload into lv_json_string
CALL METHOD /ui2/cl_json=>deserialize(
  EXPORTING
    json        = lv_json_string
  CHANGING
    data        = ls_json_data
  EXCEPTIONS
    others      = 1 ).
IF sy-subrc <> 0.
  " Handle error
ENDIF.

You now have all the fields parsed into your ABAP structure ls_json_data.

3. Use the data

Now you can use it like any ABAP structure:

WRITE: / 'Event:',        ls_json_data-event,
       / 'Date:',         ls_json_data-date,
       / 'Payment ID:',   ls_json_data-data-id,
       / 'Amount:',       ls_json_data-data-amount,
       / 'Currency:',     ls_json_data-data-currency,
       / 'Payer:',        ls_json_data-data-payer-first_name, ls_json_data-data-payer-last_name,
       / 'Email:',        ls_json_data-data-payer-email.

Ensure that you receive the request body using server->request->get_cdata() or get_input_stream() if you're implementing your own ICF handler class (implementing IF_HTTP_EXTENSION).If you're using SAP Gateway or RAP, similar JSON parsing applies with the appropriate context entity.

 

 

Sathya_Gunasekaran
Active Participant
0 Kudos
I know that if_http_extension~handle_request can handle nested str .
Sathya_Gunasekaran
Active Participant
0 Kudos
Sorry, pressed enter too soon. Can this be done in RAP? That is my original question. Thank you
jaroslav_hrbacek
Participant
0 Kudos
you can do it with RAP. As I wrote you have to define the same structures as in my ABAP example. Then build your RAP Object with root and child structure. Root goes your id, amount, fields, payer etc. Your root has many children( nested). One child is linked through payer, the next fields etc...In child payer you have first_name etc.. then you have to make all the components of an RAP object such as behavior, webservice, etc... in behavior class you can implement what ever you want to do with your data.
ArunJacob
Active Participant
0 Kudos

root:-

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Event Root'
@ObjectModel.compositionRoot: true
define view entity ZI_Event
  as select from zevent
{
  key id    as EventId,
      event,
      @ObjectModel.association.type: [#TO_COMPOSITION_CHILD]
      _Payer
}

Thanks

Sathya_Gunasekaran
Active Participant
0 Kudos
and create a z table called zevent?
ArunJacob
Active Participant
yes I hope for storing(Post) , a custom table required Sathya
Sathya_Gunasekaran
Active Participant
Thanks Arun. No, I have to write logic/use BAPIs to update some standard tables. The JSON payload doesn't link to any table in the DB. It will be a lot tidier with SEGW/HTTP Handler. 😞
ArunJacob
Active Participant
0 Kudos

yes RAP as the preferred option. use @ObjectModel.compositionRoot and @ObjectModel.composition to handle nesting

the root view of the hierarchy must be annotated with @ObjectModel.compositionRoot: true .

 

Thanks,

Sathya_Gunasekaran
Active Participant
0 Kudos
Thanks Arun. We don't have any related table(s) in SAP. How to difine custom entities as root/child