1use serde::{Deserialize, Serialize};
12use serde_qs::Config;
13
14use crate::common_types::{YapayTransactionStatus, CLEAN_WEBHOOK_REGEX};
15
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
18pub struct YapayWebhook {
19 pub token_transaction: String,
20 pub transaction: WebhookTransaction,
21}
22
23impl TryFrom<Vec<u8>> for YapayWebhook {
24 type Error = ();
25
26 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
27 let value_as_string = String::from_utf8(value).map_err(|_| ())?;
28
29 let cfg = Config::new(10, false);
30 cfg.deserialize_bytes::<Self>(clean_non_indexed(&*value_as_string).as_ref())
31 .map_err(|_| ())
32 }
33}
34
35#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
36pub struct WebhookTransaction {
37 pub order_number: String,
38 pub free: String,
39 pub transaction_id: String,
40 pub status_name: String,
41 pub status_id: YapayTransactionStatus,
42 pub date_transaction: String,
43 pub split: String,
44 pub price_payment: String,
45 pub date_payment: String,
46 pub seller_token: String,
47 pub transaction_token: String,
48 pub token_transaction: String,
49 pub price_seller: String,
50 pub price_original: String,
51 pub price_additional: String,
52 pub price_discount: String,
53 pub shipping_price: String,
54 pub shipping_type: String,
55 pub payment_method_id: String,
56 pub payment_method_name: String,
57 pub customer: Customer,
58 pub company: Company,
59 pub payment: Payment,
60 }
63
64#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
65pub struct Product {
66 pub code: Option<String>,
67 pub description: Option<String>,
68 pub extra: Option<String>,
69 pub price_unit: Option<String>,
70 pub quantity: Option<String>,
71}
72
73#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
74pub struct Customer {
75 pub name: String,
76 pub cpf: String,
77 pub cnpj: String,
78 pub email: String,
79 pub token: String,
80 pub address: Address,
81}
82
83#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
84pub struct Address {
85 pub street: String,
86 pub number: String,
87 pub neighborhood: String,
88 pub postal_code: String,
89 pub completion: String,
90 pub city: String,
91 pub state: String,
92}
93
94#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
95pub struct Company {
96 pub name: String,
97 pub cnpj: String,
98 pub cpf: String,
99 pub contact: String,
100 pub url: String,
101 pub token: String,
102}
103
104#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
105pub struct Payment {
106 pub price_payment: String,
107 pub payment_response: String,
108 pub payment_response_code: String,
109 pub url_payment: String,
110 pub date_approval: String,
111 pub selling_message: String,
112 pub number_of_voucher_sales: String,
113 pub split: String,
114 pub date_payment: String,
115 pub payment_method_id: String,
116 pub payment_method_name: String,
117 pub card_id: String,
118 pub number_proccess: String,
119}
120
121pub fn clean_non_indexed(raw: &str) -> String {
122 let mut locs = vec![];
126 for needle in CLEAN_WEBHOOK_REGEX.find_iter(raw) {
127 let start = needle.start();
128 let finish = needle.end();
129 locs.push((start, finish));
130 }
131
132 let first_idx = locs[0].0 + 1;
133 let last_idx = locs.last().map(|&(_, l)| l).unwrap();
134
135 let first_chunk = &raw[..first_idx];
136 let last_chunk = &raw[last_idx..];
137
138 first_chunk.to_string() + last_chunk
139}
140
141#[cfg(test)]
142mod tests {
143 use serde_qs::Config;
144
145 use super::*;
146
147 const fn post_cleaned() -> &'static str {
153 r#"token_transaction=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[order_number]=c2357843-db24-4a06-b&transaction[free]=&transaction[transaction_id]=670863&transaction[status_name]=Aprovada&transaction[status_id]=6&transaction[date_transaction]=2022-05-24T23%3A09%3A21&transaction[split]=3&transaction[price_payment]=104.01&transaction[date_payment]=2022-05-24T23%3A09%3A21&transaction[seller_token]=73047784b36c659&transaction[transaction_token]=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[token_transaction]=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[price_seller]=95.51&transaction[price_original]=100.0&transaction[price_additional]=0.0&transaction[price_discount]=0.0&transaction[shipping_price]=0&transaction[shipping_type]=&transaction[payment_method_id]=4&transaction[payment_method_name]=Mastercard&transaction[customer][name]=Rufino%20Beltrano&transaction[customer][cpf]=41810420814&transaction[customer][cnpj]=&transaction[customer][email]=saskenuba%40gmail.com&transaction[customer][token]=63db358c1adbc36&transaction[company][name]=Yapay%20Sandbox&transaction[company][cnpj]=&transaction[company][cpf]=90357966678&transaction[company][contact]=1112312312&transaction[company][url]=&transaction[company][token]=73047784b36c659&transaction[payment][price_payment]=104.01&transaction[payment][payment_response]=&transaction[payment][payment_response_code]=&transaction[payment][url_payment]=&transaction[payment][date_approval]=24%2F05%2F2022%20-%2023%3A09%3A21&transaction[payment][selling_message]=Mensagem%20de%20venda%20fake&transaction[payment][number_of_voucher_sales]=03076032815324372004&transaction[payment][split]=3&transaction[payment][date_payment]=24%2F05%2F2022&transaction[payment][payment_method_id]=4&transaction[payment][payment_method_name]=Mastercard&transaction[payment][card_id]=64296&transaction[payment][number_proccess]=705036&transaction[customer][address][street]=Av%20Bartholomeu%20de%20carlos&transaction[customer][address][number]=901&transaction[customer][address][neighborhood]=Jardim%20Flor%20da%20Montanha&transaction[customer][address][postal_code]=07097420&transaction[customer][address][completion]=&transaction[customer][address][city]=Guarulhos&transaction[customer][address][state]=SP"#
154 }
155
156 const fn post_not_cleaned() -> &'static str {
158 r#"token_transaction=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[order_number]=c2357843-db24-4a06-b&transaction[free]=&transaction[transaction_id]=670863&transaction[status_name]=Aprovada&transaction[status_id]=6&transaction[date_transaction]=2022-05-24T23%3A09%3A21&transaction[split]=3&transaction[price_payment]=104.01&transaction[date_payment]=2022-05-24T23%3A09%3A21&transaction[seller_token]=73047784b36c659&transaction[transaction_token]=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[token_transaction]=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[price_seller]=95.51&transaction[price_original]=100.0&transaction[price_additional]=0.0&transaction[price_discount]=0.0&transaction[shipping_price]=0&transaction[shipping_type]=&transaction[payment_method_id]=4&transaction[payment_method_name]=Mastercard&transaction[products][][code]=100brl&transaction[products][][description]=100%20reais%20de%20cr%C3%A9dito%20na%20carteira%20MercadoSkin.&transaction[products][][extra]=&transaction[products][][price_unit]=100.0&transaction[products][][quantity]=1.0&transaction[customer][name]=Rufino%20Beltrano&transaction[customer][cpf]=41810420814&transaction[customer][cnpj]=&transaction[customer][email]=saskenuba%40gmail.com&transaction[customer][token]=63db358c1adbc36&transaction[company][name]=Yapay%20Sandbox&transaction[company][cnpj]=&transaction[company][cpf]=90357966678&transaction[company][contact]=1112312312&transaction[company][url]=&transaction[company][token]=73047784b36c659&transaction[payment][price_payment]=104.01&transaction[payment][payment_response]=&transaction[payment][payment_response_code]=&transaction[payment][url_payment]=&transaction[payment][date_approval]=24%2F05%2F2022%20-%2023%3A09%3A21&transaction[payment][selling_message]=Mensagem%20de%20venda%20fake&transaction[payment][number_of_voucher_sales]=03076032815324372004&transaction[payment][split]=3&transaction[payment][date_payment]=24%2F05%2F2022&transaction[payment][payment_method_id]=4&transaction[payment][payment_method_name]=Mastercard&transaction[payment][card_id]=64296&transaction[payment][number_proccess]=705036&transaction[customer][address][street]=Av%20Bartholomeu%20de%20carlos&transaction[customer][address][number]=901&transaction[customer][address][neighborhood]=Jardim%20Flor%20da%20Montanha&transaction[customer][address][postal_code]=07097420&transaction[customer][address][completion]=&transaction[customer][address][city]=Guarulhos&transaction[customer][address][state]=SP"#
159 }
160
161 const fn post_not_cleaned_bytes() -> &'static [u8] {
163 b"token_transaction=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[order_number]=c2357843-db24-4a06-b&transaction[free]=&transaction[transaction_id]=670863&transaction[status_name]=Aprovada&transaction[status_id]=6&transaction[date_transaction]=2022-05-24T23%3A09%3A21&transaction[split]=3&transaction[price_payment]=104.01&transaction[date_payment]=2022-05-24T23%3A09%3A21&transaction[seller_token]=73047784b36c659&transaction[transaction_token]=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[token_transaction]=938ad7ab4b1c6bb227f03b1b0fe08f67&transaction[price_seller]=95.51&transaction[price_original]=100.0&transaction[price_additional]=0.0&transaction[price_discount]=0.0&transaction[shipping_price]=0&transaction[shipping_type]=&transaction[payment_method_id]=4&transaction[payment_method_name]=Mastercard&transaction[products][][code]=100brl&transaction[products][][description]=100%20reais%20de%20cr%C3%A9dito%20na%20carteira%20MercadoSkin.&transaction[products][][extra]=&transaction[products][][price_unit]=100.0&transaction[products][][quantity]=1.0&transaction[customer][name]=Rufino%20Beltrano&transaction[customer][cpf]=41810420814&transaction[customer][cnpj]=&transaction[customer][email]=saskenuba%40gmail.com&transaction[customer][token]=63db358c1adbc36&transaction[company][name]=Yapay%20Sandbox&transaction[company][cnpj]=&transaction[company][cpf]=90357966678&transaction[company][contact]=1112312312&transaction[company][url]=&transaction[company][token]=73047784b36c659&transaction[payment][price_payment]=104.01&transaction[payment][payment_response]=&transaction[payment][payment_response_code]=&transaction[payment][url_payment]=&transaction[payment][date_approval]=24%2F05%2F2022%20-%2023%3A09%3A21&transaction[payment][selling_message]=Mensagem%20de%20venda%20fake&transaction[payment][number_of_voucher_sales]=03076032815324372004&transaction[payment][split]=3&transaction[payment][date_payment]=24%2F05%2F2022&transaction[payment][payment_method_id]=4&transaction[payment][payment_method_name]=Mastercard&transaction[payment][card_id]=64296&transaction[payment][number_proccess]=705036&transaction[customer][address][street]=Av%20Bartholomeu%20de%20carlos&transaction[customer][address][number]=901&transaction[customer][address][neighborhood]=Jardim%20Flor%20da%20Montanha&transaction[customer][address][postal_code]=07097420&transaction[customer][address][completion]=&transaction[customer][address][city]=Guarulhos&transaction[customer][address][state]=SP".as_slice()
164 }
165
166 #[test]
167 fn t_clean_post() {
168 assert_eq!(post_cleaned(), clean_non_indexed(post_not_cleaned()));
169 }
170
171 #[test]
172 fn t_notification() {
173 let cfg = Config::new(10, false);
174 let result = cfg
175 .deserialize_str::<YapayWebhook>(&*clean_non_indexed(post_not_cleaned()))
176 .unwrap();
177
178 eprintln!("result = {:#?}", result);
179 }
180
181 #[test]
182 fn t_notification_bytes() {
183 let de_res = YapayWebhook::try_from(Vec::from(post_not_cleaned_bytes()));
184 assert!(de_res.is_ok());
185 }
186}