/* +-----------------+------------------------------------------------------------+ | FUNCION | search_timeout | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Busca un timeout en la cola | | | | +-----------------+------------------------------------------------------------+ */ void search_timeout() { int cont; int ret; char aux_str1[100]; /* Loguea la hora */ LogAlarm.Put(0, "search_TO(): Revisando TO...%s", currentTimeLog()); /* Busca un time out */ cont=timeout_queue.FindTO(); if (cont > -1) { /* Procesa un time out */ process_timeout(cont); } else { /* Espera para siguiente ejecucion */ LogAlarm.Put(0, "search_TO(): Esperando...\n"); Cfg.GetItem("TimeOutDaemon", "SleepTime", aux_str1); sleep(atoi(aux_str1)); LogAlarm.Put(0, "search_timeout(): Listo.\n"); } }
/* +-----------------+------------------------------------------------------------+ | FUENTE | Pos::SetPosBusy | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Agrega una caja a la lista de ocupadas | | | | +-----------------+------------------------------------------------------------+ */ int Pos::SetPosBusy(char *ca, char *suc, char *caj) { int cont=0; /* Busca el siguiente disponible */ while ((pos[cont].nro_ca[0]!='\0') && (cont<POS_MAX_MEMBERS)) { cont++; } /* Si hay una posicion libre */ if (pos[cont].nro_ca[0]=='\0') { /* Agrega el elemento */ strcpy(pos[cont].nro_ca , ca); strcpy(pos[cont].nro_caj , caj); strcpy(pos[cont].nro_suc , suc); LogAlarm.Put(5, "Objeto Pos: SetPosBusy [%s%s%s]. Posicion [%d]\n", ca, suc, caj, cont ); /* Retorna el resultado OK */ Errno=OK; return OK; } else { LogAlarm.Put(5, "Objeto Pos: SetPosBusy [%s%s%s]. NO HAY POSICIONES LIBRES\n", ca, suc, caj ); } /* Retorna el resultado error */ Errno=ENOSPC; return NOOK; }
/* +-----------------+------------------------------------------------------------+ | FUNCION | PriceOnLine::Armar_y_Enviar_Respuesta | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Arma un mensaje de respuesta local en funcion del mensaje | | | recibido y datos calculados y lo envia al TPV | +-----------------+------------------------------------------------------------+ */ int PriceOnLine::Armar_y_Enviar_Respuesta(char *szCodRta, struct trxRtaTPV *stRta) { Price_Msg *priceRta; char szCampo13[LON_CAMPO_13 + 1]; char szMsgStr[2000]; int iLen; int iRet = 0; char szCpoTerVer[25+1]; /* Arma mensaje de respuesta de rechazo hacia el TPV por configuracion erronea */ priceRta=new Price_Msg(TYPE_PRICE_VENTA_RTA); /* Completa campos de la respuesta */ priceRta->PutField( 1, mensaje_price->GetField( 1)); priceRta->PutField( 2, mensaje_price->GetField(15)); priceRta->PutField( 3, mensaje_price->GetField(16)); priceRta->PutField( 4, mensaje_price->GetField(11)); priceRta->PutField( 7, mensaje_price->GetField( 4)); priceRta->PutField( 8, mensaje_price->GetField( 5)); priceRta->PutField( 9, stRta->szCodAut); priceRta->PutField(10, ""); priceRta->PutField(11, stRta->szComerc); priceRta->PutField(15, mensaje_price->GetCodTar()); priceRta->PutField(16, "000000000000"); sprintf(szCampo13, "%03d%1s%8s%s%s ", atoi(stRta->szNroLot), FLAG_OFFLINE, PINPAD_NULO, stRta->szRespCA, stRta->szPlanSF); priceRta->PutField(13, szCampo13); priceRta->PutField( 6, szCodRta); /* Devuelve nro de terminal y version */ sprintf(szCpoTerVer, FTO_VER, stRta->szTermin, stRta->szProtoc, stRta->szPlnIso, NO_ANUL, VERSION_NRO, stRta->szTicOri, stRta->szFecOri ); priceRta->PutField(12, szCpoTerVer); /* Aplana el mensaje */ iLen = priceRta->GetMsgString(szMsgStr); /* Borra el mensaje price */ delete priceRta; /* Envia respuesta al TPV */ iRet = SQueue.SendMsg(orig_pid, szMsgStr, iLen); if (iRet != OK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al enviar respuesta\n", SQueue.GetErrno()); } else { LogAlarm.Put(0, "PriceOn: RESPUESTA LOCAL: %s\n", szCodRta); } return (iRet); }
/* +-----------------+------------------------------------------------------------+ | FUNCION | RtaRevAnul::ProcessIt | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Proceso del objeto | | | | +-----------------+------------------------------------------------------------+ */ int RtaRevAnul::ProcessIt() { int len; int ret; str_sel_cadata term_data; trxAnulHeap heap_data; char msgrta[300]; char idHeap[20]; char aux_str1[100]; int iCont; Queue EQueue; trxRevHeap heap_reve; /* Obtiene los datos de la caja en funcion de la caja del centro autorizador */ strcpy(term_data.nro_caj_ca, IsoMsg->GetField(41)); ret=ObtCaCaj(&term_data); if (ret!=OK) { /* Loguea el mensaje en caso de error */ LogAlarm.Put(0, "RtaRevAnul: ERROR (%d) al obtener datos de la caja [%s]\n", ret, term_data.nro_caj_ca); return NOOK; } /* Obtiene los datos del heap */ sprintf(idHeap,"%2.2s%3.3s%5.5s%8.8s", term_data.nro_ca, term_data.nro_suc, term_data.nro_caj, IsoMsg->GetField(11)); LogAlarm.Put(0, "RtaRevAnul: Extrayendo datos del heap [%s]\n", idHeap); ret=Heap.GetData(idHeap,(char *)&heap_reve, sizeof(heap_reve)); if (ret==NOOK) { LogAlarm.Put(0, "RtaRevAnul: Transaccion no existe en Heap [%s]\n", idHeap); return NOOK; } else { LogAlarm.Put(0, "RtaRevAnul: Reenvio a RevTrxRta\n"); Cfg.GetItem("VisaDaemon", "QueueID", aux_str1); if ( EQueue.Open(atoi(aux_str1)) == OK ) { Heap.PutData(idHeap,(char *)&heap_reve, sizeof(heap_reve)); EQueue.SendMsg(EVENT_SNDREVERSO_RTA, szMsjeISO, iLMsjeISO); } } LogAlarm.Put(0, "RtaRevAnul: Evento finalizado\n"); return OK; }
/* +-----------------+------------------------------------------------------------+ | FUENTE | Pos::SetPosFree | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Elimina una caja de la lista de ocupadas | | | | +-----------------+------------------------------------------------------------+ */ int Pos::SetPosFree(char *ca, char *suc, char *caj) { int cont=0; /* Busca la clave */ while ( ( (strcmp(pos[cont].nro_ca , ca )) || (strcmp(pos[cont].nro_caj, caj)) || (strcmp(pos[cont].nro_suc, suc)) ) && (cont<POS_MAX_MEMBERS) ) { cont++; } /* Si encuentra la clave */ if ( (strcmp(pos[cont].nro_ca , ca )==0) && (strcmp(pos[cont].nro_caj , caj)==0) && (strcmp(pos[cont].nro_suc , suc)==0) ) { LogAlarm.Put(5, "Objeto Pos: SetPosFree [%s%s%s]. Posicion [%d]\n", ca, suc, caj, cont); /* Libera el elemento */ pos[cont].nro_ca[0] = '\0'; pos[cont].nro_caj[0] = '\0'; pos[cont].nro_suc[0] = '\0'; /* Retorna el resultado OK */ Errno=OK; return OK; } else { LogAlarm.Put(5, "Objeto Pos: SetPosFree [%s%s%s]. Posicion no encontrada\n", ca, suc, caj); } /* Retorna el resultado error */ Errno=ENOENT; return NOOK; }
/* +-----------------+------------------------------------------------------------+ | FUENTE | Pos::IsPosFree | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Verifica si una caja esta libre | | | Retorna: 1:No encontrado - 0:Encontrado | +-----------------+------------------------------------------------------------+ */ int Pos::IsPosFree(char *ca, char *suc, char *caj) { int cont=0; int ret; /* Busca si la clave se encuentra */ while ( ( (strcmp(pos[cont].nro_ca , ca )) || (strcmp(pos[cont].nro_caj , caj)) || (strcmp(pos[cont].nro_suc , suc)) ) && (cont<POS_MAX_MEMBERS) ) { cont++; } /* Retorna el resultado */ ret = (cont==POS_MAX_MEMBERS); LogAlarm.Put(5, "Objeto Pos: IsPosFree [%s%s%s]. Retorno [%d]\n", ca, suc, caj, ret); return ret; }
/* +-----------------+------------------------------------------------------------+ | FUNCION | EchoTest::EnviarMsg | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Envia un mensaje por la cola administrativa | | | | +-----------------+------------------------------------------------------------+ */ int EchoTest::EnviarMsg(int orig_pid, char *msg, int len) { Queue AQueue; int iRet; char msgString[500]; char auxString1[100]; /* Abre cola de mensajes administrativos */ Cfg.GetItem("AdminDaemon", "QueueID", auxString1); iRet = AQueue.Open(atol(auxString1)); if (iRet==OK) { /* Envia mensaje */ memset(msgString, 0, sizeof(msgString)); memcpy(msgString, msg, len); iRet = AQueue.SendMsg(orig_pid, msgString, len); } if (iRet) { LogAlarm.Put(0, "EchoTest: ERROR al enviar mensaje por cola administrativa\n"); } return iRet; }
/* +-----------------+------------------------------------------------------------+ | FUNCION | EchoTest::ProcessIt | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Proceso del objeto | | | | +-----------------+------------------------------------------------------------+ */ int EchoTest::ProcessIt() { char msg_str[2000]; int len; int ret; int HeapOcup = 0; int TOQueueOcup = 0; char aux_str1[100]; char idHeap[20]; str_sel_cadata term_data; int iCantidad; /* Arma los datos de la terminal */ memset(&term_data, 0, sizeof(term_data)); strncpy(term_data.nro_suc, ping_data.nro_suc, sizeof(term_data.nro_suc)); strncpy(term_data.nro_caj, ping_data.nro_caj, sizeof(term_data.nro_caj)); strncpy(term_data.nro_ca , ping_data.nro_ca , sizeof(term_data.nro_ca )); LogAlarm.Put(0, "EchoTest: Suc:[%s] Caj:[%s] CA:[%s]\n", term_data.nro_suc, term_data.nro_caj, term_data.nro_ca); /* Obtiene datos de la terminal */ ret=getDataByNTET(&term_data); if (ret!=OK) { LogAlarm.Put( 1, "EchoTest: ERROR (%d) al obtener datos de la terminal\n", ret); EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } /* Se carga en el objeto TraceNmbr el centro autorizador con el que se trabaja */ TraceNumber.SetNroSuc(term_data.nro_suc); TraceNumber.SetNroCaj(term_data.nro_caj); TraceNumber.SetNroCA (term_data.nro_ca ); TraceNumber.SetCodConCie("0"); /* Arma mensaje iso */ mensaje_iso->PutField(7, currentTimestamp()); strcpy(aux_str1, TraceNumber); TraceNumber.Inc(); mensaje_iso->PutField(11, aux_str1); mensaje_iso->PutField(24, term_data.cod_red); mensaje_iso->PutField(41, term_data.nro_caj_ca); mensaje_iso->PutField(42, term_data.nro_com_et); /* Arma clave del heap */ sprintf(idHeap,"%02d",atoi(term_data.nro_ca)); /* Verifica si se encuentra en el heap */ LogAlarm.Put(0, "EchoTest: Busca clave en el heap [%s]\n", idHeap); ret=Heap.FindData(idHeap, (char *)&orig_pid,sizeof(orig_pid)); if (ret!=1) { LogAlarm.Put(0, "EchoTest: Heap ocupado. Clave:[%s]\n", idHeap); HeapOcup = 1; } LogAlarm.Put(0, "EchoTest: Valor de HeapOcup %d\n", HeapOcup); /* Verifica si se encuentra en la TOQ */ ret=timeout_queue.FindTimeOut(idHeap); if (ret==1) { LogAlarm.Put(0, "EchoTest: Se encontro en TOQueue. Clave:[%s]\n", idHeap); TOQueueOcup = 1; } LogAlarm.Put(0, "EchoTest: Valor de TOQueueOcup %d\n", TOQueueOcup); /* Si el ping esta activo */ if ((HeapOcup == 1) && (TOQueueOcup == 1)) { /* Envia respuesta por la cola administrativa */ LogAlarm.Put(0, "EchoTest: Ping Activo. Esta ocupado\n"); LogAlarm.Put(0, "EchoTest: Envia respuesta por la cola administrativa\n"); ret= EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } else { /* Si el head esta ocupado */ if (HeapOcup == 1) { LogAlarm.Put( 0, "EchoTest: Se encuentra en Heap pero no en TOQ\n"); ret=Heap.GetData(idHeap, (char *)&orig_pid,sizeof(orig_pid)); if (ret==NOOK) { LogAlarm.Put( 0, "EchoTest: ERROR (%d) al extraer de heap\n", Heap.GetErrno()); EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } } /* Si la TOQ esta ocupada */ if (TOQueueOcup == 1) { LogAlarm.Put( 0, "EchoTest: Se encuentra en TOQ pero no en Heap\n"); ret=timeout_queue.RemTimeOut(idHeap); if (ret==NOOK) { LogAlarm.Put(0, "EchoTest: ERROR (%d) al extraer de TOQ\n", timeout_queue.GetErrno()); EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } } } /* Registra en el heap */ LogAlarm.Put(0, "EchoTest: Registra mensaje en el heap.\n"); ret=Heap.PutData(idHeap, (char *)&orig_pid,sizeof(orig_pid)); if (ret==NOOK) { LogAlarm.Put(0, "EchoTest: ERROR (%d) al registrar en el heap\n", Heap.GetErrno()); EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } /* Registra en la TimeoutQueue */ LogAlarm.Put(0, "EchoTest: Registra mensaje en la TOQ\n"); Cfg.GetItem("TimeOutDaemon", "MsgTimeOut1", aux_str1); ret=timeout_queue.SetTimeOut(idHeap, atoi(aux_str1), GetType(), ""); if (ret==NOOK) { LogAlarm.Put(0, "EchoTest: ERROR (%d) al agregar a la TOQ\n", timeout_queue.GetErrno()); /* Retira del heap si hubo error */ ret=Heap.GetData(idHeap, (char *)&orig_pid,sizeof(orig_pid)); if (ret==NOOK) { LogAlarm.Put( 0, "EchoTest: ERROR (%d) al obtener del heap\n", Heap.GetErrno()); } EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } /* Aplana el mensaje */ len=mensaje_iso->GetMsgString(msg_str); /* Envia por la cola de X.25 */ LogAlarm.Put(0, "EchoTest: Envia a X.25. CAut [%s]\n", term_data.nro_ca); ret=XQueue.SendMsg(atoi(term_data.nro_ca)+1, msg_str, len); if (ret!=OK) { LogAlarm.Put( 0, "EchoTest: ERROR (%d) al enviar por X.25!!\n", XQueue.GetErrno()); EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } return OK; }
/* +-----------------+------------------------------------------------------------+ | FUNCION | Batch::ProcessIt | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Proceso del objeto | | | | +-----------------+------------------------------------------------------------+ */ int Batch::ProcessIt() { char aux_str[100]; char msg_str[2000]; int msg_len; int ret; str_heap_data heap_data; str_sel_ntdata term_data; char idHeap[20]; /* Obtiene los datos del mensaje */ LogAlarm.Put(5, "Batch: Obteniendo datos de la terminal.\n"); strcpy(term_data.nro_caj_ca, mensaje_iso->GetField(41)); strcpy(term_data.nro_com , mensaje_iso->GetField(42)); /* Obtiene datos de la terminal */ ret=getDataByCA(&term_data); if (ret!=OK) { LogAlarm.Put( 0, "Batch: ERROR (%d) al obtener datos de la terminal\n", ret); return NOOK; } /* Se indica al objeto TraceNmbr con que centro autorizador se trabaja */ TraceNumber.SetNroSuc(term_data.nro_suc); TraceNumber.SetNroCaj(term_data.nro_caj); TraceNumber.SetNroCA (term_data.nro_ca ); TraceNumber.SetCodConCie(term_data.cod_con_cie); /* Setea centro autorizador */ mensaje_iso->SetNroCA8583(term_data.nro_ca); /* Obtiene tarjeta y la carga para agregar 'F' final */ switch (DBTipoProtocoloISO(term_data.nro_ca)) { case PROT_ISO_AMEX: sprintf(aux_str, "%s", mensaje_iso->GetField(2)); mensaje_iso->PutField(2, aux_str); break; default: break; } /* Completar el mensaje con los datos generados */ strcpy(aux_str, TraceNumber); TraceNumber.Inc(); mensaje_iso->PutField(11, aux_str); /* Chequea consistencia del mensaje */ LogAlarm.Put(5, "Batch: Checkeo de consistencia del msg.\n"); if (!mensaje_iso->ChkReady()) { LogAlarm.Put(0,"Batch: ERROR mensaje ISO incompleto\n"); return NOOK; } /* Registra transaccion en TrxHeap */ LogAlarm.Put(5, "Batch: Obteniendo datos para el Heap.\n"); heap_data.orig_pid=orig_pid; LogAlarm.Put(5, "Batch: Poniendo datos en el Heap.\n"); sprintf(idHeap,"%2.2s%3.3s%5.5s%8.8s", term_data.nro_ca, term_data.nro_suc, term_data.nro_caj, mensaje_iso->GetField(11)); ret=Heap.PutData(idHeap,(char *)&heap_data, sizeof(heap_data)); if (ret==NOOK) { LogAlarm.Put(5, "Batch: ERROR (%d) al agregar en el Heap\n", Heap.GetErrno()); return NOOK; } /* Registra en la TimeoutQueue */ LogAlarm.Put(5, "Batch: Agregando a la TO Queue.\n"); Cfg.GetItem("TimeOutDaemon", "MsgTimeOut320", aux_str); ret=timeout_queue.SetTimeOut(idHeap, atoi(aux_str), GetType(), ""); if (ret==NOOK) { LogAlarm.Put(0, "Batch: ERROR (%d) al agregar en TimeOutQueue\n", timeout_queue.GetErrno()); return NOOK; } /* Aplana el mensaje */ msg_len=mensaje_iso->GetMsgString(msg_str); /* Envia el mensaje por X25 */ LogAlarm.Put(0, "Batch: Envia a X.25. CAut [%s]\n", term_data.nro_ca); ret=XQueue.SendMsg(atoi(term_data.nro_ca)+1, msg_str, msg_len); if (ret==NOOK) { LogAlarm.Put(0, "Batch: ERROR (%d) al enviar a Cola X.25\n", XQueue.GetErrno()); return NOOK; } LogAlarm.Put(5, "Batch: Evento finalizado\n"); return OK; }
main() { Log LogAlarm; Config CfgCred("credito.ini"); char buffer1[500]; char buffer2[500]; Queue XQueue,EQueue; long QueueID,QueuePerm; struct tm *newtime; time_t ltime; int ret; int len; Iso_Msg *IsoMsg; Iso_Msg *IsoRta; LogAlarm.Open("../log/Em.log"); LogAlarm.SetLevel(10); CfgCred.GetItem("CAVisaDaemon","QueueID",buffer1); QueueID=atol(buffer1); CfgCred.GetItem("CAVisaDaemon","QueuePerms",buffer2); QueuePerm=atol(buffer2); ret=XQueue.Create(QueueID,QueuePerm); if (ret!=OK) exit(ret); CfgCred.GetItem("Daemon","QueueID",buffer1); QueueID=atol(buffer1); CfgCred.GetItem("Daemon","QueuePerms",buffer2); QueuePerm=atol(buffer2); ret=EQueue.Open(QueueID,QueuePerm); if (ret!=OK) { exit(ret); } time(<ime); newtime=localtime(<ime); srandom(newtime->tm_sec); LogAlarm.Put(1,"Comenzando Operacion %s\n",asctime(newtime)); while (ret==OK) { len=XQueue.GetMsg(0, buffer1, sizeof(buffer1)); if (len==NOOK) { break; } IsoMsg=new Iso_Msg(buffer1,len); switch (IsoMsg->GetMsgType()) { case TYPE_VISA_VENTA: LogAlarm.Put(1,"Recibido PriceOn [%s] [%s]\n", IsoMsg->GetField(41),IsoMsg->GetField(11)); IsoRta = new Iso_Msg(TYPE_VISA_VENTA_RTA); IsoRta->PutField(2,IsoMsg->GetField(2)); IsoRta->PutField(11, IsoMsg->GetField(11)); IsoRta->PutField(24, IsoMsg->GetField(24)); sprintf(buffer1,"%012%d",random()); IsoRta->PutField(37,buffer1); sprintf(buffer1,"%06d",random()); IsoRta->PutField(38,buffer1); IsoRta->PutField(39,"00"); IsoRta->PutField(41, IsoMsg->GetField(41)); len=IsoRta->GetMsgString(buffer1); ret=EQueue.SendMsg(EVENT_PRICEONLINE_RTA,buffer1,len); break; } } }
/* +-----------------+------------------------------------------------------------+ | FUNCION | init | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Inicia las estructuras y memoria compartida | | | | +-----------------+------------------------------------------------------------+ */ int init() { int ret; int cont; int max_entries; char aux_str1[100]; char aux_str2[100]; /* Configura las señales de terminacion */ signal(SIGINT, shut_down); signal(SIGTERM, shut_down); /* Obtiene el nombre del archivo de log */ Cfg.GetItem("TimeOutDaemon", "LogName", aux_str1); LogAlarm.Open(aux_str1); /* Setea el nivel de log */ Cfg.GetItem("TimeOutDaemon", "LogLevel", aux_str1); LogAlarm.SetLevel(atoi(aux_str1)); /* Loguea hora de comienzo */ LogAlarm.Put( 0,"TimeOutDaemon::init(): Comienzo [%s] - %s", NUM_VERSION, currentTimeLog()); /* Obtiene la cantidad maxima de entradas en la cola */ Cfg.GetItem("TimeOutDaemon", "MaxEntries", aux_str1); max_entries=atoi(aux_str1); /* Obtiene la cantidad maxima de entradas en la tabla de PIDs */ Cfg.GetItem("PIDTable", "ShMemID", aux_str1); Cfg.GetItem("PIDTable", "MaxEntries", aux_str2); /* Abre tabla de PIDs */ LogAlarm.Put(0, "TimeOutDaemon::init(): Abre tabla de PIDs [%s] [%s]\n", aux_str1, aux_str2); while (PTable.Open(atoi(aux_str1), atoi(aux_str2))==NOOK) { if (PTable.GetErrno()!=ENOENT) { LogAlarm.Put(0, "TimeOutDaemon::init(): Error (%d)!!\n", PTable.GetErrno()); exit(1); } } /* Pone el pid en la tabla */ LogAlarm.Put(0, "TimeOutDaemon::init(): Adding PID to PID table...\n"); ret=PTable.PutPid(getpid()); if (ret==NOOK) { LogAlarm.Put(0, "TimeOutDaemon::init(): Error (%d)!!\n", PTable.GetErrno()); exit(1); } /* Obtiene los identificadores y permisos de la cola de timeout */ Cfg.GetItem("TimeOutDaemon", "ShMemID", aux_str1); Cfg.GetItem("TimeOutDaemon", "ShMemPerms", aux_str2); /* Crea cola de timeout */ LogAlarm.Put(0, "TimeOutDaemon::init(): Creando area de memoria compartida para la Timeout_Queue\n"); ret=timeout_queue.Create(atoi(aux_str1), max_entries, atoi(aux_str2)); if (ret==NOOK) { LogAlarm.Put(0, "TimeOutDaemon::init(): Error (%d) al crear area para la Timeout_Queue \n", timeout_queue.GetErrno()); } /* Obtiene identificador de la cola de eventos */ Cfg.GetItem("VisaDaemon", "QueueID", aux_str1); /* Abre cola de eventos */ LogAlarm.Put(0, "TimeOutDaemon::init(): Abriendo cola de eventos...\n"); ret= EQueue.Open(atoi(aux_str1)); if (ret==NOOK) { LogAlarm.Put(1, "TimeOutDaemon::init(): Error (%d) al abrir cola de eventos!!\n", EQueue.GetErrno()); return NOOK; } return OK; }
/* +-----------------+------------------------------------------------------------+ | FUNCION | process_timeout | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Procesa el timeout. | | | Parametro: cont: Posicion de la cola con el timeout | +-----------------+------------------------------------------------------------+ */ void process_timeout(int cont) { int ret; int event_type; str_timeout *timeout_data; str_timeout_event timeout_event_data; char aux_str1[100]; /* Obtiene los datos del elemento con time out vencido */ timeout_data=timeout_queue.GetTimeOut(cont); LogAlarm.Put(0, "process_timeout(): Se encontro un TO (id:%s)\n", timeout_data->id); /* Si expired==0 */ if (timeout_data->expired==0) { /* Setea el primer timeout */ Cfg.GetItem("TimeOutDaemon", "MsgTimeOut2", aux_str1); LogAlarm.Put(0, "process_timeout(): Primer timeout\n"); timeout_queue.SetOne(cont, atoi(aux_str1)); /* Generar evento TimeOut */ LogAlarm.Put(0, "process_timeout(): Generando evento TimeOut...\n"); /* Completa la estructura del timeout */ strcpy(timeout_event_data.key,timeout_data->id); strcpy(timeout_event_data.cod_ser,timeout_data->cod_ser); /* Obtiene el tipo de evento */ switch (timeout_data->event_type) { case EVENT_REVTRXANUL: LogAlarm.Put(5,"process_timeout(): generando TimeOut de Reverso Anulacion \n"); event_type=EVENT_TIMEOUT_REV_ANUL; break; case EVENT_SNDTRXANUL: LogAlarm.Put(5,"process_timeout(): Generando Timeout de Anulacion \n"); event_type=EVENT_TIMEOUT_ANULACION; break; case EVENT_CIERRE: LogAlarm.Put(5, "process_timeout(): Generando TimeOut de cierre...\n"); event_type=EVENT_TIMEOUT_CIERRE; break; case EVENT_CIERRE_B: LogAlarm.Put(5, "process_timeout(): Generando Timeout de cierre Batch\n"); event_type=EVENT_TIMEOUT_CIERRE_B; break; case EVENT_BATCH: LogAlarm.Put(5, "process_timeout(): Generando Timeout en trx de batch upload\n"); event_type=EVENT_TIMEOUT_BATCH; break; case EVENT_SNDTRXOFFLINE: LogAlarm.Put(5, "process_timeout(): Generando Timeout de Transaccion offline\n"); event_type=EVENT_TMTTRXOFFLINE; break; case EVENT_SNDREVERSO: LogAlarm.Put(5, "process_timeout(): Generando Timeout de reverso\n"); event_type=EVENT_TIMEOUT_REVERSO; break; case EVENT_ECHOTEST: LogAlarm.Put(5, "process_timeout(): Generando Timeout de echo test\n"); event_type=EVENT_TIMEOUT_ECHOTEST; break; default: LogAlarm.Put(5, "process_timeout(): Generando Timeout generico\n"); event_type=EVENT_TIMEOUT; } /* Envia el mensaje al Daemon */ ret=EQueue.SendMsg(event_type, (char *)&timeout_event_data, sizeof(str_timeout_event)); if (ret==NOOK) { LogAlarm.Put(5, "process_timeout: Error (%d) en Envio de Evento Timeout!!\n", EQueue.GetErrno()); } } else /* expired en 1 (ya se habia cumplido el 1er. timeout) */ { /* Borra el timeout de la cola */ LogAlarm.Put(0, "process_timeout: Segundo timeout. Borrando de la tabla...\n"); timeout_queue.SetSecond(cont); } }
/* +-----------------+------------------------------------------------------------+ | FUNCION | PriceOnLine::ProcessIt | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Proceso del objeto | | | | +-----------------+------------------------------------------------------------+ */ int PriceOnLine::ProcessIt() { str_sel_cadata term_data; str_heap_data heap_data; TrxData trx_data; char msg_str[2000]; char aux_str[64]; char szNroCta[64]; int cont; int len; int ret; int limite=OK; int channel_down; int pos_ocup; int TrxEnVuelo; str_upd_rev StrDataRev; char CajDevol[6]; char TrxDevol[5]; char CajVenta[6]; char TrxVenta[5]; char FecVenta[7]; char szCampo13[LON_CAMPO_13 + 1]; char szCuotas[32]; /* Modificacion PINPAD */ char szPinPad[64]; int iHayPinPad; /* Pinpad 2*/ long lCodProc; long lCodCuenta; char szCodiProc[16]; int iTipoOperacion=0; char NroTrxAux[9]; char szRowId[64]; char szFHtransm[32]; char szFHoperac[32]; long lImpoTran; long lCashBack; char szCriptograma[1024] = {0}; char szVersionEMV[20] = {0}; char szEMVProductList[512] = {0}; struct trxRtaTPV stRta; /* Blanquea estructura de respuesta */ memset(&stRta, 0, sizeof(stRta)); memset(stRta.szCodAut, ' ', sizeof(stRta.szCodAut)-1); memset(stRta.szComerc, ' ', sizeof(stRta.szComerc)-1); memset(stRta.szTermin, ' ', sizeof(stRta.szTermin)-1); memset(stRta.szNroLot, ' ', sizeof(stRta.szNroLot)-1); memset(stRta.szPlnIso, ' ', sizeof(stRta.szPlnIso)-1); memset(stRta.szProtoc, ' ', sizeof(stRta.szProtoc)-1); memset(stRta.szRespCA, ' ', sizeof(stRta.szRespCA)-1); memset(stRta.szFecOri, ' ', sizeof(stRta.szFecOri)-1); memset(stRta.szTicOri, ' ', sizeof(stRta.szTicOri)-1); memset(stRta.szPlanSF, ' ', sizeof(stRta.szPlanSF)-1); /* Track II en las IBM no viene el separador de campos '='. Se agrega */ char TrackIIprice[40]; char * indexTr; strcpy(TrackIIprice,mensaje_price->GetField(10)); if ((indexTr=strchr(TrackIIprice,'D'))!=NULL) { *indexTr='='; mensaje_price->PutField(10,TrackIIprice); } /* Se invierte la fecha de caducidad siempre */ mensaje_price->InvertirFecha(); /* Se loguean los datos de la terminal */ LogAlarm.Put(0, "PriceOn: Emp:[%s] Suc:[%s] Ter:[%s] Trx:[%s] Tar:[%s] Plan:[%s]\n", mensaje_price->GetEmpresa() , mensaje_price->GetSucursal() , mensaje_price->GetTerminal() , mensaje_price->GetTransaccion() , mensaje_price->GetCodTar() , mensaje_price->ObtPlanSf()); /* Se obtienen los datos de la terminal en base al mensaje price */ strcpy(term_data.plan_sf, mensaje_price->ObtPlanSf()); strcpy(term_data.cod_tar, mensaje_price->GetCodTar()); strcpy(term_data.nro_suc, mensaje_price->GetEmpresa()); strcpy(term_data.nro_caj, mensaje_price->GetTerminal()); /* Obtiene el tipo de operacion ( 01:T_VENT - 02:T_DEVO - 08:T_PAGO - 09:T_DEVP ) */ iTipoOperacion = atoi(mensaje_price->GetField(5)); /* Se buscan los restantes datos de la terminal */ ret=getDataByNT2(&term_data); if ( (ret!=OK) || (term_data.caj_bloq==1) ) { /* Al dar error, loguea los datos de la terminal mal configurada */ if (term_data.caj_bloq==1) { LogAlarm.Put (0, "PriceOn: ERROR Caja bloqueada por cierre anterior fallido\n"); } else { LogAlarm.Put (0, "PriceOn: ERROR (%d) al obtener datos de la terminal\n", ret); } /* Escribe en el log de errores de terminal */ LogErrTerminal.Put(0, "Fecha Hora %s", currentTimeLog() ); LogErrTerminal.Put(0, "Caja: %s - Empresa: %s - Tarjeta: %s - Plan: %s - Evento: PriceOn\n\n", mensaje_price->GetTerminal(), mensaje_price->GetEmpresa(), mensaje_price->GetCodTar(), mensaje_price->ObtPlanSf()); /* Arma mensaje de respuesta y lo envia al TPV */ sprintf(stRta.szRespCA, "102"); if ( (iTipoOperacion==T_PAGO) || (iTipoOperacion==T_DEVP) ) { Armar_y_Enviar_Respuesta("11", &stRta); } else { Armar_y_Enviar_Respuesta("08", &stRta); } return OK; } /* Se agrega en la cadena del heap el nro_tar original para devolverlo */ strcpy(heap_data.nro_tar,mensaje_price->GetField(4)); /* Se adapta el mensaje price a la forma de autorizacion */ mensaje_price->ConvMsgPrice(atoi(term_data.tip_aut)); /* Completa la estructura de Trace Number */ TraceNumber.SetNroSuc(term_data.nro_suc); TraceNumber.SetNroCaj(term_data.nro_caj); TraceNumber.SetNroCA (term_data.nro_ca ); TraceNumber.SetCodConCie(term_data.cod_con_cie); /* Si se esta haciendo un cierre de lote genera la respuesta y se la envia de vuelta al price */ if (CACS.IsCierre(atoi(term_data.nro_ca))) { if ((CACS.GetSuc(atoi(term_data.nro_ca))==atoi(term_data.nro_suc)) && (CACS.GetCaj(atoi(term_data.nro_ca))==atoi(term_data.nro_caj))) { /* Arma mensaje de respuesta y lo envia al TPV */ LogAlarm.Put(0, "PriceOn: ERROR. Cierre de lote activo notificando a Price\n"); sprintf(stRta.szRespCA, "104"); if ( (iTipoOperacion==T_PAGO) || (iTipoOperacion==T_DEVP) ) { Armar_y_Enviar_Respuesta("11", &stRta); } else { Armar_y_Enviar_Respuesta("07", &stRta); } return OK; } } /* Completar el mensaje con los datos generados por nosotros */ if (!strcmp(term_data.uco_seg,"S")) { mensaje_price->SetCodSeg(); } else { mensaje_price->SetNoCodSeg(); } /* Setea el centro autorizador */ mensaje_price->SetNroCAPrice(term_data.nro_ca); /* Convierte el mensaje a formato ISO */ mensaje_iso=new Iso_Msg(); mensaje_iso->SetNroCA8583(term_data.nro_ca); *mensaje_iso=*mensaje_price; sprintf(szFHtransm, currentTimestamp()); mensaje_iso->PutField(7, szFHtransm); strcpy(aux_str, TraceNumber); mensaje_iso->PutField(11, aux_str); mensaje_iso->PutField(24, term_data.cod_red); mensaje_iso->PutField(41, term_data.nro_caj_ca); mensaje_iso->PutField(49, term_data.cod_mon); trx_data.NroLot(term_data.nro_lot); trx_data.CodMon(term_data.cod_mon); sprintf(aux_str, "%-15s", term_data.nro_com); mensaje_iso->PutField(42, aux_str); /* Si hora operacion mayor a transmision se rechaza */ /* Quitar si sincronizan hora los servidores */ switch (DBTipoProtocoloISO(term_data.nro_ca)) { case PROT_ISO_AMEX: memset(szFHoperac, 0, sizeof(szFHoperac)); strcpy(szFHoperac, mensaje_iso->GetField(13)); strcat(szFHoperac, mensaje_iso->GetField(12)); if (strcmp(szFHoperac, szFHtransm)>0) { LogAlarm.Put(0, "PriceOn: ERROR fecha Suc[%s] Ter[%s] Operac[%s] Transm[%s]\n", mensaje_price->GetSucursal(), mensaje_price->GetTerminal(), szFHoperac, szFHtransm); sprintf(stRta.szRespCA, "109"); Armar_y_Enviar_Respuesta("02", &stRta); return OK; } break; default: break; } /* Modificacion PINPAD */ iHayPinPad = mensaje_price->UsePinPad(); if (iHayPinPad) { /* Arma el codigo de procesamiento */ lCodCuenta = atol(mensaje_price->GetField(31)); if ( (lCodCuenta != PINPAD_CA_P) && (lCodCuenta != PINPAD_CC_P) && (lCodCuenta != PINPAD_CA_D) && (lCodCuenta != PINPAD_CC_D) ) { lCodCuenta = PINPAD_CA_P; /* Caja de ahorro en pesos por defecto */ } lCodProc = atol(mensaje_iso->GetField(3)) + lCodCuenta * 1000; sprintf(szCodiProc, "%06d", lCodProc); mensaje_iso->PutField(3, szCodiProc); LogAlarm.Put(0, "PriceOn: Codigo de procesamiento PPAD: %s\n", szCodiProc); /* Agrega el pinpad al mensaje */ memset(szPinPad, 0, sizeof(szPinPad)); mensaje_price->GetPinPad(szPinPad); mensaje_iso->PutField(52, szPinPad); } /* Fin manejo PinPad */ /* Obtiene montos de la operacion */ lImpoTran = atol(mensaje_price->GetField( 6)); lCashBack = atol(mensaje_price->GetField(32)); /* CashBack Visa. Campo 4 = Compra + Retiro */ if (lCashBack>0) { switch (term_data.prot_cash[0]) { case CASHBACK_VISA: sprintf(aux_str, "%012ld", lImpoTran+lCashBack); mensaje_iso->PutField(4, aux_str); break; case CASHBACK_POSN: sprintf(aux_str, "%012ld", lImpoTran); break; default: break; } LogAlarm.Put(0, "PriceOn: CashBack. Prot:%c Imp:%ld Ret:%ld Tot:%ld\n", term_data.prot_cash[0], lImpoTran, lCashBack, atol(aux_str)); } /* Arma los datos de la transaccion para la BD */ mensaje_price->GetDBData(trx_data); mensaje_iso->GetDBData(trx_data); sprintf(aux_str,"%02d",M_CEAU); trx_data.ModAut(aux_str); trx_data.CanRet("0000"); trx_data.NroCA(term_data.nro_ca); trx_data.NroCajCa(term_data.nro_caj_ca); trx_data.NroCom(term_data.nro_com); trx_data.NroCuo(mensaje_price->ObtCuotas()); trx_data.PlanISO(term_data.plan_iso); trx_data.PlanSF(mensaje_price->ObtPlanSf()); trx_data.NroRef(""); /* Pago de resumen */ iTipoOperacion = atoi(mensaje_price->GetField(5)); switch (iTipoOperacion) { case T_PAGO: sprintf(aux_str, "%02d", T_PAGO); trx_data.CodTrx(aux_str); sprintf(szCodiProc, "%06d", OPCODE_VISA_PAGO_RESUMEN); trx_data.CodPro(szCodiProc); mensaje_iso->PutField(3, szCodiProc); break; case T_DEVP: sprintf(aux_str, "%02d", T_DEVP); trx_data.CodTrx(aux_str); sprintf(szCodiProc, "%06d", OPCODE_VISA_DEVO_RESUMEN); trx_data.CodPro(szCodiProc); mensaje_iso->PutField(3, szCodiProc); break; } /* Codigo de procesamiento */ if ( (lCashBack>0) && (iTipoOperacion==1) ) { lCodProc = 0; switch ( term_data.prot_cash[0] ) { case CASHBACK_VISA: lCodProc = OPCODE_VISA_VEN_CASHBACK; break; case CASHBACK_POSN: lCodProc = (((atol(mensaje_iso->GetField(3))/1000)%10)*1000) + OPCODE_POSN_VEN_CASHBACK; break; } if (lCodProc) { sprintf(szCodiProc, "%06d", lCodProc); mensaje_iso->PutField(3, szCodiProc); trx_data.CodPro(szCodiProc); LogAlarm.Put(0, "PriceOn: Codigo de procesamiento CASH: %s\n", szCodiProc); } } /* Numero de cuenta */ memset(szNroCta, 0, sizeof(szNroCta)); /* Agrega peticion de numero de cuenta */ if (strcmp( mensaje_price->GetField(21) , "01") == 0) { sprintf(aux_str, "%s", CAMPO_NRO_CUENTA); strcat(szNroCta, aux_str); } /* Agrega fecha de diferimento (Si no es devolucion) */ if (term_data.dias_dif > 0) { char szFechaTrx[32]; char szFechaDif[32]; sprintf(szFechaTrx,"%04d%4.4s",ObtYear(),trx_data.FecLoc()); if( (atoi(trx_data.CodTrx())!=T_DEVO) && (atoi(trx_data.CodTrx())!=T_DEVP) ) { if (getFechaDif(szFechaTrx, term_data.dias_dif, szFechaDif)==0) { sprintf(aux_str, "%s%s", CAMPO_FECHA_DIFE, szFechaDif); strcat(szNroCta, aux_str); } } } /* Agrega campo 59 */ if (strlen(szNroCta)>0) { sprintf(aux_str, "%03d%s", strlen(szNroCta), szNroCta); ret = mensaje_iso->PutField(59, aux_str); LogAlarm.Put(10, "PriceOn: Campo 59:[%s] Ret:[%d]\n", aux_str, ret); } strcpy(heap_data.anul_onl, "0"); strcpy(heap_data.plan_iso, term_data.plan_iso); strcpy(heap_data.nro_com, term_data.nro_com); strcpy(heap_data.trans_ori, "0000"); strcpy(heap_data.fecha_ori, "000000"); /* Arma el campo cuotas */ strcpy(aux_str, mensaje_price->ObtCuotas()); /* #37322 Cuotas articulos nacionales */ if (term_data.plan_esp > 0) { sprintf(aux_str, "%03d", term_data.plan_esp); } sprintf(szCuotas, "003%1.1s%2.2s",trx_data.PlanISO(), &aux_str[1]); /* Compras AMEX de contado no se envia campo 48 */ switch (DBTipoProtocoloISO(term_data.nro_ca)) { case PROT_ISO_AMEX: if (strcmp(szCuotas, "003001")==0) { memset(szCuotas, 0, sizeof(szCuotas)); } break; default: break; } /*** Se verifica que sea una devolucion para convertirla en anulacion ***/ /*** en caso que la transaccion original se encuentre en la base y ***/ /*** sea de la fecha en curso ***/ LogAlarm.Put(8, "PriceOn: Codigo de transaccion:[%s]\n", trx_data.CodTrx()); if( (atoi(trx_data.CodTrx())==T_DEVO) || (atoi(trx_data.CodTrx())==T_DEVP) ) { /* Obtiene la caja y transaccion */ strcpy(CajDevol,trx_data.NroCaj()); strcpy(TrxDevol,trx_data.NroTrx()); LogAlarm.Put(0, "PriceOn: Devolucion. CAut:[%s] TerOri:[%s] CajDevol:[%s]\n", term_data.nro_ca, CajDevol, TrxDevol); /* Agrega el monto a consulta de anulaciones */ trx_data.Monto(mensaje_price->GetField(6)); /* Reemplaza caja y transaccion por los de la operacion original */ trx_data.NroCaj(mensaje_price->GetField(27)); trx_data.NroTrx(mensaje_price->GetField(28)); /* Obtiene los datos de la operacion */ StrDataRev=*(trx_data.GetDataRev()); /* Agrega el plan */ strcpy(StrDataRev.plan_sf, trx_data.PlanSF()); /* Actualiza el estado de la transaccion y trae los datos */ ret=DBTrx.UpdAnulVenta(&StrDataRev); strcpy(CajVenta,trx_data.NroCaj()); strcpy(TrxVenta,trx_data.NroTrx()); LogAlarm.Put(0, "PriceOn: Actualizacion anulacion venta. Ret:[%d], Errno:[%d]\n",ret,DBTrx.GetErrno()); LogAlarm.Put(0, "PriceOn: TerV:[%s], TrxV[%s] TerD:[%s], TrxD[%s]\n", CajVenta, TrxVenta, CajDevol, TrxDevol); /* Devolucion de pago de resumen */ if (atoi(trx_data.CodTrx())==T_DEVP) { LogAlarm.Put(0, "PriceOn: Devolucion pago de resumen\n"); if ( (ret==1403) || (ret==-1403) ) { LogAlarm.Put(0, "PriceOn: No existe original\n"); sprintf(stRta.szRespCA, "108"); Armar_y_Enviar_Respuesta("02", &stRta); return OK; } } /* Error en la actualizacion */ if (ret==NOOK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al actualizar BD en devolucion\n", DBTrx.GetErrno()); if (atoi(trx_data.CodTrx())==T_DEVP) { sprintf(stRta.szRespCA, "107"); Armar_y_Enviar_Respuesta("02", &stRta); return OK; } } /* La transaccion esta viajando (estado 01) */ if (ret==NORTA) { /* Arma mensaje de respuesta y lo envia al TPV */ LogAlarm.Put(0, "PriceOn: ERROR al esperar respuesta en devolucion\n"); sprintf(stRta.szRespCA, "101"); Armar_y_Enviar_Respuesta("02", &stRta); return OK; } /* La transaccion original esta pendiente de envio */ if (ret==INSANULOFF) { LogAlarm.Put(0, "PriceOn: ANULACION de transaccion original no enviada\n"); if ( atol(StrDataRev.retiro) > 0 ) { LogAlarm.Put(0, "PriceOn: Anulacion offline con cashback no permitida"); sprintf(stRta.szRespCA, "110"); Armar_y_Enviar_Respuesta("02", &stRta); return OK; } /* Se arma la transaccion */ sprintf(aux_str, "%02d", T_OFLI); trx_data.ModEnv(aux_str); sprintf(aux_str, "%02d", M_CRED); trx_data.ModAut(aux_str); trx_data.NroTrc("-1"); sprintf(aux_str, "%02d", E_NOAN); trx_data.CodEst(aux_str); trx_data.CodAut(getCodAutLocal(trx_data.CodTar())); sprintf(aux_str, "%04d%4.4s", ObtYear(), trx_data.FecLoc()); trx_data.FecTrx(aux_str); trx_data.NroCaj(CajDevol); trx_data.NroTrx(TrxDevol); /* Fecha del dia */ memset(FecVenta, 0, sizeof(FecVenta)); memcpy(&FecVenta[0], &aux_str[6], 2); memcpy(&FecVenta[2], &aux_str[4], 2); memcpy(&FecVenta[4], &aux_str[2], 2); /* Se inserta como venta anulada para no enviar al CA */ LogAlarm.Put(0, "PriceOn: Inserta venta anulada (NOEN)\n"); ret= DBTrx.Insert(trx_data.GetInsVenData(), szRowId); LogAlarm.Put(0, "PriceOn: Resultado insercion: %d\n", ret); /* Arma mensaje de respuesta y lo envia al TPV */ sprintf(stRta.szCodAut, trx_data.CodAut()); sprintf(stRta.szTermin, term_data.nro_caj_ca); sprintf(stRta.szComerc, term_data.nro_com); sprintf(stRta.szPlnIso, term_data.plan_iso); sprintf(stRta.szNroLot, term_data.nro_lot); sprintf(stRta.szFecOri, FecVenta); sprintf(stRta.szTicOri, TrxVenta); sprintf(stRta.szPlanSF, term_data.plan_sf); sprintf(stRta.szRespCA, "000"); switch (DBTipoProtocoloISO(term_data.nro_ca)) { case PROT_ISO_AMEX: sprintf(stRta.szProtoc, "A"); break; default: sprintf(stRta.szProtoc, "B"); break; } Armar_y_Enviar_Respuesta("00", &stRta); return OK; } /* end del if INSANULOFF */ /**********************/ /* ANULACIONES ONLINE */ /**********************/ if (ret==INSANUL) { LogAlarm.Put(0, "PriceOn: Se continua como ANULACION\n"); /* Continua anulacion si monto cashback es coincidente */ if ( atol(StrDataRev.retiro) != atol(trx_data.Retiro()) ) { LogAlarm.Put(0, "PriceOn: Difiere monto cashback. VENTA:[%ld] ANULA:[%ld]\n", atol(StrDataRev.retiro), atol(trx_data.Retiro())); sprintf(stRta.szRespCA, "110"); Armar_y_Enviar_Respuesta("02", &stRta); return OK; } /* INSERTA DEVOLUCION */ /* Modo de envio "00" */ sprintf(aux_str, "%02d", T_ONLI); trx_data.ModEnv(aux_str); /* Modo de autorizacion "10" */ sprintf(aux_str, "%02d", M_CRED); trx_data.ModAut(aux_str); /* Numero de trace */ trx_data.NroTrc("-1"); /* Codigo de autorizacion */ trx_data.CodAut("-1"); /* Codigo de estado E_ANVE=28 */ sprintf(aux_str, "%02d", E_ANVE); trx_data.CodEst(aux_str); /* Fecha de transaccion */ sprintf(aux_str, "%04d%4.4s", ObtYear(), trx_data.FecLoc()); trx_data.FecTrx(aux_str); /* Terminal */ trx_data.NroCaj(CajDevol); /* Transaccion */ trx_data.NroTrx(TrxDevol); /* Terminal original de venta */ trx_data.NroCajOri(CajVenta); /* Transaccion original de venta */ trx_data.NroTicOri(TrxVenta); /* Numero de lote (Caja venta para cerrar) */ trx_data.NroLot(term_data.nro_lot); /* Codigo de seguridad */ trx_data.CodSeg(" "); /* Track 1 */ /*trx_data.Track1(" ");*/ /* Track 2 */ /*trx_data.Track2(" ");*/ /* Borra intento de anulacion anterior */ DBTrx.DeleteRech(trx_data.GetInsVenData(), E_RECH); /* Estado = '03' */ LogAlarm.Put(0, "PriceOn: DeleteRech '%02d' : %d\n", E_RECH, DBTrx.GetErrno()); /* Se inserta devolucion para conciliar */ if (DBTrx.Insert(trx_data.GetInsVenData(), szRowId)) { LogAlarm.Put(0, "PriceOn: ERROR al insertar devolucion: %d\n", DBTrx.GetErrno()); sprintf(stRta.szRespCA, "105"); if ( (iTipoOperacion==T_PAGO) || (iTipoOperacion==T_DEVP) ) { Armar_y_Enviar_Respuesta("11", &stRta); } else { Armar_y_Enviar_Respuesta("02", &stRta); } return OK; } strcpy(heap_data.rowid, szRowId); LogAlarm.Put(0, "PriceOn: Insert devolucion rowid [%s]: %d\n", szRowId, ret); /* TRANSFORMA DEVOLUCION EN ANULACION */ /* Obtiene datos de la caja de venta */ strcpy(term_data.nro_caj, CajVenta); ret=getDataByNT2(&term_data); /* Codigo de procesamiento */ if ( (lCashBack>0) && (iTipoOperacion==2) ) { lCodProc = 0; switch ( term_data.prot_cash[0] ) { case CASHBACK_VISA: lCodProc = OPCODE_VISA_ANU_CASHBACK; break; case CASHBACK_POSN: lCodProc = (((atol(mensaje_iso->GetField(3))/1000)%10)*1000) + OPCODE_POSN_ANU_CASHBACK; break; } if (lCodProc) { sprintf(szCodiProc, "%06d", lCodProc); mensaje_iso->PutField(3, szCodiProc); trx_data.CodPro(szCodiProc); } } else { lCodProc = 20000 + atol(mensaje_iso->GetField(3)) % 10000; sprintf(szCodiProc, "%06d", lCodProc); trx_data.CodPro(szCodiProc); } LogAlarm.Put(0, "PriceOn: Codigo de procesamiento ANUL: %s\n", szCodiProc); /* Cambia codigo de transaccion a 05 (Anulacion venta online) */ sprintf(aux_str, "%02d", T_ANVE); trx_data.CodTrx(aux_str); /* Modo de envio */ sprintf(aux_str, "%02d", T_ANUL); trx_data.ModEnv(aux_str); /* Modo de autorizacion */ sprintf(aux_str, "%02d", M_CEAU); trx_data.ModAut(aux_str); /* Numero de terminal */ trx_data.NroCaj(CajVenta); /* Numero de transaccion */ trx_data.NroTrx(TrxVenta); /* Numero de lote */ trx_data.NroLot(term_data.nro_lot); /* Numero de caja CA */ trx_data.NroCajCa(term_data.nro_caj_ca); /* Numero de comercio */ trx_data.NroCom(term_data.nro_com); /* Fecha de la transaccion */ trx_data.FecLoc(StrDataRev.fec_loc); /* Numero de trace */ TraceNumber.SetNroSuc(term_data.nro_suc); TraceNumber.SetNroCaj(term_data.nro_caj); TraceNumber.SetNroCA (term_data.nro_ca ); TraceNumber.SetCodConCie(term_data.cod_con_cie); strcpy(aux_str, TraceNumber); trx_data.NroTrc(aux_str); /* CONVIERTE MENSAJE ISO A ANULACION */ /* Campo 3: Codigo de procesamiento */ mensaje_iso->PutField(3, trx_data.CodPro()); /* Campo 11: Numero de Trace */ mensaje_iso->PutField(11, trx_data.NroTrc()); /* Campo 12: Hora local (trx original) */ sprintf(aux_str, trx_data.FecLoc()); //// mensaje_iso->PutField(12, &aux_str[4]); /* Campo 13: Fecha local (trx original) */ sprintf(aux_str, "%4.4s", trx_data.FecLoc()); //// mensaje_iso->PutField(13, aux_str); /* Campo 37: Numero referencia anulacion. Se agrega */ mensaje_iso->PutField(37, StrDataRev.nro_ref); trx_data.NroRef(StrDataRev.nro_ref); /* Campo 38: Codigo de autorizacion */ switch (DBTipoProtocoloISO(trx_data.NroCA())) { case PROT_ISO_AMEX: if (strlen(StrDataRev.cod_aut)>0) { mensaje_iso->PutField(38, StrDataRev.cod_aut); trx_data.CodAut(StrDataRev.cod_aut); } break; default: break; } /* Campo 41: Numero de caja CA */ mensaje_iso->PutField(41, term_data.nro_caj_ca); /* Campo 42: Numero de comercio CA */ sprintf(aux_str, "%-15s", term_data.nro_com); mensaje_iso->PutField(42, aux_str); /* Campo 62: Numero de ticket */ sprintf(aux_str, "004%04d", atoi(TrxVenta)); mensaje_iso->PutField(62, aux_str); /* Almacena transaccion de venta */ sprintf(NroTrxAux, "%s", TrxVenta); /* Marca anulacion online SI */ strcpy(heap_data.anul_onl, "1"); } else { LogAlarm.Put(0, "PriceOn: Se continua como DEVOLUCION\n"); /* Continua devolucion solo si monto cashback es cero */ if (lCashBack>0) { LogAlarm.Put(0, "PriceOn: Monto cashback no es cero [%ld]\n", lCashBack); sprintf(stRta.szRespCA, "110"); Armar_y_Enviar_Respuesta("02", &stRta); return OK; } /* Marca anulacion online NO */ strcpy(heap_data.anul_onl, "0"); /* Restaura caja y terminal del mensaje */ trx_data.NroCaj(CajDevol); sprintf(NroTrxAux, "%s", trx_data.NroTrx()); trx_data.NroTrx(TrxDevol); } /* Arma el campo 48 de plan, transaccion y fecha originales */ if(useCampCuot(trx_data.NroCA())==1) { trx_data.NroCajOri(CajVenta); trx_data.NroTicOri(NroTrxAux); DBTrx.SelTrxOrig(&StrDataRev); trx_data.FecOri(StrDataRev.fec_ori); LogAlarm.Put(0, "PriceOn: Datos orig. Fecha:[%s] Trx:[%s]\n", trx_data.FecOri(), trx_data.NroTicOri()); if (heap_data.anul_onl[0]=='0') /* Si es devolucion (no es anulacion) */ { strcpy(aux_str, mensaje_price->ObtCuotas()); /* #37322 Cuotas articulos nacionales */ if (term_data.plan_esp > 0) { sprintf(aux_str, "%03d", term_data.plan_esp); } sprintf(szCuotas, "013%1.1s%2.2s%04d%6.6s", trx_data.PlanISO(), &aux_str[1], atoi(trx_data.NroTicOri()), trx_data.FecOri()); } } /* Almacena datos para recuperar con la respuesta */ strcpy(heap_data.trans_ori, trx_data.NroTicOri()); strcpy(heap_data.fecha_ori, trx_data.FecOri()); } /* Fin manejo devoluciones */ // Campo 48: Cuotas if ( strlen(szCuotas) > 0 ) { mensaje_iso->PutField(48, szCuotas); LogAlarm.Put(1, "PriceOn: Campo 48 [%s]\n", mensaje_iso->GetField(48)); } /* EMV */ if(strlen(mensaje_price->GetField(34)) || strlen(mensaje_price->GetField(36))) { LogAlarm.Put(1, "PriceOn: Mensaje * EMV *\n"); if(strlen(mensaje_price->GetField(34))) { sprintf(szCriptograma, "%03d%s", strlen(mensaje_price->GetField(34)), mensaje_price->GetField(34)); mensaje_iso->PutField(55, szCriptograma); } sprintf(szVersionEMV, "%03d%s", strlen(mensaje_price->GetField(35)), mensaje_price->GetField(35)); mensaje_iso->PutField(60, szVersionEMV); mensaje_iso->PutField(19, "032"); strcat(szEMVProductList, "016 02100010040705"); /*szEMVProductList[3] = 0x0; szEMVProductList[4] = 0x14;*/ szEMVProductList[3] = 1; szEMVProductList[4] = 4; /*if(strlen(mensaje_price->GetField(36))) { strcat(szEMVProductList, ""); } */ mensaje_iso->PutField(59, szEMVProductList); ///mensaje_iso->PutField(22, "052"); ///mensaje_iso->PutField(23, mensaje_price->GetField(37)); //mensaje_iso->ClearField(12); //mensaje_iso->ClearField(13); ///mensaje_iso->PutField(46, "0011"); /*if(!strlen(mensaje_price->GetField(30))) { mensaje_iso->PutField(46, "0011"); }*/ } /* Verifica si hay transacciones en vuelo */ pos_ocup = P.IsPosFree(term_data.nro_ca, term_data.nro_suc, term_data.nro_caj); if (pos_ocup) { TrxEnVuelo=0; } else { TrxEnVuelo=1; } /* Verificamos el estado del canal X.25 */ /* Modificacion: 3/2/98 Autor: Rolando Loustric Objetivo: Se utiliza un flag interno para el estado del canal. Este flag es utilizado antes del Insert y para resolver la peticion. Antes se consultaba CACS.IsDown, y en caso de cambiar el estado del canal en medio del evento se producia un error de consistencia */ channel_down = CACS.IsDown(atoi(term_data.nro_ca)); /* Si el canal esta caido o hay transacciones en vuelo */ if (channel_down||TrxEnVuelo) { LogAlarm.Put(0, "PriceOn: Centro abajo [%d] Trx en vuelo [%d]. Autoriza localmente. CAut [%s]\n", channel_down, TrxEnVuelo, term_data.nro_ca); if (iTipoOperacion != T_PAGO) { /* Intenta aprobar localmente */ str_get_total opers_data; str_get_limit limit_data; /* Obtiene el numero de tarjeta */ strcpy(aux_str, mensaje_price->GetField(4)); for (cont=0; cont<strlen(aux_str); cont++) { if (aux_str[cont]==' ') { aux_str[cont]='\0'; } } /* Carga datos para consultar los totales de la tarjeta */ sprintf(opers_data.nro_tar, "%-*s", sizeof(opers_data.nro_tar)-1, aux_str); sprintf(opers_data.cod_est, "%0*d", sizeof(opers_data.cod_est)-1, E_PEND); strcpy(opers_data.cod_tar, term_data.cod_tar); strcpy(opers_data.plan_sf, term_data.plan_sf); strcpy(opers_data.cod_trx, trx_data.CodTrx()); /* Carga datos para obtener los limites de respaldo del tipo de tarjeta y plan */ strncpy(limit_data.cod_tar, mensaje_price->GetCodTar(), sizeof(limit_data.cod_tar)); strncpy(limit_data.plan_sf, mensaje_price->ObtPlanSf(), sizeof(limit_data.plan_sf)); /* Obtiene los limites de respaldo del tipo de tarjeta */ ret=getLimit(&limit_data); if (ret!=OK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al obtener el limite de tarjeta\n", ret); return NOOK; } LogAlarm.Put(0, "PriceOn: Limites. General:%.2f - Cuotas:%.2f - Plan %s:%.2f\n", (double)limit_data.limite/100.0 , (double)limit_data.limcuot/100.0 , limit_data.plan_sf, (double)limit_data.limplan/100.0 ); /* Obtiene el total comprado con la tarjeta */ ret=getTotalGeneral(&opers_data); if (ret!=OK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al obtener total de tarjeta!!\n", ret); return NOOK; } LogAlarm.Put(0, "PriceOn: Total de la tarjeta: %.2f\n", (double)opers_data.monto/100); /* Cambia el modo de la operacion a OFF-LINE */ sprintf(aux_str, "%02d", T_OFLI); trx_data.ModEnv(aux_str); /* Cambia el modo de ingreso */ switch (DBTipoProtocoloISO(trx_data.NroCA())) { case PROT_ISO_AMEX: if (strcmp(trx_data.ModIng(), "072")==0) { trx_data.ModIng("012"); } if (strcmp(trx_data.ModIng(), "062")==0) { trx_data.ModIng("022"); } break; default: break; } /* Pone el modo de autorizacion por Credito */ sprintf(aux_str, "%02d", M_CRED); trx_data.ModAut(aux_str); /* Pone el numero de trace (NULL) */ trx_data.NroTrc("-1"); if (heap_data.anul_onl[0]=='1') { LogAlarm.Put(0, "PriceOn: Anulacion offline no permitida\n"); sprintf(aux_str, "%02d", E_RECH); trx_data.CodEst(aux_str); limite=NOOK; } else { /* Obtiene el monto de la transaccion en curso */ long monto; monto=atol(mensaje_price->GetField(6)); LogAlarm.Put(0, "PriceOn: Esta operacion: %.2f\n", (double)monto/100); LogAlarm.Put(0, "PriceOn: Total general de la tarjeta: %.2f\n", (double)opers_data.monto/100.0); /* Si las compras realizadas anteriormente mas la actual supera el limite */ if ((opers_data.monto+monto)>limit_data.limite) { /* Se prepara el estado para registrar la operacion como rechazada */ LogAlarm.Put(0, "PriceOn: Supera el limite\n"); limite=NOOK; sprintf(aux_str, "%02d", E_RECH); trx_data.CodEst(aux_str); } else { /* Si el plan es en cuotas */ if (strncmp(term_data.plan_sf, "00", 2) != 0) { /* Obtiene el total comprado en cuotas */ ret= getTotalCuotas(&opers_data); if (ret!=OK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al obtener el total de la tarjeta en cuotas\n",ret); return NOOK; } LogAlarm.Put(0, "PriceOn: Total de la tarjeta en cuotas: %.2f\n", (double)opers_data.monto/100.0); /* Si las compras realizadas anteriormente en cuotas mas la actual supera el limite */ if ((opers_data.monto+monto)>limit_data.limcuot) { limite=NOOK; } else { /* Obtiene el total comprado en cuotas para ese plan */ ret= getTotalPlan(&opers_data); if (ret!=OK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al obtener el total de tarjeta para el plan\n",ret); return NOOK; } LogAlarm.Put(0, "PriceOn: Total de la tarjeta para el plan: %.2f\n", (double)opers_data.monto/100.0); /* Si las compras realizadas anteriormente para el plan mas la actual supera el limite */ if ((opers_data.monto+monto)>limit_data.limplan) { limite=NOOK; } else { limite=OK; } } } else { limite=OK; } /* Si la tarjeta tiene limite de respaldo para operrar offline */ if (limite==OK) { LogAlarm.Put(0, "PriceOn: No supera el limite\n"); sprintf(aux_str, "%02d", E_PEND); trx_data.CodEst(aux_str); /*Modificacion: Codigo de autorizacion local*/ /*configurable [28-12-2000][DL]*/ sprintf(aux_str, "%s", getCodAutLocal(trx_data.CodTar())); trx_data.CodAut(aux_str); } else { LogAlarm.Put(0, "PriceOn: Supera el limite\n"); sprintf(aux_str, "%02d", E_RECH); trx_data.CodEst(aux_str); } } } } else /* iTipoOperacion == T_PAGO */ { /* No se permite pago de resumen offline en cuotas */ if (strncmp(term_data.plan_sf, "00", 2) != 0) { LogAlarm.Put(0, "PriceOn: Pago de resumen offline en cuotas no permitido\n"); sprintf(aux_str, "%02d", E_RECH); trx_data.CodEst(aux_str); limite=NOOK; } else { /* Cambia el modo de la operacion a OFF-LINE */ sprintf(aux_str, "%02d", T_OFLI); trx_data.ModEnv(aux_str); /* Cambia el modo de ingreso */ switch (DBTipoProtocoloISO(trx_data.NroCA())) { case PROT_ISO_AMEX: if (strcmp(trx_data.ModIng(), "072")==0) { trx_data.ModIng("012"); } if (strcmp(trx_data.ModIng(), "062")==0) { trx_data.ModIng("022"); } break; default: break; } /* Pone el modo de autorizacion por Credito */ sprintf(aux_str, "%02d", M_CRED); trx_data.ModAut(aux_str); /* Pone el numero de trace (NULL) */ trx_data.NroTrc("-1"); /* Pone el codigo de autorizacion */ sprintf(aux_str, "%s", getCodAutLocal(trx_data.CodTar())); trx_data.CodAut(aux_str); /* Pone el codigo de estado */ sprintf(aux_str, "%02d", E_PEND); trx_data.CodEst(aux_str); /* Acepta siempre el pago offline */ limite = OK; } } } else { /* Si no esta caido el canal X.25 se cambia al estado de enviado */ sprintf(aux_str, "%02d", E_ENVI); trx_data.CodEst(aux_str); if (heap_data.anul_onl[0]!='1') /* Si no es anulacion */ { trx_data.CodAut(""); } TraceNumber.Inc(); } /* Carga la fecha de la trx */ sprintf(aux_str,"%04s%4.4s", trx_data.AnoTrx(), trx_data.FecLoc()); trx_data.FecTrx(aux_str); /* Las transacciones rechazadas localmente no se graban en la BD */ if (atoi(trx_data.CodEst())!=E_RECH) { LogAlarm.Put(0, "PriceOn: Inserta anulacion. nro_ref[%s] cod_aut[%s]\n", trx_data.NroRef(), trx_data.CodAut()); ret=DBTrx.Insert(trx_data.GetInsVenData(), szRowId); } else { /* Inserta anulacion rechazada para control */ if (heap_data.anul_onl[0]=='1') { ret=DBTrx.Insert(trx_data.GetInsVenData(), szRowId); LogAlarm.Put(0, "PriceOn: Inserta anulacion rechazada [%d]\n", DBTrx.GetErrno()); } ret=OK; } /* Cuando se produce un error en el insert verifica existencia de */ /* rechazadas, en caso de esto ser cierto las borra para permitir */ /* el nuevo pedido de autorizacion. */ if (ret==NOOK) { int testRech=0; /* Testing de variables rechazadas */ testRech=DBTrx.DeleteRech(trx_data.GetInsVenData(), E_RECH); /* Estado = '03' */ if (testRech==OK) { LogAlarm.Put(0, "PriceOn: Intento de Reautorizar Trx: [%s] ya rechazada\n", mensaje_price->GetField(11)); ret=DBTrx.Insert(trx_data.GetInsVenData(), szRowId); } if ((testRech==OK && ret==NOOK) || testRech==NOOK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) en %s!!\n", DBTrx.GetErrno(), testRech==OK ? "REINSERT" : "Insert Original"); sprintf(stRta.szRespCA, "105"); if ( (iTipoOperacion==T_PAGO) || (iTipoOperacion==T_DEVP) ) { Armar_y_Enviar_Respuesta("11", &stRta); } else { Armar_y_Enviar_Respuesta("02", &stRta); } return NOOK; } } /* Verificamos el estado del canal X.25 */ /* Si esta caido, generamos la respuesta y la devolvemos */ if (channel_down||TrxEnVuelo) { /* Arma mensaje de respuesta y lo envia al TPV */ if (limite==OK) { sprintf(stRta.szCodAut, getCodAutLocal(trx_data.CodTar())); sprintf(stRta.szTermin, term_data.nro_caj_ca); sprintf(stRta.szComerc, term_data.nro_com); sprintf(stRta.szPlnIso, term_data.plan_iso); sprintf(stRta.szNroLot, term_data.nro_lot); sprintf(stRta.szFecOri, trx_data.FecOri()); sprintf(stRta.szTicOri, trx_data.NroTicOri()); sprintf(stRta.szPlanSF, term_data.plan_sf); sprintf(stRta.szRespCA, "000"); switch (DBTipoProtocoloISO(term_data.nro_ca)) { case PROT_ISO_AMEX: sprintf(stRta.szProtoc, "A"); break; default: sprintf(stRta.szProtoc, "B"); break; } Armar_y_Enviar_Respuesta("00", &stRta); } else { sprintf(stRta.szRespCA, "103"); if ( (atoi(trx_data.CodTrx())==T_PAGO) || (atoi(trx_data.CodTrx())==T_DEVP) ) { Armar_y_Enviar_Respuesta("11", &stRta); } else { Armar_y_Enviar_Respuesta("38", &stRta); } } return OK; } else /* El vinculo esta activo */ { /* Arma los datos para el heap */ mensaje_price->GetHeapData(&heap_data); if (heap_data.anul_onl[0]=='1') { strcpy(heap_data.nro_term, CajVenta); strcpy(heap_data.nro_trans, TrxVenta); } strcpy(heap_data.plan_sf, term_data.plan_sf); strcpy(heap_data.nro_caj_ca,term_data.nro_caj_ca); heap_data.orig_pid=orig_pid; char idHeap[20]; /* Arma clave para el heap */ sprintf(idHeap,"%2.2s%3.3s%5.5s%8.8s", term_data.nro_ca, term_data.nro_suc, term_data.nro_caj, mensaje_iso->GetField(11)); /* Pone los datos en el heap */ LogAlarm.Put(95, "PriceOn: idHeap [%s] \n", idHeap); LogAlarm.Put(95, "PriceOn: anul_onl[%s] plan_iso[%s] plan_sf[%s] nro_com[%s]\n", heap_data.anul_onl, heap_data.plan_iso, heap_data.plan_sf, heap_data.nro_com); //LogAlarm.Put(0, "PriceOn: heap_data.rowid [%s] \n", heap_data.rowid); ret=Heap.PutData(idHeap,(char *)&heap_data, sizeof(heap_data)); if (ret==NOOK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al poner info en Heap\n", Heap.GetErrno()); return NOOK; } /* Registrar en la TimeoutQueue */ Cfg.GetItem("TimeOutDaemon", "MsgTimeOut1", aux_str); ret=timeout_queue.SetTimeOut(idHeap,atoi(aux_str), GetType(), ""); if (ret==NOOK) { LogAlarm.Put(0, "PriceOn: ERROR (%d) al agregar a TimeOutQueue!!\n", timeout_queue.GetErrno()); return NOOK; } /* Aplana el mensaje */ memset(msg_str,'\0',sizeof(msg_str)); len=mensaje_iso->GetMsgString(msg_str); /* Envia el mensaje al CA */ LogAlarm.Put(0, "PriceOn: Envia a X.25. CAut [%s]\n", term_data.nro_ca); ret=XQueue.SendMsg(atoi(term_data.nro_ca)+1, msg_str, len); if (ret==OK) { /* Bloquea la caja */ ret = P.SetPosBusy(term_data.nro_ca, term_data.nro_suc, term_data.nro_caj); if (ret!=OK) { LogAlarm.Put(0, "PriceOn: No se pudo bloquear la caja!!\n"); } LogAlarm.Put(2, "PriceOn: Respuesta enviada OK\n"); } else { LogAlarm.Put(0, "PriceOn: ERROR al enviar a X25\n"); return NOOK; } } return OK; }
/* +-----------------+------------------------------------------------------------+ | FUNCION | Cierre::ProcessIt | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Proceso del objeto | | | | +-----------------+------------------------------------------------------------+ */ int Cierre::ProcessIt() { char aux_str[100]; char msg_str[2000]; int msg_len; int ret; str_heap_data heap_data; BatchData batch_data; str_sel_ntdata term_data; char aux_str1[100]; char idHeap[20]; /* Obtiene los datos del mensaje */ strcpy(term_data.nro_caj_ca, mensaje_iso->GetField(41)); strcpy(term_data.nro_com , mensaje_iso->GetField(42)); /* Completa la estructura con los datos del mensaje */ batch_data.NroCajCa(term_data.nro_caj_ca); /* Obtiene datos de la terminal */ ret=getDataByCACie(&term_data); if (ret!=OK) { LogAlarm.Put( 0, "Cierre: ERROR (%d) al obtener datos de la terminal\n", ret); return NOOK; } /* Indica al objeto TraceNmbr el centro autorizador */ TraceNumber.SetNroSuc(term_data.nro_suc); TraceNumber.SetNroCaj(term_data.nro_caj); TraceNumber.SetNroCA (term_data.nro_ca ); TraceNumber.SetCodConCie(term_data.cod_con_cie); /* Completar el mensaje con los datos generados */ mensaje_iso->PutField(7, currentTimestamp()); strcpy(aux_str, TraceNumber); TraceNumber.Inc(); mensaje_iso->PutField(11, aux_str); mensaje_iso->PutField(15, currentTimestamp()); /* Chequea consistencia del mensaje */ LogAlarm.Put(95, "Cierre: Chequea consistencia del mensaje\n"); if (!mensaje_iso->ChkReady()) { LogAlarm.Put( 0, "Cierre: ERROR de consistencia en el mensaje\n"); return NOOK; } /* Registrar transaccion en TrxHeap */ LogAlarm.Put(95, "Cierre: Obtiene datos para el Heap\n"); heap_data.orig_pid=orig_pid; /* Pone datos en el heap */ LogAlarm.Put(95, "Cierre: Poniendo datos en el Heap.\n"); sprintf(idHeap,"%2.2s%3.3s%5.5s%8.8s",term_data.nro_ca,term_data.nro_suc,term_data.nro_caj,mensaje_iso->GetField(11)); ret=Heap.PutData(idHeap,(char *)&heap_data, sizeof(heap_data)); if (ret==NOOK) { LogAlarm.Put(0, "Cierre: ERROR (%d) al poner los datos en el heap!!\n", Heap.GetErrno()); return NOOK; } /* Registra en la TimeoutQueue con un timeout diferente a los otros eventos */ LogAlarm.Put( 5, "Cierre: Agrega a la cola de timeout\n"); Cfg.GetItem("TimeOutDaemon", "MsgTimeOut500", aux_str1); ret=timeout_queue.SetTimeOut(idHeap, atoi(aux_str1), GetType(), ""/*CodSer*/); if (ret==NOOK) { LogAlarm.Put( 0, "Cierre: ERROR (%d) al agregar en cola de timeout!!\n", timeout_queue.GetErrno()); return NOOK; } /* Si se graba registro de cierre */ memset(aux_str1, 0, sizeof(aux_str1)); Cfg.GetItem("AdminDaemon", "InsertCierre", aux_str1); if (aux_str1[0] != 'N') { /* Completa la estructura */ batch_data.NroCA(term_data.nro_ca); mensaje_iso->GetDBData(batch_data); batch_data.CanRet("0000"); sprintf(aux_str, "%02d", E_ENVI); batch_data.CodEst(aux_str); batch_data.NroSuc(term_data.nro_suc); batch_data.NroCaj(term_data.nro_caj); batch_data.NroCom(term_data.nro_com); /* Registra en la base de datos */ LogAlarm.Put( 5, "Cierre: Registra en base de datos\n"); ret=DBBatch.Insert(batch_data.GetInsData()); if (ret!=OK) { LogAlarm.Put( 1, "Cierre: ERROR (%d) al registrar en base de datos\n", DBBatch.GetErrno()); return NOOK; } } /* Aplana el mensaje */ msg_len=mensaje_iso->GetMsgString(msg_str); /* Envia el mensaje al centro autorizador */ LogAlarm.Put(0, "Cierre: Envia a X.25. CAut [%s]\n", term_data.nro_ca); ret=XQueue.SendMsg(atol(term_data.nro_ca)+1, msg_str, msg_len); if (ret!=OK) { LogAlarm.Put(0, "Cierre: ERROR (%d) mandando mensaje a X.25!!\n", SQueue.GetErrno()); return NOOK; } return OK; }
/* +-----------------+------------------------------------------------------------+ | FUNCION | SndTrxOffLine::ProcessIt | +-----------------+------------------------------------------------------------+ | DESCRIPCION | Proceso del objeto | | | | +-----------------+------------------------------------------------------------+ */ int SndTrxOffLine::ProcessIt() { int len; int ret; int iCont; str_sel_cadata term_data; char msg_str[2000]; char aux_str[20]; trxOffHeap infoHeap; DBInfoEnvio InfoEnvio; str_fet_bu_trx trxOff; int pos_ocup; str_tarjeta data_tar; char aux_str1[100]; DBTrxPk trxPk; char idHeap[20]; char szFechaEnvio[16]; int iErrorBD; int iNroCuotas; /* Carga estructura para busqueda de transaccion offline */ strncpy(trxOff.cod_tar , CodTarjeta, sizeof(trxOff.cod_tar)); strncpy(trxOff.cod_est , "00" , sizeof(trxOff.cod_est)); strncpy(trxOff.nro_caj_ca, NroCajCa , sizeof(trxOff.nro_caj_ca)); strncpy(trxOff.nro_trx , NroTrx , sizeof(trxOff.nro_trx)); trxOff.nro_caj_ca[sizeof(trxOff.nro_caj_ca)-1]='\0'; trxOff.cod_tar [sizeof(trxOff.cod_tar) -1]='\0'; trxOff.cod_est [sizeof(trxOff.cod_est) -1]='\0'; trxOff.nro_trx [sizeof(trxOff.nro_trx) -1]='\0'; /* Busca en BD una transaccion offline */ LogAlarm.Put(0, "TrxOff: Lee offline [%s] [%s] [%s] [%s]\n", trxOff.nro_caj_ca, trxOff.cod_tar, trxOff.cod_est, trxOff.nro_trx); ret=DBGetNextTrx(&trxOff, &iErrorBD); if (ret!=OK) { LogAlarm.Put( 0, "TrxOff: Retorno de recuperacion de offline:%d Errno:%d\n", ret, iErrorBD); EnviarMsg(orig_pid, "ERROR", 5); return OK; } //LogAlarm.Put(0, "TrxOff: Rowid a enviar [%s]\n",trxOff.rowid); /* Obtiene datos del centro autorizador */ LogAlarm.Put(5, "TrxOff: Obtiene codigo de centro\n"); strcpy(data_tar.cod_tar, trxOff.cod_tar); ret = ObtCA(&data_tar); if (ret!=OK) { LogAlarm.Put(0, "TrxOff: ERROR al obtener CA. Tar:[%s]\n", trxOff.cod_tar); EnviarMsg(orig_pid, "ERROR", 5); return OK; } /* Verifica si la caja esta libre */ strcpy(term_data.nro_caj, trxOff.nro_caj); pos_ocup = P.IsPosFree(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (pos_ocup) { /* Marca la caja como ocupada */ ret = P.SetPosBusy(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (ret!=OK) { LogAlarm.Put(0, "TrxOff: ERROR al setear caja como ocupada\n"); } } else { /* Retorna envio de caja bloqueada */ LogAlarm.Put(0, "TrxOff: ERROR. Caja bloqueada\n"); EnviarMsg(orig_pid, "BLOCK", 5); return NOOK; } /* Arma el mensaje base de acuerdo al codigo de transaccion */ switch (atoi(trxOff.cod_trx)) { case T_VENT: IsoMsg=new Iso_Msg(TYPE_VISA_VENTA_LOCAL); break; case T_DEVO: IsoMsg=new Iso_Msg(TYPE_VISA_DEVOL_LOCAL); break; case T_PAGO: IsoMsg=new Iso_Msg(TYPE_VISA_VENTA_LOCAL); sprintf(aux_str1, "%06d", OPCODE_VISA_PAGO_RESUMEN); IsoMsg->PutField(3, aux_str1); break; case T_DEVP: IsoMsg=new Iso_Msg(TYPE_VISA_DEVOL_LOCAL); sprintf(aux_str1, "%06d", OPCODE_VISA_DEVO_RESUMEN); IsoMsg->PutField(3, aux_str1); break; default: /* Tipo de transaccion desconocida */ /* Libera la caja */ ret = P.SetPosFree(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (ret != OK) { LogAlarm.Put(0, "TrxOff: ERROR en SetPosFree. CA:[%s] Emp:[%s] Caj:[%s]\n", data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); } LogAlarm.Put(0, "TrxOff: ERROR. Mensaje desconocido\n"); EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } /* Setea centro autorizador */ IsoMsg->SetNroCA8583(data_tar.nro_ca); /* Arma la informacion para el heap */ infoHeap.origPid=orig_pid; strncpy( infoHeap.nroSuc , trxOff.nro_suc, sizeof(infoHeap.nroSuc ) ); strncpy( infoHeap.nroTerm , trxOff.nro_caj, sizeof(infoHeap.nroTerm ) ); strncpy( infoHeap.nroTrans, trxOff.nro_tic, sizeof(infoHeap.nroTrans) ); strncpy( infoHeap.fechaTrx, trxOff.fec_loc, sizeof(infoHeap.fechaTrx) ); strncpy( infoHeap.codTar , trxOff.cod_tar, sizeof(infoHeap.codTar ) ); strncpy( infoHeap.NroCajCa, trxOff.nro_caj_ca,sizeof(infoHeap.NroCajCa)); strcpy ( infoHeap.Rowid, trxOff.rowid); infoHeap.nroSuc [sizeof(infoHeap.nroSuc )-1]='\0'; infoHeap.nroTerm [sizeof(infoHeap.nroTerm )-1]='\0'; infoHeap.nroTrans[sizeof(infoHeap.nroTrans )-1]='\0'; infoHeap.fechaTrx[sizeof(infoHeap.fechaTrx )-1]='\0'; infoHeap.codTar [sizeof(infoHeap.codTar )-1]='\0'; infoHeap.NroCajCa[sizeof(infoHeap.NroCajCa )-1]='\0'; /* Convierte la tarjeta a standard ISO (sin espsacio y formato LLL-VAR */ int counter=0; for (counter=0;counter<sizeof(trxOff.nro_tar);counter++) { if (trxOff.nro_tar[counter]<'0' || trxOff.nro_tar[counter]>'9') { break; } } trxOff.nro_tar[counter]='\0'; /* Configura datos de la terminal */ strcpy(term_data.cod_tar, trxOff.cod_tar); strcpy(term_data.nro_suc, infoHeap.nroSuc); strcpy(term_data.nro_caj, infoHeap.nroTerm); strcpy(term_data.plan_sf, trxOff.plan_sf); /* Busca terminal en base de datos */ ret=getDataByNT2(&term_data); if ( (ret!=OK) || (term_data.caj_bloq==1) ) { /* Loguea error de terminal */ LogErrTerminal.Put(0, "Fecha Hora %s", currentTimeLog() ); LogErrTerminal.Put(0, "Caja: %s - Sucursal: %s - Tarjeta: %s - Plan: %s - Evento: TrxOff\n\n", term_data.nro_caj, term_data.nro_suc, term_data.cod_tar, term_data.plan_sf); LogAlarm.Put(0, "TrxOff: ERROR (%d) de terminal (%s) bloqueada (%d)\n", ret, term_data.nro_caj, term_data.caj_bloq); /* Libera la caja */ ret = P.SetPosFree(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (ret != OK) { LogAlarm.Put(0, "TrxOff: ERROR en SetPosFree. CA:[%s] Emp:[%s] Caj:[%s]\n", data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); } EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } /* Numero de Tarjeta */ sprintf(aux_str1,"%02d%s",counter,trxOff.nro_tar); IsoMsg->PutField(2, aux_str1); /* Monto */ sprintf(aux_str1,"%012ld",atol(trxOff.monto)); IsoMsg->PutField(4, aux_str1); /* Fecha de transmision */ sprintf(szFechaEnvio, currentTimestamp()); IsoMsg->PutField(7, szFechaEnvio); /* Si hora operacion mayor a transmision se rechaza */ /* Quitar si sincronizan hora los servidores */ switch (DBTipoProtocoloISO(trxOff.nro_ca)) { case PROT_ISO_AMEX: if (strcmp(trxOff.fec_loc, szFechaEnvio)>0) { LogAlarm.Put(0, "TrxOff: Ter:[%s] Trx:[%04d]\n", infoHeap.nroTerm, atoi(infoHeap.nroTrans)); LogAlarm.Put(0, "TrxOff: ERROR fecha/hora FHoperac[%s] FHtransm[%s]\n", trxOff.fec_loc, szFechaEnvio); /* Libera la caja */ ret = P.SetPosFree(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (ret != OK) { LogAlarm.Put(0, "TrxOff: ERROR en SetPosFree. CA:[%s] Emp:[%s] Caj:[%s]\n", data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); } EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } break; default: break; } /* Numero de trace */ TraceNumber.SetNroSuc(term_data.nro_suc); TraceNumber.SetNroCaj(term_data.nro_caj); TraceNumber.SetNroCA (term_data.nro_ca ); TraceNumber.SetCodConCie(term_data.cod_con_cie); strcpy(aux_str, TraceNumber); TraceNumber.Inc(); IsoMsg->PutField(11, aux_str); /* Hora local */ IsoMsg->PutField(12, trxOff.fec_loc+4); /* Fecha local */ IsoMsg->PutField(13, trxOff.fec_loc); /* Fecha de expiracion */ IsoMsg->PutField(14, trxOff.fec_ven); /* Fecha de captura */ switch (DBTipoProtocoloISO(trxOff.nro_ca)) { case PROT_ISO_AMEX: break; default: IsoMsg->PutField(17, trxOff.fec_loc); break; } /* Modo de ingreso */ IsoMsg->PutField(22, trxOff.mod_ing ); /* Codigo de red */ IsoMsg->PutField(24, term_data.cod_red); /* Codigo de condicion */ IsoMsg->PutField(25, "00" ); /* Track 2 si ingreso fue por banda */ switch (DBTipoProtocoloISO(trxOff.nro_ca)) { case PROT_ISO_AMEX: break; default: if ( !strcmp(trxOff.mod_ing, "022") || !strcmp(trxOff.mod_ing, "062") ) { sprintf(aux_str1, "%02d%s", strlen(trxOff.track2), trxOff.track2); IsoMsg->PutField(35, aux_str1); } break; } /* Codigo de autorizacion */ sprintf(aux_str1, "%s", trxOff.cod_aut); switch (DBTipoProtocoloISO(trxOff.nro_ca)) { case PROT_ISO_AMEX: if( (atoi(trxOff.cod_trx)==T_DEVO) || (atoi(trxOff.cod_trx)==T_DEVP) ) { if (atoi(trxOff.mod_env)==T_OFLI) { sprintf(aux_str1, " "); // Devolucion offline Amex } } break; default: break; } IsoMsg->PutField(38, aux_str1); /* Terminal centro autorizador */ IsoMsg->PutField(41, term_data.nro_caj_ca); /* Comercio centro autorizador */ sprintf(aux_str1,"%-15s",term_data.nro_com); IsoMsg->PutField(42, aux_str1); /* #37322 Cuotas articulos nacionales */ iNroCuotas = ( term_data.plan_esp > 0 ) ? term_data.plan_esp : atoi(trxOff.nro_cuo) ; /* Campo Cuotas */ sprintf(aux_str1,"003%1.1s%2.2d",trxOff.plan_iso, iNroCuotas); if( (atoi(trxOff.cod_trx)==T_DEVO) || (atoi(trxOff.cod_trx)==T_DEVP) ) { if(useCampCuot(trxOff.nro_ca)==1) { sprintf(aux_str1, "013%1.1s%02d%04d%6s", trxOff.plan_iso, iNroCuotas, atoi(trxOff.nro_tic_ori), trxOff.fec_ori); } } /* Compras AMEX de contado no se envia campo 48 */ switch (DBTipoProtocoloISO(trxOff.nro_ca)) { case PROT_ISO_AMEX: if (strcmp(aux_str1, "003001")==0) { memset(aux_str1, 0, sizeof(aux_str1)); } break; default: break; } /* Agrega campo */ if ( strlen(aux_str1) > 0 ) { IsoMsg->PutField(48, aux_str1); } /* Codigo de moneda */ IsoMsg->PutField(49, trxOff.cod_mon ); /* Fecha de diferimiento (si no es devolucion) */ if (term_data.dias_dif > 0) { if( (atoi(trxOff.cod_trx)!=T_DEVO) && (atoi(trxOff.cod_trx)!=T_DEVP) ) { char szFechaDif[6+1]; if (getFechaDif(trxOff.fec_trx, term_data.dias_dif, szFechaDif)==0) { ret = strlen(CAMPO_FECHA_DIFE) + strlen(szFechaDif); sprintf(aux_str1, "%03d%s%s", ret, CAMPO_FECHA_DIFE, szFechaDif); ret = IsoMsg->PutField(59, aux_str1); LogAlarm.Put(10, "TrxOff: Campo 59:[%s] Ret:[%d]\n", aux_str1, ret); } } } /* Numero de ticket */ sprintf(aux_str1,"004%04d", atoi(trxOff.nro_tic)); IsoMsg->PutField(62, aux_str1 ); LogAlarm.Put(0, "TrxOff: Emp:[%s] Suc:[%s] Ter:[%s] Trx:[%04d] Rowid:[%s]\n", term_data.nro_suc, term_data.nro_caj_sf, infoHeap.nroTerm, atoi(infoHeap.nroTrans), trxOff.rowid); /* Arma clave para el heap */ sprintf(idHeap, "%2.2s%3.3s%5.5s%8.8s", term_data.nro_ca, term_data.nro_suc, term_data.nro_caj, IsoMsg->GetField(11)); /* Pone datos en el heap */ LogAlarm.Put(5, "TrxOff: Pone datos en el Heap\n"); ret=Heap.PutData(idHeap,(char *)&infoHeap, sizeof(infoHeap)); if (ret==NOOK) { LogAlarm.Put(0, "TrxOff: ERROR (%d) al insertar en Heap. Clave:[%s]\n", Heap.GetErrno(), idHeap); /* Libera la caja */ ret = P.SetPosFree(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (ret != OK) { LogAlarm.Put(0, "TrxOff: ERROR en SetPosFree. CA:[%s] Emp:[%s] Caj:[%s]\n", data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); } EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } /* Carga estructura para actualizar la base de datos */ strncpy( trxPk.nroSuc , trxOff.nro_suc, sizeof(trxPk.nroSuc ) ); strncpy( trxPk.nroTerm , trxOff.nro_caj, sizeof(trxPk.nroTerm ) ); strncpy( trxPk.nroTrans, trxOff.nro_tic, sizeof(trxPk.nroTrans) ); strncpy( trxPk.fechaTrx, trxOff.fec_loc, sizeof(trxPk.fechaTrx) ); strncpy( trxPk.rowid , trxOff.rowid , sizeof(trxPk.rowid ) ); /* Carga estructura para actualizar la base de datos */ strncpy(InfoEnvio.cod_est, "01", sizeof(InfoEnvio.cod_est )); strncpy(InfoEnvio.fec_env, szFechaEnvio, sizeof(InfoEnvio.fec_env )); strncpy(InfoEnvio.nro_lot, "0000", sizeof(InfoEnvio.nro_lot)); strncpy(InfoEnvio.nro_trc, IsoMsg->GetField(11), sizeof(InfoEnvio.nro_trc)); /* Actualiza la base de datos */ ret=DBUpdEnvio(trxPk , InfoEnvio); LogAlarm.Put(0, "TrxOff: Actualiza informacion de Envio. Retorno:%d\n", ret); /* Registra en cola de timeout */ strcpy(aux_str, IsoMsg->GetField(11)); Cfg.GetItem("TimeOutDaemon", "MsgTimeOut1", aux_str1); LogAlarm.Put(0, "TrxOff: Timeout ID Trace [%s]\n", idHeap); ret=timeout_queue.SetTimeOut(idHeap, atoi(aux_str1), GetType(), ""); if (ret==NOOK) { LogAlarm.Put(0, "TrxOff: ERROR (%d) al registrar en TOQ\n",ret); /* Libera la caja */ ret = P.SetPosFree(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (ret != OK) { LogAlarm.Put(0, "TrxOff: ERROR en SetPosFree. CA:[%s] Emp:[%s] Caj:[%s]\n", data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); } /* Retira del heap */ ret=Heap.GetData(idHeap,(char *)&infoHeap, sizeof(infoHeap)); if (ret == NOOK) { LogAlarm.Put( 0, "TrxOff: ERROR (%d) al obtener del heap\n", Heap.GetErrno()); } /* Envia respuesta */ EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } /* Aplana el mensaje */ len=IsoMsg->GetMsgString(msg_str); /* Loguea el mensaje */ for (iCont=0; iCont<64; iCont++) { if (IsoMsg->ChkField(iCont)) { LogAlarm.Put(5, "TrxOff: Campo %02d: Valor:[%s]\n", iCont, IsoMsg->GetField(iCont) ); } } /* Envia el mensaje a X25 */ LogAlarm.Put(0, "TrxOff: Envia a X.25. CAut [%s]\n", term_data.nro_ca); ret=XQueue.SendMsg(atoi(term_data.nro_ca)+1, msg_str, len); if (ret!=OK) { LogAlarm.Put(0, "TrxOff: ERROR en Envio X.25(%d)\n", XQueue.GetErrno()); /* Libera la caja */ ret = P.SetPosFree(data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); if (ret != OK) { LogAlarm.Put(0, "TrxOff: ERROR en SetPosFree. CA:[%s] Emp:[%s] Caj:[%s]\n", data_tar.nro_ca, trxOff.nro_suc, trxOff.nro_caj); } /* Envia respuesta */ EnviarMsg(orig_pid, "ERROR", 5); return NOOK; } return OK; }