📄 db_op.ec
字号:
/*========================================================================
功能: 对数据库表操作
作者:
王永忠: 2001/03/31:规范程序设计
王永忠: 2001/04/02:修改原merchant为merchant_base
增加根据商户号到商户受理卡类资料表中查找该商户的受理卡
类信息,并设置卡使能状态数组。
王永忠: 2001/04/09:修改路由表操作函数
周国祥:2001/04/27: 放开load_mcc_param()函数
王永忠: 2001/07/09:修改update_table()函数,增加返回码1
王永忠: 2001/08/21:将AUTH_PUR(授权消费)从卡段交易路由中移到交易
路由中.
王永忠: 2001/09/26:在load_bank_tab()中添加对$(WORKDIR)/etc/IP_FILTER
文件的处理, 以便在网间处理时不再查询数据库系统, 并且不需要
人工维护该文件.
王永忠: 2001/10/16:添加select_tran_ls()函数用来在有些地方替换用来使用的
select_ls_record()函数。
王永忠: 2001/10/19:在select_tran_ls()函数添加对OFFLINE交易的支持
周国祥: 2002/05/10:增加load_bank_tab_netm()函数, 添加对网控器监控的支持
=========================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include "mytools.h"
#include "shmsys.h"
#include "macro_def.h"
#include "public.h"
$include "db_struct.h"
$include sqlca;
extern int errno;
void error_handler ();
void warning_handler ();
void notfound_handler ();
EXEC SQL WHENEVER SQLERROR CALL error_handler;
EXEC SQL WHENEVER SQLWARNING CALL warning_handler;
EXEC SQL WHENEVER NOT FOUND CALL notfound_handler;
EXEC SQL BEGIN DECLARE SECTION;
S_sys_param G_sys_param;
S_merchant_base G_merchant_base;
S_merchant_switch G_merchant_switch;
S_edc_terminal G_edc_terminal;
S_edc_card G_edc_card;
S_bank_base G_bank_base;
S_wb_list G_wb_list;
S_saf_ls G_saf_ls;
S_tran_ls G_tran_ls;
S_sys_module G_sys_module;
S_mcc_param *G_mcc_par=NULL;
short indi;
int G_bank_base_num;
int G_card_router_num;
int G_tran_router_num;
int G_bankcard_router_num;
int G_adv_router_num;
int G_mcc_table_size;
S_default_route G_default_router;
S_card_route *G_card_router_tab=NULL;
S_tran_route *G_tran_router_tab=NULL;
S_bankcard_route *G_bankcard_router_tab=NULL;
S_adv_route *G_adv_router_tab=NULL;
S_bank_base *G_bank_tab=NULL;
S_tran_limit_amt G_tran_limit_amt;
EXEC SQL END DECLARE SECTION;
int bank_cmp ( void *bank1 , void *bank2 );
/***************************************************************
功能:
从cur_tran_ls表中获得交易统计
ENTRY:
sqlstring 此串中必须使用 select count(*), sum(amount) from
RETURN: -1, FAIL
0, SUCC, RESULT-->num, amt
****************************************************************/
int select_posls_total( sqlstring, num, amt )
char *sqlstring;
int *num;
double *amt;
{
EXEC SQL BEGIN DECLARE SECTION;
char sqlstr[1024];
int num0;
double amt0;
EXEC SQL END DECLARE SECTION;
if (strlen(sqlstring) > 1024)
return -1;
else
strcpy( sqlstr, sqlstring );
num0 = 0;
amt0 = 0;
EXEC SQL PREPARE sel_posls_t FROM :sqlstr;
EXEC SQL DECLARE sel_ls CURSOR WITH HOLD FOR sel_posls_t;
if( SQLCODE<0 ) {
errcall(ERROR, "DECLARE数据库游标失败[%ld][%s]", SQLCODE, sqlstr);
return -1;
}
EXEC SQL OPEN sel_ls;
if( SQLCODE<0 ) {
errcall(ERROR, "OPEN数据库游标失败[%ld][%s]", SQLCODE, sqlstr);
return -1;
}
EXEC SQL FETCH sel_ls INTO :num0, :amt0:indi;
if( SQLCODE<0 ) {
errcall(ERROR, "FETCH数据库游标失败[%ld][%s]", SQLCODE, sqlstr);
EXEC SQL CLOSE sel_ls;
return -1;
}
EXEC SQL CLOSE sel_ls;
if(num0 == 0)
amt0 = 0;
*num = num0;
*amt = amt0;
return 0;
}
/***************************************************************
功能:
用于查询 cur_tran_ls, his_tran_ls, err_tran_ls 表中
唯一记录 --> po
ENTRY: sqlstr 格式必须为: select * from
po 用来保存找到的原交易信息
pb PUBLIC结构
RETURN: -1 FAIL
0 FOUND
-2 NOT FOUND
****************************************************************/
int select_tran_ls( sqlstring, po, pb)
char *sqlstring;
S_tran_ls *po;
PUBLIC *pb;
{
EXEC SQL BEGIN DECLARE SECTION;
char sqlstr[1024];
S_tran_ls posls;
EXEC SQL END DECLARE SECTION;
if (strlen(sqlstring) > 1024)
{
errcall(ERROR, "SQL语句长度超过系统设置的字节数,SQL[%s]", sqlstring);
return -1;
}
else
strcpy( sqlstr, sqlstring );
//现在查找原交易的原则为根据一定的条件,将可能满足的记录取出,
//然后在这些记录中查找,这种方法可以使用数据库系统的索引,从而
//提高查找原交易的速度
EXEC SQL PREPARE sel_tran_ls FROM :sqlstr;
EXEC SQL DECLARE sel_tran_ls_cur CURSOR WITH HOLD FOR sel_tran_ls;
if( SQLCODE < 0 ) {
errcall(ERROR, "DECLARE数据库游标失败[%ld] [%s]", SQLCODE, sqlstr);
return -1;
}
EXEC SQL OPEN sel_tran_ls_cur;
if( SQLCODE < 0 ) {
errcall(ERROR, "OPEN数据库游标失败[%ld] [%s]", SQLCODE, sqlstr);
return -1;
}
while(1) {
//循环查找流水记录
EXEC SQL FETCH sel_tran_ls_cur INTO :posls;
if( SQLCODE < 0 ) {
errcall(ERROR, "Fetch数据库游标失败[%ld][%s]", SQLCODE, sqlstr);
EXEC SQL CLOSE sel_tran_ls_cur;
return -1;
}
if( SQLCODE == SQLNOTFOUND ) {
errcall(DEBUG, "没有找到交易的原交易信息!!");
EXEC SQL CLOSE sel_tran_ls_cur;
return -2;
}
del_st_space("cur_tran_ls", &posls);
//根据交易类型进行不同的原交易判断
switch(pb->Tran_type) {
case POS_VOID:
if(pb->Void_invoice_no != 0) {
//增加撤消交易金额为0时, 查找原交易时不使用交易金额
//作为判断条件
if (fabs(atol(pb->Tran_amount)/100.) < 0.01){
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.snd_settle_flag[0]== 'N' &&
posls.invoice_no == pb->Void_invoice_no &&
#if 0
posls.tran_type == pb->Void_tran_type &&
#endif
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
else {//(pb->Tran_amount != 0)
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.snd_settle_flag[0]== 'N' &&
posls.invoice_no == pb->Void_invoice_no &&
#if 0
posls.tran_type == pb->Void_tran_type &&
#endif
fabs(atol(pb->Tran_amount)/100. - posls.tran_amt) < 0.01 &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
}
else {//(pb->Void_invoice_no == 0)
//修改票据号为0时, 原使用TRACE_NO作为查找原交易的依据,
//为使用AUTH_NO作为查找原交易的依据.
if (fabs(atol(pb->Tran_amount)/100.) < 0.01){
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.snd_settle_flag[0]== 'N' &&
#if 0
posls.tran_type == pb->Void_tran_type &&
#endif
!strcmp(posls.auth_no, pb->Auth_no) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
else {//(pb->Tran_amount != 0)
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.snd_settle_flag[0]== 'N' &&
#if 0
posls.tran_type == pb->Void_tran_type &&
#endif
fabs(atol(pb->Tran_amount)/100. - posls.tran_amt) < 0.01 &&
!strcmp(posls.auth_no, pb->Auth_no) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
}
case REVERSAL:
$ifdef zgx021122_modi;
if (pb->Invoice_no != 0) {
$else;
if (pb->Void_invoice_no != 0) {
$endif;
if (posls.saf_flag[0] == '0' &&
posls.tran_flag[0] == '0' &&
$ifdef zgx021122_modi;
posls.invoice_no == pb->Invoice_no &&
$else;
posls.invoice_no == pb->Invoice_no &&
posls.void_invoice_no == pb->Void_invoice_no &&
$endif;
posls.snd_settle_flag[0]== 'N' &&
posls.rcv_settle_flag[0]== 'N' &&
posls.agt_settle_flag[0]== 'N' &&
posls.adv_settle_flag[0]== 'N' &&
#if 0
(fabs(posls.tran_amt - atol(pb->Tran_amount)/100.) < 0.001) &&
#endif
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
else {
if (posls.saf_flag[0] == '0' &&
posls.tran_flag[0] == '0' &&
posls.snd_settle_flag[0]== 'N' &&
posls.rcv_settle_flag[0]== 'N' &&
posls.agt_settle_flag[0]== 'N' &&
posls.adv_settle_flag[0]== 'N' &&
#if 0
(fabs(posls.tran_amt - atol(pb->Tran_amount)/100.) < 0.001) &&
#endif
!strcmp(posls.auth_no, pb->Auth_no) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
case CONFIRM:
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.tran_type == PRE_AUTH &&
!strcmp(posls.auth_no, pb->Auth_no) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
case REFUND:
case ADJUST:
if(pb->Void_invoice_no != 0) {
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.invoice_no == pb->Void_invoice_no &&
(posls.tran_type == CONFIRM ||
posls.tran_type == PURCHASE) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
else {
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.trace_no == pb->Void_trace_no &&
(posls.tran_type == CONFIRM ||
posls.tran_type == PURCHASE) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
}
#ifdef wyz_add_010705
case PRE_AUTH:
if (posls.tran_flag[0] == '0' &&
//posls.saf_flag[0] == '0' &&
//posls.tran_type== pb->Tran_type &&
!strcmp(posls.auth_no, pb->Auth_no) &&
!strcmp(posls.snd_bank_id, pb->Snd_bank_id) &&
!strcmp(posls.snd_host_id, pb->Snd_host_id) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
#endif
case OFFLINE:
//在OFFLINE交易中查找是否有该交易的预授权交易,授权号
if (posls.tran_flag[0] == '0' &&
posls.saf_flag[0] == '0' &&
posls.tran_type == PRE_AUTH &&
!strcmp(posls.auth_no, pb->Auth_no) &&
!strcmp(posls.resp_code, SUCCESS)){
EXEC SQL CLOSE sel_tran_ls_cur;
memcpy( po, &posls, sizeof( S_tran_ls ) );
return 0;
}
else
break;
default:
errcall(ERROR, "不处理该交易[%d]", pb->Tran_type);
return -1;
}//end of switch()
}//end of while(1)
}
/***************************************************************
功能:
用于查询 cur_tran_ls, his_tran_ls, err_tran_ls 表中
唯一记录 --> po
ENTRY: sqlstr 格式必须为: select * from
RETURN: -1 FAIL
0 FOUND,RESULT ---> po
-2 NOT FOUND
****************************************************************/
int select_ls_record( sqlstring, po )
char *sqlstring;
S_tran_ls *po;
{
EXEC SQL BEGIN DECLARE SECTION;
char sqlstr[1024];
S_tran_ls l_tran_ls;
EXEC SQL END DECLARE SECTION;
if (strlen(sqlstring) > 1024)
return -1;
strcpy(sqlstr, sqlstring);
EXEC SQL PREPARE sel_posls FROM :sqlstr;
EXEC SQL DECLARE sel_ls1 CURSOR WITH HOLD FOR sel_posls;
if( SQLCODE < 0 ) {
errcall(ERROR, "DECLARE数据库游标失败[%ld][%s]", SQLCODE, sqlstr);
return -1;
}
EXEC SQL OPEN sel_ls1;
if( SQLCODE < 0 ) {
errcall(ERROR, "OPEN数据库游标失败[%ld][%s]", SQLCODE, sqlstr);
return -1;
}
EXEC SQL FETCH sel_ls1 INTO :l_tran_ls;
if( SQLCODE < 0 ) {
errcall(ERROR, "Fetch数据库游标失败[%ld][%s]", SQLCODE, sqlstr);
EXEC SQL CLOSE sel_ls1;
return -1;
}
if( SQLCODE == SQLNOTFOUND ) {
errcall(DEBUG, "没有找到交易的流水信息!!");
EXEC SQL CLOSE sel_ls1;
return -2;
}
EXEC SQL CLOSE sel_ls1;
del_st_space("cur_tran_ls", &l_tran_ls);
memcpy(po, &l_tran_ls, sizeof(S_tran_ls));
return 0;
}
/***************************************************************
功能:
对任意表的更新
ENTRY: sqlstring
RETURN: -1 FAIL
0 SUCC
1 NOTFOUND
****************************************************************/
int update_table( sqlstring )
char *sqlstring;
{
EXEC SQL BEGIN DECLARE SECTION;
char sqlstr[1024];
EXEC SQL END DECLARE SECTION;
if (strlen(sqlstring) > 1024)
return -1;
strcpy( sqlstr, sqlstring );
EXEC SQL EXECUTE IMMEDIATE :sqlstr;
if (SQLCODE) {
if (SQLCODE == SQLNOTFOUND){
errcall(DEBUG, "更新数据库没找到[%s]", sqlstr);
return 1;
};
errcall(ERROR, "更新数据库失败[%d][%s]", SQLCODE, sqlstr);
return -1;
}
if (sqlca.sqlerrd[2] == 0) {
errcall(DEBUG, "更新数据库没找到[%s]", sqlstr);
return 1;
}
return 0;
}
/***************************************************************
功能:
取本地系统参数表信息
ENTRY: NULL
RETURN: -1 FAIL
0 SUCC, RESULT --> sy
****************************************************************/
int select_sys_param( sy )
S_sys_param *sy;
{
EXEC SQL BEGIN DECLARE SECTION;
S_sys_param l_sys_param;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT DISTINCT * INTO :l_sys_param FROM sys_param;
if (SQLCODE) {
errcall(ERROR, "取系统参数表失败![%ld]", SQLCODE);
return -1;
}
del_st_space("sys_param", &l_sys_param);
memcpy(sy, &l_sys_param, sizeof(S_sys_param));
return 0;
}
/***************************************************************
功能:
联行行号比较
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -