物流处理 完成了顺丰api对接
This commit is contained in:
224
ruoyi-oa/src/main/java/com/ruoyi/oa/utils/SfRouteQueryUtil.java
Normal file
224
ruoyi-oa/src/main/java/com/ruoyi/oa/utils/SfRouteQueryUtil.java
Normal file
@@ -0,0 +1,224 @@
|
||||
package com.ruoyi.oa.utils;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.ruoyi.oa.domain.OaExpress;
|
||||
import com.ruoyi.oa.domain.vo.OaExpressVo;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Base64;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.UUID;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 顺丰路由地址查询工具
|
||||
*/
|
||||
public class SfRouteQueryUtil {
|
||||
// 顺丰开放平台 partnerID
|
||||
private static final String PARTNER_ID = "YIX65G10";
|
||||
// 顺丰开放平台接口地址
|
||||
private static final String API_URL = "https://bspgw.sf-express.com/std/service";
|
||||
|
||||
// 顺丰开放平台 checkWord
|
||||
private static final String CHECK_WORD = "PkJL4cpEQIUuV1goWvhIznqthletmddX";
|
||||
|
||||
// 顺丰OAuth认证
|
||||
private static final String OAUTH_URL = "https://sfapi.sf-express.com/oauth2/accessToken";
|
||||
|
||||
private static final String GRANT_TYPE = "password";
|
||||
/**
|
||||
* 查询顺丰路由
|
||||
* @param mailNo 顺丰运单号
|
||||
* @return 查询结果JSON
|
||||
*/
|
||||
public static String queryRoute(String mailNo,String phoneNumber) {
|
||||
List<String> mailNos = Arrays.asList(mailNo);
|
||||
try {
|
||||
// 1. 构造业务数据msgData
|
||||
JSONObject msgData = new JSONObject();
|
||||
msgData.put("language", "zh-CN");
|
||||
msgData.put("trackingType", "1"); // 1:运单号 2:订单号
|
||||
msgData.put("methodType", "1"); // 1:标准路由
|
||||
msgData.put("trackingNumber", mailNos);
|
||||
msgData.put("checkPhoneNo", StringUtils.right(phoneNumber, 4));
|
||||
String msgDataStr = msgData.toJSONString();
|
||||
System.out.println(msgDataStr);
|
||||
|
||||
// 2. 公共参数
|
||||
String requestID = UUID.randomUUID().toString().replaceAll("-", "");
|
||||
String serviceCode = "EXP_RECE_SEARCH_ROUTES";
|
||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
// String msgDigest = genSign(msgDataStr, timestamp, CHECK_WORD);
|
||||
// System.out.println(msgDigest);
|
||||
String accessToken = oAuth();
|
||||
System.out.println(accessToken);
|
||||
// 3. 拼接表单参数
|
||||
StringBuilder formParams = new StringBuilder();
|
||||
formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8"));
|
||||
formParams.append("&requestID=").append(URLEncoder.encode(requestID, "UTF-8"));
|
||||
formParams.append("&serviceCode=").append(URLEncoder.encode(serviceCode, "UTF-8"));
|
||||
formParams.append("×tamp=").append(URLEncoder.encode(timestamp, "UTF-8"));
|
||||
formParams.append("&accessToken=").append(URLEncoder.encode(accessToken, "UTF-8"));
|
||||
formParams.append("&msgData=").append(URLEncoder.encode(msgDataStr, "UTF-8"));
|
||||
String formBody = formParams.toString();
|
||||
System.out.println(formBody);
|
||||
|
||||
// 4. 发送POST请求
|
||||
return doPost(API_URL, formBody);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 顺丰msgDigest生成方式:Base64(MD5(URLEncode(msgData+timestamp+partnerId+checkWord)))
|
||||
*/
|
||||
private static String genSign(String msgData, String timestamp, String checkWord) throws Exception {
|
||||
String toVerifyText = msgData + timestamp + checkWord;
|
||||
MessageDigest md5 = MessageDigest.getInstance("MD5");
|
||||
md5.update(toVerifyText.getBytes("UTF-8"));
|
||||
byte[] digest = md5.digest();
|
||||
return Base64.getEncoder().encodeToString(digest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 顺丰OAUTH2
|
||||
*/
|
||||
private static String oAuth() throws Exception {
|
||||
StringBuilder formParams = new StringBuilder();
|
||||
formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8"));
|
||||
formParams.append("&secret=").append(URLEncoder.encode(CHECK_WORD, "UTF-8"));
|
||||
formParams.append("&grantType=").append(URLEncoder.encode(GRANT_TYPE, "UTF-8"));
|
||||
String oauthResponse = doPost(OAUTH_URL, formParams.toString());
|
||||
JSONObject jsonObject = JSON.parseObject(oauthResponse);
|
||||
return jsonObject.getString("accessToken");
|
||||
}
|
||||
/**
|
||||
* 发送POST请求(表单格式)
|
||||
*/
|
||||
private static String doPost(String urlStr, String formBody) throws Exception {
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
|
||||
conn.setDoOutput(true);
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
os.write(formBody.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
int code = conn.getResponseCode();
|
||||
if (code == 200) {
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("HTTP请求失败,状态码:" + code);
|
||||
}
|
||||
}
|
||||
|
||||
public static OaExpressVo parseData(String result) {
|
||||
if (StringUtils.isBlank(result)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 解析最外层的JSON
|
||||
JSONObject outerJson = JSON.parseObject(result);
|
||||
if (outerJson == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 获取apiResultData字符串并再次解析
|
||||
String apiResultDataStr = outerJson.getString("apiResultData");
|
||||
if (StringUtils.isBlank(apiResultDataStr)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject innerJson = JSON.parseObject(apiResultDataStr);
|
||||
if (innerJson == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. 提取所需数据
|
||||
JSONObject msgData = innerJson.getJSONObject("msgData");
|
||||
if (msgData == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONArray routeResps = msgData.getJSONArray("routeResps");
|
||||
if (routeResps == null || routeResps.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject firstRouteResp = routeResps.getJSONObject(0);
|
||||
if (firstRouteResp == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONArray routes = firstRouteResp.getJSONArray("routes");
|
||||
if (routes == null || routes.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject lastRoute = routes.getJSONObject(routes.size() - 1);
|
||||
if (lastRoute == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String acceptTime = lastRoute.getString("acceptTime");
|
||||
String firstStatusName = lastRoute.getString("firstStatusName");
|
||||
|
||||
OaExpressVo oaExpressVo = new OaExpressVo();
|
||||
// 转换日期并设置,如果日期格式不正确则设置为null
|
||||
if (StringUtils.isNotBlank(acceptTime)) {
|
||||
try {
|
||||
Date date = DateUtils.parseDate(acceptTime);
|
||||
oaExpressVo.setAcceptTime(date);
|
||||
} catch (Exception e) {
|
||||
oaExpressVo.setAcceptTime(null);
|
||||
}
|
||||
}
|
||||
oaExpressVo.setFirstStatusName(firstStatusName);
|
||||
System.out.println(acceptTime);
|
||||
System.out.println(firstStatusName);
|
||||
return oaExpressVo;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* main方法测试
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
String mailNo = "SF0282456509537";
|
||||
String result = queryRoute(mailNo,"18012017423");
|
||||
System.out.println(result);
|
||||
OaExpressVo oaExpress = parseData(result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user