一、前言
本文將基于springboot2.4.0實現快遞物流查詢,物流信息的獲取通過快遞鳥第三方實現
http://www.kdniao.com
二、快遞物流查詢
1、快遞鳥工具類
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
|
@Slf4j public class KdniaoUtil { /** * 快遞查詢接口 * * @param queryDTO 請求參數 * @return 物流信息 * @author zhengqingya * @date 2021/10/25 17:39 */ public static KdniaoApiVO getLogisticInfo(KdniaoApiDTO queryDTO) { KdniaoApiVO kdniaoApiVO = new KdniaoUtil().getLogisticBase(queryDTO); Assert.isTrue( "true" .equals(kdniaoApiVO.getSuccess()), kdniaoApiVO.getReason()); kdniaoApiVO.handleData(); return kdniaoApiVO; } /** * 快遞查詢接口 * * @param queryDTO 請求參數 * @return 物流信息 * @author zhengqingya * @date 2021/10/25 17:39 */ @SneakyThrows (Exception. class ) private KdniaoApiVO getLogisticBase(KdniaoApiDTO queryDTO) { String EBusinessID = queryDTO.getEBusinessID(); String ApiKey = queryDTO.getApiKey(); String ReqURL = queryDTO.getReqURL(); String shipperCode = queryDTO.getShipperCode(); String logisticCode = queryDTO.getLogisticCode(); // 組裝應用級參數 Map<String, String> requestParamMap = Maps.newHashMap(); requestParamMap.put( "shipperCode" , shipperCode); requestParamMap.put( "LogisticCode" , logisticCode); String RequestData = JSON.toJSONString(requestParamMap); // 組裝系統級參數 Map<String, String> params = Maps.newHashMap(); params.put( "RequestData" , this .urlEncoder(RequestData, "UTF-8" )); params.put( "EBusinessID" , EBusinessID); params.put( "RequestType" , "8001" ); String dataSign = this .encrypt(RequestData, ApiKey, "UTF-8" ); params.put( "DataSign" , this .urlEncoder(dataSign, "UTF-8" )); params.put( "DataType" , "2" ); // 以form表單形式提交post請求,post請求體中包含了應用級參數和系統級參數 String resultJson = this .sendPost(ReqURL, params); return JSON.parseObject(resultJson, KdniaoApiVO. class ); } /** * MD5加密 * str 內容 * charset 編碼方式 * * @throws Exception */ @SuppressWarnings ( "unused" ) private String MD5(String str, String charset) throws Exception { MessageDigest md = MessageDigest.getInstance( "MD5" ); md.update(str.getBytes(charset)); byte [] result = md.digest(); StringBuffer sb = new StringBuffer( 32 ); for ( int i = 0 ; i < result.length; i++) { int val = result[i] & 0xff ; if (val <= 0xf ) { sb.append( "0" ); } sb.append(Integer.toHexString(val)); } return sb.toString().toLowerCase(); } /** * base64編碼 * str 內容 * charset 編碼方式 * * @throws UnsupportedEncodingException */ private String base64(String str, String charset) throws UnsupportedEncodingException { String encoded = Base64.encode(str.getBytes(charset)); return encoded; } @SuppressWarnings ( "unused" ) private String urlEncoder(String str, String charset) throws UnsupportedEncodingException { String result = URLEncoder.encode(str, charset); return result; } /** * 電商Sign簽名生成 * content 內容 * keyValue ApiKey * charset 編碼方式 * * @return DataSign簽名 * @throws UnsupportedEncodingException ,Exception */ @SuppressWarnings ( "unused" ) private String encrypt(String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception { if (keyValue != null ) { return base64(MD5(content + keyValue, charset), charset); } return base64(MD5(content, charset), charset); } /** * 向指定 URL 發送POST方法的請求 * url 發送請求的 URL * params 請求的參數集合 * * @return 遠程資源的響應結果 */ @SuppressWarnings ( "unused" ) private String sendPost(String url, Map<String, String> params) { OutputStreamWriter out = null ; BufferedReader in = null ; StringBuilder result = new StringBuilder(); try { URL realUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); // 發送POST請求必須設置如下兩行 conn.setDoOutput( true ); conn.setDoInput( true ); // POST方法 conn.setRequestMethod( "POST" ); // 設置通用的請求屬性 conn.setRequestProperty( "accept" , "*/*" ); conn.setRequestProperty( "connection" , "Keep-Alive" ); conn.setRequestProperty( "user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)" ); conn.setRequestProperty( "Content-Type" , "application/x-www-form-urlencoded" ); conn.connect(); // 獲取URLConnection對象對應的輸出流 out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8" ); // 發送請求參數 if (params != null ) { StringBuilder param = new StringBuilder(); for (Map.Entry<String, String> entry : params.entrySet()) { if (param.length() > 0 ) { param.append( "&" ); } param.append(entry.getKey()); param.append( "=" ); param.append(entry.getValue()); } log.info( "[快遞鳥] 請求參數: [{}]" , param); out.write(param.toString()); } // flush輸出流的緩沖 out.flush(); // 定義BufferedReader輸入流來讀取URL的響應 in = new BufferedReader( new InputStreamReader(conn.getInputStream(), "UTF-8" )); String line; while ((line = in.readLine()) != null ) { result.append(line); } } catch (Exception e) { e.printStackTrace(); } //使用finally塊來關閉輸出流、輸入流 finally { try { if (out != null ) { out.close(); } if (in != null ) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result.toString(); } } |
2、請求類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Data @SuperBuilder @NoArgsConstructor @AllArgsConstructor @ApiModel ( "快遞鳥-物流-查詢base參數" ) public class KdniaoApiBaseDTO { @ApiModelProperty (value = "用戶ID" , required = true , example = "xx" ) private String eBusinessID; @ApiModelProperty (value = "API key" , required = true , example = "xx" ) private String apiKey; @ApiModelProperty (value = "請求url" , required = true , example = "https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx" ) private String reqURL; } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Data @SuperBuilder @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode (callSuper = true ) @ApiModel ( "快遞鳥-物流-查詢參數" ) public class KdniaoApiDTO extends KdniaoApiBaseDTO { @ApiModelProperty (value = "快遞公司編碼" , required = true , example = "ZTO" ) private String shipperCode; @ApiModelProperty (value = "快遞單號" , required = true , example = "xxx" ) private String logisticCode; } |
3、響應結果類
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
|
@Data @SuperBuilder @NoArgsConstructor @AllArgsConstructor @ApiModel ( "快遞鳥-物流-響應參數" ) public class KdniaoApiVO { /** * {@link KdniaoLogisticsStatusEnum } * 增值物流狀態: * 0-暫無軌跡信息 * 1-已攬收 * 2-在途中 * 201-到達派件城市, 202-派件中, 211-已放入快遞柜或驛站, * 3-已簽收 * 301-正常簽收, 302-派件異常后最終簽收, 304-代收簽收, 311-快遞柜或驛站簽收, * 4-問題件 * 401-發貨無信息, 402-超時未簽收, 403-超時未更新, 404-拒收(退件), 405-派件異常, 406-退貨簽收, 407-退貨未簽收, 412-快遞柜或驛站超時未取 */ @ApiModelProperty ( "增值物流狀態" ) private Integer StateEx; @ApiModelProperty ( "增值物流狀態名稱" ) private String statusExName; @ApiModelProperty ( "快遞單號" ) private String LogisticCode; @ApiModelProperty ( "快遞公司編碼" ) private String ShipperCode; @ApiModelProperty ( "失敗原因" ) private String Reason; @ApiModelProperty ( "事件軌跡集" ) private List<TraceItem> Traces; /** * {@link KdniaoLogisticsStatusEnum } */ @ApiModelProperty ( "物流狀態:0-暫無軌跡信息,1-已攬收,2-在途中,3-簽收,4-問題件" ) private Integer State; @ApiModelProperty ( "狀態名稱" ) private String statusName; @ApiModelProperty ( "用戶ID" ) private String EBusinessID; @ApiModelProperty ( "送貨人" ) private String DeliveryMan; @ApiModelProperty ( "送貨人電話號碼" ) private String DeliveryManTel; @ApiModelProperty ( "成功與否 true/false" ) private String Success; @ApiModelProperty ( "所在城市" ) private String Location; @Data @Builder @NoArgsConstructor @AllArgsConstructor @ApiModel ( "事件軌跡集" ) public static class TraceItem { /** * {@link KdniaoLogisticsStatusEnum } */ @ApiModelProperty ( "當前狀態(同StateEx)" ) private Integer Action; @ApiModelProperty ( "狀態名稱" ) private String actionName; @ApiModelProperty ( "描述" ) private String AcceptStation; @ApiModelProperty ( "時間" ) private String AcceptTime; @ApiModelProperty ( "所在城市" ) private String Location; } public void handleData() { this .statusName = KdniaoLogisticsStatusEnum.getEnum( this .State).getDesc(); this .statusExName = KdniaoLogisticsStatusEnum.getEnum( this .StateEx).getDesc(); if (CollectionUtils.isEmpty( this .Traces)) { this .Traces = Lists.newArrayList(); } this .Traces.forEach(item -> item.actionName = KdniaoLogisticsStatusEnum.getEnum(item.Action).getDesc()); } } |
4、物流編碼、狀態枚舉類
溫馨小提示:更多物流編碼值可參考官網快遞鳥接口支持的快遞公司編碼。
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
|
@Getter @AllArgsConstructor public enum KdniaoLogisticsCodeEnum { /** * 申通 */ STO( "STO" , "申通" ), /** * 中通 */ ZTO( "ZTO" , "中通" ), /** * 圓通 */ YTO( "YTO" , "圓通" ), /** * 韻達 */ YD( "YD" , "韻達" ), /** * 順豐 */ SF( "SF" , "順豐" ); /** * 物流編碼 */ private final String code; /** * 物流名 */ private final String name; private static final List<KdniaoLogisticsCodeEnum> LIST = Lists.newArrayList(); static { LIST.addAll(Arrays.asList(KdniaoLogisticsCodeEnum.values())); } /** * 根據值查找相應枚舉 */ @SneakyThrows (Exception. class ) public static KdniaoLogisticsCodeEnum getEnumByName(String name) { for (KdniaoLogisticsCodeEnum itemEnum : LIST) { if (itemEnum.getName().equals(name)) { return itemEnum; } } throw new Exception( "暫無此物流編碼信息,請聯系系統管理員!" ); } } |
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
|
@Getter @AllArgsConstructor public enum KdniaoLogisticsStatusEnum { /** * 暫無軌跡信息 */ NO_TRACE( 0 , "暫無軌跡信息" ), /** * 已攬收 */ HAVE_PAID( 1 , "已攬收" ), /** * 已攬收 ----------------------------------------------------------------------------- */ ON_THE_WAY( 2 , "在途中" ), /** * 到達派件城市 */ ARRIVE_AT_THE_DISPATCH_CITY( 201 , "到達派件城市" ), /** * 派件中 */ IN_THE_DELIVERY( 202 , "派件中" ), /** * 已放入快遞柜或驛站 */ HAS_STORED( 211 , "已放入快遞柜或驛站" ), /** * 簽收 ----------------------------------------------------------------------------- */ SIGN( 3 , "簽收" ), /** * 正常簽收 */ SIGN_NORMAL( 301 , "正常簽收" ), /** * 派件異常后最終簽收 */ SIGN_ABNORMAL( 302 , "派件異常后最終簽收" ), /** * 代收簽收 */ SIGN_COLLECTION( 304 , "代收簽收" ), /** * 快遞柜或驛站簽收 */ SIGN_STORED( 311 , "快遞柜或驛站簽收" ), /** * 問題件 ----------------------------------------------------------------------------- */ PROBLEM_SHIPMENT( 4 , "問題件" ), /** * 發貨無信息 */ DELIVERY_NO_INFO( 401 , "發貨無信息" ), /** * 超時未簽收 */ NO_SIGN_OVER_TIME( 402 , "超時未簽收" ), /** * 超時未更新 */ NOT_UPDATED_DUE_TO_TIMEOUT( 403 , "超時未更新" ), /** * 拒收(退件) */ REJECTION( 404 , "拒收(退件)" ), /** * 派件異常 */ SEND_A_ABNORMAL( 405 , "派件異常" ), /** * 退貨簽收 */ RETURN_TO_SIGN_FOR( 406 , "退貨簽收" ), /** * 退貨未簽收 */ RETURN_NOT_SIGNED_FOR( 407 , "退貨未簽收" ), /** * 快遞柜或驛站超時未取 */ STORED_OVER_TIME( 412 , "快遞柜或驛站超時未取" ), /** * - */ DEFAULT( 0 , "-" ); /** * 狀態 */ private final Integer status; /** * 描述 */ private final String desc; private static final List<KdniaoLogisticsStatusEnum> LIST = Lists.newArrayList(); static { LIST.addAll(Arrays.asList(KdniaoLogisticsStatusEnum.values())); } /** * 根據物流狀態查找相應枚舉 */ public static KdniaoLogisticsStatusEnum getEnum(Integer status) { for (KdniaoLogisticsStatusEnum itemEnum : LIST) { if (itemEnum.getStatus().equals(status)) { return itemEnum; } } return KdniaoLogisticsStatusEnum.DEFAULT; } } |
5、測試api
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Slf4j @RestController @RequestMapping ( "/test" ) @Api (tags = "測試api" ) public class TestController { @ApiOperation ( "查詢物流信息-快遞鳥" ) @GetMapping ( "getLogisticByKdniao" ) public KdniaoApiVO getLogisticByKdniao( @ModelAttribute KdniaoApiDTO params) { return KdniaoUtil.getLogisticInfo(params); } } |
接口文檔 http://127.0.0.1/doc.html
三、本文demo源碼
https://gitee.com/zhengqingya/java-workspace
到此這篇關于SpringBoot實現快遞物流查詢功能(快遞鳥)的文章就介紹到這了,更多相關SpringBoot快遞物流查詢內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/qq_38225558/article/details/121003383