From f0478a9f9f430ecafe7112d4dd6760e979912778 Mon Sep 17 00:00:00 2001 From: Joshi <3040996759@qq.com> Date: Wed, 23 Jul 2025 15:26:27 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9C=80=E8=A6=81=E5=90=84=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E7=9A=84key=E5=92=8Csecret,=E8=BF=98=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E5=BC=80=E9=80=9A=E7=89=A9=E6=B5=81=E8=AF=A6=E6=83=85=E6=88=96?= =?UTF-8?q?=E8=80=85=E7=89=A9=E6=B5=81=E8=BD=A8=E8=BF=B9=E7=9A=84=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E6=89=8D=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oa/service/impl/OaExpressServiceImpl.java | 13 ++- .../com/ruoyi/oa/utils/StoRouteQueryUtil.java | 103 ++++++++++------- .../com/ruoyi/oa/utils/YdRouteQueryUtil.java | 25 ++-- .../com/ruoyi/oa/utils/YtRouteQueryUtil.java | 107 ++++++++++-------- 4 files changed, 144 insertions(+), 104 deletions(-) diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/OaExpressServiceImpl.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/OaExpressServiceImpl.java index 5eeba76..7136b4a 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/OaExpressServiceImpl.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/service/impl/OaExpressServiceImpl.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.oa.utils.BestRouteQueryUtil; import com.ruoyi.oa.utils.SfRouteQueryUtil; +import com.ruoyi.oa.utils.StoRouteQueryUtil; import com.ruoyi.oa.utils.ZtoTrackQueryUtil; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -19,6 +20,7 @@ import com.ruoyi.oa.mapper.OaExpressMapper; import com.ruoyi.oa.service.IOaExpressService; import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Collection; @@ -162,7 +164,8 @@ public class OaExpressServiceImpl implements IOaExpressService { oaExpressVo.setLastUpdateTime(oaExpressVo1.getAcceptTime()); oaExpressVo.setLastStatus(oaExpressVo1.getFirstStatusName()); } - }else if (expressType.equals("YD") && oaExpressVo.getStatus() == 1L) { + } + if (expressType.equals("YD") && oaExpressVo.getStatus() == 1L) { // 韵达快递轨迹查询 String result = com.ruoyi.oa.utils.YdRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode()); OaExpressVo ydVo = com.ruoyi.oa.utils.YdRouteQueryUtil.parseData(result); @@ -170,7 +173,8 @@ public class OaExpressServiceImpl implements IOaExpressService { oaExpressVo.setLastUpdateTime(ydVo.getLastUpdateTime()); oaExpressVo.setLastStatus(ydVo.getLastStatus()); } - } else if (expressType.equals("YT") && oaExpressVo.getStatus() == 1L) { + } + if (expressType.equals("YT") && oaExpressVo.getStatus() == 1L) { // 圆通快递轨迹查询 String result = com.ruoyi.oa.utils.YtRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode()); OaExpressVo ytVo = com.ruoyi.oa.utils.YtRouteQueryUtil.parseData(result); @@ -178,9 +182,10 @@ public class OaExpressServiceImpl implements IOaExpressService { oaExpressVo.setLastUpdateTime(ytVo.getLastUpdateTime()); oaExpressVo.setLastStatus(ytVo.getLastStatus()); } - } else if (expressType.equals("STO") && oaExpressVo.getStatus() == 1L) { + } + if (expressType.equals("STO") && oaExpressVo.getStatus() == 1L) { // 申通快递轨迹查询 - String result = com.ruoyi.oa.utils.StoRouteQueryUtil.queryRoute(oaExpressVo.getExpressCode()); + String result = StoRouteQueryUtil.queryRoute(Collections.singletonList(oaExpressVo.getExpressCode())); OaExpressVo stoVo = com.ruoyi.oa.utils.StoRouteQueryUtil.parseData(result); if (stoVo != null) { oaExpressVo.setLastUpdateTime(stoVo.getLastUpdateTime()); diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/StoRouteQueryUtil.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/StoRouteQueryUtil.java index ee21a25..171bc9b 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/StoRouteQueryUtil.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/StoRouteQueryUtil.java @@ -1,6 +1,7 @@ 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.codec.binary.Base64; @@ -11,29 +12,47 @@ import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; public class StoRouteQueryUtil { // 请填写你自己的key/secret - private static final String APP_KEY = ""; + private static final String APP_KEY = "CAKWRqzGkVRVVFj"; private static final String APP_SECRET = ""; - private static final String API_URL = "https://open.sto.cn/openapi/traceQuery"; // 申通轨迹查询接口 + private static final String FROM_CODE = ""; // 你的from_code + private static final String API_URL = "http://cloudinter-linkgatewaytest.sto.cn/gateway/link.do"; + + // 申通签名算法 body+appSecret,MD5后Base64 + public static String sign(String body, String secret) { + String text = body + secret; + byte[] md5 = DigestUtils.md5(text); + return Base64.encodeBase64String(md5); + } /** - * 查询申通轨迹 - * @param mailNo 运单号 + * 查询申通轨迹,支持批量单号 + * @param waybillNos 运单号集合 * @return 查询结果JSON */ - public static String queryRoute(String mailNo) { + public static String queryRoute(List waybillNos) { try { - // 构造请求参数,具体参数请参考申通官方文档 + // 构造content参数 + JSONObject content = new JSONObject(); + content.put("order", "asc"); + JSONArray waybillNoList = new JSONArray(); + for (String no : waybillNos) waybillNoList.add(no); + content.put("waybillNoList", waybillNoList); + String contentStr = content.toJSONString(); + + // 构造请求参数 JSONObject params = new JSONObject(); - params.put("appKey", APP_KEY); - params.put("timestamp", System.currentTimeMillis()); - params.put("sign", ""); // 签名算法见官方文档 - params.put("method", "sto.trace.query.common"); - params.put("format", "json"); - params.put("billNo", mailNo); - // 其他参数可根据实际需求补充 + params.put("api_name", "STO_TRACE_QUERY_COMMON"); + params.put("content", contentStr); + params.put("from_appkey", APP_KEY); + params.put("from_code", FROM_CODE); + params.put("to_appkey", "sto_trace_query"); + params.put("to_code", "sto_trace_query"); + params.put("data_digest", sign(contentStr, APP_SECRET)); String jsonParams = params.toJSONString(); URL url = new URL(API_URL); @@ -64,44 +83,44 @@ public class StoRouteQueryUtil { } /** - * 解析申通返回数据,转为OaExpressVo + * 解析申通返回数据,转为OaExpressVo列表 */ public static OaExpressVo parseData(String result) { - if (result == null || result.isEmpty()) return null; - try { - JSONObject json = JSON.parseObject(result); - // 具体字段请根据申通返回格式调整 - JSONObject data = json.getJSONObject("data"); - if (data == null) return null; - OaExpressVo vo = new OaExpressVo(); - vo.setExpressCode(data.getString("billNo")); - vo.setLastStatus(data.getString("status")); - vo.setLastUpdateTime(data.getDate("updateTime")); - // 你可以根据实际返回内容补充更多字段 - return vo; - } catch (Exception e) { - e.printStackTrace(); + if (result == null || result.trim().isEmpty()) { return null; } - } - - // 申通签名算法 body+appSecret,MD5后Base64 - public static String sign(String body, String secret) { - String text = body + secret; - byte[] md5 = DigestUtils.md5(text); - return Base64.encodeBase64String(md5); + try { + JSONObject json = JSON.parseObject(result); + JSONObject data = json.getJSONObject("data"); + if (data == null) return null; + for (String waybillNo : data.keySet()) { + JSONArray arr = data.getJSONArray(waybillNo); + if (arr == null || arr.isEmpty()) continue; + JSONObject last = arr.getJSONObject(arr.size() - 1); + OaExpressVo vo = new OaExpressVo(); + vo.setExpressCode(last.getString("waybillNo")); + vo.setLastUpdateTime(last.getDate("opTime")); + vo.setLastStatus(last.getString("scanType")); + vo.setRemark(last.getString("memo")); + return vo; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; } // main方法测试 public static void main(String[] args) { - String mailNo = "测试单号"; - String body = "{\"orderNo\":\"" + mailNo + "\"}"; - String secret = "你的密钥"; - String sign = sign(body, secret); - System.out.println("申通签名:" + sign); - String result = queryRoute(mailNo); // 你可以根据实际参数完善queryRoute + List waybillNos = new ArrayList<>(); + waybillNos.add("777031922725111"); // 测试单号 + String result = queryRoute(waybillNos); System.out.println("申通原始返回:" + result); OaExpressVo vo = parseData(result); - System.out.println("解析后:" + vo); + if (vo != null) { + System.out.println("解析后:" + vo); + } else { + System.out.println("未解析到数据"); + } } } \ No newline at end of file diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YdRouteQueryUtil.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YdRouteQueryUtil.java index 925464e..848f6d4 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YdRouteQueryUtil.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YdRouteQueryUtil.java @@ -3,14 +3,17 @@ package com.ruoyi.oa.utils; import com.yundasys.OpenApiHttpUtils; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; +import com.alibaba.fastjson2.JSONArray; import com.ruoyi.oa.domain.vo.OaExpressVo; import java.security.MessageDigest; +import java.util.ArrayList; +import java.util.List; public class YdRouteQueryUtil { // 请根据实际环境切换key/secret private static final String APP_KEY = "004160"; // 生产环境 private static final String APP_SECRET = "ac9ee46d749e44b98e7a9e38f3c8f8f3"; // 生产环境 - private static final String API_URL = "https://u-openapi.yundasys.com/openapi/outer/logictis/query"; + private static final String API_URL = "https://openapi.yundaex.com/openapi/outer/logictis/query"; /** * 查询韵达轨迹 @@ -26,22 +29,26 @@ public class YdRouteQueryUtil { * 解析韵达返回数据,转为OaExpressVo */ public static OaExpressVo parseData(String result) { - if (result == null || result.isEmpty()) return null; + if (result == null || result.trim().isEmpty()) { + return null; + } try { JSONObject json = JSON.parseObject(result); - // 具体字段请根据韵达返回格式调整 JSONObject data = json.getJSONObject("data"); if (data == null) return null; + JSONArray steps = data.getJSONArray("steps"); + if (steps == null || steps.isEmpty()) return null; + JSONObject last = steps.getJSONObject(steps.size() - 1); OaExpressVo vo = new OaExpressVo(); - vo.setExpressCode(data.getString("mailNo")); - vo.setLastStatus(data.getString("status")); - vo.setLastUpdateTime(data.getDate("updateTime")); - // 你可以根据实际返回内容补充更多字段 + vo.setExpressCode(data.getString("mailno")); + vo.setLastUpdateTime(last.getDate("time")); + vo.setLastStatus(last.getString("action")); + vo.setRemark(last.getString("description")); return vo; } catch (Exception e) { e.printStackTrace(); - return null; } + return null; } // MD5签名算法(如需自定义签名,可用此方法) @@ -60,7 +67,7 @@ public class YdRouteQueryUtil { // main方法测试 public static void main(String[] args) { - String mailNo = "测试单号"; + String mailNo = "464569453467736"; String result = queryRoute(mailNo); System.out.println("韵达原始返回:" + result); OaExpressVo vo = parseData(result); diff --git a/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YtRouteQueryUtil.java b/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YtRouteQueryUtil.java index 7bd69e7..b7246bc 100644 --- a/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YtRouteQueryUtil.java +++ b/ruoyi-oa/src/main/java/com/ruoyi/oa/utils/YtRouteQueryUtil.java @@ -1,6 +1,7 @@ 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.codec.binary.Base64; @@ -11,32 +12,43 @@ import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; public class YtRouteQueryUtil { - // 请填写你自己的key/secret - private static final String APP_KEY = ""; - private static final String APP_SECRET = ""; - private static final String API_URL = "https://openapi.yto.net.cn/openApi/queryTrack"; // 圆通轨迹查询接口 + // 请填写你自己的密钥、method、v + private static final String SECRET = "TEST"; + private static final String METHOD = "123456"; // 示例 + private static final String VERSION = "v1"; // 示例 + private static final String API_URL = " https://openuat.yto56test.com:6443/open/track_query_adapter/v1/hpLkUl/TEST"; + + // 圆通签名算法 param+method+v+secret,MD5后Base64 + public static String sign(String param, String method, String v, String secret) { + String data = param + method + v; + byte[] md5 = DigestUtils.md5(data + secret); + return Base64.encodeBase64String(md5); + } /** * 查询圆通轨迹 - * @param mailNo 运单号 + * @param number 运单号 * @return 查询结果JSON */ - public static String queryRoute(String mailNo) { + public static String queryRoute(String number) { try { - // 构造请求参数,具体参数请参考圆通官方文档 - JSONObject params = new JSONObject(); - params.put("app_key", APP_KEY); - params.put("timestamp", System.currentTimeMillis()); - params.put("sign", ""); // 签名算法见官方文档 - params.put("method", "yto.marketing.waybill.trace.get"); - params.put("format", "json"); - params.put("user_id", ""); // 用户ID(如有) - params.put("waybill_no", mailNo); - // 其他参数可根据实际需求补充 - - String jsonParams = params.toJSONString(); + String timestamp = String.valueOf(System.currentTimeMillis()); + JSONObject paramObj = new JSONObject(); + paramObj.put("NUMBER", number); + String param = paramObj.toJSONString(); + String sign = sign(param, METHOD, VERSION, SECRET); + JSONObject req = new JSONObject(); + req.put("timestamp", timestamp); + req.put("param", param); + req.put("sign", sign); + req.put("format", "JSON"); + req.put("method", METHOD); + req.put("v", VERSION); + String jsonParams = req.toJSONString(); URL url = new URL(API_URL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); @@ -65,46 +77,43 @@ public class YtRouteQueryUtil { } /** - * 解析圆通返回数据,转为OaExpressVo + * 解析圆通返回数据,转为OaExpressVo列表 */ public static OaExpressVo parseData(String result) { - if (result == null || result.isEmpty()) return null; - try { - JSONObject json = JSON.parseObject(result); - // 具体字段请根据圆通返回格式调整 - JSONObject data = json.getJSONObject("data"); - if (data == null) return null; - OaExpressVo vo = new OaExpressVo(); - vo.setExpressCode(data.getString("mailNo")); - vo.setLastStatus(data.getString("status")); - vo.setLastUpdateTime(data.getDate("updateTime")); - // 你可以根据实际返回内容补充更多字段 - return vo; - } catch (Exception e) { - e.printStackTrace(); + if (result == null || result.trim().isEmpty()) { return null; } - } - - // 圆通签名算法 param+method+v+secret,MD5后Base64 - public static String sign(String param, String method, String v, String secret) { - String data = param + method + v; - byte[] md5 = DigestUtils.md5(data + secret); - return Base64.encodeBase64String(md5); + try { + if (result.trim().startsWith("{")) { + JSONObject json = JSON.parseObject(result); + if (json.containsKey("map")) return null; // 查询为空 + } else if (result.trim().startsWith("[")) { + JSONArray arr = JSON.parseArray(result); + if (arr.isEmpty()) return null; + JSONObject last = arr.getJSONObject(arr.size() - 1); + OaExpressVo vo = new OaExpressVo(); + vo.setExpressCode(last.getString("waybill_No")); + vo.setLastUpdateTime(last.getDate("upload_Time")); + vo.setLastStatus(last.getString("infoContent")); + vo.setRemark(last.getString("processInfo")); + return vo; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; } // main方法测试 public static void main(String[] args) { - String mailNo = "测试单号"; - String param = "{\"NUMBER\":\"" + mailNo + "\"}"; - String method = "yto.marketing.waybill.trace.get"; // 请根据实际接口填写 - String v = "1.01"; // 请根据实际接口填写 - String secret = "你的密钥"; - String sign = sign(param, method, v, secret); - System.out.println("圆通签名:" + sign); - String result = queryRoute(mailNo); // 你可以根据实际参数完善queryRoute + String number = "YT2600227881409"; // 测试单号 + String result = queryRoute(number); System.out.println("圆通原始返回:" + result); OaExpressVo vo = parseData(result); - System.out.println("解析后:" + vo); + if (vo != null) { + System.out.println("解析后:" + vo); + } else { + System.out.println("解析后无数据"); + } } } \ No newline at end of file