package com.gear.oa.utils; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.gear.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.Arrays; public class BestRouteQueryUtil { // 百世开放平台 partnerID private static final String PARTNER_ID = "7285"; // 百世开放平台接口地址(请替换为实际地址) private static final String API_URL = "http://openapi.800best.com/api-server/ky/api/process"; // 百世开放平台 partnerKey private static final String PARTNER_KEY = "NMGA0BQI"; // 固定参数 private static final String SERVICE_TYPE = "KY_TRACE_QUERY"; /** * 查询百世快递路由 * @param mailNo 运单号 * @return 查询结果OaExpressVo */ public static OaExpressVo queryRoute(String mailNo) { try { // 1. 构造业务数据bizData JSONObject bizData = new JSONObject(); bizData.put("logisticCompanyID", "BESTQJT"); bizData.put("codes", Arrays.asList(mailNo)); String bizDataStr = bizData.toJSONString(); // 2. 生成签名(签名前不做URLEncode) String sign = genSign(bizDataStr, PARTNER_KEY); // 3. 拼接表单参数(此处做URLEncode) StringBuilder formParams = new StringBuilder(); formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8")); formParams.append("&serviceType=").append(URLEncoder.encode(SERVICE_TYPE, "UTF-8")); formParams.append("&sign=").append(URLEncoder.encode(sign, "UTF-8")); formParams.append("&bizData=").append(URLEncoder.encode(bizDataStr, "UTF-8")); String formBody = formParams.toString(); // 4. 发送POST请求(表单格式,UTF-8编码) return doPost(API_URL, formBody); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 百世签名生成方式:MD5(bizData + partnerKey),再转大写 */ private static String genSign(String bizData, String partnerKey) throws Exception { String toSign = bizData + partnerKey; MessageDigest md5 = MessageDigest.getInstance("MD5"); md5.update(toSign.getBytes("UTF-8")); byte[] digest = md5.digest(); StringBuilder sb = new StringBuilder(); for (byte b : digest) { sb.append(String.format("%02x", b)); } return sb.toString(); } /** * 发送POST请求(表单格式,UTF-8编码) */ private static OaExpressVo 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 parseData(sb.toString()); } } else { throw new RuntimeException("HTTP请求失败,状态码:" + code); } } /** * 解析百世快递返回数据,只取第一个轨迹的acceptTime和remark */ public static OaExpressVo parseData(String result) { if (StringUtils.isBlank(result)) { System.out.println("返回结果为空"); return null; } try { JSONObject json = JSON.parseObject(result); Boolean success = json.getBoolean("result"); if (success == null || !success) { System.out.println("查询失败:" + json.getString("resultInfo")); return null; } JSONArray orderTraceList = json.getJSONArray("orderTraceList"); if (orderTraceList == null || orderTraceList.isEmpty()) { System.out.println("无轨迹信息"); return null; } // 只取第一个轨迹的最后一个步骤 JSONObject orderTrace = orderTraceList.getJSONObject(0); JSONArray steps = orderTrace.getJSONArray("steps"); if (steps == null || steps.isEmpty()) { System.out.println("无轨迹步骤信息"); return null; } JSONObject step = steps.getJSONObject(steps.size() - 1); OaExpressVo vo = new OaExpressVo(); vo.setExpressCode(orderTrace.getString("code")); vo.setFirstStatusName(step.getString("remark")); String acceptTimeStr = step.getString("acceptTime"); if (acceptTimeStr != null) { // 假设格式为 yyyy-MM-dd HH:mm:ss try { vo.setAcceptTime(java.sql.Timestamp.valueOf(acceptTimeStr)); } catch (Exception e) { vo.setAcceptTime(null); } } return vo; } catch (Exception e) { e.printStackTrace(); return null; } } // main方法测试 public static void main(String[] args) { String mailNo = "80004559434"; OaExpressVo vo = queryRoute(mailNo); System.out.println(vo); } }