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引入組件聲明,以為聲明包含了原型定義,以及參數結構定義。另外,由於引入了異常處理程序,現在應用程序編寫起來就清晰多了,無需考慮各種文件操作的異常報錯處理,是不是很方便呢。
至此,組件和交易模版介紹完了,按照這個模版,就可以編寫實際使用的各個模塊程序,掛在交易主控中執行了。