feat(oa): 添加顺心捷达快递轨迹查询功能
- 新增 SxjdRouteQueryUtil工具类,用于查询顺心捷达快递轨迹 - 在OaExpressServiceImpl 中集成顺心捷达轨迹查询逻辑 - 实现了顺心捷达快递的轨迹查询和解析功能
This commit is contained in:
@@ -244,6 +244,15 @@ public class OaExpressServiceImpl implements IOaExpressService {
|
||||
oaExpressVo.setLastStatus(stoVo.getFirstStatusName());
|
||||
}
|
||||
}
|
||||
if (expressType.equals("SXJD") && oaExpressVo.getStatus() == 1L) {
|
||||
// 顺心捷达快递轨迹查询
|
||||
String result = SxjdRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode());
|
||||
OaExpressVo sxjdVo = SxjdRouteQueryUtil.parseData(result);
|
||||
if (sxjdVo != null) {
|
||||
oaExpressVo.setLastUpdateTime(sxjdVo.getLastUpdateTime());
|
||||
oaExpressVo.setLastStatus(sxjdVo.getLastStatus());
|
||||
}
|
||||
}
|
||||
OaExpress add = BeanUtil.toBean(oaExpressVo, OaExpress.class);
|
||||
baseMapper.updateById(add);;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
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.vo.OaExpressVo;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
/**
|
||||
* 顺心捷达路由地址查询工具
|
||||
*/
|
||||
public class SxjdRouteQueryUtil {
|
||||
|
||||
// 顺心捷达开放平台配置
|
||||
private static final String APP_KEY = "d2f3f98ebff25410e1280ed89c01be75";
|
||||
private static final String APP_CODE = "000466";
|
||||
private static final String APP_SECRET = "902379cccfa1981f23bfb1833264de87";
|
||||
private static final String SX_CUSTOMER_CODE = "C20001611";
|
||||
|
||||
// 顺心捷达API地址 - 根据环境选择
|
||||
// 测试环境: https://oms.sit.sf-express.com:9010/api/gateway/service
|
||||
// 生产环境: https://oms.sxjdfreight.com/api/gateway/service
|
||||
// 沙箱环境: https://oms.sxjdfreight.com/api/gateway/sandbox
|
||||
private static final String API_URL = "https://oms.sit.sf-express.com:9010/api/gateway/service";
|
||||
|
||||
/**
|
||||
* 查询顺心捷达轨迹
|
||||
* @param waybillId 运单号
|
||||
* @return 查询结果JSON
|
||||
*/
|
||||
public static String queryRoute(String waybillId) {
|
||||
return queryRoute(waybillId, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询顺心捷达轨迹(支持子单号查询)
|
||||
* @param waybillId 运单号
|
||||
* @param queryType 查询方式 1=查询母单轨迹 2=按子单号查询子单轨迹
|
||||
* @param subWaybillId 子运单号
|
||||
* @return 查询结果JSON
|
||||
*/
|
||||
public static String queryRoute(String waybillId, Integer queryType, String subWaybillId) {
|
||||
try {
|
||||
// 1. 构造请求数据
|
||||
JSONObject data = new JSONObject();
|
||||
data.put("waybillId", waybillId);
|
||||
if (queryType != null) {
|
||||
data.put("queryType", queryType);
|
||||
}
|
||||
if (StringUtils.isNotBlank(subWaybillId)) {
|
||||
data.put("subWaybillId", subWaybillId);
|
||||
}
|
||||
|
||||
String dataStr = data.toJSONString();
|
||||
String timestamp = String.valueOf(System.currentTimeMillis());
|
||||
String messageId = UUID.randomUUID().toString();
|
||||
|
||||
// 2. 生成签名
|
||||
String dataDigest = generateDataDigest(dataStr, timestamp);
|
||||
|
||||
// 3. 构造表单参数
|
||||
StringBuilder formParams = new StringBuilder();
|
||||
formParams.append("apiType=SX_QUERY_TRACK");
|
||||
formParams.append("&appKey=").append(URLEncoder.encode(APP_KEY, "UTF-8"));
|
||||
formParams.append("&sxCustomerCode=").append(URLEncoder.encode(SX_CUSTOMER_CODE, "UTF-8"));
|
||||
formParams.append("×tamp=").append(URLEncoder.encode(timestamp, "UTF-8"));
|
||||
formParams.append("&dataDigest=").append(URLEncoder.encode(dataDigest, "UTF-8"));
|
||||
formParams.append("&messageId=").append(URLEncoder.encode(messageId, "UTF-8"));
|
||||
formParams.append("&data=").append(URLEncoder.encode(dataStr, "UTF-8"));
|
||||
|
||||
String formBody = formParams.toString();
|
||||
System.out.println("顺心捷达请求参数:" + formBody);
|
||||
|
||||
// 4. 发送POST请求
|
||||
return doPost(API_URL, formBody);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析顺心捷达返回数据,转为OaExpressVo
|
||||
*/
|
||||
public static OaExpressVo parseData(String result) {
|
||||
if (result == null || result.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
JSONObject json = JSON.parseObject(result);
|
||||
|
||||
// 检查响应状态
|
||||
if (!json.getBooleanValue("success")) {
|
||||
System.err.println("顺心捷达查询失败:" + json.getString("message"));
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject data = json.getJSONObject("data");
|
||||
if (data == null) return null;
|
||||
|
||||
JSONArray trackInfoList = data.getJSONArray("trackInfoList");
|
||||
if (trackInfoList == null || trackInfoList.isEmpty()) return null;
|
||||
|
||||
// 获取最新的轨迹信息(第一条是最新的)
|
||||
JSONObject latestTrack = trackInfoList.getJSONObject(0);
|
||||
|
||||
OaExpressVo vo = new OaExpressVo();
|
||||
vo.setExpressCode(latestTrack.getString("waybillId"));
|
||||
vo.setLastUpdateTime(new Date(latestTrack.getLongValue("operationTime")));
|
||||
vo.setLastStatus(latestTrack.getString("step"));
|
||||
vo.setRemark(latestTrack.getString("trackDesc"));
|
||||
|
||||
return vo;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成数据签名
|
||||
* 签名算法:MD5(data + timestamp + appSecret) 然后Base64编码
|
||||
*/
|
||||
private static String generateDataDigest(String data, String timestamp) throws Exception {
|
||||
String signStr = data + timestamp + APP_SECRET;
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(signStr.getBytes(StandardCharsets.UTF_8));
|
||||
byte[] digest = md.digest();
|
||||
|
||||
// 使用Base64编码,URL安全模式
|
||||
return new String(Base64.encodeBase64URLSafe(digest), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送POST请求
|
||||
*/
|
||||
private static String doPost(String urlStr, String formData) throws Exception {
|
||||
URL url = new URL(urlStr);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
connection.setRequestProperty("Accept", "application/json");
|
||||
connection.setConnectTimeout(10000);
|
||||
connection.setReadTimeout(30000);
|
||||
|
||||
// 发送请求数据
|
||||
try (OutputStream os = connection.getOutputStream()) {
|
||||
byte[] input = formData.getBytes(StandardCharsets.UTF_8);
|
||||
os.write(input, 0, input.length);
|
||||
}
|
||||
|
||||
// 读取响应
|
||||
StringBuilder response = new StringBuilder();
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
}
|
||||
|
||||
connection.disconnect();
|
||||
return response.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为顺心捷达快递
|
||||
* 根据运单号规则判断:通常以S开头
|
||||
*/
|
||||
public static boolean isSxjdExpress(String waybillId) {
|
||||
if (StringUtils.isBlank(waybillId)) {
|
||||
return false;
|
||||
}
|
||||
// 顺心捷达运单号通常以S开头,长度为12位
|
||||
return waybillId.startsWith("S") && waybillId.length() >= 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* MD5编码方法(用于测试)
|
||||
*/
|
||||
public static String md5Encode(String str) {
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
md.update(str.getBytes(StandardCharsets.UTF_8));
|
||||
byte[] digest = md.digest();
|
||||
String r = new String(Base64.encodeBase64URLSafe(digest), StandardCharsets.UTF_8);
|
||||
return r;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试方法
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// 测试签名生成
|
||||
String data = "{ \"customerOrderNo\":\"QW2315464601\", \"orderChannelNo\":\"SE1231322\", \"orderType\":1,\"whetherEwb\":true,\"senderCompany\":\"测试公司890\", \"senderName\":\"测试收\", \"senderMobile\":\"12345667634\", \"senderTel\":\"0755-8658521\", \"senderProv\":\"广东省\", \"senderCity\":\"广州市\", \"senderArea\":\"越秀区\", \"senderAddress\":\"白云街道102号筒子巷\", \"receiverCompany\":\"绿色公司\", \"receiverName\":\"大师傅\", \"receiverTel\":\"021-85685452\", \"receiverMobile\":\"12313213213\", \"receiverProv\":\"广东省\", \"receiverCity\":\"广州市\", \"receiverArea\":\"海珠区\", \"receiverAddress\":\"华洲街道\", \"cargoName\":\"装修物品\", \"totalPackages\":3, \"totalWeight\":12, \"totalVolume\":15, \"pickupWay\":\"送货(不含上楼)\", \"backSignBill\":\"电子回单\", \"remark\":\"客户接入:sxCustomerCode必填\", \"insuranceValue\":800, \"codAmount\":1024, \"fcodAmount\":620, \"getGoodMode\":\"上门接货\", \"orderSource\":\"PDD\",\"productName\":\"顺心包裹\",\"payType\":\"现付\",\"subMailNos\":\"20220426013,20220426014,20220426015\"}";
|
||||
String timestamp = System.currentTimeMillis() + "";
|
||||
String app_secret = "773bebe1bd75680a9e03ee579874d5a2";
|
||||
String dataDigest = md5Encode(data + timestamp + app_secret);
|
||||
System.out.println("测试签名生成:" + dataDigest);
|
||||
|
||||
// 测试轨迹查询
|
||||
String waybillId = "S60201493742";
|
||||
String result = queryRoute(waybillId);
|
||||
System.out.println("顺心捷达原始返回:" + result);
|
||||
|
||||
OaExpressVo vo = parseData(result);
|
||||
if (vo != null) {
|
||||
System.out.println("解析后结果:");
|
||||
System.out.println("运单号:" + vo.getExpressCode());
|
||||
System.out.println("最新状态:" + vo.getLastStatus());
|
||||
System.out.println("更新时间:" + vo.getLastUpdateTime());
|
||||
System.out.println("描述:" + vo.getRemark());
|
||||
} else {
|
||||
System.out.println("解析失败或数据为空");
|
||||
}
|
||||
|
||||
// 测试运单号判断
|
||||
System.out.println("\n运单号判断测试:");
|
||||
System.out.println("S60201493742 是否为顺心捷达:" + isSxjdExpress("S60201493742"));
|
||||
System.out.println("SF1234567890 是否为顺心捷达:" + isSxjdExpress("SF1234567890"));
|
||||
System.out.println("1234567890 是否为顺心捷达:" + isSxjdExpress("1234567890"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user