1use serde::Deserialize;
6
7#[derive(Debug, Clone, Deserialize)]
11pub struct PddConvertResponse {
12 #[serde(default, rename = "goods_zs_unit_generate_response")]
14 pub response: Option<PddConvertResult>,
15}
16
17#[derive(Debug, Clone, Deserialize)]
19pub struct PddConvertResult {
20 #[serde(default)]
22 pub multi_group_mobile_short_url: Option<String>,
23 #[serde(default)]
25 pub multi_group_url: Option<String>,
26 #[serde(default)]
28 pub mobile_url: Option<String>,
29 #[serde(default)]
31 pub multi_group_short_url: Option<String>,
32 #[serde(default)]
34 pub mobile_short_url: Option<String>,
35 #[serde(default)]
37 pub multi_group_mobile_url: Option<String>,
38 #[serde(default)]
40 pub request_id: Option<String>,
41 #[serde(default)]
43 pub url: Option<String>,
44 #[serde(default)]
46 pub short_url: Option<String>,
47}
48
49#[derive(Debug, Clone, Deserialize)]
53pub struct PddGoodsDetailSimpleResponse {
54 #[serde(default, rename = "goods_basic_detail_response")]
56 pub response: Option<PddGoodsBasicDetailResult>,
57}
58
59#[derive(Debug, Clone, Deserialize)]
61pub struct PddGoodsBasicDetailResult {
62 #[serde(default)]
64 pub goods_list: Option<Vec<PddGoodsBasicItem>>,
65 #[serde(default)]
67 pub request_id: Option<String>,
68}
69
70#[derive(Debug, Clone, Deserialize)]
72pub struct PddGoodsBasicItem {
73 #[serde(default)]
75 pub goods_name: Option<String>,
76 #[serde(default)]
78 pub goods_pic: Option<String>,
79 #[serde(default)]
81 pub min_normal_price: Option<i64>,
82 #[serde(default)]
84 pub goods_id: Option<i64>,
85 #[serde(default)]
87 pub min_group_price: Option<i64>,
88}
89
90#[derive(Debug, Clone, Deserialize)]
94pub struct PddGoodsDetailFullResponse {
95 #[serde(default, rename = "goods_search_response")]
97 pub response: Option<PddGoodsSearchResult>,
98}
99
100#[derive(Debug, Clone, Deserialize)]
102pub struct PddGoodsSearchResult {
103 #[serde(default)]
105 pub goods_list: Option<Vec<PddGoodsDetailItem>>,
106 #[serde(default)]
108 pub request_id: Option<String>,
109 #[serde(default)]
111 pub total_count: Option<i64>,
112}
113
114#[derive(Debug, Clone, Deserialize)]
116pub struct PddGoodsDetailItem {
117 #[serde(default)]
119 pub goods_id: Option<i64>,
120 #[serde(default)]
122 pub goods_name: Option<String>,
123 #[serde(default)]
125 pub goods_desc: Option<String>,
126 #[serde(default)]
128 pub goods_thumbnail_url: Option<String>,
129 #[serde(default)]
131 pub goods_image_url: Option<String>,
132 #[serde(default)]
134 pub goods_gallery_urls: Option<Vec<String>>,
135 #[serde(default)]
137 pub min_normal_price: Option<i64>,
138 #[serde(default)]
140 pub min_group_price: Option<i64>,
141 #[serde(default)]
143 pub sales_tip: Option<String>,
144 #[serde(default)]
146 pub promotion_rate: Option<i64>,
147 #[serde(default)]
149 pub coupon_discount: Option<i64>,
150 #[serde(default)]
152 pub coupon_min_order_amount: Option<i64>,
153 #[serde(default)]
155 pub coupon_remain_quantity: Option<i64>,
156 #[serde(default)]
158 pub coupon_total_quantity: Option<i64>,
159 #[serde(default)]
161 pub coupon_start_time: Option<i64>,
162 #[serde(default)]
164 pub coupon_end_time: Option<i64>,
165 #[serde(default)]
167 pub mall_id: Option<i64>,
168 #[serde(default)]
170 pub mall_name: Option<String>,
171 #[serde(default)]
173 pub merchant_type: Option<i32>,
174 #[serde(default)]
176 pub cat_id: Option<i64>,
177 #[serde(default)]
179 pub cat_name: Option<String>,
180 #[serde(default, rename = "cat_id_1")]
182 pub cat_id1: Option<i64>,
183 #[serde(default, rename = "cat_id_2")]
185 pub cat_id2: Option<i64>,
186 #[serde(default, rename = "cat_id_3")]
188 pub cat_id3: Option<i64>,
189 #[serde(default, rename = "cat_name_1")]
191 pub cat_name1: Option<String>,
192 #[serde(default, rename = "cat_name_2")]
194 pub cat_name2: Option<String>,
195 #[serde(default, rename = "cat_name_3")]
197 pub cat_name3: Option<String>,
198 #[serde(default)]
200 pub has_coupon: Option<bool>,
201 #[serde(default)]
203 pub is_brand_goods: Option<bool>,
204 #[serde(default)]
206 pub desc_txt: Option<String>,
207 #[serde(default)]
209 pub lgst_txt: Option<String>,
210 #[serde(default)]
212 pub serv_txt: Option<String>,
213 #[serde(default)]
215 pub activity_tags: Option<Vec<i32>>,
216}
217
218#[derive(Debug, Clone, Deserialize)]
222pub struct PddOrderResponse {
223 #[serde(default, rename = "order_list_get_response")]
225 pub response: Option<PddOrderListResult>,
226}
227
228#[derive(Debug, Clone, Deserialize)]
230pub struct PddOrderListResult {
231 #[serde(default)]
233 pub total_count: Option<i64>,
234 #[serde(default)]
236 pub order_list: Option<Vec<PddOrderInfo>>,
237 #[serde(default)]
239 pub request_id: Option<String>,
240}
241
242#[derive(Debug, Clone, Deserialize)]
244pub struct PddOrderInfo {
245 #[serde(default)]
247 pub order_sn: Option<String>,
248 #[serde(default)]
250 pub goods_id: Option<i64>,
251 #[serde(default)]
253 pub goods_name: Option<String>,
254 #[serde(default)]
256 pub goods_thumbnail_url: Option<String>,
257 #[serde(default)]
259 pub goods_quantity: Option<i32>,
260 #[serde(default)]
262 pub goods_price: Option<i64>,
263 #[serde(default)]
265 pub order_amount: Option<i64>,
266 #[serde(default)]
268 pub promotion_amount: Option<i64>,
269 #[serde(default)]
271 pub promotion_rate: Option<i64>,
272 #[serde(default)]
274 pub order_status: Option<i32>,
275 #[serde(default)]
277 pub order_status_desc: Option<String>,
278 #[serde(default)]
280 pub order_create_time: Option<i64>,
281 #[serde(default)]
283 pub order_pay_time: Option<i64>,
284 #[serde(default)]
286 pub order_group_success_time: Option<i64>,
287 #[serde(default)]
289 pub order_receive_time: Option<i64>,
290 #[serde(default)]
292 pub order_settle_time: Option<i64>,
293 #[serde(default)]
295 pub order_modify_at: Option<i64>,
296 #[serde(default)]
298 pub custom_parameters: Option<String>,
299 #[serde(default)]
301 pub p_id: Option<String>,
302 #[serde(default)]
304 pub type_field: Option<i32>,
305 #[serde(default)]
307 pub order_type: Option<i32>,
308 #[serde(default)]
310 pub mall_id: Option<i64>,
311 #[serde(default)]
313 pub mall_name: Option<String>,
314 #[serde(default)]
316 pub cat_ids: Option<Vec<i64>>,
317}
318
319#[derive(Debug, Clone, Deserialize)]
323pub struct PddAuthorizeResponse {
324 #[serde(default, rename = "rp_promotion_url_generate_response")]
326 pub response: Option<PddAuthorizeResult>,
327}
328
329#[derive(Debug, Clone, Deserialize)]
331pub struct PddAuthorizeResult {
332 #[serde(default)]
334 pub url_list: Option<Vec<PddAuthorizeUrl>>,
335 #[serde(default)]
337 pub request_id: Option<String>,
338}
339
340#[derive(Debug, Clone, Deserialize)]
342pub struct PddAuthorizeUrl {
343 #[serde(default)]
345 pub mobile_url: Option<String>,
346 #[serde(default)]
348 pub url: Option<String>,
349}
350
351#[derive(Debug, Clone, Deserialize)]
355pub struct PddAuthorizeQueryResponse {
356 #[serde(default, rename = "authority_query_response")]
358 pub response: Option<PddAuthorizeQueryResult>,
359}
360
361#[derive(Debug, Clone, Deserialize)]
363pub struct PddAuthorizeQueryResult {
364 #[serde(default)]
366 pub bind: Option<i32>,
367 #[serde(default)]
369 pub request_id: Option<String>,
370}
371
372#[cfg(test)]
373mod tests {
374 use super::*;
375
376 #[test]
377 fn test_pdd_convert_response_deserialize() {
378 let json = r#"{
379 "goods_zs_unit_generate_response": {
380 "multi_group_mobile_short_url": "https://p.pinduoduo.com/2sB0eGpK",
381 "mobile_url": "https://mobile.yangkeduo.com/duo_coupon_landing.html",
382 "short_url": "https://p.pinduoduo.com/bOL0pBPH",
383 "request_id": "16942627387113959"
384 }
385 }"#;
386
387 let response: PddConvertResponse = serde_json::from_str(json).unwrap();
388 assert!(response.response.is_some());
389 let result = response.response.unwrap();
390 assert_eq!(
391 result.multi_group_mobile_short_url,
392 Some("https://p.pinduoduo.com/2sB0eGpK".to_string())
393 );
394 assert_eq!(
395 result.short_url,
396 Some("https://p.pinduoduo.com/bOL0pBPH".to_string())
397 );
398 }
399
400 #[test]
401 fn test_pdd_goods_detail_simple_response_deserialize() {
402 let json = r#"{
403 "goods_basic_detail_response": {
404 "goods_list": [{
405 "goods_name": "测试商品",
406 "goods_pic": "https://img.pddpic.com/test.jpeg",
407 "min_normal_price": 1900,
408 "goods_id": 453581732819,
409 "min_group_price": 990
410 }],
411 "request_id": "16942480364163726"
412 }
413 }"#;
414
415 let response: PddGoodsDetailSimpleResponse = serde_json::from_str(json).unwrap();
416 assert!(response.response.is_some());
417 let result = response.response.unwrap();
418 assert!(result.goods_list.is_some());
419 let goods = result.goods_list.unwrap();
420 assert_eq!(goods.len(), 1);
421 assert_eq!(goods[0].goods_name, Some("测试商品".to_string()));
422 assert_eq!(goods[0].goods_id, Some(453581732819));
423 }
424
425 #[test]
426 fn test_pdd_order_response_deserialize() {
427 let json = r#"{
428 "order_list_get_response": {
429 "total_count": 1,
430 "order_list": [{
431 "order_sn": "123456789",
432 "goods_id": 453581732819,
433 "goods_name": "测试商品",
434 "order_status": 2,
435 "order_amount": 9900,
436 "promotion_amount": 990
437 }],
438 "request_id": "16942626445817516"
439 }
440 }"#;
441
442 let response: PddOrderResponse = serde_json::from_str(json).unwrap();
443 assert!(response.response.is_some());
444 let result = response.response.unwrap();
445 assert_eq!(result.total_count, Some(1));
446 assert!(result.order_list.is_some());
447 let orders = result.order_list.unwrap();
448 assert_eq!(orders.len(), 1);
449 assert_eq!(orders[0].order_sn, Some("123456789".to_string()));
450 assert_eq!(orders[0].order_status, Some(2));
451 }
452
453 #[test]
454 fn test_pdd_authorize_response_deserialize() {
455 let json = r#"{
456 "rp_promotion_url_generate_response": {
457 "url_list": [{
458 "mobile_url": "https://mobile.yangkeduo.com/duo_coupon_landing.html_",
459 "url": "https://mobile.yangkeduo.com/duo_coupon_landing.html"
460 }],
461 "request_id": "16942480613190789"
462 }
463 }"#;
464
465 let response: PddAuthorizeResponse = serde_json::from_str(json).unwrap();
466 assert!(response.response.is_some());
467 let result = response.response.unwrap();
468 assert!(result.url_list.is_some());
469 let urls = result.url_list.unwrap();
470 assert_eq!(urls.len(), 1);
471 assert!(urls[0].mobile_url.is_some());
472 }
473
474 #[test]
475 fn test_pdd_authorize_query_response_deserialize() {
476 let json = r#"{
477 "authority_query_response": {
478 "bind": 1,
479 "request_id": "16942467231374196"
480 }
481 }"#;
482
483 let response: PddAuthorizeQueryResponse = serde_json::from_str(json).unwrap();
484 assert!(response.response.is_some());
485 let result = response.response.unwrap();
486 assert_eq!(result.bind, Some(1));
487 }
488
489 #[test]
490 fn test_response_with_missing_fields() {
491 let json = r#"{"order_list_get_response": {"total_count": 0}}"#;
492
493 let response: PddOrderResponse = serde_json::from_str(json).unwrap();
494 assert!(response.response.is_some());
495 let result = response.response.unwrap();
496 assert_eq!(result.total_count, Some(0));
497 assert!(result.order_list.is_none());
498 }
499}