/* +-----------------+------------------------------------------------------------+ | 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 | 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; }