Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 

Background


During one of my SAP Cloud Platform Integration projects on FSN where Bank Integration was carried out, I came across MIME Multipart Response which contained attachment file embedded into it along with the payload response.

We are making HTTP call to Bank using an HTTP API Request and in Response its sending back the Payload in MIME Multipart format.

It can get slightly tricky to handle MIME Multi part which have 2 MIME Objects (Payload+Attchment).

In order to help the community here is my solution approach.

 

Integration Flow




 

Solution Approach


Cloud Integration tenant is making HTTP Request with Encrypted and Signed Payload along with Header Attributes to Client Server. In response Client server is sending back the Payload containing MIME Multipart Response along with Header Attributes.

This MIME Multipart is containing 2 parts

  1. Payload (Encrypted & Signed).

  2. Attachment (Encrypted)


 



 

 

After receiving the Response from Client server, store the Response in Header Attribute and use Decoder as shown in below pic.



With this Multi part Decoder the mail Response Body (which is 1st Part ) can be extracted

Next you can use Content modifier to extract the Attachment Decryption Key and overwrite the BODY with the earlier saved Header Attribute of Original Body(Client response).

With below Groovy you can extract the attachment and decrypt the same using the Decryption key extracted in previous step.

Note:

import com.sap.gateway.ip.core.customdev.util.Message;

import java.util.HashMap;

import com.sap.gateway.ip.core.customdev.processor.MessageImpl;

import java.util.Map;

import java.util.Iterator;

import java.nio.charset.Charset;

import java.nio.Buffer;

import java.nio.CharBuffer;

import java.nio.ByteBuffer

import javax.activation.DataHandler;

import java.io.*;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.xml.sax.InputSource;

import javax.xml.transform.*;

import javax.xml.transform.stream.*;

import javax.xml.transform.dom.DOMSource;

import javax.xml.xpath.*;

import java.lang.Object;

import javax.mail.internet.MimeMultipart;

import javax.mail.util.ByteArrayDataSource;

import javax.mail.BodyPart;

import java.io.StringReader;

import javax.ws.rs.core.MediaType;

import org.apache.commons.io.FileUtils;

import org.apache.camel.impl.DefaultAttachment;

import java.nio.charset.StandardCharsets;

//Java keystore

import java.security.KeyStore;

import com.sap.it.api.keystore.KeystoreService;

import com.sap.it.api.keystore.exception.KeystoreException;

import org.apache.xml.security.encryption.*;

import java.security.*;

import java.security.cert.*;

import java.util.Collections;

import org.apache.camel.impl.DefaultAttachment;

import javax.mail.util.ByteArrayDataSource;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.DESedeKeySpec;

import javax.crypto.Cipher;

import javax.crypto.SecretKeyFactory;

import org.apache.commons.codec.binary.Base64;

 

 

def Message processData(Message message) {

 

def messageLog = messageLogFactory.getMessageLog(message);

 

//Headers

def map = message.getHeaders();

String decryptionKey = map.get("Key");

//Extract Body as BYTES

def body = message.getBody(InputStream.class);

 

byte[] data1 = body.getBytes();

 

MimeMultipart mp = new MimeMultipart(new ByteArrayDataSource(data1, MediaType.TEXT_XML));

int count = mp.getCount();

//Handling BYTE ARRAY STREAM

ByteArrayOutputStream baos = new ByteArrayOutputStream();

//Extracting MIME one by one

for (int i = 0; i < count; i++) {

BodyPart bodyPart = mp.getBodyPart(i);

String contentType = bodyPart.getContentType();

System.out.println("ContentType "+contentType);

System.out.println("Content "+bodyPart.getContent());

if(bodyPart.isMimeType("text/xml"))

{

continue;

}

else

{

ByteArrayInputStream bai = (ByteArrayInputStream)bodyPart.getContent();

byte[] buf = new byte[8192];

for (;;) {

int nread = bai.read(buf, 0, buf.length);

if (nread <= 0) {

break;

}

baos.write(buf, 0, nread);

}

//Decrypting BYTEArray using Decryption Key

byte[] attachment = baos.toByteArray();

int ivLen = 8;

byte[] keyiv = new byte[ivLen];

for( i=0 ; i<ivLen ; i++) {

keyiv[i] = attachment[i];

}

int dataLen = attachment.length-ivLen;

byte[] data = new byte[dataLen];

for ( i=0 ; i<dataLen ; i++) {

data[i] = attachment[i+ivLen];

}

Key deskey = null;

DESedeKeySpec spec = new DESedeKeySpec(Base64.decodeBase64(decryptionKey));

SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");

deskey = keyfactory.generateSecret(spec);

Cipher cipher = Cipher.getInstance("TripleDES/CBC/NoPadding");//PKCS5Padding NoPadding

IvParameterSpec ips = new IvParameterSpec(keyiv);

cipher.init(Cipher.DECRYPT_MODE, deskey, ips);

byte[] bout = cipher.doFinal(data);

byte[] decryptedStatementFile = Base64.decodeBase64(bout);

def dataSource = new ByteArrayDataSource(decryptedStatementFile, "text/plain");

def attachmentobj = new DefaultAttachment(dataSource);

//Creating attachment object from Decrypted BYTE Array

message.addAttachmentObject("ResponseDecrypted.txt", attachmentobj);

 

String attachstr = new String(attachment, StandardCharsets.UTF_8);

if(messageLog != null){

messageLog.addAttachmentAsString("Response2Payload:", attachstr, "text/plain");

}

 

bai.close();

 

}

}

 

return message;

 

}

 

 

 

And finally this attachment can be sent via Email to SMTP Receiver make sure to TICK the below box in your receiver settings.

 



iFlow would look something like this.



 

Summary


In order to summarize, MIME multipart handling needs Standard Decoder component along with the some sophisticated scripting.

Here scripting focus on 3 areas: First, getting the Message Body as BYTE Input Stream. Second, using loop extract the 2 parts one by one as BYTE Array and Finally, Decode using the Decryption Key Algo (if Applicable).

Also thing to be noted here is that attachment which was extracted and decoded/decrypted can only be sent as an attachment via mail as its a MIME object.
1 Comment