1use std::error::Error;
2
3static BASE_URL_PRODUCTION: &str =
4 "https://cig.dhl.de/services/production/rest/sendungsverfolgung?xml=";
5static BASE_URL_SANDBOX: &str = "https://cig.dhl.de/services/sandbox/rest/sendungsverfolgung?xml=";
6
7static SANDBOX_XML_PARAM: &str = r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?> <data appname="zt12345" language-code="{language_code}" password="geheim" piece-code="00340434161094022115" request="d-get-piece-detail"/>"#;
8static PRODUCTION_XML_PARAM: &str = r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?> <data appname="{zt_kennung}" language-code="{language_code}" password="{passwd_zt_kennung}" piece-code="{sendungsnummer}" request="d-get-piece-detail"/>"#;
9pub struct SendungsverfolgungBuilder {
42 zt_kennung: Option<String>,
43 passwd_zt_kennung: Option<String>,
44 entwickler_id: Option<String>,
45 passwd_entwicklerportal: Option<String>,
46 language_code: Option<String>,
47 sandbox: Option<bool>,
48 app_id: Option<String>,
49 app_token: Option<String>,
50}
51
52impl Default for SendungsverfolgungBuilder {
53 fn default() -> Self {
54 Self::new()
55 }
56}
57impl SendungsverfolgungBuilder {
58 pub fn new() -> SendungsverfolgungBuilder {
59 SendungsverfolgungBuilder {
60 zt_kennung: None,
61 passwd_zt_kennung: None,
62 entwickler_id: None,
63 passwd_entwicklerportal: None,
64 language_code: Some("de".to_string()),
65 sandbox: None,
66 app_id: None,
67 app_token: None,
68 }
69 }
70
71 pub fn entwickler_id(mut self, entwickler_id: String) -> SendungsverfolgungBuilder {
73 self.entwickler_id = Some(entwickler_id);
74 self
75 }
76 pub fn passwd_entwicklerportal(
78 mut self,
79 passwd_entwicklerportal: String,
80 ) -> SendungsverfolgungBuilder {
81 self.passwd_entwicklerportal = Some(passwd_entwicklerportal);
82 self
83 }
84 pub fn zt_kennung(mut self, zt_kennung: String) -> SendungsverfolgungBuilder {
86 self.zt_kennung = Some(zt_kennung);
87 self
88 }
89 pub fn passwd_zt_kennung(mut self, passwd_zt_kennung: String) -> SendungsverfolgungBuilder {
91 self.passwd_zt_kennung = Some(passwd_zt_kennung);
92 self
93 }
94 pub fn sandbox(mut self, sandbox: bool) -> SendungsverfolgungBuilder {
96 self.sandbox = Some(sandbox);
97 self
98 }
99 pub fn language_code(mut self, language_code: String) -> SendungsverfolgungBuilder {
102 self.language_code = Some(language_code);
103 self
104 }
105 pub fn app_token(mut self, app_token: String) -> SendungsverfolgungBuilder {
107 self.app_token = Some(app_token);
108 self
109 }
110 pub fn app_id(mut self, app_id: String) -> SendungsverfolgungBuilder {
112 self.app_id = Some(app_id);
113 self
114 }
115
116 pub fn build(self) -> Result<Sendungsverfolgung, Box<dyn Error>> {
118 let sandbox = self.sandbox.unwrap_or(true); let entwickler_id = match self.entwickler_id {
120 Some(entwickler_id) => Some(entwickler_id),
121 None => {
122 if sandbox {
123 return Err("Entwickler ID not set. Needet in sandbox mode.".into());
125 } else {
126 None
127 }
128 }
129 };
130 let zt_kennung = match self.zt_kennung {
131 Some(u) => Some(u),
132 None => {
133 if !sandbox {
134 Err("Can't build Sendungsverfolgung, zt_kennung not set. Needet in production mode.")?;
136 }
137 None
138 }
139 };
140 let passwd_zt_kennung = match self.passwd_zt_kennung {
141 Some(p) => Some(p),
142 None => {
143 if !sandbox {
144 return Err("Can't build Sendungsverfolgung, passwd_zt_kennung not set. Needet in production mode.".into());
145 }
146 None
147 }
148 };
149 let passwd_entwicklerportal = match self.passwd_entwicklerportal {
150 Some(p) => Some(p),
151 None => {
152 if sandbox {
153 return Err(
154 "Can't build Sendungsverfolgung, passwd_entwicklerportal not set. Needet in sandbox mode".into(),
155 );
156 }
157 None
158 }
159 };
160 let app_token = match self.app_token {
161 Some(l) => Some(l),
162 None => {
163 if !sandbox {
164 return Err("Can't build Sendungsverfolgung, app_token not set. Needet in production mode.".into());
165 }
166 None
167 }
168 };
169 let app_id = match self.app_id {
170 Some(l) => Some(l),
171 None => {
172 if !sandbox {
173 return Err("Can't build Sendungsverfolgung, app_id not set. Needet in production mode.".into());
174 }
175 None
176 }
177 };
178 let language_code = match self.language_code {
179 Some(l) => l,
180 None => "de".to_string(),
181 };
182 Ok(Sendungsverfolgung {
183 zt_kennung,
184 passwd_zt_kennung,
185 entwickler_id,
186 passwd_entwicklerportal,
187 language_code,
188 sandbox,
189 app_id,
190 app_token,
191 })
192 }
193}
194
195#[derive(Debug)]
228pub struct Sendungsverfolgung {
229 zt_kennung: Option<String>,
230 passwd_zt_kennung: Option<String>,
231 entwickler_id: Option<String>,
232 passwd_entwicklerportal: Option<String>,
233 language_code: String,
234 sandbox: bool,
235 app_id: Option<String>,
236 app_token: Option<String>,
237}
238impl Sendungsverfolgung {
239 pub fn get_piece_detail(
242 &self,
243 sendungsnummer: &str,
244 ) -> Result<std::string::String, Box<dyn Error>> {
245 let mut xml_param = {
246 if self.sandbox {
247 SANDBOX_XML_PARAM.to_string()
248 } else {
249 PRODUCTION_XML_PARAM.to_string()
250 }
251 };
252 xml_param = xml_param.replace("{language_code}", &self.language_code);
253
254 if !self.sandbox {
255 xml_param = xml_param.replace("{sendungsnummer}", sendungsnummer);
256 xml_param = xml_param.replace(
257 "{zt_kennung}",
258 self.zt_kennung
259 .as_ref()
260 .ok_or("zt_kennung not set in production mode.")?,
261 );
262 xml_param = xml_param.replace(
263 "{passwd_zt_kennung}",
264 self.passwd_zt_kennung
265 .as_ref()
266 .ok_or("passwd_zt_kennung not set in production mode.")?,
267 );
268 }
269 let url = {
270 if self.sandbox {
271 BASE_URL_SANDBOX.to_string() + &xml_param
272 } else {
273 BASE_URL_PRODUCTION.to_string() + &xml_param
274 }
275 };
276
277 let url = url::Url::parse(&url)?;
278 let auth_user = {
279 if self.sandbox {
280 self.entwickler_id
281 .as_ref()
282 .ok_or("entwickler_id not set in sandbox mode.")?
283 } else {
284 self.app_id
285 .as_ref()
286 .ok_or("app_id not set in production mode.")?
287 }
288 };
289 let auth_password = {
290 if self.sandbox {
291 self.passwd_entwicklerportal
292 .as_ref()
293 .ok_or("passwd_entwicklerportal not set sandbox mode.")?
294 } else {
295 self.app_token
296 .as_ref()
297 .ok_or("app_token not set in production mode.")?
298 }
299 };
300
301 let client = reqwest::blocking::Client::new();
302 let responce = client
303 .get(url)
304 .basic_auth(auth_user, Some(auth_password))
305 .body("")
306 .send()?;
307 Ok(responce.text()?)
308 }
309}