1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use std::sync::Arc;

use reqwest::Client;
use yaserde::ser::to_string;

use crate::client::error::{FnsApiError, HttpClientError, OpenApiClientError};
use crate::dto::ticket_request;
use crate::dto::ticket_response::Envelope;
use crate::models::auth_response::{AuthResponse, AuthResponseResult, AuthResponseToken};
use crate::models::ticket::TicketResponse;
use crate::traits::check_query::CheckQueryTrait;
use crate::traits::ticket::TicketResponseTrait;

pub mod error;

pub struct OpenApiClient {
    http_client: Client,
    master_token: String,
    user_token: Option<AuthResponseToken>,
}

impl OpenApiClient {
    pub fn new(master_token: &String) -> Self {
        OpenApiClient {
            http_client: Client::new(),
            master_token: master_token.to_string(),
            user_token: None,
        }
    }
    pub async fn authorize(&mut self) -> Result<AuthResponse, OpenApiClientError> {
        let model = crate::models::auth_request::AuthRequest::new(&self.master_token);
        let auth_request = self.http_client
            .post("https://openapi.nalog.ru:8090/open-api/AuthService/0.1")
            .body(model.to_string())
            .send()
            .await;
        match auth_request {
            Ok(response) => {
                match response.text().await {
                    Ok(xml_string) => {
                        let auth_response = AuthResponse::new(&xml_string);
                        match auth_response.clone() {
                            Ok(res) => {
                                match res.result {
                                    AuthResponseResult::Ok(token) => {
                                        self.user_token = Some(token)
                                    }
                                    _ => {}
                                }
                            }
                            _ => {}
                        };
                        auth_response
                    }
                    Err(error) => {
                        Err(OpenApiClientError::FnsApiError(FnsApiError { message: error.to_string() }))
                    }
                }
            }
            Err(error) => {
                Err(OpenApiClientError::HttpClientError(HttpClientError { message: error.to_string() }))
            }
        }
    }
    pub async fn get_ticket(&self, check_query: impl CheckQueryTrait) -> Result<Arc<dyn TicketResponseTrait>, OpenApiClientError> {
        match &self.user_token {
            None => {
                Err(OpenApiClientError::Error(String::from("Отсутствует FNS-OpenApi-UserToken")))
            }
            Some(user_token) => {
                let ticket_request = ticket_request::Envelope {
                    body: ticket_request::Body {
                        send_message_request: ticket_request::SendMessageRequest {
                            message: ticket_request::Message {
                                get_ticket_request: ticket_request::GetTicketRequest {
                                    get_ticket_info: ticket_request::GetTicketInfo {
                                        sum: check_query.s(),
                                        date: check_query.t(),
                                        r#fn: check_query.r#fn(),
                                        type_operation: check_query.n(),
                                        fiscal_document_id: check_query.i(),
                                        fiscal_sign: check_query.fp(),
                                    }
                                }
                            }
                        }
                    }
                };
                println!("{}", to_string(&ticket_request).unwrap());
                let ticket_info_query = self.http_client.post("https://openapi.nalog.ru:8090/open-api/ais3/KktService/0.1")
                    .body(to_string(&ticket_request).unwrap())
                    .header("FNS-OpenApi-Token", &self.master_token)
                    .header("FNS-OpenApi-UserToken", &user_token.value);
                let ticket_info_response = ticket_info_query.send()
                    .await;
                match ticket_info_response {
                    Ok(response) => {
                        match response.text().await {
                            Ok(text) => {
                                let deserialize = crate::models::serde::Serde::from_xml::<Envelope>(&text);
                                match deserialize {
                                    Ok(dto) => {
                                        TicketResponse::new(dto)
                                    }
                                    Err(xml_deserialization_error) => {
                                        Err(OpenApiClientError::DeserializationError(xml_deserialization_error))
                                    }
                                }
                            }
                            Err(error) => {
                                Err(OpenApiClientError::FnsApiError(FnsApiError { message: error.to_string() }))
                            }
                        }
                    }
                    Err(error) => {
                        Err(OpenApiClientError::HttpClientError(HttpClientError::new(error)))
                    }
                }
            }
        }
        // match ticket_info_response {
        //     Ok(response) => {
        //         let header = response.headers();
        //         let content_type = header[CONTENT_TYPE].to_str().unwrap();
        //         let mut headers = HeaderMap::new();
        //         headers.insert(header::CONTENT_TYPE, content_type.parse().unwrap());
        //         (StatusCode::OK, headers, response.text().await.unwrap().to_string()).into_response()
        //     }
        //     Err(e) => {
        //         (StatusCode::BAD_GATEWAY, e.to_string()).into_response()
        //     }
        // }
    }
}