1#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
2#[serde(rename_all = "PascalCase")]
3pub struct Aplicativo {
4 pub nombre: String,
5 pub url: Option<String>,
6 pub id: String,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
10#[serde(rename_all = "PascalCase")]
11pub struct EnlacePago {
12 pub id: Option<u64>,
13 pub identificador_enlace_comercio: Option<String>,
14 pub nombre_producto: Option<String>,
15 pub descripcion_producto: Option<String>,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
19#[serde(rename_all = "PascalCase")]
20pub struct ClientePagoUrl {
21 pub nombre: String,
22 pub e_mail: String,
23}
24
25fn convert_to_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
26where
27 D: serde::Deserializer<'de>,
28{
29 let s: String = serde::Deserialize::deserialize(deserializer)?;
30 s.parse::<u64>().map_err(serde::de::Error::custom)
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize, Default)]
34#[serde(rename_all = "PascalCase")]
35pub struct ClienteSubscripcion {
36 #[serde(deserialize_with = "convert_to_u64", serialize_with = "serialize_to_string")]
37 pub cantidad_compra: u64,
38 pub e_mail: String,
39 pub id_suscripcion: String,
40 #[serde(deserialize_with = "convert_to_u64", serialize_with = "serialize_to_string")]
41 pub dia_pago_suscripcion: u64,
42}
43
44fn convert_to_f64<'de, D>(deserializer: D) -> Result<f64, D::Error>
45where
46 D: serde::Deserializer<'de>,
47{
48 let s: String = serde::Deserialize::deserialize(deserializer)?;
49 s.parse::<f64>().map_err(serde::de::Error::custom)
50}
51
52fn serialize_to_string<S, T>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
53where
54 S: serde::Serializer,
55 T: std::fmt::Display,
56{
57 serializer.serialize_str(&value.to_string())
58}
59
60#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
61#[serde(rename_all = "PascalCase")]
62pub struct NotificacionWebhook<T> {
63 pub id_cuenta: String,
64 pub fecha_transaccion: chrono::DateTime<chrono::Utc>,
65 #[serde(deserialize_with = "convert_to_f64", serialize_with = "serialize_to_string")]
66 pub monto: f64,
67 pub modulo_utilizado: String,
68 pub forma_pago_utilizada: String,
69 pub id_transaccion: String,
70 pub resultado_transaccion: String,
71 pub codigo_autorizacion: String,
72 pub id_intento_pago: Option<String>,
73 pub cantidad_cuotas: Option<u64>,
74 pub cantidad: u64,
75 pub es_productiva: bool,
76 pub aplicativo: Aplicativo,
77 pub enlace_pago: EnlacePago,
78 pub cliente: T,
79 pub tarjeta: Option<String>,
80 pub es_internacional: bool,
81 pub id_externo: Option<String>,
82 pub id_grupo_tarjetas: Option<String>,
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 const NOTIFICACION_SUBSCRIPCION: &str = r#"{"IdCuenta":"f250b17b-3d76-4221-a843-ced2a23f4f56","FechaTransaccion":"2025-11-05T18:50:00.8073206-06:00","Monto":"1.00","ModuloUtilizado":"API","FormaPagoUtilizada":"PagoNormal","IdTransaccion":"a2e6a75b-1342-47a9-8b5a-0931068e65cf","ResultadoTransaccion":"ExitosaAprobada","CodigoAutorizacion":"94ac59dc-cdde-406c-b96e-0acaa634c867","IdIntentoPago":null,"CantidadCuotas":null,"Cantidad":1,"EsProductiva":false,"Aplicativo":{"Nombre":"AuthenticDoc","Url":null,"Id":"fea52937-0dcf-40a5-b268-eb3d81ee37ef"},"EnlacePago":{"Id":null,"IdentificadorEnlaceComercio":null,"NombreProducto":null,"DescripcionProducto":null},"Cliente":{"CantidadCompra":"1","IdSuscripcion":"afc60537-4f7a-43ca-927b-fed42649cfad","EMail":"technology@illuminodes.com","DiaPagoSuscripcion":"5"},"Tarjeta":null,"EsInternacional":false,"IdExterno":null,"IdGrupoTarjetas":null}"#;
89 const NOTIFICACION_PAGO: &str = r#"{"IdCuenta":"f250b17b-3d76-4221-a843-ced2a23f4f56","FechaTransaccion":"2025-11-05T19:05:41.2574339-06:00","Monto":"7.00","ModuloUtilizado":"BotonPago","FormaPagoUtilizada":"PagoNormal","IdTransaccion":"ce7baafd-444a-4c20-8edb-64dbc4747664","ResultadoTransaccion":"ExitosaAprobada","CodigoAutorizacion":"a0debc29-3737-444e-b66c-a59de0faf4fe","IdIntentoPago":"f8a5cc8d-947a-467e-bf0c-78f6a8e5f075","CantidadCuotas":null,"Cantidad":1,"EsProductiva":false,"Aplicativo":{"Nombre":"AuthenticDoc","Url":null,"Id":"fea52937-0dcf-40a5-b268-eb3d81ee37ef"}, "EnlacePago":{"Id":2507594,"IdentificadorEnlaceComercio":"test_enlace_23","NombreProducto":"Café Premium","DescripcionProducto":null},"Cliente":{"Nombre":"Diego Dominguez","EMail":"technology@illuminodes.com"},"Tarjeta":"0000 0000 0000 1374 ","EsInternacional":false,"IdExterno":"test_enlace_23","IdGrupoTarjetas":null}"#;
90
91 #[test]
92 fn test_deserializacion_subscripcion() {
93 let notificacion: NotificacionWebhook<ClienteSubscripcion> =
94 serde_json::from_str(NOTIFICACION_SUBSCRIPCION).unwrap();
95 println!("{notificacion:#?}",);
96 let string = serde_json::to_string(¬ificacion).unwrap();
97 assert_eq!(string, NOTIFICACION_SUBSCRIPCION);
98 }
99 #[test]
100 fn test_deserializacion_pago() {
101 let notificacion: NotificacionWebhook<ClientePagoUrl> =
102 serde_json::from_str(NOTIFICACION_PAGO).unwrap();
103 println!("{notificacion:?}",);
104
105 let string = serde_json::to_string(¬ificacion).unwrap();
106 assert_eq!(string, NOTIFICACION_PAGO);
107 }
108}