Click here to Skip to main content
15,881,938 members
Articles / Programming Languages / C#

Mocking Financial Middleware System

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
5 Nov 2015CPOL10 min read 15.2K   254   8   2
Article helps reducing offsite development efforts by presenting a Mocking Layer for financial Middleware systems

Contents

Introduction

Gaining experience over financial applications is no way ordinary. As you have to take care number of additional stuff that normally developers skip or don’t know. For example full filling Regulatory Requirements like Audit Log, maker checker rules, taking extreme safety measures in executing financial transactions and their reversals, security,  data archiving, Anti Money Laundering, KYC to name a few.

Integration is primarily core part of any financial application as either way you have to integrate with banking host or middle ware and this is not an easy job at all.  Do keep in mind that Host systems usually refers to Core Banking Systems and Middle ware is actually channel integrator that talks to host systems like ATM, SMS, phone banking, IVR, WAP, etc

In the development environment the most critical challenge is to write integration code offsite because middleware or host systems are not available at development centers. This critical limitation  forces companies to do all the integration onsite which obviously increase the development and post production support cost because in majority of cases fixes needs to be investigated onsite.

This article helps easing this problem by creating mocking integration layer at development center by creating a virtual environment that mimics host systems/middle ware systems.

Image 1

By creating a mocking layer we can easily mimic middle ware at development center which significantly helps in development/support activities.

Image 2

Mock Integration Layer

This integration layer should be designed with following set of Goals.

  • Front End application must not be changed in any way for this mocking layer and see it as true integration layer just like production
  • Layer should be change friendly, which means adding new transaction should be a very easy and should not require any development effort at all

Customization on Front End Application at offsite development center for this mocking integration layer would kill the objective as we will never be sure of the quality because of the customization made in the application.

If this mocking layer is not change friendly that means we are adding additional development cost over project by maintaining this layer eventually lead the development team to do the activity onsite and discard this mocking layer.

The Design

Host systems normally communicate via message based communication protocol over TCP/IP. This can be ISO 8583 message format, simply character delimited text format or other vendor driven format. Each message is tag as a transaction with Request/Response format. Each Request/Response has Header and data section. A typical message header could be like

Content

Byte Length

Description

Message Size in bytes

4

0600 if message length is 600

Message Type

2

01-Request

02-Response

Transaction Code

4

0001-Balance Inquiry

DateTime

14

YYYYMMDDHHmmss [20150901112910]

STAN

6

123456

Sample message header is elaborated below for easy understanding

Image 3

As now we understood how a typical host system works we need to design the mocking layer to have following modules

  • A TCP/IP module for communication between frontend and mocking layer
  • A mechanism to assemble message request/response
  • A data section that contains Dummy Consumer Information

TCP/IP Module

TCP/IP module is the simplest one and can be built using examples present all over the web. We need to understand that this is mocking layer being built to use for offsite development hence no production like performance requirement is required. A simple TCP/IP module is sufficient for this purpose.

Assembling Request/Response message

This is the core part of the mocking layer and it must be design in such ways that addition/modifications could be made in a fly. XML is great in doing wonders as it has great flexibility and power over data driven applications. Let’s name this critical xml file as TransactonMetaInfo.xml and start creating it

A basic version could be like:

XML
<Root Client="ABC Bank" Product="ACME Product">
   <Header Type="Request"
      <Field Name="MessageType" EvalFunction="" DefaultValue="" />
      <Field Name="Transactioncode" EvalFunction="" DefaultValue="" />
      <Field Name="TranDateTime" EvalFunction="" DefaultValue="" />
      <Field Name="STAN" EvalFunction="" DefaultValue="" />
   </Header>
   <Header Type="Response">
      <Field Name="MessageType" EvalFunction="" DefaultValue="" />
      <Field Name="Transactioncode" EvalFunction="" DefaultValue="" />
      <Field Name="TranDateTime" EvalFunction="" DefaultValue="" />
      <Field Name="STAN" EvalFunction="" DefaultValue="" />
   </Header>
   <Transaction DispName="Balance Inquiry" Code="9999">
      <Request Code="11" Example="">
         <Header Type="Request"/>
         <Field Name="CustomerPan" EvalFunction="" DefaultValue="" />
      </Request>
      <Response Code="22" Example="">
         <Header Type="Response"/>
         <Field Name="ResponseCode" EvalFunction="" DefaultValue=""/>
         <Field Name="Balance" EvalFunction="" DefaultValue=""/>
      </Response>
   </Transaction>
</Root>

The xml is pretty straight forward. Root tag defines name of the client and product to which this xml is bind to. This eliminates the risk in case if mocking layer is used for multiple clients for example Bank of America, Citi Bank, etc.

We will discuss Header tag later; right now the most important design element is the transaction. Each transaction serves specific business need. For example Balance Inquiry is a transaction which serves specific need and could have a transaction code 9999. Similarly we could have another transaction Bill Inquiry or Bill Payment and the list goes on and on. Each transaction is composed of a request and response message. Let’s understand this by creating a scenario. Assuming Internet Banking as originating channel create a request message for Balance Inquiry transaction and send to the middle ware, the middle ware forward this request to Banking Host which actually process the request and in turn create a response message back to middle ware, middle ware reformat the response and give it back to the originating channel (Internet banking). This complete cycle is called One Transaction.

A request constitutes a header and additional parameters. Similarly a response also contains a header and additional information. Since a header is constant for all subsequent transactions of a specific client implementation then a natural order would be to have two type of headers {request/response} in the beginning of xml.

XML provides a great flexibility to add/update/remove a field on the fly, rather whole transaction set can be created in real time. All you need to do is to modify fields.

A field can have a default value. If a default value is provided then default value priority is high which means the mocking layer ignores the data in the message against this field and force the field to have a default value. A field can also have evaluation function. Eval functions are built in system functions that can be trigger at run time when a request message is received. 

Header tag is introduced to identify the fields that will be common for all transaction sets.  Headers can further be divided into request and response type because of different values in their fields. Isolated headers also gives flexibility to modify individual headers means if response header has additional content then this can be achieved as well.  

At this stage though we have constructed a basic design but it has limitations. Each request needs to be appropriately split automatically while message is received by the mocking layer. This requires have additional evaluation functions will let mocking engine do the job easily. We are providing following functions

Command Function

Description

GetMessageFieldByIndex

As the name suggest this eval function searches field by index in the request and return the value present at the index location. For example: GetMessageFieldByIndex(2) will return 0001 for request  message: 0064~01~0001~20151009132331~123456~010000001

Date.Now

This returns current date and time in yyyymmddhhmmss format.

ResolveXPath

This function evaluates provided XPath and must return single value.

Let’s modify our XML based on new gained knowledge.

XML
<Root Client="ABC Bank" Product="ACME Product">
   <Header Type="Request"
      <Field Name="MessageType" EvalFunction="" DefaultValue="1" />
      <Field Name="Transactioncode" EvalFunction="GetMessageFieldByIndex(1)" DefaultValue="" />
      <Field Name="TranDateTime" EvalFunction="GetMessageFieldByIndex(3)" DefaultValue="" />
      <Field Name="STAN" EvalFunction="GetMessageFieldByIndex(4)" DefaultValue="" />
   </Header>
   <Header Type="Response">
      <Field Name="MessageType" EvalFunction="" DefaultValue="2" />
      <Field Name="Transactioncode" EvalFunction="" DefaultValue="GetMessageFieldByIndex(1)" />
      <Field Name="TranDateTime" EvalFunction="Date.Now" DefaultValue="" />
      <Field Name="STAN" EvalFunction="GetMessageFieldByIndex(4)" DefaultValue="" />
   </Header>
   <Transaction DispName="Balance Inquiry" Code="9999">
      <Request Code="11" Example="">
         <Header Type="Request"/>
            <Field Name="CustomerPan" EvalFunction="GetMessageFieldByIndex(5)" DefaultValue="" />
      </Request>
      <Response Code="22" Example="">
         <Header Type="Response"/>
     <Field Name="ResponseCode" EvalFunction="" DefaultValue="0"/>
     <Field Name="Balance" EvalFunction="" DefaultValue=""/>
      </Response>
   </Transaction>
</Root>

 

Above approach now brings an automated way of creating request and response list based on original request message. The only thing left is the customer data that is balance. Filling this gap is easy, we only need to filter customer data using Customer PAN and get available balance and the best way to achieve this in a way that modification can be made on the fly is XPATH.

The only piece of the puzzle missing now is customer’s data. Our mocking layer will be very limited if hard coded messages is returned for all cases. The layer should be customer aware and behave differently for individual customer. This also becomes handy for comprehensive testing as different customers can be configures with different values for producing different output. One obvious test is to configure one customer with zero balance to testing balance not available cases.

This can easily be achieved if we introduce a customer’s tag in our XML as briefly outlined below.

Customer tag is flexible as it allows addition of new customer and their linked information. It also supports creating new data hierarchies. The last missing element is to create a link mechanism between message fields and customer. Lets do this as well and close the deal.

XML
<Root Client="ABC Bank" Product="ACME Product">
   <Header Type="Request"
      <Field Name="MessageType" EvalFunction="" DefaultValue="1" />
      <Field Name="Transactioncode" EvalFunction="GetMessageFieldByIndex(1)" DefaultValue="" />
      <Field Name="TranDateTime" EvalFunction="GetMessageFieldByIndex(3)" DefaultValue="" />
      <Field Name="STAN" EvalFunction="GetMessageFieldByIndex(4)" DefaultValue="" />
   </Header>
   <Header Type="Response">
      <Field Name="MessageType" EvalFunction="" DefaultValue="2" />
      <Field Name="Transactioncode" EvalFunction="" DefaultValue="GetMessageFieldByIndex(1)" />
      <Field Name="TranDateTime" EvalFunction="Date.Now" DefaultValue="" />
      <Field Name="STAN" EvalFunction="GetMessageFieldByIndex(4)" DefaultValue="" />
   </Header>
   <Transaction DispName="Balance Inquiry" Code="9999">
      <Request Code="11" Example="">
         <Header Type="Request"/>
            <Field Name="CustomerPan" EvalFunction="GetMessageFieldByIndex(5)" DefaultValue="" />
      </Request>
      <Response Code="22" Example="">
         <Header Type="Response"/>
     <Field Name="ResponseCode" EvalFunction="" DefaultValue="0"/>
     <Field Name="Balance" 
       EvalFunction="ResolveXPath('//Customers/Customer/Account[@PAN={0}]/@Balance, GetMessageFieldByIndex(5));" DefaultValue=""/>
      </Response>
   </Transaction>
   <Customers>
      <Customer UserID="testUser1" Name="Test User 1" DateOfBirth="01/01/1995" 
                Gender="MA" PhoneMobile="03339999999" AddressOffice="" 
                CNIC="0123456789123" Email="testUser1@test.com" 
                Fax="" TotalAccounts="1">
         <Account BranchCode="0101" Number="010000001" IBAN="" PAN="010000001"
               Currency="PKR" Balance="100" AccountTitle="Test User 1"              
               AccountType="SAVING" BranchName="Head Office Branch"/>
      </Customer>
    <Customer UserID=" testUser2" Name="Test User 2" DateOfBirth="10/01/1996" 
              Gender="MA" PhoneMobile="03349999999" AddressOffice="" 
              CNIC="0123456789124" Email="testUser2@test.com" 
              Fax="" TotalAccounts="1">
        <Account BranchCode="0101" Number="010000002" IBAN="" PAN="010000002"
               Currency="PKR" Balance="100" AccountTitle="Test User 1"              
               AccountType="SAVING" BranchName="Head Office Branch"/>
      </Customer>
   <Customers>
</Root>

If we closely look at below field tag you can easily understand how a link is created between field and data.

XML
<Field Name="Balance" 
       EvalFunction="ResolveXPath('//Customers/Customer/Account[@PAN={0}]/@Balance, GetMessageFieldByIndex(4));" 
       DefaultValue=""/>

Yes, it is the XPath that again comes handy in getting data specific result. We already have created a command function ResolveXPath that takes XPath as input parameter and return results. The beauty of XPath is it can easily manage change. If you create a complex data hierarchy XPath will not let one down. Now we have got all the necessary elements to create a mocking layer which is not a big deal any more.

Blocks - Adding More Complexity

Up till now we have managed very simple transaction set which returns simple value, Like Balance Inquiry which returns available balance. In real world there are far more complex transactions that return lists of different sets, like in customer account inquiry where a customer can have multiple accounts and each account have different values. Like one account type could be saving and another account type can be load or else. A different approach is required for managing these transaction set.

Block fields help us in these situations. A block field is again a field that evaluates an XPath expression and repeats all the child field tags to the number of objects the Xpath returned. Let’s take a deep look into this.

XML
<Field Name="Block" 
       EvalFunction="ResolveBlock('//Customers/Customer[@PAN={0}]/Account',GetMessageFieldByIndex(5));" 
       DefaultValue="">

  <Field Name="AccountNumber" 
         EvalFunction="ResolveXPath('//Customers/Customer[@PAN={0}]/Account[@Id={1}]/@Number',GetMessageFieldByIndex(5), ContextId);" 
         DefaultValue=""/>
  <Field Name="AccountTitle" 
         EvalFunction="ResolveXPath('//Customers/Customer[@PAN={0}]/Account[@Id={1}]/@AccountTitle',GetMessageFieldByIndex(5), ContextId);" 
         DefaultValue=""/>
</Field>

In the above example the evalFunction of Block field is special as it contains ResolveBlock command function. This function evaluates XPath expression and store the retrieved object in an array list. In above case All accounts data will get fetched for a specific customer matching the provided CNIC. This account information is now holded in an Array list because it will further be used in subsequent child field evaluation like for AccountNumber field the eval function now taking two parameters [CNIC and Account Id]. The second parameter [Account Id] is the only parameter that isolate a specific customer account, once an account is identified, getting account number is no big deal as elaborated in the XPath.

Image 4

What we are looking above is a new Transaction named Get Account Inquiry. This transaction returns number of account information plus individual account details like account number and account title using Block field. 

Using the Code

Mocking layer application design is extremely simple even simple enough to write a pseudo code as well.

C#
Function Process(string rawMessage, XmlDocument metaXML) 
{
    string[] splittedMessageArray = split rawMessage using ‘~’ as delimeter;
    Dictionary<string, string> request = new Dictionary<string, string>();
    For each field f in Header and Request of MetaXml Document
        If f.DefaultValue is not empty Then
           Value = f.DefaultValue
        Else
           EvaluateFunction = f.EvalFunction;
           Value = Evaluate(EvaluateFunction, splittedMessageArray, metaXML)
        End IF
        Request[f.Name] = Value;
    End For

    Arraylist responseFieldList = new ArrayList();

    For each field f in Header and Response of MetaXml Document
        If f.DefaultValue is not empty Then
           Value = f.DefaultValue
        Else
           EvaluateFunction = f.EvalFunction;
           Value = Evaluate(EvaluateFunction, splittedMessageArray, metaXML)
        End IF
        responseFieldList.Add(Value);
    End For
    String outMessage = string.join(‘~’, responseFieldList);
    Byte[] outByte = Encoding.ASCII.GetBytes(fourByteSize);

    return outByte;
}

It’s a three step process, Split the receiving message, Build request map by reading header and fields of a transaction using splitting message array and finally create a response array by reading response header and fields and filling the values using source message array and xpath. That’s it, no rocket science.

In the code Message Complexity is managed by MessageManager class. Similarly Transaction Meta Info is being managed by MetaInfoManager, it’s a singleton class that reads the file and store the XML content in memory.

TCP communication is being managed by a downloaded open source class TCPServer3 over which I have made some tweaking for my specific purpose. 

Points of Interest

The interesting approach here is the flexibility driven by XPath is very powerful. A complete mocking layer can be constructed in hours and is seriously change friendly. A transaction can be altered in minutes by adding/removing a field or by changing an XPath.

History

Version 1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Product Manager Avanza Solutions
Pakistan Pakistan
Asif embarked on his programming journey back in 1991 when he first encountered 80286 8-16 MHz systems. His programming repertoire began with dBase III+, FoxPro, C, and assembly language, where he honed exceptional skills that have been a cornerstone of his development career.

Over the years, Asif's programming saga has seen him delve into a wide array of technologies and languages, ranging from C++, VC++, Java, Delphi, RPG400, SQL Server, and Oracle, to name just a few. His insatiable curiosity continues to lead him towards newer horizons, such as DOT Net Technologies, SOA architectures, BI, DSL, and beyond. These learning experiences are underscored by a robust theoretical foundation, with a penchant for research.

Beyond the realm of technology, Asif's interests include delving into the pages of fiction, exploring biotechnology, and gazing at the wonders of Astronomy. He finds joy in watching movies, and during his free time, he delights in quality moments spent with his children.

Comments and Discussions

 
GeneralInteresting Topic Pin
aarif moh shaikh5-Nov-15 18:13
professionalaarif moh shaikh5-Nov-15 18:13 
Question100% Agree Pin
Garth J Lancaster5-Nov-15 12:43
professionalGarth J Lancaster5-Nov-15 12:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.