Passing base64 encoded raw content as attachment (pdf) to S/4HANA Business Object via Attachment API, using SAP CPI as middleware
I came across a problem while working on a customer project, where we were implementing an interface to upload PDF files to S/4 HANA public cloud business object via Attachments API. Here I am sharing my experience and implementation via this blog with you, hoping that this will be useful to you sometime. Please add your comments and suggestions about this blog.
There is an external system which sends, over HTTPS, the pdf file content, encoded as base64, along with other information like the business object and its instance to which the file is to be added. S/4 HANA public cloud uses Attachments API to upload this file to the specified instance of the object Billing Document.
The external system sends the payload as mentioned below. This payload includes
- Billing Document ID (0090000044) to which the pdf file needs to be attached
- File name to be used for attachment (BLL2.pdf)
- Content of the pdf file encoded as base64 (highlighted in image). File content should not be sent without encoding for security reasons.
The Attachments API does not consume the base64 encoded file content directly as a message body. It required decoding of this content and obtaining technical parameters before the file could be uploaded to the Billing Document instance. Hence, we need to do these steps in the middleware like SAP CPI and pass the message header and body as expected by Attachments API.
To solve this problem I will focus only on the development required in the middleware (SAP CPI), in this blog. Assuming, below pre-requisites and other required things are already in place.
- Communication system and Communication user for inbound is defined in S/4. For help refer to blog
- Communication Arrangement is defined for Billing Integration scenario in S/4. For help refer to blog
- Have basic idea of various components used in integration flow in SAP CPI
- Nice to have read the help documentation on Attachments Refer to blog for reading.
We need a middleware like SAP CPI which can decode the base64 content and help to obtain other technical parameters to consume the services of the Attachments API. Thus, we developed an integration flow (iflow) which receives the payload from external system, transforms it and passes it to S/4 system. The contents of the iflow can be seen in the image below.
The iflow basically reads the incoming payload and extracts the various elements out of it to prepare the required header and body content that is required by the Attachments API. Iflow does the following steps and activities within.
1. Sender: Element Type: Participants ->Sender
Sender is an external system (element type: Participant) , e.g., postman, which sends the payload over HTTPS to the endpoint of this iflow. The endpoint needs to be defined in this connection as shown in the image. You can give endpoint of your choice.
2. Receive Payload (Step 1) : Element Type: Transformation->Content Modifier
- This component receives the payload (format mentioned above in the picture Payload_format.jpg ) from external system over HTTPS and stores it as part of message body
- Also, we define a message header element X-CSRF-Token as a constant. The value of X-CSRF-Token needs to be obtained in next step, by connecting with S/4 system before we can trigger the Attachments API
3. Get CSRF-token and Cookie (Step 2): The Attachments API need a CSRF token as part of message header to get invoked. This token and the cookie are retrieved by making a HTTP GET call to S/4 Attachments Later these parameters are passed in step 6 while posting data to the API.
3.1 Create Branch: Element Type: Routing->Multicast->Sequential Multicast
This element is required to send the message to multiple paths in a sequential manner. Since we need to make a call to S/4 to fetch the X-CSRF-Token and at the same time retain the payload body, we need to create two branches that are executed sequentially.
- Branch 1 is executed first. This makes a GET HTTP call to S/4 endpoint defined in communication arrangement and in response receives the value of the message header elements X-CSRF-Token and Cookie which is used later.
- Branch 2 is processed later, and it just carries the payload as is to next step.
3.2 Aggregate and Merge: Element Type: Routing->Gather
Aggregates the messages coming from two branches. Define the aggregation strategy as shown in the picture.
4. Define Message Headers (Step 3): Element Type: Transformation->Content Modifier
To trigger the Attachments API on S/4 a set of message headers needs be passed along with the body. Define and create these message headers here as shown in the picture and described below
- Cookie: defined as a constant and the value will be filled using the script
- X-CSRF-Token: Source type is header i.e., the value is picked from header data
- Slug: Refers to the name of the file to be uploaded and the value will be filled using the script (fetched from payload)
- Content-type: Refers to the type of file to be attached and here we hardcode it to application/pdf for PDF file.
- BusinessObjectTypeName: Refers to the name of the business object to which the file needs to be attached. VBRK refers to Billing Document.
- LinkedSAPObjectKey: Refers to Billing Document ID in S/4 to which the file needs to be attached. Value will be filled using script (fetched from payload)
5. Set Message Headers & Body (Step 4): Element Type: Transformation->Script->Groovy Script
In this step we will set the values to the message headers defined in previous step. Define a groovy script where you write the logic to read the payload received from external system and set the values of some of the message headers: Cookie, Slug and LinkedSAPObjectKey. The code is mentioned in the image.
A key point to note here is that we must set the message body with the base64 encoded content of the file in scripting (line 21). Only then the decoder can decode it and it can be consumed by S/4.
6. Decode Message Body (Step 5): Element Type: Transformation->Decoder->Base64 Decoder
In this step we decode the base64 content of the pdf file passed in the payload under the element <attachment>. The output of this step is the decoded content which can be passed to Attachments API in S/4.
7. Invoke Attachments API (Step 6): Element Type: Call->External Call->Request Reply
In this step the Attachments API on S/4 is triggered by passing the message headers and the message body (which is decoded base64 content) with a POST HTTP call to S/4.
Connect this element to a receiver system, in this case S/4, using HTTP adapter. The connection must be defined as shown in the image below.
The content should be attached as a pdf file to the specified Billing Document in S/4 HANA public cloud system as shown in the image below. You should be able to download this pdf file and open it.
To test the process your user should have the required authorization in BTP. Take the following steps to test:
- Save and deploy the above mentioned iflow.
- Once successfully deployed go to Monitor->Integration->Manage Integration Content->All.
- Iflow should appear here, and you should copy the endpoint URL, thus generated.
- Create a POST request in postman and specify the end point URL obtained in previous step.
- Specify the payload in Body section as Raw->text file.
- Click on Send and you should receive a response code 201 for successful operation.
- Login to S/4 system and open the app Manage Billing Document.
- Select and open the Billing Document ID that was used in payload for file to attach.
- You should be able to see the attachment under the Attachments