ztk_rust_sdk/pdd/
response.rs

1//! 拼多多平台响应结构体
2//!
3//! 定义拼多多平台 API 的响应结构体
4
5use serde::Deserialize;
6
7/// 拼多多转链响应
8///
9/// convert 接口的响应
10#[derive(Debug, Clone, Deserialize)]
11pub struct PddConvertResponse {
12    /// 转链结果
13    #[serde(default, rename = "goods_zs_unit_generate_response")]
14    pub response: Option<PddConvertResult>,
15}
16
17/// 拼多多转链结果
18#[derive(Debug, Clone, Deserialize)]
19pub struct PddConvertResult {
20    /// 推广短链接 (唤起拼多多 APP)
21    #[serde(default)]
22    pub multi_group_mobile_short_url: Option<String>,
23    /// 双人团推广长链接
24    #[serde(default)]
25    pub multi_group_url: Option<String>,
26    /// 普通长链,微信环境下进入领券页点领券拉起小程序
27    #[serde(default)]
28    pub mobile_url: Option<String>,
29    /// 双人团推广短链接
30    #[serde(default)]
31    pub multi_group_short_url: Option<String>,
32    /// 对应 mobile_url 的短链接
33    #[serde(default)]
34    pub mobile_short_url: Option<String>,
35    /// 推广长链接 (可唤起拼多多 APP)
36    #[serde(default)]
37    pub multi_group_mobile_url: Option<String>,
38    /// 请求 ID
39    #[serde(default)]
40    pub request_id: Option<String>,
41    /// 普通长链,微信环境下优先拉起微信小程序
42    #[serde(default)]
43    pub url: Option<String>,
44    /// 对应 url 的短链接
45    #[serde(default)]
46    pub short_url: Option<String>,
47}
48
49/// 拼多多商品详情响应 (简版)
50///
51/// goods_detail_simple 接口的响应
52#[derive(Debug, Clone, Deserialize)]
53pub struct PddGoodsDetailSimpleResponse {
54    /// 商品详情结果
55    #[serde(default, rename = "goods_basic_detail_response")]
56    pub response: Option<PddGoodsBasicDetailResult>,
57}
58
59/// 拼多多商品基本详情结果
60#[derive(Debug, Clone, Deserialize)]
61pub struct PddGoodsBasicDetailResult {
62    /// 商品列表
63    #[serde(default)]
64    pub goods_list: Option<Vec<PddGoodsBasicItem>>,
65    /// 请求 ID
66    #[serde(default)]
67    pub request_id: Option<String>,
68}
69
70/// 拼多多商品基本信息
71#[derive(Debug, Clone, Deserialize)]
72pub struct PddGoodsBasicItem {
73    /// 商品名称
74    #[serde(default)]
75    pub goods_name: Option<String>,
76    /// 商品主图
77    #[serde(default)]
78    pub goods_pic: Option<String>,
79    /// 商品原价 (单位: 分)
80    #[serde(default)]
81    pub min_normal_price: Option<i64>,
82    /// 商品 ID
83    #[serde(default)]
84    pub goods_id: Option<i64>,
85    /// 拼团价 (单位: 分)
86    #[serde(default)]
87    pub min_group_price: Option<i64>,
88}
89
90/// 拼多多商品详情响应 (详版)
91///
92/// goods_detail_full 接口的响应
93#[derive(Debug, Clone, Deserialize)]
94pub struct PddGoodsDetailFullResponse {
95    /// 商品详情结果
96    #[serde(default, rename = "goods_search_response")]
97    pub response: Option<PddGoodsSearchResult>,
98}
99
100/// 拼多多商品搜索结果
101#[derive(Debug, Clone, Deserialize)]
102pub struct PddGoodsSearchResult {
103    /// 商品列表
104    #[serde(default)]
105    pub goods_list: Option<Vec<PddGoodsDetailItem>>,
106    /// 请求 ID
107    #[serde(default)]
108    pub request_id: Option<String>,
109    /// 总数量
110    #[serde(default)]
111    pub total_count: Option<i64>,
112}
113
114/// 拼多多商品详细信息
115#[derive(Debug, Clone, Deserialize)]
116pub struct PddGoodsDetailItem {
117    /// 商品 ID
118    #[serde(default)]
119    pub goods_id: Option<i64>,
120    /// 商品名称
121    #[serde(default)]
122    pub goods_name: Option<String>,
123    /// 商品描述
124    #[serde(default)]
125    pub goods_desc: Option<String>,
126    /// 商品主图
127    #[serde(default)]
128    pub goods_thumbnail_url: Option<String>,
129    /// 商品轮播图
130    #[serde(default)]
131    pub goods_image_url: Option<String>,
132    /// 商品详情图列表
133    #[serde(default)]
134    pub goods_gallery_urls: Option<Vec<String>>,
135    /// 商品原价 (单位: 分)
136    #[serde(default)]
137    pub min_normal_price: Option<i64>,
138    /// 拼团价 (单位: 分)
139    #[serde(default)]
140    pub min_group_price: Option<i64>,
141    /// 已售数量
142    #[serde(default)]
143    pub sales_tip: Option<String>,
144    /// 佣金比例 (千分比)
145    #[serde(default)]
146    pub promotion_rate: Option<i64>,
147    /// 优惠券面额 (单位: 分)
148    #[serde(default)]
149    pub coupon_discount: Option<i64>,
150    /// 优惠券门槛 (单位: 分)
151    #[serde(default)]
152    pub coupon_min_order_amount: Option<i64>,
153    /// 优惠券剩余数量
154    #[serde(default)]
155    pub coupon_remain_quantity: Option<i64>,
156    /// 优惠券总数量
157    #[serde(default)]
158    pub coupon_total_quantity: Option<i64>,
159    /// 优惠券开始时间 (秒级时间戳)
160    #[serde(default)]
161    pub coupon_start_time: Option<i64>,
162    /// 优惠券结束时间 (秒级时间戳)
163    #[serde(default)]
164    pub coupon_end_time: Option<i64>,
165    /// 店铺 ID
166    #[serde(default)]
167    pub mall_id: Option<i64>,
168    /// 店铺名称
169    #[serde(default)]
170    pub mall_name: Option<String>,
171    /// 店铺类型: 1-个人,2-企业,3-旗舰店,4-专卖店,5-专营店,6-普通店
172    #[serde(default)]
173    pub merchant_type: Option<i32>,
174    /// 商品类目 ID
175    #[serde(default)]
176    pub cat_id: Option<i64>,
177    /// 商品类目名称
178    #[serde(default)]
179    pub cat_name: Option<String>,
180    /// 一级类目 ID
181    #[serde(default, rename = "cat_id_1")]
182    pub cat_id1: Option<i64>,
183    /// 二级类目 ID
184    #[serde(default, rename = "cat_id_2")]
185    pub cat_id2: Option<i64>,
186    /// 三级类目 ID
187    #[serde(default, rename = "cat_id_3")]
188    pub cat_id3: Option<i64>,
189    /// 一级类目名称
190    #[serde(default, rename = "cat_name_1")]
191    pub cat_name1: Option<String>,
192    /// 二级类目名称
193    #[serde(default, rename = "cat_name_2")]
194    pub cat_name2: Option<String>,
195    /// 三级类目名称
196    #[serde(default, rename = "cat_name_3")]
197    pub cat_name3: Option<String>,
198    /// 是否有优惠券
199    #[serde(default)]
200    pub has_coupon: Option<bool>,
201    /// 是否品牌商品
202    #[serde(default)]
203    pub is_brand_goods: Option<bool>,
204    /// 描述评分
205    #[serde(default)]
206    pub desc_txt: Option<String>,
207    /// 物流评分
208    #[serde(default)]
209    pub lgst_txt: Option<String>,
210    /// 服务评分
211    #[serde(default)]
212    pub serv_txt: Option<String>,
213    /// 活动标签
214    #[serde(default)]
215    pub activity_tags: Option<Vec<i32>>,
216}
217
218/// 拼多多订单查询响应
219///
220/// query_orders 接口的响应
221#[derive(Debug, Clone, Deserialize)]
222pub struct PddOrderResponse {
223    /// 订单查询结果
224    #[serde(default, rename = "order_list_get_response")]
225    pub response: Option<PddOrderListResult>,
226}
227
228/// 拼多多订单列表结果
229#[derive(Debug, Clone, Deserialize)]
230pub struct PddOrderListResult {
231    /// 订单总数
232    #[serde(default)]
233    pub total_count: Option<i64>,
234    /// 订单列表
235    #[serde(default)]
236    pub order_list: Option<Vec<PddOrderInfo>>,
237    /// 请求 ID
238    #[serde(default)]
239    pub request_id: Option<String>,
240}
241
242/// 拼多多订单信息
243#[derive(Debug, Clone, Deserialize)]
244pub struct PddOrderInfo {
245    /// 订单号
246    #[serde(default)]
247    pub order_sn: Option<String>,
248    /// 商品 ID
249    #[serde(default)]
250    pub goods_id: Option<i64>,
251    /// 商品名称
252    #[serde(default)]
253    pub goods_name: Option<String>,
254    /// 商品主图
255    #[serde(default)]
256    pub goods_thumbnail_url: Option<String>,
257    /// 商品数量
258    #[serde(default)]
259    pub goods_quantity: Option<i32>,
260    /// 商品价格 (单位: 分)
261    #[serde(default)]
262    pub goods_price: Option<i64>,
263    /// 订单金额 (单位: 分)
264    #[serde(default)]
265    pub order_amount: Option<i64>,
266    /// 佣金金额 (单位: 分)
267    #[serde(default)]
268    pub promotion_amount: Option<i64>,
269    /// 佣金比例 (千分比)
270    #[serde(default)]
271    pub promotion_rate: Option<i64>,
272    /// 订单状态: -1-未支付,0-已支付,1-已成团,2-确认收货,3-审核成功,4-审核失败,5-已经结算,8-非多多进宝商品
273    #[serde(default)]
274    pub order_status: Option<i32>,
275    /// 订单状态描述
276    #[serde(default)]
277    pub order_status_desc: Option<String>,
278    /// 订单创建时间 (秒级时间戳)
279    #[serde(default)]
280    pub order_create_time: Option<i64>,
281    /// 订单支付时间 (秒级时间戳)
282    #[serde(default)]
283    pub order_pay_time: Option<i64>,
284    /// 订单成团时间 (秒级时间戳)
285    #[serde(default)]
286    pub order_group_success_time: Option<i64>,
287    /// 订单确认收货时间 (秒级时间戳)
288    #[serde(default)]
289    pub order_receive_time: Option<i64>,
290    /// 订单结算时间 (秒级时间戳)
291    #[serde(default)]
292    pub order_settle_time: Option<i64>,
293    /// 订单更新时间 (秒级时间戳)
294    #[serde(default)]
295    pub order_modify_at: Option<i64>,
296    /// 自定义参数
297    #[serde(default)]
298    pub custom_parameters: Option<String>,
299    /// 推广位 ID
300    #[serde(default)]
301    pub p_id: Option<String>,
302    /// 是否直推: 1-直推,0-非直推
303    #[serde(default)]
304    pub type_field: Option<i32>,
305    /// 订单类型: 0-普通订单,1-礼金订单
306    #[serde(default)]
307    pub order_type: Option<i32>,
308    /// 店铺 ID
309    #[serde(default)]
310    pub mall_id: Option<i64>,
311    /// 店铺名称
312    #[serde(default)]
313    pub mall_name: Option<String>,
314    /// 类目 ID
315    #[serde(default)]
316    pub cat_ids: Option<Vec<i64>>,
317}
318
319/// 拼多多授权备案响应
320///
321/// authorize 接口的响应
322#[derive(Debug, Clone, Deserialize)]
323pub struct PddAuthorizeResponse {
324    /// 授权备案结果
325    #[serde(default, rename = "rp_promotion_url_generate_response")]
326    pub response: Option<PddAuthorizeResult>,
327}
328
329/// 拼多多授权备案结果
330#[derive(Debug, Clone, Deserialize)]
331pub struct PddAuthorizeResult {
332    /// URL 列表
333    #[serde(default)]
334    pub url_list: Option<Vec<PddAuthorizeUrl>>,
335    /// 请求 ID
336    #[serde(default)]
337    pub request_id: Option<String>,
338}
339
340/// 拼多多授权备案 URL
341#[derive(Debug, Clone, Deserialize)]
342pub struct PddAuthorizeUrl {
343    /// 移动版授权备案地址
344    #[serde(default)]
345    pub mobile_url: Option<String>,
346    /// 电脑版授权备案地址
347    #[serde(default)]
348    pub url: Option<String>,
349}
350
351/// 拼多多授权备案查询响应
352///
353/// authorize_query 接口的响应
354#[derive(Debug, Clone, Deserialize)]
355pub struct PddAuthorizeQueryResponse {
356    /// 授权查询结果
357    #[serde(default, rename = "authority_query_response")]
358    pub response: Option<PddAuthorizeQueryResult>,
359}
360
361/// 拼多多授权备案查询结果
362#[derive(Debug, Clone, Deserialize)]
363pub struct PddAuthorizeQueryResult {
364    /// 绑定状态: 1 表示授权备案成功,其他值表示失败
365    #[serde(default)]
366    pub bind: Option<i32>,
367    /// 请求 ID
368    #[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}