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引入组件声明,以为声明包含了原型定义,以及参数结构定义。另外,由于引入了异常处理程序,现在应用程序编写起来就清晰多了,无需考虑各种文件操作的异常报错处理,是不是很方便呢。
至此,组件和交易模版介绍完了,按照这个模版,就可以编写实际使用的各个模块程序,挂在交易主控中执行了。
Déclaration:Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn