예제 #1
0
        /// <summary>
        /// Parses a byte buffer containing an ISO8583 message. The buffer must
        /// not include the length header. If it includes the ISO message header,
        /// then its length must be specified so the message type can be found.
        /// </summary>
        /// <param name="buf">The byte buffer containing the message, starting
        /// at the ISO header or the message type.</param>
        /// <param name="isoHeaderLength">Specifies the position at which the message
        /// type is located, which is algo the length of the ISO header.</param>
        /// <param name="encoder">The encoder to use for reading string values.</param>
        /// <returns>The parsed message.</returns>
        public IsoMessage ParseMessage(byte[] buf, int isoHeaderLength, Encoding encoder)
        {
            IsoMessage m    = new IsoMessage(isoHeaderLength > 0 ? encoder.GetString(buf, 0, isoHeaderLength) : null);
            int        type = ((buf[isoHeaderLength] - 48) << 12)
                              | ((buf[isoHeaderLength + 1] - 48) << 8)
                              | ((buf[isoHeaderLength + 2] - 48) << 4)
                              | (buf[isoHeaderLength + 3] - 48);

            m.Type = type;

            //Parse the bitmap
            bool     extended = (HexByteValue(buf[isoHeaderLength + 4]) & 8) > 0;
            BitArray bs       = new BitArray(extended ? 128 : 64);
            int      pos      = 0;

            for (int i = isoHeaderLength + 4; i < isoHeaderLength + 20; i++)
            {
                int hex = HexByteValue(buf[i]);
                bs.Set(pos++, (hex & 8) > 0);
                bs.Set(pos++, (hex & 4) > 0);
                bs.Set(pos++, (hex & 2) > 0);
                bs.Set(pos++, (hex & 1) > 0);
            }
            //Extended bitmap?
            if (bs.Get(0))
            {
                for (int i = isoHeaderLength + 20; i < isoHeaderLength + 36; i++)
                {
                    int hex = HexByteValue(buf[i]);
                    bs.Set(pos++, (hex & 8) > 0);
                    bs.Set(pos++, (hex & 4) > 0);
                    bs.Set(pos++, (hex & 2) > 0);
                    bs.Set(pos++, (hex & 1) > 0);
                }
                pos = 36 + isoHeaderLength;
            }
            else
            {
                pos = 20 + isoHeaderLength;
            }

            //Parse each field
            Dictionary <int, FieldParseInfo> guide = _parseMap[type];
            List <int> index = _parseOrder[type];

            foreach (int i in index)
            {
                FieldParseInfo fpi = guide[i];
                if (i <= bs.Count)
                {                 // TM extended parsing
                    if (bs.Get(i - 1))
                    {
                        IsoValue val = fpi.Parse(buf, pos, encoder);
                        m.SetField(i, val);
                        pos += val.Length;
                        if (val.Type == IsoType.LLVAR || val.Type == IsoType.LLVARnp)
                        {
                            pos += 2;
                            //@@@ TAM temporary hardcode, must be a better way to parse Padding F
                            if (val.Type == IsoType.LLVAR && (val.Length % 2 != 0))
                            {
                                pos += 1;
                            }
                        }
                        else if (val.Type == IsoType.LLLVAR)
                        {
                            //@@@ TAM packe 3 change to  4 for Paymark
                            //pos += 3;
                            pos += 4;
                        }
                        else if (val.Type == IsoType.LLLVARnp)                         // for NAB the LLLVAR Non packed(ascci codec) will have HEX as length so 6 digits(303139 = 019)
                        {
                            pos += 6;
                        }
                    }
                }
            }
            return(m);
        }
예제 #2
0
        /// <summary>
        /// Creates a MessageFactory and configures it from the XML file read
        /// from the absolute path specified.
        /// </summary>
        /// <param name="filename">An absolute path to the XML configuration file.</param>
        /// <returns>A new configured MessageFactory.</returns>
        public static MessageFactory CreateFromFile(string filename)
        {
            XmlDocument xml = new XmlDocument();

            xml.Load(filename);
            MessageFactory m = new MessageFactory();

            foreach (XmlNode node in xml.DocumentElement.ChildNodes)
            {
                if (node.NodeType == XmlNodeType.Element)
                {
                    if ("header".Equals(node.Name))
                    {
                        string type   = node.Attributes["type"].Value;
                        string header = node.ChildNodes[0].Value;
                        m.SetIsoHeader(Convert.ToInt16(type, 16), header);
                    }
                    else if ("template".Equals(node.Name))
                    {
                        int        type  = Convert.ToInt16(node.Attributes["type"].Value, 16);
                        IsoMessage templ = new IsoMessage();
                        templ.Type = type;
                        foreach (XmlNode field in node.ChildNodes)
                        {
                            if (field.NodeType == XmlNodeType.Element && "field".Equals(field.Name))
                            {
                                int    num    = Convert.ToInt16(field.Attributes["num"].Value);
                                string ftype  = field.Attributes["type"].Value;
                                string length = field.Attributes["length"] == null ? "0" : field.Attributes["length"].Value;
                                string val    = field.ChildNodes[0].Value;
                                //Ir creando mensaje con esto
                                templ.SetValue(num, val,
                                               (IsoType)Enum.Parse(typeof(IsoType), ftype),
                                               Convert.ToInt16(length));
                            }
                        }
                        m.AddMessageTemplate(templ);
                    }
                    else if ("parse".Equals(node.Name))
                    {
                        int type = Convert.ToInt16(node.Attributes["type"].Value, 16);
                        Dictionary <int, FieldParseInfo> guide = new Dictionary <int, FieldParseInfo>();
                        foreach (XmlNode field in node.ChildNodes)
                        {
                            if (field.NodeType == XmlNodeType.Element && "field".Equals(field.Name))
                            {
                                string       num     = field.Attributes["num"].Value;
                                string       ftype   = field.Attributes["type"].Value;
                                XmlAttribute lenAttr = field.Attributes["length"];
                                int          len     = 0;
                                if (lenAttr != null)
                                {
                                    len = Convert.ToInt16(lenAttr.Value);
                                }
                                //TODO ir creando guia con esto
                                FieldParseInfo fpi = new FieldParseInfo((IsoType)Enum.Parse(typeof(IsoType), ftype), len);
                                guide[Convert.ToInt16(num)] = fpi;
                            }
                        }
                        m.SetParseDictionary(type, guide);
                    }
                    else if ("assign-date".Equals(node.Name))
                    {
                        string val = node.Attributes["value"].Value;
                        m.AssignDate = "true".Equals(val);
                    }
                }
            }

            return(m);
        }