We got an interesting scenario where a product manager wanted to store documents in an SAP Easy DMS.
SAP Easy DMS is a Document Management System that tracks, manages, and stores documents.
Power Automate is a service that helps you create automated workflows between your favourite apps and services to synchronise files, get notifications, collect data, and more.
As we have no direct connectors from Power Automate to SAP Easy DMS, hence we had to build our own ODATA Services in SAP Abap and consume it from Power Automate.
Let us get started
Steps to Create OData to Upload file in SAP
1. Create a structure with field type string to capture data in ODATA service with other required fields as shown below.
2. Create OData service in SEGW using the above Structure (Entity Types & Entity Set). Generate and Activate Services.
3. Redefine Create Method and use the below code sequence.
4. Read data into method
5. Convert Base 64 input data into Xtring
6. Convert XSTRING_TO_BINARY
7. Create document using FM BAPI_DOCUMENT_CREATE2
8. Once document creation is successful use FM CVAPI_DOC_CHECKIN to upload file in Document.
some sample code
DATA : lv_xstring TYPE xstring, lv_op_length TYPE i, lv_doctype TYPE dokar, lv_docnumber TYPE doknr, lv_docpart TYPE doktl_d, lv_docversion TYPE dokvr, ls_return TYPE bapiret2, ls_entity TYPE zst_dms_doc_upload, ls_docdata TYPE bapi_doc_draw2, ls_objectdescr TYPE bapi_doc_drat, lt_objectdescr TYPE TABLE OF bapi_doc_drat, ls_pdf_checkin TYPE drao, lt_pdf_checkin TYPE STANDARD TABLE OF drao, ls_files TYPE cvapi_doc_file, lt_files TYPE STANDARD TABLE OF cvapi_doc_file, lt_content TYPE STANDARD TABLE OF orblk WITH DEFAULT KEY, ls_msg TYPE messages, ls_api_control TYPE cvapi_api_control. io_data_provider->read_entry_data( IMPORTING es_data = ls_entity ). CALL FUNCTION 'SCMS_BASE64_DECODE_STR' EXPORTING input = ls_entity-file_content IMPORTING output = lv_xstring EXCEPTIONS failed = 1 OTHERS = 2. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = lv_xstring IMPORTING output_length = lv_op_length TABLES binary_tab = lt_content. " SET VALUES ls_docdata-documenttype = 'Mention Document Type'. ls_docdata-documentversion = '00'. ls_docdata-documentpart = '000'. ls_docdata-laboratory = '000 '. ls_objectdescr-description = 'Test Document Aditya' && ':' && sy-datum && '-' && sy-uzeit. ls_objectdescr-language = 'E'. ls_objectdescr-language_iso = 'EN'. APPEND ls_objectdescr TO lt_objectdescr. " CREATE ATTACHMENT CALL FUNCTION 'BAPI_DOCUMENT_CREATE2' EXPORTING documentdata = ls_docdata IMPORTING documenttype = lv_doctype documentnumber = lv_docnumber documentpart = lv_docpart documentversion = lv_docversion return = ls_return TABLES documentdescriptions = lt_objectdescr. COMMIT WORK AND WAIT. * Files Data ls_files-filename = ls_entity-file_name. ls_files-storage_cat = ‘Mention Storage Category’. ls_files-appnr = '1'. ls_files-dappl = ls_entity-file_application. "PDF/WIN ls_files-description = ls_entity-file_description. ls_files-checked_in = 'X'. ls_files-updateflag = 'I'. APPEND ls_files TO lt_files. * Control Data ls_api_control-no_update_task = 'X'. ls_api_control-api_mode = 'X'. ls_api_control-commit_flag = 'X'. * Prepare checkin file data. LOOP AT lt_content INTO DATA(lw_content). ls_pdf_checkin-dokar = lv_doctype. ls_pdf_checkin-doknr = lv_docnumber. ls_pdf_checkin-dokvr = lv_docversion. ls_pdf_checkin-doktl = lv_docpart. ls_pdf_checkin-appnr = '1'. ls_pdf_checkin-zaehl = sy-tabix. ls_pdf_checkin-orln = lv_op_length. ls_pdf_checkin-orblk = lw_content. APPEND ls_pdf_checkin TO lt_pdf_checkin. CLEAR : ls_pdf_checkin. ENDLOOP. * Wait for 10 seconds WAIT UP TO 5 SECONDS. CALL FUNCTION 'CVAPI_DOC_CHECKIN' EXPORTING pf_dokar = lv_doctype pf_doknr = lv_docnumber pf_dokvr = lv_docversion pf_doktl = lv_docpart pf_ftp_dest = 'SAPFTPA' pf_http_dest = 'SAPHTTPA' ps_api_control = ls_api_control IMPORTING psx_message = ls_msg TABLES pt_files_x = lt_files pt_content = lt_pdf_checkin. COMMIT WORK AND WAIT.
Consume ODATA from Power Automate
Before we did into Power Automate, it is important to mention that we tested the endpoint using Postman and it worked really well – however while automating it using Power Automate, it failed with the following error “CSRF Token Validation Failed”.
I found from this blog that we had to pass the Cookie – from the initial POST while getting the x-csrf token – to the next POST while posting the document; that too in some specific format.
We are going to see all these in detail.
This is how the entire flow looks alike
1. Trigger the flow on a Selected File from SharePoint Online
2. Get file properties
3. Get file content
4. HTTP – GET x-csrf-token
in ODATA, on change requests (PUT, POST, and DELETE) of REST clients to an ABAP server, the client has to provide a CSRF (Cross-Site Request Forgery) token.
Such a token can be retrieved via a previous service call to the ABAP server. For this, first on a none-changing call (GET, HEAD, OPTIONS), the client has to get this token by setting the HTTP header X-CSRF-Token to the value Fetch. A CSRF token is returned by the ABAP server in the same header and can be used for subsequent, server state changing calls using header X-CSRF-Token.
If this header is not present on a server state changing REST call, the server will respond with a HTTP 403 (“Forbidden”) return code, the HTTP header is set to “Required” and an error text (for example, “CSRF token validation failed”) is returned.
The validity of the CSRF token depends on the release of the ABAP component SAP_BASIS and on the activation of the security session management (which is controlled via the transaction SICF_SESSIONS on the granularity of SAP clients):
a) Release < 7.03/7.31 or the security session management is inactive: An own CSRF cookie gets generated (sap-XSRF_<SystemID>_<SAPClient>) and this CSRF token remains valid for 24 hours (86400 seconds).
b) Release >= 7.03/7.31, the validity is bound to the security session, which depends on the system parameter http/security_session_timeout value (see transaction RZ11 for details on this parameter). By default, the security session management is active in these releases.
5. Compose – Base64
6. Initialize variable – FileName
7. Variable – Set x-csrf-token
8. Variable – Set-Cookie
9. Various compose actions are needed to set the cookie
Compose – Split All
Compose – Sap-client
Compose – MYSAPSSO2
Compose – SAP SESSIONID
Compose – SPNegoTokenRequested
Compose – Postman Cookie Format
concat(outputs(‘Compose_-MYSAPSSO2′),’; ‘,outputs(‘Compose-SAP_SESSIONID’),’; ‘,outputs(‘Compose-SPNegoTokenRequested’),’; ‘,outputs(‘Compose-_Sap-client’))
Compose – Document Extension
10. Check whether the uploaded file is a PDF or an OFFICE File
11. Finally HTTP – POST to SAP Easy DMS
This was an interesting approach to connecting SAP using ODATA from a Microsoft Power Platform.
Hoping to share my knowledge soon.
Thanks for reading this post 🙂