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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
use serde::{Deserialize, Serialize};
use serde_qs::Config;
use crate::common_types::{TransactionStatus, CLEAN_WEBHOOK_REGEX};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct YapayWebhook {
pub token_transaction: String,
pub transaction: WebhookTransaction,
}
impl TryFrom<Vec<u8>> for YapayWebhook {
type Error = ();
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
let value_as_string = String::from_utf8(value).map_err(|_| ())?;
let cfg = Config::new(10, false);
cfg.deserialize_bytes::<Self>(clean_non_indexed(&*value_as_string).as_ref())
.map_err(|_| ())
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct WebhookTransaction {
pub order_number: String,
pub free: String,
pub transaction_id: String,
pub status_name: String,
pub status_id: TransactionStatus,
pub date_transaction: String,
pub split: String,
pub price_payment: String,
pub date_payment: String,
pub seller_token: String,
pub transaction_token: String,
pub token_transaction: String,
pub price_seller: String,
pub price_original: String,
pub price_additional: String,
pub price_discount: String,
pub shipping_price: String,
pub shipping_type: String,
pub payment_method_id: String,
pub payment_method_name: String,
pub customer: Customer,
pub company: Company,
pub payment: Payment,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Product {
pub code: Option<String>,
pub description: Option<String>,
pub extra: Option<String>,
pub price_unit: Option<String>,
pub quantity: Option<String>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Customer {
pub name: String,
pub cpf: String,
pub cnpj: String,
pub email: String,
pub token: String,
pub address: Address,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Address {
pub street: String,
pub number: String,
pub neighborhood: String,
pub postal_code: String,
pub completion: String,
pub city: String,
pub state: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Company {
pub name: String,
pub cnpj: String,
pub cpf: String,
pub contact: String,
pub url: String,
pub token: String,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Payment {
pub price_payment: String,
pub payment_response: String,
pub payment_response_code: String,
pub url_payment: String,
pub date_approval: String,
pub selling_message: String,
pub number_of_voucher_sales: String,
pub split: String,
pub date_payment: String,
pub payment_method_id: String,
pub payment_method_name: String,
pub card_id: String,
pub number_proccess: String,
}
pub fn clean_non_indexed(raw: &str) -> String {
let mut locs = vec![];
for needle in CLEAN_WEBHOOK_REGEX.find_iter(raw) {
let start = needle.start();
let finish = needle.end();
locs.push((start, finish));
}
let first_idx = locs[0].0 + 1;
let last_idx = locs.last().map(|&(_, l)| l).unwrap();
let first_chunk = &raw[..first_idx];
let last_chunk = &raw[last_idx..];
first_chunk.to_string() + last_chunk
}
#[cfg(test)]
mod tests {
use serde_qs::Config;
use super::*;
const fn post_cleaned() -> &'static str {
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"#
}
const fn post_not_cleaned() -> &'static str {
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"#
}
const fn post_not_cleaned_bytes() -> &'static [u8] {
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()
}
#[test]
fn t_clean_post() {
assert_eq!(post_cleaned(), clean_non_indexed(post_not_cleaned()));
}
#[test]
fn t_notification() {
let cfg = Config::new(10, false);
let result = cfg
.deserialize_str::<YapayWebhook>(&*clean_non_indexed(post_not_cleaned()))
.unwrap();
eprintln!("result = {:#?}", result);
}
#[test]
fn t_notification_bytes() {
let de_res = YapayWebhook::try_from(Vec::from(post_not_cleaned_bytes()));
assert!(de_res.is_ok());
}
}