wompi_models/
webhook.rs

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(&notificacion).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(&notificacion).unwrap();
106        assert_eq!(string, NOTIFICACION_PAGO);
107    }
108}