예제 #1
0
        public static Iso8583Message ProcessIncommingMessage(int sourceId, Iso8583Message originalMessage)
        {
            SourceNode sourceNode = new SourceNodeRepository().Get(sourceId);

            //Configure Original Data Element
            DateTime transmissionDate = DateTime.UtcNow;

            //Configuring the original data element (intended for transaction matching (e.g. to identify a transaction for correction or reversal)
            //consists of 5 data elements: MTI (1-4), STAN (5-10), Date&Time (11-20), AcquirerInsttutionCode (21-31), ForwardingInstCode(32-42)
            string transactionDate = string.Format("{0}{1}",
                                                   string.Format("{0:00}{1:00}", transmissionDate.Month, transmissionDate.Day),
                                                   string.Format("{0:00}{1:00}{2:00}", transmissionDate.Hour,
                                                                 transmissionDate.Minute, transmissionDate.Second));

            //string originalDataElement = $"{originalMessage.MessageTypeIdentifier}{originalMessage.Fields[11]}{transactionDate}";
            string originalDataElement = originalMessage.MessageTypeIdentifier.ToString() + originalMessage.Fields[11] + transactionDate;

            //if the originalDataElement is empty (for non-reversal), add it
            if (!(originalMessage.Fields.Contains(MessageField.ORIGINAL_DATA_ELEMENT_FIELD)))
            {
                originalMessage.Fields.Add(MessageField.ORIGINAL_DATA_ELEMENT_FIELD, originalDataElement);
            }
            MessageLogger.LogMessage("Validating message...");

            //check if it's a reversal message
            if (originalMessage.MessageTypeIdentifier == MTI.REVERSAL_ADVICE || originalMessage.MessageTypeIdentifier == MTI.REPEAT_REVERSAL_ADVICE)
            {
                MessageLogger.LogMessage("\nReversal message!");
                //confirm that this transaction actually needs to be reversed
                bool           isReversal;
                Iso8583Message reversalMessage = GetReversalMessage(originalMessage, out isReversal);

                if (!isReversal)
                {
                    MessageLogger.LogMessage("Invalid Reversal transaction");
                    return(reversalMessage);
                }
                //continue if it's a reversal message
                originalMessage = reversalMessage;
            }

            string         cardPan          = originalMessage.Fields[MessageField.CARD_PAN_FIELD].ToString();
            decimal        amount           = Convert.ToDecimal(originalMessage[MessageField.AMOUNT_FIELD].Value);                          //The amount is in kobo
            string         channelCode      = originalMessage.Fields[MessageField.CHANNEL_ID_FIELD].Value.ToString().Substring(0, 2);
            string         tTypeCode        = originalMessage.Fields[MessageField.TRANSACTION_TYPE_FIELD].Value.ToString().Substring(0, 2); //first two positions for the transaction type
            string         expiryDate       = originalMessage.Fields[MessageField.EXPIRY_DATE_FIELD].Value.ToString();
            DateTime       expiryDateOfCard = ConvertToDateTime(expiryDate);
            Iso8583Message responseMessage;       //rsponse message to return after performing some checks

            if (expiryDateOfCard <= DateTime.Now) //card expired
            {
                responseMessage = SetReponseMessage(originalMessage, ResponseCode.EXPIRED_CARD.ToString());
                MessageLogger.LogMessage("Expired card");
                return(responseMessage);
            }
            //check the amount, only for balance enq should the amount be zero
            if (amount <= 0 && tTypeCode != TransactionTypeCode.BALANCE_ENQUIRY.ToString())
            {
                responseMessage = SetReponseMessage(originalMessage, ResponseCode.INVALID_AMOUNT.ToString());         //Invalid amount
                MessageLogger.LogMessage("Invalid Amount");
                return(responseMessage);
            }

            Combo  theCombo          = null;
            Scheme theScheme         = null;
            var    sourceNodeSchemes = sourceNode.Schemes;
            string pan   = originalMessage.Fields[MessageField.CARD_PAN_FIELD].Value.ToString();
            var    route = new RouteRepository().GetByCardPAN(pan.Substring(0, 6));

            if (route == null)
            {
                MessageLogger.LogMessage("Route is null.");
                responseMessage = SetReponseMessage(originalMessage, ResponseCode.ROUTING_ERROR.ToString());
                return(responseMessage);
            }

            //get the sourcenode by the route
            theScheme = sourceNodeSchemes.Where(s => s.RouteId == route.FirstOrDefault().Id).FirstOrDefault();
            if (theScheme == null)
            {
                MessageLogger.LogMessage("No such secheme");
                responseMessage = SetReponseMessage(originalMessage, ResponseCode.TRANSACTION_NOT_PERMITTED_ON_TERMINAL.ToString());
                return(responseMessage);
            }
            theCombo = theScheme.Combos.Where(c => c.TransactionType.Code.Equals(tTypeCode) && c.Channel.Code.Equals(channelCode)).FirstOrDefault();
            if (theCombo == null)   //of course, scheme also = null
            {
                MessageLogger.LogMessage("Invalid transaction type-channel-fee combo");
                responseMessage = SetReponseMessage(originalMessage, ResponseCode.TRANSACTION_NOT_PERMITTED_ON_TERMINAL.ToString()); // Transaction not allowed on terminal
                return(responseMessage);
            }

            var sinkNnode = route.FirstOrDefault().SinkNode;

            if (sinkNnode == null)
            {
                MessageLogger.LogMessage("Sink node is null.");
                responseMessage = SetReponseMessage(originalMessage, ResponseCode.ISSUER_OR_SWITCH_INOPERATIVE.ToString());
                return(responseMessage);
            }

            //At this point, everything is assumed to be okay
            Fee fee = theCombo.Fee;

            if (fee == null)
            {
                MessageLogger.LogMessage("Unacceptable transaction fee");
                responseMessage = SetReponseMessage(originalMessage, ResponseCode.UNACCEPTABLE_TRANSACTION_FEE.ToString());  // Transaction type not allowed in this scheme
                return(responseMessage);
            }

            //calculate the transaction fee and embed in the  message
            originalMessage = SetTransactionFee(originalMessage, ComputeFee(fee, amount));


            var clientPeer = Program.ClientPeers.Where(p => p.Name.Equals(theScheme.Route.SinkNode.Id.ToString())).FirstOrDefault();

            if (clientPeer == null)
            {
                MessageLogger.LogMessage("Clientpeer is null");
                originalMessage = SetReponseMessage(originalMessage, ResponseCode.ISSUER_OR_SWITCH_INOPERATIVE.ToString());
                return(originalMessage);
            }
            ////////
            Iso8583Message replyFromFEP = SendMessageToFEP(clientPeer, originalMessage);        //sends message to the client

            return(replyFromFEP);
        }