1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use serde_xml_rs::to_string;
4
5use std::collections::BTreeMap;
6
7mod util;
8
9#[derive(Serialize, Debug)]
10pub struct Header {
11 #[serde(rename(serialize = "MessageID"))]
12 message_id: i64,
13 #[serde(rename(serialize = "SystemID"))]
14 system_id: String,
15}
16
17#[derive(Serialize, Debug)]
18#[serde(rename(serialize = "RequestInput"))]
19pub struct DHIRequest {
20 #[serde(rename(serialize = "ISO8583-87"))]
21 iso_fields: Value,
22}
23
24impl DHIRequest {
25 pub fn new(iso_obj: Value) -> Self {
26 let mut req = DHIRequest {
27 iso_fields: iso_obj,
28 };
29 if req.iso_fields.get("i007") == None {
30 req.iso_fields["i007"] = serde_json::value::Value::String(util::get_mmddhhmmss());
31 }
32 if req.iso_fields.get("i011") == None {
33 req.iso_fields["i011"] = serde_json::value::Value::String(util::gen_stan());
34 }
35 if req.iso_fields.get("i012") == None {
36 req.iso_fields["i012"] = serde_json::value::Value::String(util::get_hhmmss());
37 }
38 if req.iso_fields.get("i013") == None {
39 req.iso_fields["i013"] = serde_json::value::Value::String(util::get_mmdd());
40 }
41 if req.iso_fields.get("i037") == None {
42 req.iso_fields["i037"] = serde_json::value::Value::String(util::gen_rrn());
43 }
44 req
45 }
46
47 pub fn serialize(&self) -> Result<String, serde_xml_rs::Error> {
48 let serialized = to_string(&self)?;
49 let serialized = format!("{:05}{}", serialized.len(), serialized);
50 Ok(serialized)
51 }
52}
53
54#[derive(Deserialize, Debug)]
55#[serde(rename(deserialize = "Result"))]
56#[serde(rename_all = "PascalCase")]
57pub struct DHIResult {
58 code: i32,
59 description: String,
60}
61
62#[derive(Deserialize, Debug)]
63#[serde(rename(deserialize = "RequestResponse"))]
64pub struct DHIResponse {
65 #[serde(rename(deserialize = "Result"))]
66 res: DHIResult,
67
68 #[serde(rename(deserialize = "ISO8583-87"))]
69 iso_fields: BTreeMap<String, String>,
70}
71
72impl DHIResponse {
73 pub fn serialize(&self) -> Result<String, serde_json::error::Error> {
74 let serialized = serde_json::to_string(&self.iso_fields)?;
75 Ok(serialized)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use serde_xml_rs::from_reader;
83
84 #[test]
85 fn dhi_request_new_existing_fields() {
86 let iso_data = r#"{
87 "i000": "0100",
88 "i002": "555544******0895",
89 "i007": "Transmission date & time ",
90 "i011": "STAN",
91 "i012": "hhmmss",
92 "i013": "MMDD",
93 "i037": "Retrieval Reference Number"
94 }"#;
95
96 let r: DHIRequest = DHIRequest::new(serde_json::from_str(&iso_data).unwrap());
97 assert_eq!(
98 r.iso_fields["i007"], "Transmission date & time ",
99 "i007 original value should be left untouched"
100 );
101 assert_eq!(
102 r.iso_fields["i011"], "STAN",
103 "i011 original value should be left untouched"
104 );
105 assert_eq!(
106 r.iso_fields["i012"], "hhmmss",
107 "i012 original value should be left untouched"
108 );
109 assert_eq!(
110 r.iso_fields["i013"], "MMDD",
111 "i013 original value should be left untouched"
112 );
113 assert_eq!(
114 r.iso_fields["i037"], "Retrieval Reference Number",
115 "Provided RRN should be left untouched"
116 );
117 }
118
119 #[test]
120 fn dhi_response_deserialization() {
121 let s = r##"
122 <?xml version="1.0"?>
123 <RequestResponse>
124 <Header/>
125 <Result><Code>0</Code><Description>OK</Description></Result>
126 <ISO8583-87><i000>0110</i000><i002>555544******0961</i002><i003>300000</i003><i004>000000000000</i004><i007>2804114717</i007><i043><![CDATA[IDDQD AM. 341215574 341215574 MSKRU]]></i043><i120>UD038IR0044444CR009ES0048100IA0103510198686</i120></ISO8583-87>"
127 </RequestResponse>
128 "##;
129
130 let resp: DHIResponse = from_reader(s.as_bytes()).unwrap();
131
132 assert_eq!(resp.res.code, 0);
133 assert_eq!(resp.res.description, "OK");
134
135 assert_eq!(resp.iso_fields["i000"], "0110");
136 assert_eq!(resp.iso_fields["i002"], "555544******0961");
137 assert_eq!(resp.iso_fields["i003"], "300000");
138 assert_eq!(resp.iso_fields["i004"], "000000000000");
139 assert_eq!(resp.iso_fields["i007"], "2804114717");
140 assert_eq!(
141 resp.iso_fields["i043"],
142 "IDDQD AM. 341215574 341215574 MSKRU"
143 );
144 assert_eq!(
145 resp.iso_fields["i120"],
146 "UD038IR0044444CR009ES0048100IA0103510198686"
147 );
148
149 assert_eq!(resp.serialize().unwrap(), "{\"i000\":\"0110\",\"i002\":\"555544******0961\",\"i003\":\"300000\",\"i004\":\"000000000000\",\"i007\":\"2804114717\",\"i043\":\"IDDQD AM. 341215574 341215574 MSKRU\",\"i120\":\"UD038IR0044444CR009ES0048100IA0103510198686\"}");
150 }
151}