银联接口开发随笔(2)

      上一篇日志写了些常见的概念,这一篇想说一下ISO8583协议,因为在银行交易中这个协议是关键,网络间传输的都是基于该协议的数据,网上介绍该协议的文章比较多,这里找到一篇比较好的(http://blog.csdn.net/AndrewWang79/article/details/3859176)。我没有别的可以多讲的,只想讲讲如何设计一个协议处理程序的思路

        在了解了协议以后我们会发现,网络间传输的数据包是每个域的数据组成,每个数据又会拥有各自的属性,比如像协议中提到的第二域:

        / *   FLD   2   */   {0,"PRIMARY   ACCOUNT   NUMBER   ",   22,   0,   2,   1,   NULL,0},

 0表示数据类型,22表示该域的总长度22个字节。

 在了解这样的情况以后,我们脑袋中自然会想到三个名词,数据包,域字段,域字段属性,这里稍等一下,在我们读过的关于面像对像设计的书中是不是都会有提到,在我们观察事物的时候,总是将名字与类联系在一起?我们这里也不仿一试,估且定义三个类

 Class ISO8583Package{},

 Class ISO8583Field{},

 Class ISO8583FieldAttribute{}

     这样用Package表示报文,Field表示报文中的每个域,而FieldAttribute表示每一个域的类型。根据协议的要求,每个域的特性如下

      typedef struct ISO8583  
     {  
       int bit_flag; /*
域数据类型0 -- string, 1 -- int, 2 -- binary*/  
       char *data_name; /*
域名*/  
       int length; /*
数据域长度*/  
       int length_in_byte;/*
实际长度(如果是变长)*/  
       int variable_flag; /*
是否变长标志0:否 22位变长, 33位变长*/  
       int datatyp; /*0 -- string, 1 -- int, 2 -- binary*/  
       char *data; /*
存放具体值*/  
       int attribute; /*
保留*/  
     } ;

   我们可以直接根据协议的要求把ISO8583FieldAttribute类换为Struct类型,名字也估且叫ISO8583 Structure吧,完整 的程序如下

   

 public struct ISO8583Structure
    {
        
public int bit_flag; /*域数据类型0 -- string, 1 -- int, 2 -- binary*/
        
public string data_name; /*域名*/
        
public int length; /*数据域长度*/
        
public int length_in_byte;/*实际长度(如果是变长)*/
        
public int variable_flag; /*是否变长标志0:否 2:2位变长, 3:3位变长*/
        
public int datatyp; /*0 -- string, 1 -- int, 2 -- binary*/
        
public string data; /*存放具体值*/
        
public int attribute; /*保留*/

    }

 

     由于每个域都会有ISO8583 Structure的定义,那这样我们可以看看Class Field{}的雏形

       public class ISO8583Field

      {

       public ISO8583Structure _ISO8583Structure;

}

     ISO8583Package组包类中初始化需要的域

   

View Code
  public class ISO8583Package
    {
        
//用于保存初始结构
        public Dictionary<int, ISO8583Structure> ISO8583Collection;
        
//用于保存存实际报文域数据
        public Dictionary<int, ISO8583Field> ISO8583CollectionData;

        
public ISO8583Package()
        {
            
//初始化默认位图类型
            initDefaultField();

        }

        
public byte[] GetField(int i)
        {
            
return null;
        }
        
public byte[] GetISO8583Package()
        {
            
return null;
        }

        
public bool SetField(ISO8583Field field)
        {
            
return false;
        }
        
public bool SetBitMap()
        {
            
return false;
        }

        
/// <summary>
        
/// 根据域索引设置值
        
/// </summary>
        
/// <param name="FieldValue"></param>
        
/// <param name="i"></param>
        public void SetField(string FieldValue, int i)
        {
            ISO8583Field field 
= new ISO8583Field();
            field._ISO8583Structure 
= ISO8583Collection[i];
            field._ISO8583Structure.data 
= FieldValue;

        }

        
/// <summary>
        
/// 根据银行接口要求来初始化
        
/// </summary>
        private void initDefaultField()
        {
            
//初始化ISO8583Collection,根据协议要求采取默认初始化
            ISO8583Structure structure1;
            structure1.bit_flag 
= 1/*域数据类型0 -- string, 1 -- int, 2 -- binary*/
            structure1.data_name 
= "信息类型"/*域名*/
            structure1.length 
= 4/*数据域长度*/
            structure1.length_in_byte 
= 0;/*实际长度(如果是变长)*/
            structure1.variable_flag 
= 0/*是否变长标志0:否 2:2位变长, 3:3位变长*/
            structure1.datatyp 
= 1/*0 -- string, 1 -- int, 2 -- binary*/
            structure1.data 
= ""/*存放具体值*/
            structure1.attribute 
= 0/*保留*/
            ISO8583Collection.Add(
1,structure1);

            ISO8583Structure structure3;
            structure3.bit_flag 
= 0/*域数据类型0 -- string, 1 -- int, 2 -- binary*/
            structure3.data_name 
= "处理码"/*域名*/
            structure3.length 
= 6/*数据域长度*/
            structure3.length_in_byte 
= 0;/*实际长度(如果是变长)*/
            structure3.variable_flag 
= 0/*是否变长标志0:否 2:2位变长, 3:3位变长*/
            structure3.datatyp 
= 0/*0 -- string, 1 -- int, 2 -- binary*/
            structure3.data 
= ""/*存放具体值*/
            structure3.attribute 
= 0/*保留*/
            ISO8583Collection.Add(
1, structure3);

            ISO8583Structure structure11;
            structure11.bit_flag 
= 0/*域数据类型0 -- string, 1 -- int, 2 -- binary*/
            structure11.data_name 
= "终端流水"/*域名*/
            structure11.length 
= 6/*数据域长度*/
            structure11.length_in_byte 
= 0;/*实际长度(如果是变长)*/
            structure11.variable_flag 
= 0/*是否变长标志0:否 2:2位变长, 3:3位变长*/
            structure11.datatyp 
= 1/*0 -- string, 1 -- int, 2 -- binary*/
            structure11.data 
= ""/*存放具体值*/
            structure11.attribute 
= 0/*保留*/
            ISO8583Collection.Add(
1, structure11);
        }

 

 

这时候当我们拿到一个实际开发任务的时候,比如某个银行给你的接口要求如下

数据元

数据类型

发送方及数值

备注

T→P

P→T

0

信息类型

N4

0800

0810

 

1

位元表

B64

M

M

 

3

处理码

N6

M

M

XXXXXX

11

交易流水

N6

M

M

终端交易流水

      这段报文需要01311域的数据,我们在组包的时候初始化一些基本参数,如ISO8583Package类的构造函数里所看到的,在实际使用过程中再重新设置这些值就可以了。

现在我们来看一下使用的类的情况,先看一下代码示例,如下

public class ISO8583Base

    {

       

        ISO8583Package _ISO8583Package;

       

        public ISO8583Base()

        {

            _ISO8583Package = new ISO8583Package();

        }

        /// <summary>

        /// 根据银行接口要求设置域值

        /// </summary>

        /// <param name="CommandType"></param>

        /// <param name="ProcessCode"></param>

        /// <param name="SerialNaumber"></param>

        public ISO8583Base(string CommandType,string ProcessCode,string SerialNaumber)

        {

            _ISO8583Package.SetField(CommandType, 1);

            _ISO8583Package.SetField(ProcessCode, 3);

            _ISO8583Package.SetField(SerialNaumber, 11);

        }

 

}

在构造函数里进行域数据赋值。

这里我所写的都是一些想法,跟实际情况有很大差距,实际跟银联接口无任何关系,只是在这里说一下拿到需求以后我们写程序的想法

posted @ 2011-07-13 15:14  赵一村  阅读(3841)  评论(1编辑  收藏  举报