Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Brayan Sarmiento
API-Gateway-GK
Commits
56f10e15
Commit
56f10e15
authored
Jul 25, 2023
by
bsarmiento31
Browse files
Initial commit
parents
Changes
135
Hide whitespace changes
Inline
Side-by-side
gatewayGK/RespuestasXML/SaltarEmpaque/AddReceiptLinesResponse.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
EvaPOS_API_FRAME.RespuestasXML
{
/// <summary>
/// Respuesta a petición de agregar item - (AddReceiptLinesResponse)
/// </summary>
public
class
AddReceiptLinesResponse
:
Respuesta
{
public
int
RequestID
{
get
;
set
;
}
private
string
_xml
;
public
AddReceiptLinesResponse
(
int
sessionId
,
TipoMensaje
messageType
,
int
requestID
)
:
base
(
sessionId
,
messageType
)
{
RequestID
=
requestID
;
}
public
override
string
TextoXML
{
get
=>
_xml
=
$"""
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
schema
:
AddReceiptLinesResponse
xmlns
:
schema
=
"http://bc.si.retail.ibm.com/POSBCSchema"
>
<
AddReceiptLinesResult
>
<
RequestID
>{
RequestID
}</
RequestID
>
</
AddReceiptLinesResult
>
</
schema
:
AddReceiptLinesResponse
>
""";
}
}
}
gatewayGK/RespuestasXML/SignOffResponse.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
EvaPOS_API_FRAME.RespuestasXML
{
public
class
SignOffResponse
:
Respuesta
{
public
string
RequestID
{
get
;
set
;
}
private
string
_xml
;
public
SignOffResponse
(
int
sessionId
,
TipoMensaje
messageType
,
string
requestID
)
:
base
(
sessionId
,
messageType
)
{
RequestID
=
requestID
;
}
public
override
string
TextoXML
{
get
=>
_xml
=
$"""
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
schema
:
SignOffResponse
xmlns
:
schema
=
"http://bc.si.retail.ibm.com/POSBCSchema"
>
<
SignOffResult
>
<
RequestID
>{
RequestID
}</
RequestID
>
</
SignOffResult
>
</
schema
:
SignOffResponse
>
""";
}
}
}
gatewayGK/RespuestasXML/Suspend/SuspendTransactionResponse.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
gatewayGK.RespuestasXML.Suspend
{
public
class
SuspendTransactionResponse
:
Respuesta
{
public
int
RequestID
{
get
;
set
;
}
private
string
_xml
;
public
SuspendTransactionResponse
(
int
sessionId
,
TipoMensaje
messageType
,
int
requestID
)
:
base
(
sessionId
,
messageType
)
{
RequestID
=
requestID
;
}
public
override
string
TextoXML
{
get
=>
_xml
=
$"""
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
schema
:
SuspendTransactionResponse
xmlns
:
schema
=
"http://bc.si.retail.ibm.com/POSBCSchema"
>
<
SuspendTransactionResult
>
<
RequestID
>{
RequestID
}</
RequestID
>
</
SuspendTransactionResult
>
</
schema
:
SuspendTransactionResponse
>
""";
}
}
}
gatewayGK/RespuestasXML/Suspend/SuspendTransactionResponseError.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
EvaPOS_API_FRAME.RespuestasXML.Suspend
{
/// <summary>
/// Respuesta cuando no esta disponible el comando suspender
/// </summary>
public
class
SuspendTransactionResponseError
:
Respuesta
{
public
int
RequestID
{
get
;
set
;
}
public
string
Message
{
get
;
set
;
}
public
string
ErrorCode
{
get
;
set
;
}
private
string
_xml
;
public
SuspendTransactionResponseError
(
int
sessionId
,
TipoMensaje
messageType
,
int
requestID
,
string
message
,
string
errorCode
)
:
base
(
sessionId
,
messageType
)
{
RequestID
=
requestID
;
Message
=
message
;
ErrorCode
=
errorCode
;
}
public
override
string
TextoXML
{
get
=>
_xml
=
$"""
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
schema
:
SuspendTransactionResponse
xmlns
:
schema
=
"http://bc.si.retail.ibm.com/POSBCSchema"
>
<
SuspendTransactionResult
>
<
RequestID
>{
RequestID
}</
RequestID
>
<
ExceptionResult
>
<
Message
>{
Message
}</
Message
>
<
ErrorCode
>{
ErrorCode
}</
ErrorCode
>
</
ExceptionResult
>
</
SuspendTransactionResult
>
</
schema
:
SuspendTransactionResponse
>
""";
}
}
}
gatewayGK/RespuestasXML/TerminateLane/TerminateResponse.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
EvaPOS_API_FRAME.RespuestasXML.TerminateLane
{
/// <summary>
/// Respuesta para cerrar la lane
/// </summary>
public
class
TerminateResponse
:
Respuesta
{
public
bool
RequestID
{
get
;
set
;
}
private
string
_xml
;
public
TerminateResponse
(
int
sessionId
,
TipoMensaje
messageType
,
bool
requestID
)
:
base
(
sessionId
,
messageType
)
{
RequestID
=
requestID
;
}
public
override
string
TextoXML
{
get
=>
_xml
=
$"""
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
schema
:
TerminateResponse
xmlns
:
schema
=
"http://bc.si.retail.ibm.com/POSBCSchema"
>
<
TerminateResult
>
<
RequestID
>{
RequestID
}</
RequestID
>
</
TerminateResult
>
</
schema
:
TerminateResponse
>
""";
}
}
}
gatewayGK/RespuestasXML/TotalsEventResponse.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
System
;
using
System.Collections.Generic
;
using
System.Globalization
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
EvaPOS_API_FRAME.RespuestasXML
{
/// <summary>
/// Respuesta a petición de agregar item - (TotalsEvent)
/// Tambien se usa para la segunda respuesta de finalizar y pagar
/// </summary>
public
class
TotalsEventResponse
:
Respuesta
{
public
int
RequestID
{
get
;
set
;
}
public
string
Key
{
get
;
set
;
}
public
int
Value
{
get
;
set
;
}
public
string
Total
{
get
;
set
;
}
public
string
SubTotal
{
get
;
set
;
}
public
string
Tax
{
get
;
set
;
}
public
string
BalanceDue
{
get
;
set
;
}
public
string
ChangeDue
{
get
;
set
;
}
public
string
FoodstampChangeDue
{
get
;
set
;
}
public
string
FoodstampTotal
{
get
;
set
;
}
public
string
FoodstampBalanceDue
{
get
;
set
;
}
public
string
CouponTotal
{
get
;
set
;
}
public
int
TotalItems
{
get
;
set
;
}
public
int
TotalCoupons
{
get
;
set
;
}
public
string
TotalSavings
{
get
;
set
;
}
public
string
TenderApplied
{
get
;
set
;
}
private
string
_xml
;
public
TotalsEventResponse
(
int
sessionId
,
TipoMensaje
messageType
,
int
requestID
,
string
total
,
string
subTotal
,
string
tax
,
string
balanceDue
,
string
changeDue
,
string
foodstampChangeDue
,
string
foodstampTotal
,
string
foodstampBalanceDue
,
string
couponTotal
,
int
totalItems
,
int
totalCoupons
,
string
totalSavings
,
string
tenderApplied
)
:
base
(
sessionId
,
messageType
)
{
RequestID
=
requestID
;
//Key = key;
//Value = value;
Total
=
total
;
SubTotal
=
subTotal
;
Tax
=
tax
;
BalanceDue
=
balanceDue
;
ChangeDue
=
changeDue
;
FoodstampChangeDue
=
foodstampChangeDue
;
FoodstampTotal
=
foodstampTotal
;
FoodstampBalanceDue
=
foodstampBalanceDue
;
CouponTotal
=
couponTotal
;
TotalItems
=
totalItems
;
TotalCoupons
=
totalCoupons
;
TotalSavings
=
totalSavings
;
TenderApplied
=
tenderApplied
;
}
public
override
string
TextoXML
{
get
=>
_xml
=
$"""
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
schema
:
TotalsEvent
xmlns
:
schema
=
"http://bc.si.retail.ibm.com/POSBCSchema"
>
<
RequestID
>{
RequestID
}</
RequestID
>
<
TransactionTotals
>
<
Total
>{
Total
}</
Total
>
<
SubTotal
>{
SubTotal
}</
SubTotal
>
<
Tax
>{
Tax
}</
Tax
>
<
BalanceDue
>{
BalanceDue
}</
BalanceDue
>
<
ChangeDue
>{
ChangeDue
}</
ChangeDue
>
<
FoodstampChangeDue
>{
FoodstampChangeDue
}</
FoodstampChangeDue
>
<
FoodstampTotal
>{
FoodstampTotal
}</
FoodstampTotal
>
<
FoodstampBalanceDue
>{
FoodstampBalanceDue
}</
FoodstampBalanceDue
>
<
CouponTotal
>{
CouponTotal
}</
CouponTotal
>
<
TotalItems
>{
TotalItems
}</
TotalItems
>
<
TotalCoupons
>{
TotalCoupons
}</
TotalCoupons
>
<
TotalSavings
>{
TotalSavings
}</
TotalSavings
>
<
TenderApplied
>{
TenderApplied
}</
TenderApplied
>
</
TransactionTotals
>
</
schema
:
TotalsEvent
>
""";
}
}
}
gatewayGK/RespuestasXML/TransactionStatusEvent.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
namespace
EvaPOS_API_FRAME.RespuestasXML
{
public
class
TransactionStatusEvent
:
Respuesta
{
public
int
RequestID
{
get
;
set
;
}
public
string
Status
{
get
;
set
;
}
public
int
ID
{
get
;
set
;
}
public
string
Type
{
get
;
set
;
}
public
string
Category
{
get
;
set
;
}
public
string
Date
{
get
;
set
;
}
public
string
Time
{
get
;
set
;
}
private
string
_xml
;
public
TransactionStatusEvent
(
int
sessionId
,
TipoMensaje
messageType
,
int
requestID
,
string
status
,
int
iD
,
string
type
,
string
category
,
string
date
,
string
time
)
:
base
(
sessionId
,
messageType
)
{
RequestID
=
requestID
;
Status
=
status
;
ID
=
iD
;
Type
=
type
;
Category
=
category
;
Date
=
date
;
Time
=
time
;
}
public
override
string
TextoXML
{
get
=>
_xml
=
$"""
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
schema
:
TransactionStatusEvent
xmlns
:
schema
=
"http://bc.si.retail.ibm.com/POSBCSchema"
>
<
RequestID
>{
RequestID
}</
RequestID
>
<
TransactionStatus
>
<
Status
>{
Status
}</
Status
>
<
ID
>{
ID
}</
ID
>
<
Type
>{
Type
}</
Type
>
<
Category
>{
Category
}</
Category
>
<
Date
>{
Date
}</
Date
>
<
Time
>{
Time
}</
Time
>
</
TransactionStatus
>
</
schema
:
TransactionStatusEvent
>
""";
}
}
}
gatewayGK/Servidor/EvaPosSrvAplicacion.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvResp
;
namespace
EvaPosSrvAplicacion
{
public
interface
IAplicacion
{
public
Respuestas
Procesar
(
IComando
comando
);
}
}
\ No newline at end of file
gatewayGK/Servidor/EvaPosSrvAplicacionImp.cs
0 → 100644
View file @
56f10e15
using
EvaPosSrvResp
;
using
EvaPosSrvAplicacion
;
namespace
EvaPosSrvAplicacionImp
{
/// <summary>
/// Clase que ejecuta el comando y retorna respuesta.
/// </summary>
public
class
Aplicacion
:
IAplicacion
{
public
Respuestas
Procesar
(
IComando
comando
)
{
return
comando
.
Ejecutar
();
}
}
}
\ No newline at end of file
gatewayGK/Servidor/EvaPosSrvDTO.cs
0 → 100644
View file @
56f10e15
// Espacio de nombres que reune objetos DTO (data transfer object ) para comunicación con capa de presentación.
// Los DTO no incluyen lógica, solo datos (no son un remplazo de las Entidades - objetos del negocio.)
using
System
;
namespace
EvaPosSrvDTO
{
/// <summary>
/// TipoMensaje encapsula identificadores permitidos de tipo de mensaje.
/// </summary>
public
class
TipoMensaje
{
/// <summary>
/// Valor del tipo de mensaje.
/// </summary>
//REVISAR: Creado para xml, set era private
public
string
Tipo
{
get
;
set
;
}
//REVISAR: Creado para xml constructor vacio
public
TipoMensaje
()
{
}
private
TipoMensaje
(
string
tipo
)
{
Tipo
=
tipo
;
}
/// <summary>
/// Mensajes tipo EVENT.
/// </summary>
//REVISAR: Creado para xml, set era private
public
static
TipoMensaje
Event
{
get
;
set
;
}
=
new
TipoMensaje
(
"EVENT"
);
/// <summary>
/// Mensajes tipo REQest.
/// </summary>
//REVISAR: Creado para xml, set era private
public
static
TipoMensaje
Req
{
get
;
set
;
}
=
new
TipoMensaje
(
"REQ"
);
/// <summary>
/// Mensajes tipo RESPonse.
/// </summary>
//REVISAR: Creado para xml, set era private
public
static
TipoMensaje
Resp
{
get
;
set
;
}
=
new
TipoMensaje
(
"RESP"
);
/// <summary>
/// Retorna un tipo de mensaje correspondiente al parámetro.
/// </summary>
public
static
TipoMensaje
FijaTipoMensaje
(
string
tipo
)
{
var
t
=
tipo
switch
{
"REQ"
=>
TipoMensaje
.
Req
,
"EVENT"
=>
TipoMensaje
.
Event
,
"RESP"
=>
TipoMensaje
.
Resp
,
_
=>
throw
new
Exception
(
$"Tipo de mensaje no reconocido
{
tipo
}
"
)
};
return
t
;
}
}
/// <summary>
/// Clase base de DTO.
/// </summary>
public
abstract
class
DTOBase
{
/// <summary>
/// Id de la sesión.
/// </summary>
//REVISAR: Creado para xml, set era private
public
Int32
IdSesion
{
get
;
set
;
}
/// <summary>
/// Tipo del mensaje.
/// </summary>
//REVISAR: Creado para xml, set era private
public
TipoMensaje
TipoMensaje
{
get
;
set
;
}
/// <summary>
/// Constructor base.
/// </summary>
public
DTOBase
(
int
idSesion
,
TipoMensaje
tipo
)
{
IdSesion
=
idSesion
;
TipoMensaje
=
tipo
;
}
//REVISAR: Creado para xml, set era private, cosntructor vacio
public
DTOBase
()
{
}
}
// TODO - ARREGLAR EL MECANISMO DE TERMINACION DEL SERVIDOR.
/// <summary>
/// DTO con mensaje de terminación de conexión, para pruebas.
/// </summary>
public
class
FinDePruebaDTO
:
DTOBase
{
/// <summary>
/// Mensaje de terminación de conexión, para pruebas.
/// </summary>
public
string
MensajeFin
{
get
;
private
set
;
}
=
"<|ACK|>"
;
public
FinDePruebaDTO
()
:
base
(
1
,
TipoMensaje
.
Event
)
{}
}
// TODO - validar manejo de errores y su notificación a clientes que interactuan con el servidor.
/// <summary>
/// Retorna mensajes de error.
/// </summary>
public
class
ErrorDTO
:
DTOBase
{
/// <summary>
/// Texto del mensaje de error.
/// </summary>
public
string
Texto
{
get
;
private
set
;
}
/// <summary>
/// Constructor con texto del mensaje de error.
/// </summary>
public
ErrorDTO
(
int
sessionId
,
TipoMensaje
messageType
,
string
texto
)
:
base
(
sessionId
,
messageType
)
{
Texto
=
texto
;
}
/// <summary>
/// Representación del objeto en un string.
/// </summary>
public
override
string
ToString
()
{
return
$"ErrorDTO - Texto:
{
Texto
}
"
;
}
}
/// <summary>
/// InitializeRequest DTO
/// </summary>
public
class
InitializeRequestDTO
:
DTOBase
{
/// <summary>
/// Campo OperatorID
/// </summary>
public
string
OperatorID
{
get
;
set
;
}
/// <summary>
/// Campo TerminalNumber
/// </summary>
public
int
TerminalNumber
{
get
;
set
;
}
/// <summary>
/// Campo Recovery
/// </summary>
public
bool
Recovery
{
get
;
set
;
}
public
InitializeRequestDTO
(
int
sessionId
,
TipoMensaje
messageType
)
:
base
(
sessionId
,
messageType
)
{}
}
}
\ No newline at end of file
gatewayGK/Servidor/EvaPosSrvResp.cs
0 → 100644
View file @
56f10e15
using
System
;
using
System.Collections.Generic
;
using
System.Xml
;
using
EvaPosSrvDTO
;
namespace
EvaPosSrvResp
{
/// <summary>
/// Interface que define adaptadores para conversión de
/// mensaje XML en DTO.
/// </summary>
public
interface
IAdaptadorDTO
{
/// <summary>
/// Identifica el mensaje al cual el adaptador genera DTO.
/// Le referencia se usa por el servidor de mensajes para interpretar
/// el mensaje en un DTO a pasar a un comando.
/// La referencia corresponde a un string contenido en el mensaje
/// que permite identificar su tipo.
/// </summary>
public
string
Referencia
{
get
;
set
;
}
/// <summary>
/// Nombre del elemento xml con los datos para el DTO.
/// El nombre del elemento se presenta en formato xpath para ubicar el nodo desde el
/// elemento raiz del mensaje.
/// </summary>
public
string
NombreElementoXMLDatos
{
get
;
set
;
}
/// <summary>
/// Inicializar DTO adecuado al mensaje.
/// </summary>
public
DTOBase
ObtieneDTO
(
int
idSesion
,
TipoMensaje
tipoMensaje
,
XmlElement
docXml
);
/// <summary>
/// Retorna una "shallow copy" del objeto.
/// </summary>
public
IAdaptadorDTO
CreaCopia
();
}
/// <summary>
/// Directorio de adaptadores DTO.
/// Almacena instancia de adaptadores indexadas por su Referencia.
/// Usado para identificar el adaptador que procesa un mensaje particular
/// asociado por la propiedad Referencia del adaptador.
/// </summary>
public
class
DirectorioAdaptadoresDTO
{
private
Dictionary
<
string
,
IAdaptadorDTO
>
dir
=
new
Dictionary
<
string
,
IAdaptadorDTO
>();
/// <summary>
/// Agrega un adaptador al directorio.
/// </summary>
public
void
AgregaAdaptador
(
IAdaptadorDTO
adp
)
{
dir
.
Add
(
adp
.
Referencia
,
adp
);
}
/// <summary>
/// Recupera una "shallow copy" del adaptador asociado al parámmetro.
/// </summary>
public
IAdaptadorDTO
ObtieneAdaptador
(
string
referencia
)
{
IAdaptadorDTO
adp
;
try
{
adp
=
dir
[
referencia
];
}
catch
(
KeyNotFoundException
)
{
throw
new
Exception
(
$"No se encuentra adaptador con referencia '
{
referencia
}
'."
);
}
return
adp
.
CreaCopia
();
}
}
/// <summary>
/// Trama, integra las partes que incluyen mensaje xml e información de control.
/// </summary>
public
struct
TramaSCO
{
/// <summary>
/// Longitud del mensaje.
/// Es la suma de la longitud de las cadenas de texto de la sección de encabezado
/// y de la sección te contenido xml.
/// </summary>
public
UInt32
Longitud
{
get
;
set
;
}
/// <summary>
/// Id de la sesión.
/// </summary>
public
Int32
IdSesion
{
get
;
set
;
}
/// <summary>
/// Tipo del mensaje, con valores predefinidos según el tipo de datos.
/// </summary>
public
TipoMensaje
TipoMensaje
{
get
;
set
;
}
/// <summary>
/// Texto del encabezado según los valores de tipo de mensaje e id de sesión.
/// </summary>
public
string
TextoEncabezado
{
get
=>
$"soeps~Message-Type=
{
TipoMensaje
.
Tipo
}
|Session-Id=
{
IdSesion
}
|~"
;
}
/// <summary>
/// Texto del contenido xml del mensaje, con sus valores incluidos.
/// Debe ser inicializado por el que crea el objeto.
/// </summary>
public
string
TextoXML
{
get
;
set
;
}
/// <summary>
/// Objeto xml del mensaje, construido a partir del texto xml.
/// </summary>
public
XmlDocument
ContenidoXML
{
get
{
var
doc
=
new
XmlDocument
();
doc
.
LoadXml
(
TextoXML
);
return
doc
;
}
}
/// <summary>
/// Constructor genérico.
/// </summary>
public
TramaSCO
(
UInt32
longitud
,
Int32
idSesion
,
TipoMensaje
tipo
,
string
textoXML
)
{
Longitud
=
longitud
;
IdSesion
=
idSesion
;
TipoMensaje
=
tipo
;
TextoXML
=
textoXML
;
}
/// <summary>
/// Constructor usado para calcular Longitud del mensaje (encabezado + texto xml).
/// </summary>
public
TramaSCO
(
Int32
idSesion
,
TipoMensaje
tipo
,
string
textoXML
)
{
IdSesion
=
idSesion
;
TipoMensaje
=
tipo
;
TextoXML
=
textoXML
;
Longitud
=
Convert
.
ToUInt32
(
TextoEncabezado
.
Length
+
TextoXML
.
Length
);
}
}
/// <summary>
/// Definición mensajes respuesta para el SCO.
/// </summary>
public
abstract
class
Respuesta
{
/// <summary>
/// String con el encabezado y contenido xml de mensajes de respuesta.
/// </summary>
public
Int32
SessionId
{
get
;
private
set
;
}
public
TipoMensaje
MessageType
{
get
;
private
set
;
}
public
abstract
string
TextoXML
{
get
;
}
public
TramaSCO
TramaSCO
{
get
=>
new
TramaSCO
(
SessionId
,
MessageType
,
TextoXML
);
}
public
Respuesta
(
int
sessionId
,
TipoMensaje
tipo
)
{
SessionId
=
sessionId
;
MessageType
=
tipo
;
}
}
/// <summary>
/// Respuesta en modo texto genérico. Usada para pruebas básicas de comunicación.
/// </summary>
public
class
RespuestaGenerica
:
Respuesta
{
private
string
_mensaje
;
/// <summary>
/// Constructor mensaje básico.
/// </summary>
public
RespuestaGenerica
(
string
mensaje
)
:
base
(
1
,
TipoMensaje
.
Resp
)
{
_mensaje
=
mensaje
;
}
/// <summary>
/// Retorna mensaje.
/// </summary>
public
override
string
TextoXML
{
get
=>
_mensaje
;
}
}
/// <summary>
/// Colección de respuestas.
/// </summary>
public
class
Respuestas
:
List
<
Respuesta
>
{
}
}
\ No newline at end of file
gatewayGK/Servidor/EvaPosSrvRespImp.cs
0 → 100644
View file @
56f10e15
using
System
;
using
System.Xml
;
using
EvaPOS_API_FRAME.Adaptadores
;
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
GatewaySCO
;
// ****************************************************************
//
// ESPACIO DE NOMBRES PARA IMPLEMENTAR ADAPTADORES Y RESPUESTAS
//
// ****************************************************************
namespace
EvaPosSrvRespImp
{
/// <summary>
/// Clase para inicializar el directorio de adaptadores de entrada.
/// Los adaptadores de entrada inicializan al dto asociada con el mensaje de entrada.
/// Para agregar un adaptador de entrada, modifique el método ' public static IniciaDirectorioAdaptadores Cargar()'
/// agregando la nueva instancia del objeto adaptador, usando el método 'AgregaAdaptador'. Ejemplo:
///
/// public static IniciaDirectorioAdaptadores Cargar()
/// {
/// return new IniciaDirectorioAdaptadores()
/// .AgregaAdaptador(new AdaptadorInitializeRequest())
/// .AgregarAdaptador(new AdaptadorQueryStatusRequest());
/// }
///
/// Agrega nueva instancia del AdaptadorQueryStatusRequest() al directorio de adaptadores.
/// </summary>
public
class
IniciaDirectorioAdaptadores
{
public
DirectorioAdaptadoresDTO
DirectorioAdaptadores
{
get
;
private
set
;}
=
new
DirectorioAdaptadoresDTO
();
public
IniciaDirectorioAdaptadores
AgregaAdaptador
(
IAdaptadorDTO
adaptador
)
{
DirectorioAdaptadores
.
AgregaAdaptador
(
adaptador
);
return
this
;
}
public
static
IniciaDirectorioAdaptadores
Cargar
()
{
return
new
IniciaDirectorioAdaptadores
()
.
AgregaAdaptador
(
new
AdaptadorInitializeRequest
())
.
AgregaAdaptador
(
new
AdaptadorQueryStatusRequest
())
.
AgregaAdaptador
(
new
AdaptadorReportStatusEventsRequest
())
.
AgregaAdaptador
(
new
AdaptadorAddItemRequest
())
.
AgregaAdaptador
(
new
AdaptadorSignOffRequest
())
.
AgregaAdaptador
(
new
AdaptadorAddReceiptLinesRequest
())
.
AgregaAdaptador
(
new
AdaptadorGetTotalsRequest
())
.
AgregaAdaptador
(
new
AdaptadorAddTenderDebitRequest
())
.
AgregaAdaptador
(
new
AdaptadorPrintCurrentReceipts
())
.
AgregaAdaptador
(
new
AdaptadorReprintReceiptsRequest
())
.
AgregaAdaptador
(
new
AdaptadorTerminateRequest
())
.
AgregaAdaptador
(
new
AdaptadoresVoidTransactionRequest
())
.
AgregaAdaptador
(
new
AdaptadorRemoveReceiptLines
())
.
AgregaAdaptador
(
new
AdaptadorCancelAction
())
.
AgregaAdaptador
(
new
AdaptadorAddCustomerBirthdateRequest
())
.
AgregaAdaptador
(
new
AdaptadorAddCustomerRequest
())
.
AgregaAdaptador
(
new
AdaptadorSuspendTransactionRequest
());
}
}
}
gatewayGK/Servidor/EvaPosSrvSCO.cs
0 → 100644
View file @
56f10e15
#define TRACE
#define DEBUG
// EvaPos-API : servidor api, sockets y rest.
using
System.Net
;
using
System.Net.Sockets
;
using
System.Text
;
using
System.Xml
;
using
Serilog
;
using
Serilog.Events
;
using
GatewaySCO
;
using
EvaPosSrvDTO
;
using
EvaPosSrvResp
;
using
EvaPosSrvAplicacion
;
using
EvaPOS_API_FRAME.RespuestasXML
;
using
EvaPOS_API_FRAME.Comandos
;
namespace
EvaPosSCOSrv
{
/// <summary>
/// Esta clase <c>ServidorSocket</c>activa servidor socktes.
/// Usa por default ip localhost 127.0.0.1 y puerto 11.0000
/// La operación del servidor es como sigue:
///
/// </summary>
public
class
ServidorSocket
{
ILogger
log
=
Log
.
ForContext
<
ServidorSocket
>();
readonly
static
bool
_isDebug
=
Log
.
IsEnabled
(
LogEventLevel
.
Debug
);
/// <summary>
/// Longitud máxima de mensaje de entrada.
/// </summary>
public
const
Int32
LongMaxMensaje
=
1
_024
*
8
;
/// <summary>
/// Dirección ip para vincular el socket.
/// </summary>
public
string
Direccion
{
get
;
private
set
;
}
=
"127.0.0.1"
;
/// <summary>
/// Puerto a vincular socket.
/// </summary>
public
Int32
Puerto
{
get
;
private
set
;
}
=
11
_000
;
/// <summary>
/// Longitud de la cola de conexión al socket.
/// </summary>
public
int
LongColaConexiones
{
get
;
private
set
;
}
=
10
;
/// <summary>
/// Fija timeout usado para enviar / recibir em modo sincrónico, en milisegundos.
/// Si el timeout se excede, se presenta una excepción.
/// Default a 5 segundos.
/// </summary>
public
int
TimeOutSincMs
{
get
;
private
set
;
}
=
3000
;
long
_numeroConexionesEntrantes
=
0
;
DirectorioAdaptadoresDTO
_adaptadores
;
CreaDirectorioCmds
_comandos
;
Sesion
_sesion
;
Presentacion
_presentacion
;
IAplicacion
_aplicacion
;
/// <summary>
/// Constructor servidor socket. Usa ip y puerto defualt.
/// El método IniciarAync() activa el servidor.
/// </summary>
public
ServidorSocket
()
{
}
/// <summary>
/// Constructor servidor socket. Usa ip y puerto defualt.
/// El método IniciarAync() activa el servidor.
/// <param name="direccion">Dirección IP servidor, típicamente '127.0.0.1'.</param>
/// <param name="puerto">Número de puerto para el socket, default 11.000</param>
/// <returns>Retorna tipo Task.</returns>
/// </summary>
public
ServidorSocket
(
string
direccion
,
Int32
puerto
)
{
Direccion
=
direccion
;
Puerto
=
puerto
;
}
/// <summary>
/// Fija IP del servidor.
/// </summary>
public
ServidorSocket
ConIp
(
string
direccion
)
{
Direccion
=
direccion
;
return
this
;
}
/// <summary>
/// Fija puerto del servidor.
/// </summary>
public
ServidorSocket
EnPuerto
(
int
puerto
)
{
Puerto
=
puerto
;
return
this
;
}
/// <summary>
/// Fija directorio de adaptadores.
/// </summary>
public
ServidorSocket
AgregaDispensadorAdaptadores
(
DirectorioAdaptadoresDTO
adaptadores
)
{
_adaptadores
=
adaptadores
;
return
this
;
}
/// <summary>
/// Fija directorio de comandos.
/// </summary>
public
ServidorSocket
AgregaDirectorioCmds
(
CreaDirectorioCmds
comandos
)
{
_comandos
=
comandos
;
return
this
;
}
/// <summary>
/// Fija aplicación a procesar comandos.
/// </summary>
public
ServidorSocket
AgregaProcesadorAplicacion
(
IAplicacion
aplicacion
)
{
_aplicacion
=
aplicacion
;
return
this
;
}
// TODO - este metodo no se puede usar en la invocación fluida, estudiar.
/// <summary>
/// Pone en marcha el servidor socket, vinculando a la IP y puertos asignados.
/// </summary>
public
ServidorSocket
Activa
()
{
_sesion
=
new
Sesion
();
_presentacion
=
new
Presentacion
(
_adaptadores
,
_comandos
);
ActivaServidor
();
return
this
;
}
/// <summary>
/// Activa el servidor en ip y puerto indicado en los parámetros globales.
/// <returns>Retorna tipo Task.</returns>
/// </summary>
private
void
ActivaServidor
()
{
IPEndPoint
ipEndPoint
=
new
(
IPAddress
.
Parse
(
Direccion
),
Puerto
);
int
cont
=
0
;
// Clave usar 'using' para liberar correctamente recursos.
using
Socket
tcpSocket
=
new
(
ipEndPoint
.
AddressFamily
,
SocketType
.
Stream
,
ProtocolType
.
Tcp
);
// Configuración comportamiento socket tcp.
// No se permite a otro socket compartir el puerto.
// TODO - Investigar: cuando servidor y cliente están en la misma instanción de s.o.
// no comparten el puerto?.
//tcpSocket.ExclusiveAddressUse = true;
// El socket espera los segundos del parémetro para terminar de enviar
// datos (si hay en el buffer de salida), despues que se llama Socket.Close.
tcpSocket
.
LingerState
=
new
LingerOption
(
true
,
3
);
// Desactiva algoritmo Nagle.
tcpSocket
.
NoDelay
=
true
;
// Timeout entrada / salida.
tcpSocket
.
ReceiveTimeout
=
0
;
tcpSocket
.
SendTimeout
=
TimeOutSincMs
;
//tcpSocket.Blocking = false;
tcpSocket
.
Bind
(
ipEndPoint
);
tcpSocket
.
Listen
(
LongColaConexiones
);
// Inicializa objetos de procesamiento de los mensajes de comunicación.
Sesion
sesion
=
new
Sesion
();
Presentacion
presentacion
=
new
Presentacion
(
_adaptadores
,
_comandos
);
// Id proceso. Compilación difiere según .net usado.
int
id
=
-
1
;
#if NETFRAMEWORK
id
=
Process
.
GetCurrentProcess
().
Id
;
#elif (NETSTANDARD || NET5_0_OR_GREATER)
id
=
Environment
.
ProcessId
;
#endif
log
.
Information
(
"EvaPOS servidor socket en {ip} : {puerto}, proceso id {id}"
,
Direccion
,
Puerto
,
id
);
if
(
_isDebug
)
{
log
.
Debug
(
"Versión .Net {version}"
,
Environment
.
Version
);
log
.
Debug
(
"Longitud máxima mensaje aceptado bytes {long}"
,
LongMaxMensaje
);
Log
.
Debug
(
"Tcp Socket configuración:"
);
Log
.
Debug
(
$" Blocking
{
tcpSocket
.
Blocking
}
"
);
Log
.
Debug
(
$" Version eva 1.3"
);
Log
.
Debug
(
$" ExclusiveAddressUse
{
tcpSocket
.
ExclusiveAddressUse
}
"
);
Log
.
Debug
(
$" LingerState
{
tcpSocket
.
LingerState
.
Enabled
}
,
{
tcpSocket
.
LingerState
.
LingerTime
}
"
);
Log
.
Debug
(
$" NoDelay
{
tcpSocket
.
NoDelay
}
"
);
Log
.
Debug
(
$" ReceiveBufferSize
{
tcpSocket
.
ReceiveBufferSize
}
"
);
Log
.
Debug
(
$" ReceiveTimeout
{
tcpSocket
.
ReceiveTimeout
}
"
);
Log
.
Debug
(
$" SendBufferSize
{
tcpSocket
.
SendBufferSize
}
"
);
Log
.
Debug
(
$" SendTimeout
{
tcpSocket
.
SendTimeout
}
"
);
Log
.
Debug
(
$" Ttl
{
tcpSocket
.
Ttl
}
"
);
Log
.
Debug
(
$" IsBound
{
tcpSocket
.
IsBound
}
"
);
}
// TODO - El socket temporal debe liberar recursos?
// Socket entrada.
Socket
socketEntrada
;
try
{
bool
continuar
=
true
;
while
(
continuar
)
{
log
.
Information
(
"Esperando conexión..."
);
socketEntrada
=
tcpSocket
.
Accept
();
continuar
=
ProcesaConexion
(
socketEntrada
,
_numeroConexionesEntrantes
++);
while
(!
continuar
)
{
tcpSocket
.
Close
();
IPEndPoint
ipEndPoint2
=
new
(
IPAddress
.
Parse
(
Direccion
),
Puerto
);
using
Socket
tcpSocket2
=
new
(
ipEndPoint2
.
AddressFamily
,
SocketType
.
Stream
,
ProtocolType
.
Tcp
);
tcpSocket2
.
LingerState
=
new
LingerOption
(
true
,
3
);
tcpSocket2
.
NoDelay
=
true
;
tcpSocket2
.
ReceiveTimeout
=
0
;
tcpSocket2
.
SendTimeout
=
TimeOutSincMs
;
tcpSocket2
.
Bind
(
ipEndPoint
);
tcpSocket2
.
Listen
(
LongColaConexiones
);
Sesion
sesion2
=
new
Sesion
();
Presentacion
presentacion2
=
new
Presentacion
(
_adaptadores
,
_comandos
);
socketEntrada
=
tcpSocket2
.
Accept
();
continuar
=
ProcesaConexion
(
socketEntrada
,
_numeroConexionesEntrantes
++);
}
}
if
(
tcpSocket
.
Connected
)
tcpSocket
.
Shutdown
(
SocketShutdown
.
Both
);
log
.
Information
(
"Conexion Cerrada"
);
}
finally
{
tcpSocket
.
Close
();
}
}
/// <summary>
/// Retorna longitud del mensaje representada en los 4 primeros bytes del arreglo bytes de argumento.
/// </summary>
private
uint
LongitudMensaje
(
byte
[]
arregloBytes
)
{
// Extrae longitud. Primeros 4 bytes del arreglo.
byte
[]
bytesConLongMensaje
=
new
byte
[
4
];
Buffer
.
BlockCopy
(
arregloBytes
,
0
,
bytesConLongMensaje
,
0
,
4
);
if
(
BitConverter
.
IsLittleEndian
)
Array
.
Reverse
(
bytesConLongMensaje
);
var
longitud
=
BitConverter
.
ToUInt32
(
bytesConLongMensaje
,
0
);
return
longitud
;
}
/// <summary>
/// Procesa socket entrada de conexión.
/// </summary>
private
bool
ProcesaConexion
(
Socket
socket
,
long
nroConexion
)
{
bool
result
=
true
;
Respuestas
respuestas
=
null
;
int
contIngreso
=
0
;
if
(
_isDebug
)
{
Log
.
Debug
(
"Conexión remota #{nro} ip {ip} en puerto {pto}"
,
nroConexion
,
IPAddress
.
Parse
(((
IPEndPoint
)
socket
.
RemoteEndPoint
).
Address
.
ToString
()),
((
IPEndPoint
)
socket
.
RemoteEndPoint
).
Port
.
ToString
());
contIngreso
++;
}
while
(
true
)
{
try
{
// Lee mensajes hasta que llegue mensaje de terminación o socket cerrado por el cliente.
// Lee longitud mensaje entrante, 4 bytes.
Log
.
Debug
(
"Esperando mensaje..."
);
var
bufferLongitud
=
new
byte
[
4
];
int
bytesLeidos
=
0
;
while
(
bytesLeidos
<
4
)
{
bytesLeidos
+=
socket
.
Receive
(
bufferLongitud
,
bytesLeidos
,
bufferLongitud
.
Length
,
SocketFlags
.
None
);
}
// Lee porción de datos del mensaje, hasta la longitud indicada en los 4 primeros bytes.
var
longitudMensaje
=
LongitudMensaje
(
bufferLongitud
);
Log
.
Debug
(
"Longitud mensaje {long} - buffer longitud mensaje >>{buffer}<<"
,
longitudMensaje
,
bufferLongitud
);
if
(
longitudMensaje
>
LongMaxMensaje
)
throw
new
Exception
(
$"Mensaje recibido de
{
longitudMensaje
}
bytes supera máximo permitido de
{
LongMaxMensaje
}
bytes."
);
Log
.
Debug
(
"Leyendo bytes con mensaje..."
);
var
bufferEntrada
=
new
byte
[
longitudMensaje
];
bytesLeidos
=
0
;
while
(
bytesLeidos
<
longitudMensaje
)
{
bytesLeidos
+=
socket
.
Receive
(
bufferEntrada
,
bytesLeidos
,
bufferEntrada
.
Length
,
SocketFlags
.
None
);
}
Log
.
Information
(
"Bytes recibidos {bytes}"
,
bytesLeidos
);
// Procesando entrada: se obtiene mensaje, con el cual se
// identifica comando que lo procesa, se ejecuta el comando
// y se retornarn respuestas al cliente que ha emitido el mensaje.
TramaSCO
msj
=
_sesion
.
Entrada
(
bufferEntrada
,
bytesLeidos
);
IComando
cmd
=
_presentacion
.
Entrada
(
msj
);
//Enviamos la respuesta del pinpad primero del datafono antes de que entre al comando procesar
if
(
cmd
.
Referencia
==
"scsns:AddTender"
)
{
Respuestas
respuestaDatafono
=
EjecutarProcesarDatafonoDirecto
();
foreach
(
var
respuesta
in
respuestaDatafono
)
{
Log
.
Debug
(
"Respuesta del pinpad del datafono"
);
var
bufferSalida
=
_sesion
.
Salida
(
respuesta
.
TramaSCO
);
socket
.
Send
(
bufferSalida
,
0
,
bufferSalida
.
Length
,
SocketFlags
.
None
);
Log
.
Information
(
"Bytes enviados {bytes}"
,
bufferSalida
.
Length
);
}
}
respuestas
=
_aplicacion
.
Procesar
(
cmd
);
Log
.
Debug
(
"Respuestas de cmd ref '{cmd}' : {nroRespuestas}"
,
cmd
.
Referencia
,
respuestas
.
Count
);
// Enviando respuestas.
int
i
=
1
;
foreach
(
var
respuesta
in
respuestas
)
{
Log
.
Debug
(
"Respuesta #{i}"
,
i
++);
var
bufferSalida
=
_sesion
.
Salida
(
respuesta
.
TramaSCO
);
socket
.
Send
(
bufferSalida
,
0
,
bufferSalida
.
Length
,
SocketFlags
.
None
);
Log
.
Information
(
"Bytes enviados {bytes}"
,
bufferSalida
.
Length
);
}
log
.
Information
(
"Fin del ciclo, se enviaron {nro} respuestas"
,
respuestas
.
Count
);
if
(
cmd
.
Referencia
==
"scsns:Terminate"
)
{
result
=
false
;
break
;
}
}
catch
(
SocketException
ex
)
{
if
(
ex
.
SocketErrorCode
==
SocketError
.
ConnectionAborted
)
{
// La conexión fue anulada por el software en el equipo remoto
log
.
Warning
(
"La conexión fue anulada por el software en el equipo remoto."
);
}
else
{
// Otra excepción de SocketException
log
.
Error
(
"Error de Socket: {error}"
,
ex
);
}
result
=
false
;
break
;
}
catch
(
Exception
e
)
{
log
.
Error
(
"Error : {error}"
,
e
);
result
=
false
;
break
;
}
}
return
result
;
}
//Metodo de respuesta para el pinpad del datafono
public
Respuestas
EjecutarProcesarDatafonoDirecto
()
{
Respuestas
respuestaPinPad
=
null
;
POSBCStatusEventPinPadStatus
posbcEventWaitScreenPaidPad
=
null
;
posbcEventWaitScreenPaidPad
=
new
POSBCStatusEventPinPadStatus
(
1
,
TipoMensaje
.
Event
,
"INFO"
,
"WAITING_FOR_PINPAD_INPUT"
,
"Siga las instrucciones del Datafono"
);
respuestaPinPad
=
new
Respuestas
{
posbcEventWaitScreenPaidPad
};
return
respuestaPinPad
;
}
}
/// <summary>
/// Clase que controla el nivel básico de entrada y salida de mensajes.
/// Extrae la información del mensaje, limpiando la información de control.
/// </summary>
class
Sesion
{
static
ILogger
log
=
Log
.
ForContext
<
Sesion
>();
readonly
static
bool
_isDebug
=
Log
.
IsEnabled
(
LogEventLevel
.
Debug
);
/// <summary>
/// Interpreta arreglo de bytes en mensaje, extrayendo del arreglo de bytes
/// y copiando el contenido en un objeto tipo Trama.
/// </summary>
public
TramaSCO
Entrada
(
byte
[]
buffer
,
int
nroBytes
)
{
if
(
_isDebug
)
{
log
.
Debug
(
"Buffer entrada: >>{subBuffer}<<"
,
buffer
);
}
TramaSCO
trama
=
new
TramaSCO
();
trama
.
Longitud
=
Convert
.
ToUInt32
(
nroBytes
);
log
.
Debug
(
"Longitud mensaje: {long}"
,
trama
.
Longitud
);
// Extrae encabezado. String con patron soeps~<texto>~
string
datos
=
Encoding
.
UTF8
.
GetString
(
buffer
,
0
,
nroBytes
);
int
inicioXML
=
datos
.
IndexOf
(
"<"
);
string
parteEncabezado
=
datos
.
Substring
(
0
,
inicioXML
);
log
.
Debug
(
"Encabezado: {encabezado}"
,
parteEncabezado
);
// Extrae valor campo Session-Id en string.
int
inicioSessionId
=
parteEncabezado
.
IndexOf
(
"Session-Id"
);
int
finSessionId
=
parteEncabezado
.
Substring
(
inicioSessionId
).
IndexOf
(
"|"
);
string
sessionId
=
parteEncabezado
.
Substring
(
inicioSessionId
,
finSessionId
);
string
valorSessionId
=
sessionId
.
Split
(
'='
)[
1
];
trama
.
IdSesion
=
Int32
.
Parse
(
valorSessionId
);
// Extrae valor campo Message-Type en string.
int
inicioMessageType
=
parteEncabezado
.
IndexOf
(
"Message-Type"
);
int
finMessageType
=
parteEncabezado
.
Substring
(
inicioMessageType
).
IndexOf
(
"|"
);
string
messageType
=
parteEncabezado
.
Substring
(
inicioMessageType
,
finMessageType
);
string
valorMessageType
=
messageType
.
Split
(
'='
)[
1
];
trama
.
TipoMensaje
=
TipoMensaje
.
FijaTipoMensaje
(
valorMessageType
);
// Extraer contenido.
trama
.
TextoXML
=
datos
.
Substring
(
inicioXML
);
log
.
Debug
(
"Mensaje string con contenido: {contenido}"
,
trama
.
TextoXML
);
return
trama
;
}
/// <summary>
/// Empaca string de entrada en arreglo de bytes.
/// Agrega encabeado con longitud del mensaje (4 bytes big-endian).
/// No interpreta string de mensaje.
/// <returns>Arreglo bytes con mensaje y cabecera con su longitud en bytes. Mensaje codificado UTF-8.</returns>
/// </summary>
public
byte
[]
Salida
(
TramaSCO
trama
)
{
// Codifica longitud del mensaje en los 4 primeros bytes.
byte
[]
bytesConLongMensaje
=
BitConverter
.
GetBytes
(
trama
.
Longitud
);
// Bytes mas significativos deben ir primero, usa 'big-endian'.
if
(
BitConverter
.
IsLittleEndian
)
Array
.
Reverse
(
bytesConLongMensaje
);
Log
.
Debug
(
"Longitud mensaje: {long} - bytes con longitud: {bytes}"
,
trama
.
Longitud
,
bytesConLongMensaje
);
// Codifica en bytes texto del mensaje.
byte
[]
bytesConMensaje
=
Encoding
.
UTF8
.
GetBytes
(
trama
.
TextoEncabezado
+
trama
.
TextoXML
);
Log
.
Debug
(
"Texto mensaje: '{texto}'"
,
trama
.
TextoEncabezado
+
trama
.
TextoXML
);
// Copia los 2 arreglos de bytes en un arreglo unificado.
byte
[]
bytes
=
new
byte
[
bytesConLongMensaje
.
Length
+
bytesConMensaje
.
Length
];
Buffer
.
BlockCopy
(
bytesConLongMensaje
,
0
,
bytes
,
0
,
bytesConLongMensaje
.
Length
);
Buffer
.
BlockCopy
(
bytesConMensaje
,
0
,
bytes
,
bytesConLongMensaje
.
Length
,
bytesConMensaje
.
Length
);
if
(
_isDebug
)
log
.
Debug
(
"Buffer salida: >>{bytes}<<"
,
bytes
);
return
bytes
;
}
}
/// <summary>
/// Clase que interpreta los mensajes y los transforma en objetos DTO.
/// </summary>
class
Presentacion
{
DirectorioAdaptadoresDTO
_adaptadores
;
CreaDirectorioCmds
_comandos
;
public
Presentacion
(
DirectorioAdaptadoresDTO
adaptadores
,
CreaDirectorioCmds
comandos
)
{
_comandos
=
comandos
;
_adaptadores
=
adaptadores
;
}
/// <summary>
/// Retorna DTO con los datos del mensaje.
/// </summary>
public
IComando
Entrada
(
TramaSCO
mensaje
)
{
IComando
cmd
;
try
{
XmlElement
?
docXml
=
mensaje
.
ContenidoXML
.
DocumentElement
;
if
(
docXml
==
null
)
throw
new
Exception
(
"Contenido XML vacío."
);
XmlNode
?
nodoRaiz
=
docXml
.
SelectSingleNode
(
"."
);
if
(
nodoRaiz
==
null
)
throw
new
Exception
(
"Contenido XML vacío."
);
Log
.
Debug
(
"Mensaje, contenido xml: '{nodoInicial}'"
,
Util
.
ContenidoXmlComoString
(
nodoRaiz
));
// Según el elemento XML raíz, se determina el comando y dto adecuados.
// Se puede considerar incluir en el comando pasar los datos de mensaje
// directamente, sin embargo, esto no se hace así: el comando solo debe
// depender de los datos pasados en una DTO. De esta manera, el comando
// es independizado del formato del mensaje.
// Al adaptador se encarga de tranformar los datos del mensaje en
// valores inicializados en el DTO.
cmd
=
_comandos
.
ObtieneComando
(
nodoRaiz
.
Name
);
IAdaptadorDTO
adaptador
=
_adaptadores
.
ObtieneAdaptador
(
nodoRaiz
.
Name
);
DTOBase
dto
=
adaptador
.
ObtieneDTO
(
mensaje
.
IdSesion
,
mensaje
.
TipoMensaje
,
docXml
);
cmd
.
CargaDTO
(
dto
);
}
catch
(
Exception
e
)
{
Log
.
Error
(
"Excepción procesando Mensaje XML: {e}"
,
e
.
Message
);
ErrorDTO
dto
=
new
ErrorDTO
(
mensaje
.
IdSesion
,
mensaje
.
TipoMensaje
,
$"Mensaje XML con valor nulo o no reconocido: '
{
e
.
Message
}
'"
);
cmd
=
new
ErrorCmd
();
cmd
.
CargaDTO
(
dto
);
}
return
cmd
;
}
}
}
gatewayGK/appsettings.json
0 → 100644
View file @
56f10e15
{
"GatewayConfig"
:
{
"POS"
:
"gk_test"
,
"POS_comment"
:
"Indicates the set of commands to instantiate, according to the type of POS: evapos, tests, gk, etc."
,
"IpSCO"
:
"127.0.0.1"
,
"IpSCO_comment"
:
"SCO IP, local or remote"
,
"PortSCO"
:
6697
,
"PortSCO_comment"
:
"SCO IP Port"
,
"Language"
:
"es"
,
"Language_comment"
:
"Language code as needed by the POS application"
},
"Serilog"
:
{
"Using"
:
[
"Serilog.Sinks.Console"
,
"Serilog.Sinks.File"
],
"MinimumLevel"
:
"Debug"
,
"WriteTo"
:
[
{
"Name"
:
"Console"
,
"Args"
:
{
}
},
{
"Name"
:
"File"
,
"Args"
:
{
"path"
:
"logs/scogateway-log.txt"
,
"rollingInterval"
:
"Day"
}
}
]
},
"Logging"
:
{
"LogLevel"
:
{
"Default"
:
"Debug"
,
"Microsoft.AspNetCore"
:
"Warning"
}
}
}
\ No newline at end of file
gatewayGK/gatewayGK.csproj
0 → 100644
View file @
56f10e15
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<!-- Copiar el appsetting.json al directorio de salida de compilación. -->
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="RestSharp" Version="110.2.0" />
<PackageReference Include="Serilog" Version="3.0.1" />
<PackageReference Include="Serilog.Settings.Configuration" Version="7.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>
</Project>
Prev
1
…
3
4
5
6
7
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment