AS400银行核心系统开发中的技术总结--交易和组件写法
*交易和组件写法
Firebird核心系统的整体结构,是由主控--交易--组件这几个层次组成的。联机交易主控由C程序编写,异步交易主控和日终批量主控由CL和RPGLE程序编写。主控通过交易码调用相应的交易RPGLE程序,交易程序又通过CALLP调用不同模块的组件RPGLE程序,完成整个处理逻辑。交易程序和组件程序都总结了一套模版样例,下面就介绍样例程序的写法。
在介绍交易和组件程序写法之前,先介绍统一由/COPY引入的通用程序,这部分程序放在DSCPPGM中。注意/COPY不宜滥用,一定要结合命名规范,否则极易导致程序可读性差。
首先是HEAD。这个文件定义了copyright和几个日期fmt规则。
- **BEGIN***************************************************************
- **程序名称:程序公共控制头 *
- **功能描述:程序公共控制头 *
- ** *
- **版本:2014-10-21_1 *
- ** *
- **设计人员:PACMAN 开发人员:AUTOGEN *
- **设计日期:2011-08-30 开发日期:2011-08-30 *
- ** *
- **END*****************************************************************
- **
- HCOPYRIGHT('Firebird V2.1 corebanking system, CSW SHANGHAI')
- HDATFMT(*ISO) TIMFMT(*ISO) DATEDIT(*YMD)
然后是ENUM,这个文件是引入枚举常量定义,在数据字典和枚举值部分已经有了介绍,这里就不重复了。
接下来是PGDS,这个文件定义了每个程序都会引入的PSDS和INFDS结构定义,错误结构定义,错误信息数组,接口数组条数,以及特殊用途变量等。
- **BEGIN***************************************************************
- **程序名称:程序公共控制头 *
- **功能描述:程序公共控制头 *
- ** *
- **版本:2014-11-23_1 *
- ** *
- **设计人员:PACMAN 开发人员:AUTOGEN *
- **设计日期:2011-08-30 开发日期:2011-08-30 *
- ** *
- **END*****************************************************************
- **
- **公共常量
- **输出传票数组条数
- DC_NBOTVC C CONST(100)
- **输入券别数组条数
- DC_NBINCS C CONST(30)
- **输入费用数组条数
- DC_NBINFE C CONST(30)
- **输出费用数组条数
- DC_NBOTFE C CONST(30)
- **替换错误参数条数
- DC_NBMSDS C CONST(9)
- **记录被锁错误信息
- DC_MGLOCK C CONST('记录被锁')
- **********************************************************************
- **错误处理结构
- **程序状态结构
- DRPGPSDS SDS
- D PG_MAINPROC 1 10A
- D PG_STATUS 11 15A
- D PG_PRVSTAT 16 20A
- D PG_SRCLINE 21 28A
- D PG_ROUTINE 29 36A
- D PG_PARMNUM 37 39S 0
- D PG_MSID 40 46A
- D PG_PGMLIB 81 90A
- D PG_EXCPDT 91 170A
- D PG_LSERRFL 175 184A
- D PG_JOBDATE 191 198A
- D PG_FLINFO 209 243A
- D PG_JOBNAME 244 253A
- D PG_JOBUSER 254 263A
- D PG_JOBNUM 264 269S 0
- D PG_RUNDATE 276 281S 0
- D PG_RUNTIME 282 287S 0
- D PG_SRCFILE 304 313A
- D PG_SRCLIB 314 323A
- D PG_SRCMBR 324 333A
- D PG_PGMNAME 334 343A
- D PG_MODNAME 344 353A
- D PG_SRCLNADD 354 355B 0
- D PG_FLILNADD 356 357B 0
- D PG_USRPRF 358 367A
- D PG_EXTERR 368 371I 0
- **文件状态结构
- DFILESDS DS BASED(FILEDSP)
- D FL_FILE 1 8A
- D FL_OPNIND 9 9A
- D FL_EOFIND 10 10A
- D FL_STATUS 11 15S 0
- D FL_OPCODE 16 21A
- D FL_ROUTINE 22 29A
- D FL_SRCLINE 30 37A
- D FL_RECORD 38 45A
- D FL_MSID 46 52A
- D FL_SRCLNADD 77 78B 0
- D FL_ODPTYPE 81 82A
- D FL_FILENAME 83 92A
- D FL_LIBRARY 93 102A
- D FL_SPLFILE 103 112A
- D FL_SPLLIB 113 122A
- D FL_RCDLEN 125 126I 0
- D FL_KEYLEN 127 128I 0
- D FL_MEMBER 129 138A
- D FL_TYPE 147 148I 0
- D FL_RCDNUM 156 159I 0
- D FL_SPLNUM 160 163I 0
- D FL_OVERFLOW 188 189I 0
- D FL_BASEDMBRS 211 212I 0
- D FL_OPENID 214 215B 0
- D FL_RCDFMTLEN 216 217I 0
- D FL_CCSID 218 219I 0
- D FL_FBSIZE 367 370I 0
- D FL_KEYNUM 387 388I 0
- D FL_FBKEYLEN 393 394I 0
- D FL_MBRNUM 395 396I 0
- D FL_RRN 397 400I 0
- D FL_KEY 401 2400A
- **文件状态结构指针
- DFILEDSP S *
- **********************************************************************
- **公共结构
- **引入数据字典
- DDICT E DS EXTNAME(DICT) QUALIFIED TEMPLATE
- **公共错误信息接口
- DPMG E DS EXTNAME(MESG) QUALIFIED
- **错误信息替换数组
- DA_MSDS S DIM(C_NBMSDS) LIKE(DICT.@@MSDS)
- **********************************************************************
- **特殊变量
- **是否执行过错误处理程序
- DPG_ERYNFG S LIKE(DICT.@@YNFG) INZ(YNFG_NO)
- **是否程序已执行初始化
- DPG_FRYNFG S LIKE(DICT.@@YNFG) INZ(YNFG_YES)
最后是通用处理过程PGCM,这个程序定义了错误捕获程序以及检查,退出等通用过程,并以#开头的过程名,与交易中普通@开头过程名以示区分。
- **BEGIN***************************************************************
- **程序名称:程序公共子程序 *
- **功能描述:程序公共子程序 *
- ** *
- **版本:2014-10-21_1 *
- ** *
- **设计人员:PACMAN 开发人员:AUTOGEN *
- **设计日期:2011-08-30 开发日期:2011-08-30 *
- ** *
- **END*****************************************************************
- **
- **********************************************************************
- ** #EXIT返回
- **********************************************************************
- C #EXIT BEGSR
- **
- C EVAL PG_FRYNFG = YNFG_NO
- C/IF DEFINED(USELR)
- C EVAL *INLR = *ON
- C/ENDIF
- C RETURN
- **
- C ENDSR
- **********************************************************************
- ** #ERR 取错误信息
- **********************************************************************
- C #ERR BEGSR
- **
- C EVAL PMG.MSFLNM = PG_SRCMBR
- C IF PMG.BKMSDS = *BLANKS
- C CALL 'SCNCMMG'
- C PARM PMG
- C PARM A_MSDS
- C ENDIF
- C EXSR #EXIT
- **
- C ENDSR
- **********************************************************************
- ** #CHKMSG检查程序返回信息
- **********************************************************************
- C #CHKMSG BEGSR
- **
- C IF PMG.BKMSID *BLANKS
- C EXSR #EXIT
- C ENDIF
- **
- C ENDSR
- **********************************************************************
- ** *PSSR程序异常处理
- **********************************************************************
- C *PSSR BEGSR
- **
- C IF PG_ERYNFG = YNFG_NO
- C EVAL PG_ERYNFG = YNFG_YES
- C EVAL PMG.MSFLNM = PG_SRCMBR
- C EVAL PMG.MSCDLN = PG_SRCLINE
- C EVAL PMG.BKMSID = 'F' + PG_MSID
- C EVAL PMG.BKMSDS = PG_EXCPDT
- C EVAL PMG.OTMSDS = PG_STATUS+' '+PG_PGMLIB+' '+
- C PG_PGMNAME
- C EXSR #EXIT
- C ENDIF
- **
- C ENDSR
- **********************************************************************
- ** #FLEX文件异常处理
- **********************************************************************
- C #FLEX BEGSR
- **
- C EVAL PMG.MSFLNM = PG_SRCMBR
- C EVAL PMG.MSCDLN = FL_SRCLINE
- C EVAL PMG.BKMSID = 'F' + FL_MSID
- C IF FL_STATUS = 1218
- C CALL 'GETOBJTXT'
- C PARM FL_LIBRARY V_FLEXLIB 10
- C PARM FL_FILENAME V_FLEXOBJ 10
- C PARM '*FILE' V_FLEXTYP 7
- C PARM *BLANKS V_FLEXTEXT 50
- C EVAL PMG.BKMSDS = %TRIM(V_FLEXTEXT) +
- C %TRIM(FL_FILENAME) + '.' +
- C %TRIM(FL_MEMBER) + C_MGLOCK +
- C ',' + PG_EXCPDT
- C ELSE
- C EVAL PMG.BKMSDS = PG_EXCPDT
- C ENDIF
- C EVAL PMG.OTMSDS = PG_FLINFO
- C EXSR #EXIT
- **
- C ENDSR
交易程序样例以6位交易码000000为例,交易程序名为T000000A,有两个输入T000000I1,T000000I2,两个输出T000000O1,T00000O2。其中I2和O2是数组。
T000000I1程序如下。
- A REF(DICT)
- A R RT000000I1
- A BKBRNO R REFFLD(@@BRNO)
- A COLHDG('机构')
- A TEXT('机构')
T000000I2程序如下。
- A REF(DICT)
- A R RT000000I2
- A BKTLNO R REFFLD(@@TLNO)
- A COLHDG('柜员')
- A TEXT('柜员')
T000000O1程序如下。
- A REF(DICT)
- A R RT000000O1
- A BKTRWB R REFFLD(@@TRWB)
- A COLHDG('交易流水号')
- A TEXT('交易流水号')
T000000O1程序如下。
- A REF(DICT)
- A R RT000000O2
- A BKACNO R REFFLD(@@ACNO)
- A COLHDG('账号')
- A TEXT('账号')
交易程序T000000A程序如下。
- **BEGIN***************************************************************
- **程序名称:交易程序模板 *
- **功能描述:交易程序开发规范 *
- ** *
- **设计人员:CSWWM 开发人员:CSWWM *
- **设计日期:2011-08-30 开发日期:2011-08-30 *
- **-------------------------------------------------------------------*
- **维护人员:CSWYJ *
- **维护日期:2014-10-17 *
- **维护内容:按新规范改写 *
- ** *
- **END*****************************************************************
- H/COPY DSCPPGM,HEAD
- **********************************************************************
- **引入数据字典枚举常量
- D/COPY DSCPPGM,ENUM
- **引入公共程序体
- D/COPY DSCPPGM,PGDS
- **********************************************************************
- **决定是否以*LR=*ON结束,统一使用激活组管理则保持注释
- D*/DEFINE USELR
- **定义常量
- DC_I1 C CONST('交易程序模版')
- DC_MGBRNO C CONST('机构号')
- DC_NBI2 C CONST(20)
- DC_NBO2 C CONST(20)
- *************************
- **引入调用服务原型
- D/COPY CETPEXP,SCETPSVP
- D/COPY CNCMSVC,SCNCMTAP
- **定义参照外部结构的结构、数组
- DT_INHD E DS EXTNAME(INHD) QUALIFIED TEMPLATE
- DT_INFE E DS EXTNAME(INFE) QUALIFIED TEMPLATE
- DT_INCS E DS EXTNAME(INCS) QUALIFIED TEMPLATE
- DT_OTHD E DS EXTNAME(OTHD) QUALIFIED TEMPLATE
- DT_OTVC E DS EXTNAME(OTVC) QUALIFIED TEMPLATE
- DT_I1 E DS EXTNAME(T000000I1) QUALIFIED TEMPLATE
- DT_I2 E DS EXTNAME(T000000I2) QUALIFIED TEMPLATE
- DT_O1 E DS EXTNAME(T000000O1) QUALIFIED TEMPLATE
- DT_O2 E DS EXTNAME(T000000O2) QUALIFIED TEMPLATE
- *************************
- **定义参照内部结构、变量(LIKE)的结构、数组
- DPIN DS QUALIFIED
- D INHD LIKEDS(T_INHD)
- D INFE DIM(C_NBINFE) LIKEDS(T_INFE)
- D INCS DIM(C_NBINCS) LIKEDS(T_INCS)
- D I1 LIKEDS(T_I1)
- D I2 DIM(C_NBI2) LIKEDS(T_I2)
- **
- DPOT DS QUALIFIED
- D OTHD LIKEDS(T_OTHD)
- D OTVC DIM(C_NBOTVC) LIKEDS(T_OTVC)
- D O1 LIKEDS(T_O1)
- D O2 DIM(C_NBO2) LIKEDS(T_O2)
- *************************
- **临时变量(无法参照定义)的结构体
- DD_VARS DS
- **定义参照数据字典(LIKE)的变量
- D V_BKTRWB LIKE(DICT.@@TRWB)
- **定义无法参照(自定义)的临时变量
- D V_NUM 5P 0
- **********************************************************************
- **定义程序入口
- C *ENTRY PLIST
- C PARM PMG
- C PARM PIN
- C PARM POT
- /FREE
-
- EXSR @INIT;
- EXSR @CHEK;
- EXSR @MAIN;
- EXSR @RETN;
- EXSR #EXIT;
-
- //---------------------------------------
- //程序初始化
- //---------------------------------------
- BEGSR @INIT;
- //初始化公共定义的结构
- CLEAR PMG;
- CLEAR A_MSDS;
- //初始化交易自有输出接口,注意已在覆盖方法中初始化过OTHD,OTVC的不要清
- CLEAR POT.O1;
- CLEAR POT.O2;
- //初始化自定义结构
- CLEAR D_VARS;
- ENDSR;
-
- //---------------------------------------
- //检查输入接口值的正确性
- //---------------------------------------
- BEGSR @CHEK;
- //机构号必输
- IF PIN.I1.BKBRNO = *BLANKS;
- EVAL PMG.BKMSID = 'EIOND';
- EVAL A_MSDS(1) = C_I1;
- EVAL A_MSDS(2) = C_MGBRNO;
- EXSR #ERR;
- ENDIF;
-
- //---------------------------------------
- //程序的主流程
- //---------------------------------------
- BEGSR @MAIN;
- //变更
- CLEAR TPSVF1;
- CLEAR TPSVF2;
- EVAL TPSVF1.BKBRNO = PIN.I1.BKBRNO;
- CALLP SCETPSV(PMG:TPSVF1:TPSVF2);
- EXSR #CHKMSG;
- //调用某模块记账服务
- //CALLP SCETPAC(PMG:TPSVF1:POT.OTVC);
- //EXSR #CHKMSG;
- ENDSR;
-
- //---------------------------------------
- //程序返回处理
- //---------------------------------------
- BEGSR @RETN;
- //登记返回数组条数
- CLEAR TPSVF1;
- EVAL CMTAF1.RDYNFG = YNFG_NO;
- EVAL CMTAF1.WTYNFG = YNFG_YES;
- EVAL CMTAF1.FDFLNM = 'O2RECD';
- EVAL CMTAF1.FDSQNU = V_NUM;
- CALLP SCNCMTA(PMG:CMTAF1);
- EXSR #CHKMSG;
- ENDSR;
-
- /END-FREE
- C/COPY DSCPPGM,PGCM
在交易程序中,如果需要调用模块组件,那么会用/COPY引入组件的PROTOTYPE声明和组件参数结构定义,这部分在组件样例中介绍。
交易的参数统一为3个。先是PMG,错误信息结构,用于将出错信息返回主控,判断交易是否成功,组织出错报文。再是PIN,输入复合结构,依次由INHD输入应用头,INFE输入费用数组,INCS输入券面数组,I1,I2等交易自身结构组成。最后是POT,输出复合结构,依次由OTHD输出应用头,OTVC输出记账传票数组,O1,O2等交易自身结构组成。这部分可以参见报文格式一节内容。
程序中将所有临时变量都定义在D_VARS结构下,这样方便一开始的初始化,可以用CLEAR D_VARS直接清值。
交易程序中调用了组件程序模版SCETPSV,同样第一个参数要是PMG,这样结合#CHKMSG,可以让出错信息层层传递返回。接着是组件自己的参数。如果是记账组件,那么最后一个参数必须是传票数组POT.OTVC层层传递,以实现将交易所有产生的记账传票流水按套顺序重组,返回前端打印。现有的很多系统,只能体现交易所有借贷传票,无法体现传票先后顺序,也不能按会计原理进行最小成套归类,并保证每套不会出现多借多贷,而Firebird则做到了这一点。
在返回处理过程中,特别注意如果是输出有数组,需要在这段中调用SCNCMTA设置输出数组实际有值的条数,主控会根据实际条数去简化返回报文。
组件程序样例SCETPSV,除了固定的PMG参数外,有F1,F2两个自有参数。组件由SCETPSVP组件声明,SCETPSVF1,SCETPSVF2两个参数结构定义,SCETPSV组件程序这几个部分组成。
SCETPSVF1参数文件如下。
- A REF(DICT)
- A R RSCETPSVF1
- A BKBRNO R REFFLD(@@BRNO)
- A COLHDG('机构号')
- A TEXT('机构号')
SCETPSVF2参数文件如下。
- A REF(DICT)
- A R RSCETPSVF2
- A MTTLNO R REFFLD(@@TLNO)
- A COLHDG('柜员号')
- A TEXT('柜员号')
SCETPSVP组件声明文件如下。
- **BEGIN***************************************************************
- **程序名称:服务程序模板原型 *
- **功能描述:服务程序模版原型及参数接口定义 *
- ** *
- **版本:2014-10-21_1 *
- ** *
- **设计人员:CSWWM 开发人员:CSWWM *
- **设计日期:2011-08-30 开发日期:2011-08-30 *
- **-------------------------------------------------------------------*
- **维护人员:CSWYJ *
- **维护日期:2014-10-17 *
- **维护内容:按新规范改写 *
- ** *
- **END*****************************************************************
- **常量定义
- DC_NBTPSVF2 C CONST(50)
- *************************
- **参数接口定义
- DTPSVF1 E DS EXTNAME(SCETPSVF1) QUALIFIED
- DT_TPSVF2 E DS EXTNAME(SCETPSVF2) QUALIFIED TEMPLATE
- DTPSVF2 DS QUALIFIED
- D RECD LIKE(DICT.@@RECD)
- D ARR DIM(C_NBTPSVF2) LIKEDS(T_TPSVF2)
- *************************
- **程序原型定义
- DSCETPSV PR EXTPGM('SCETPSV')
- D PMG LIKEDS(PMG)
- D TPSVF1 LIKEDS(TPSVF1)
- D TPSVF2 LIKEDS(TPSVF2)
这里要注意的是,组件的数组与交易接口数组不同,全部是带上RECD实际记录条数的复合结构。这样才能知道最大容量的数组,实际存放了多少条有效记录。
组件程序SCETPSV文件如下。
- **BEGIN***************************************************************
- **程序名称:组件程序模板 *
- **功能描述:组件程序开发规范 *
- ** *
- **设计人员:CSWWM 开发人员:CSWWM *
- **设计日期:2011-08-30 开发日期:2011-08-30 *
- **-------------------------------------------------------------------*
- **维护人员: *
- **维护日期: *
- **维护内容: *
- ** *
- **END*****************************************************************
- H/COPY DSCPPGM,HEAD
- **********************************************************************
- **在F表中声明的程序操作的数据表,且同时声明数据表的操作方式
- **数据表声明顺序如下:
- **1)、声明操作方式为只读(I)的数据表;
- **2)、声明操作方式为读(I)、写(A)的数据表;
- **3)、声明操作方式为更改(U)的数据表;
- **4)、声明操作方式为更新(U)、写(A)的数据表;
- **5)、声明操作方式为只写(O)的数据表;
- FACNBRMF UF E K DISK INFSR(#FLEX) INFDS(S_CNBRMF)
- F QUALIFIED
- FACNTLMF UF A E K DISK INFSR(#FLEX) INFDS(S_CNTLMF)
- F QUALIFIED COMMIT
- **********************************************************************
- **引入数据字典枚举常量
- D/COPY DSCPPGM,ENUM
- **引入程序公共结构
- D/COPY DSCPPGM,PGDS
- *************************
- **文件结构定义
- DS_CNBRMF DS LIKEDS(FILESDS)
- DK_CNBRMF DS LIKEREC(ACNBRMF.RACNBRMF:*KEY)
- DR_CNBRMF DS LIKEREC(ACNBRMF.RACNBRMF:*INPUT)
- DW_CNBRMF DS LIKEREC(ACNBRMF.RACNBRMF:*OUTPUT)
- DS_CNTLMF DS LIKEDS(FILESDS)
- DR_CNTLMF DS LIKEREC(ACNTLMF.RACNTLMF:*INPUT)
- *************************
- **决定是否以*LR=*ON结束
- D*/DEFINE USELR
- **常量定义
- DC_F1 C CONST('组件程序模版')
- DC_MGBRMF C CONST('机构表')
- DC_MGBRNO C CONST('机构号')
- *************************
- **引入调用服务原型
- D/COPY CETPEXP,SCETPSVP
- **定义参照外部结构(EXTNAME)的结构、数组
- **定义参照内部结构、变量(LIKE)的结构、数组
- *************************
- **临时变量结构
- DD_VARS DS
- **定义参照数据字典(LIKE)的变量
- D V_BKBRNO LIKE(DICT.@@BRNO)
- **定义无法参照的临时变量
- D V_NUM 5P 0
- ********************************************************************
- **程序入口定义
- C *ENTRY PLIST
- C PARM PMG
- C PARM TPSVF1
- C PARM TPSVF2
- /FREE
-
- EXSR @INIT;
- EXSR @CHEK;
- EXSR @MAIN;
- EXSR #EXIT;
-
- //---------------------------------------------------------
- //程序初始化
- //---------------------------------------------------------
- BEGSR @INIT;
- //初始化公共定义的结构
- CLEAR PMG;
- CLEAR A_MSDS;
- //初始化文件读取操作结构,除文件异常结构外
- CLEAR K_CNBRMF;
- CLEAR R_CNBRMF;
- CLEAR R_CNTLMF;
- //初始化自定义结构
- CLEAR D_VARS;
- ENDSR;
-
- //---------------------------------------------------------
- //检查接口传递值的正确性
- //---------------------------------------------------------
- BEGSR @CHEK;
- //机构号为空
- IF TPSVF1.BKBRNO = *BLANKS;
- PMG.BKMSID = 'EIOND';
- A_MSDS(1) = C_F1;
- A_MSDS(2) = C_MGBRNO;
- EXSR #ERR;
- ENDIF;
- ENDSR;
-
- //---------------------------------------------------------
- //程序的主流程
- //---------------------------------------------------------
- BEGSR @MAIN;
- K_CNBRMF.BKBRNO = TPSVF1.BKBRNO;
- FILEDSP = %ADDR(S_CNBRMF);
- CHAIN %KDS(K_CNBRMF) ACNBRMF.RACNBRMF R_CNBRMF;
- IF NOT %FOUND(ACNBRMF);
- PMG.BKMSID = 'ENTRD';
- A_MSDS(1) = C_MGBRMF;
- A_MSDS(2) = C_MGBRNO + K_CNBRMF.BKBRNO;
- EXSR #ERR;
- ENDIF;
- EVAL-CORR W_CNBRMF = R_CNBRMF;
- UPDATE ACNBRMF.RACNBRMF W_CNBRMF;
- EVAL-CORR TPSVF2.ARR(1) = W_CNBRMF;
- ENDSR;
-
- /END-FREE
- C/COPY DSCPPGM,PGCM
这里值得注意的是,组件程序本身也要/COPY引入组件声明,以为声明包含了原型定义,以及参数结构定义。另外,由于引入了异常处理程序,现在应用程序编写起来就清晰多了,无需考虑各种文件操作的异常报错处理,是不是很方便呢。
至此,组件和交易模版介绍完了,按照这个模版,就可以编写实际使用的各个模块程序,挂在交易主控中执行了。
Stellungnahme:Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn