• Java之各平台快递对接


    韵达快递、安能快递、百世快递、中国邮政快递、EMS、德邦快递、极兔快递、顺丰快递、申通快递、众邮快递、圆通快递、中通快递
     
    Express接口类 

    1. public interface Express {
    2. /**
    3. * 快递编码
    4. *
    5. * @return String
    6. */
    7. String expressCode();
    8. /**
    9. * 根据快递编码相关信息查询快递信息
    10. *
    11. * @param request 请求参数
    12. * @return ExpressSearchResponse
    13. * @throws NoSuchAlgorithmException
    14. */
    15. ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException;
    16. }

    SelectExpress类

    1. import org.springframework.boot.CommandLineRunner;
    2. import org.springframework.context.ApplicationContext;
    3. import org.springframework.stereotype.Service;
    4. import javax.annotation.Resource;
    5. import java.util.HashMap;
    6. import java.util.Map;
    7. @Service
    8. public class SelectExpress implements CommandLineRunner {
    9. @Resource
    10. private ApplicationContext applicationContext;
    11. private Map expressMap = new HashMap<>();
    12. /**
    13. * 根据名字返回相应的实现类
    14. *
    15. * @param code 快递公司编码
    16. * @return 实现类
    17. */
    18. public Express get(String code) {
    19. return expressMap.get(code);
    20. }
    21. @Override
    22. public void run(String... args) throws Exception {
    23. applicationContext.getBeansOfType(Express.class).values()
    24. .forEach(express -> expressMap.put(express.expressCode(), express));
    25. }
    26. }

    ExpressSearchRequest请求类

    1. import io.swagger.annotations.ApiModelProperty;
    2. import lombok.Data;
    3. import java.io.Serializable;
    4. @Data
    5. public class ExpressSearchRequest implements Serializable {
    6. private static final long serialVersionUID = -880253965590928905L;
    7. @ApiModelProperty(value = "真实物流单号")
    8. private String logisticsNo;
    9. @ApiModelProperty(value = "物流公司名称", hidden = true)
    10. private String expressName;
    11. @ApiModelProperty(value = "物流公司编码", hidden = true)
    12. private String expressCode;
    13. @ApiModelProperty(value = "订单编码", hidden = true)
    14. private String orderNo;
    15. @ApiModelProperty(value = "收件人姓名", hidden = true)
    16. private String receiverName;
    17. @ApiModelProperty(value = "收件人手机号", hidden = true)
    18. private String receiverMobile;
    19. @ApiModelProperty(value = "收人地址:省份名称", hidden = true)
    20. private String provinceName;
    21. @ApiModelProperty(value = "收人地址:地市名称", hidden = true)
    22. private String cityName;
    23. @ApiModelProperty(value = "收人地址:区县名称", hidden = true)
    24. private String districtName;
    25. @ApiModelProperty(value = "收件人详细地址", hidden = true)
    26. private String detailAddress;
    27. }

     ExpressSearchResponse返回类

    1. import io.swagger.annotations.ApiModelProperty;
    2. import lombok.Data;
    3. import java.io.Serializable;
    4. import java.util.ArrayList;
    5. import java.util.List;
    6. @Data
    7. public class ExpressSearchResponse implements Serializable {
    8. private static final long serialVersionUID = 8570085965157271803L;
    9. @ApiModelProperty("快递公司名称")
    10. private String logisticsName = "";
    11. @ApiModelProperty("快递单号")
    12. private String logisticsNo = "";
    13. @ApiModelProperty("描述")
    14. List descList = new ArrayList<>();
    15. }

    ExpressDescDTO返回类子类 

    1. import io.swagger.annotations.ApiModelProperty;
    2. import lombok.Data;
    3. import java.io.Serializable;
    4. @Data
    5. public class ExpressDescDTO implements Serializable {
    6. private static final long serialVersionUID = 2774275564551643616L;
    7. @ApiModelProperty("轨迹描述")
    8. private String desc = "";
    9. @ApiModelProperty("日期")
    10. private String date = "";
    11. }

     ResponseController返回结果封装类

    1. import com.alibaba.fastjson.JSONArray;
    2. import com.alibaba.fastjson.JSONObject;
    3. import com.jumi.microservice.warehouse.entity.dto.ExpressDescDTO;
    4. import com.jumi.microservice.warehouse.entity.dto.ExpressSearchRequest;
    5. import com.jumi.microservice.warehouse.entity.dto.ExpressSearchResponse;
    6. import java.text.SimpleDateFormat;
    7. import java.util.ArrayList;
    8. import java.util.Comparator;
    9. import java.util.Date;
    10. import java.util.List;
    11. import java.util.stream.Collectors;
    12. public class ResponseController {
    13. /**
    14. * 校验返回结果
    15. *
    16. * @param jsonArray json数组
    17. * @param request 请求参数
    18. * @return ExpressSearchResponse
    19. */
    20. public ExpressSearchResponse checkResult(JSONArray jsonArray, ExpressSearchRequest request) {
    21. ExpressSearchResponse expressSearchResponse = new ExpressSearchResponse();
    22. expressSearchResponse.setLogisticsName(request.getExpressName());
    23. expressSearchResponse.setLogisticsNo(request.getLogisticsNo());
    24. if (jsonArray == null || jsonArray.isEmpty()) {
    25. expressSearchResponse.setDescList(new ArrayList<>());
    26. }
    27. return expressSearchResponse;
    28. }
    29. /**
    30. * 组装返回实体类
    31. *
    32. * @param expressSearchResponse 返回信息
    33. * @param jsonArr json数组
    34. * @param descKey 描述
    35. * @param dateKey 时间
    36. * @return 组装返回实体类
    37. */
    38. public ExpressSearchResponse controller(ExpressSearchResponse expressSearchResponse, JSONArray jsonArr,
    39. String descKey, String dateKey) {
    40. if (jsonArr == null || jsonArr.isEmpty()) {
    41. return expressSearchResponse;
    42. }
    43. List list = new ArrayList<>();
    44. for (Object j : jsonArr) {
    45. JSONObject json = JSONObject.parseObject(j.toString());
    46. ExpressDescDTO expressDescDTO = new ExpressDescDTO();
    47. if (json.getString(descKey) == null || json.getString(dateKey) == null) {
    48. return expressSearchResponse;
    49. }
    50. expressDescDTO.setDesc(json.getString(descKey));
    51. expressDescDTO.setDate(json.getString(dateKey));
    52. list.add(expressDescDTO);
    53. }
    54. list = list.stream().sorted(Comparator.comparing(ExpressDescDTO::getDate).reversed()).collect(Collectors.toList());
    55. expressSearchResponse.setDescList(list);
    56. return expressSearchResponse;
    57. }
    58. /**
    59. * 组装返回实体类
    60. *
    61. * @param expressSearchResponse 返回信息
    62. * @param jsonArr json数组
    63. * @param descKey 描述
    64. * @param dateKey 时间
    65. * @return 组装返回实体类
    66. */
    67. public ExpressSearchResponse controllerZto(ExpressSearchResponse expressSearchResponse, JSONArray jsonArr,
    68. String descKey, String dateKey) {
    69. if (jsonArr == null || jsonArr.isEmpty()) {
    70. return expressSearchResponse;
    71. }
    72. List list = new ArrayList<>();
    73. for (Object j : jsonArr) {
    74. JSONObject json = JSONObject.parseObject(j.toString());
    75. ExpressDescDTO expressDescDTO = new ExpressDescDTO();
    76. if (json.getString(descKey) == null || json.getString(dateKey) == null) {
    77. return expressSearchResponse;
    78. }
    79. expressDescDTO.setDesc(json.getString(descKey));
    80. expressDescDTO.setDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(Long.parseLong(json.getString(dateKey)))));
    81. list.add(expressDescDTO);
    82. }
    83. list = list.stream().sorted(Comparator.comparing(ExpressDescDTO::getDate).reversed()).collect(Collectors.toList());
    84. expressSearchResponse.setDescList(list);
    85. return expressSearchResponse;
    86. }
    87. }

    通用查询快递方法 

    1. /**
    2. * 查询快递
    3. *
    4. * @param sn 快递单号
    5. * @param name 快递公司名称
    6. * @param code 快递公司编码
    7. * @return 结果
    8. */
    9. public ExpressSearchResponse queryExpress(String sn, String name, String code) {
    10. ExpressSearchResponse response;
    11. if (StringUtils.isBlank(sn)) {
    12. return new ExpressSearchResponse();
    13. }
    14. Express express = selectExpress.get(code);
    15. ExpressSearchRequest request = new ExpressSearchRequest();
    16. request.setExpressName(name);
    17. request.setLogisticsNo(sn);
    18. request.setExpressCode(code);
    19. return express.logisticsSearch(request);
    20. }

     HttpClientUtils工具类 

    1. import org.apache.http.HttpEntity;
    2. import org.apache.http.HttpResponse;
    3. import org.apache.http.client.methods.HttpGet;
    4. import org.apache.http.client.methods.HttpPost;
    5. import org.apache.http.entity.StringEntity;
    6. import org.apache.http.impl.client.HttpClients;
    7. import org.apache.http.util.EntityUtils;
    8. import org.springframework.stereotype.Component;
    9. import java.io.IOException;
    10. import java.util.Map;
    11. import java.util.Set;
    12. @Component
    13. public class HttpClientUtils {
    14. /**
    15. * http get
    16. *
    17. * @param url 可带参数的 url 链接
    18. * @param heads http 头信息
    19. */
    20. public String get(String url, Map heads) {
    21. org.apache.http.client.HttpClient httpClient = HttpClients.createDefault();
    22. HttpResponse httpResponse = null;
    23. String result = "";
    24. HttpGet httpGet = new HttpGet(url);
    25. if (heads != null) {
    26. Set keySet = heads.keySet();
    27. for (String s : keySet) {
    28. httpGet.addHeader(s, heads.get(s));
    29. }
    30. }
    31. try {
    32. httpResponse = httpClient.execute(httpGet);
    33. HttpEntity httpEntity = httpResponse.getEntity();
    34. if (httpEntity != null) {
    35. result = EntityUtils.toString(httpEntity, "utf-8");
    36. }
    37. } catch (IOException e) {
    38. e.printStackTrace();
    39. }
    40. return result;
    41. }
    42. /**
    43. * http post
    44. */
    45. public String post(String url, String data, Map heads) {
    46. org.apache.http.client.HttpClient httpClient = HttpClients.createDefault();
    47. HttpResponse httpResponse = null;
    48. String result = "";
    49. HttpPost httpPost = new HttpPost(url);
    50. if (heads != null) {
    51. Set keySet = heads.keySet();
    52. for (String s : keySet) {
    53. httpPost.addHeader(s, heads.get(s));
    54. }
    55. }
    56. try {
    57. StringEntity s = new StringEntity(data, "utf-8");
    58. httpPost.setEntity(s);
    59. httpResponse = httpClient.execute(httpPost);
    60. HttpEntity httpEntity = httpResponse.getEntity();
    61. if (httpEntity != null) {
    62. result = EntityUtils.toString(httpEntity, "utf-8");
    63. }
    64. } catch (IOException e) {
    65. e.printStackTrace();
    66. }
    67. return result;
    68. }
    69. }

     MD5工具类

    1. import com.google.common.collect.Maps;
    2. import org.springframework.stereotype.Component;
    3. import java.nio.charset.StandardCharsets;
    4. import java.security.MessageDigest;
    5. import java.util.Map;
    6. import java.util.concurrent.locks.ReentrantLock;
    7. @Component
    8. public class MD5 {
    9. private static int DIGITS_SIZE = 16;
    10. private static char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    11. private static Map rDigits = Maps.newHashMapWithExpectedSize(16);
    12. static {
    13. for (int i = 0; i < digits.length; ++i) {
    14. rDigits.put(digits[i], i);
    15. }
    16. }
    17. private static MD5 me = new MD5();
    18. private MessageDigest mHasher;
    19. private ReentrantLock opLock = new ReentrantLock();
    20. private MD5() {
    21. try {
    22. mHasher = MessageDigest.getInstance("md5");
    23. } catch (Exception e) {
    24. throw new RuntimeException(e);
    25. }
    26. }
    27. public static MD5 getInstance() {
    28. return me;
    29. }
    30. public String getMD5String(String content) {
    31. return bytes2string(hash(content));
    32. }
    33. public String getMD5String(byte[] content) {
    34. return bytes2string(hash(content));
    35. }
    36. public byte[] getMD5Bytes(byte[] content) {
    37. return hash(content);
    38. }
    39. /**
    40. * 对字符串进行md5
    41. *
    42. * @param str
    43. * @return md5 byte[16]
    44. */
    45. public byte[] hash(String str) {
    46. opLock.lock();
    47. try {
    48. byte[] bt = mHasher.digest(str.getBytes(StandardCharsets.UTF_8));
    49. if (null == bt || bt.length != DIGITS_SIZE) {
    50. throw new IllegalArgumentException("md5 need");
    51. }
    52. return bt;
    53. } finally {
    54. opLock.unlock();
    55. }
    56. }
    57. /**
    58. * 对二进制数据进行md5
    59. *
    60. * @param data
    61. * @return md5 byte[16]
    62. */
    63. public byte[] hash(byte[] data) {
    64. opLock.lock();
    65. try {
    66. byte[] bt = mHasher.digest(data);
    67. if (null == bt || bt.length != DIGITS_SIZE) {
    68. throw new IllegalArgumentException("md5 need");
    69. }
    70. return bt;
    71. } finally {
    72. opLock.unlock();
    73. }
    74. }
    75. /**
    76. * 将一个字节数组转化为可见的字符串
    77. *
    78. * @param bt
    79. * @return
    80. */
    81. public String bytes2string(byte[] bt) {
    82. int l = bt.length;
    83. char[] out = new char[l << 1];
    84. for (int i = 0, j = 0; i < l; i++) {
    85. out[j++] = digits[(0xF0 & bt[i]) >>> 4];
    86. out[j++] = digits[0x0F & bt[i]];
    87. }
    88. return new String(out);
    89. }
    90. }

    MD5加密工具类

    1. import org.slf4j.Logger;
    2. import org.slf4j.LoggerFactory;
    3. import org.springframework.stereotype.Component;
    4. import java.security.MessageDigest;
    5. @Component
    6. public class Md5Utils {
    7. private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
    8. private static byte[] md5(String s) {
    9. MessageDigest algorithm;
    10. try {
    11. algorithm = MessageDigest.getInstance("MD5");
    12. algorithm.reset();
    13. algorithm.update(s.getBytes("UTF-8"));
    14. byte[] messageDigest = algorithm.digest();
    15. return messageDigest;
    16. } catch (Exception e) {
    17. log.error("MD5 Error...", e);
    18. }
    19. return null;
    20. }
    21. private static final String toHex(byte hash[]) {
    22. if (hash == null) {
    23. return null;
    24. }
    25. StringBuffer buf = new StringBuffer(hash.length * 2);
    26. int i;
    27. for (i = 0; i < hash.length; i++) {
    28. if ((hash[i] & 0xff) < 0x10) {
    29. buf.append("0");
    30. }
    31. buf.append(Long.toString(hash[i] & 0xff, 16));
    32. }
    33. return buf.toString();
    34. }
    35. public static String hash(String s) {
    36. try {
    37. return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8");
    38. } catch (Exception e) {
    39. log.error("not supported charset...{}", e);
    40. return s;
    41. }
    42. }
    43. }

    pom.xml——>引入顺丰、申通、众邮快递SDK。引入谷歌工具包:调用com.google.common.collect.Maps。

    1. <dependency>
    2. <groupId>com.expressgroupId>
    3. <artifactId>lop-zhongyou-api-sdkartifactId>
    4. <version>2.0.0version>
    5. <scope>compilescope>
    6. dependency>
    7. <dependency>
    8. <groupId>com.expressgroupId>
    9. <artifactId>sf-csim-express-sdkartifactId>
    10. <version>2.0.0version>
    11. <scope>compilescope>
    12. dependency>
    13. <dependency>
    14. <groupId>com.expressgroupId>
    15. <artifactId>sto-link-sdkartifactId>
    16. <version>2.0.0version>
    17. <scope>compilescope>
    18. dependency>
    19. <dependency>
    20. <groupId>com.google.guavagroupId>
    21. <artifactId>guavaartifactId>
    22. <version>22.0version>
    23. dependency>

     韵达快递——>接收OrderInfo类

    1. import lombok.Data;
    2. @Data
    3. public class OrderInfo {
    4. private String orderid;
    5. private String mailno;
    6. private UserInfo sender;
    7. private UserInfo receiver;
    8. }

     韵达快递——>接收子类UserInfo类 

    1. import lombok.Data;
    2. @Data
    3. public class UserInfo {
    4. private String name;
    5. private String province;
    6. private String city;
    7. private String county;
    8. private String address;
    9. private String phone;
    10. private String mobile;
    11. }

    例1:YdExpress——>韵达快递

    1. import cn.hutool.core.util.StrUtil;
    2. import com.alibaba.fastjson.JSON;
    3. import com.alibaba.fastjson.JSONArray;
    4. import com.alibaba.fastjson.JSONObject;
    5. import OrderInfo;
    6. import UserInfo;
    7. import ExpressSearchRequest;
    8. import ExpressSearchResponse;
    9. import org.slf4j.Logger;
    10. import org.slf4j.LoggerFactory;
    11. import org.springframework.data.redis.core.RedisTemplate;
    12. import org.springframework.stereotype.Service;
    13. import javax.annotation.Resource;
    14. import java.io.*;
    15. import java.net.HttpURLConnection;
    16. import java.net.URL;
    17. import java.nio.charset.StandardCharsets;
    18. import java.security.MessageDigest;
    19. import java.util.ArrayList;
    20. import java.util.List;
    21. import java.util.concurrent.TimeUnit;
    22. /**
    23. * 韵达
    24. */
    25. @Service
    26. public class YdExpress extends ResponseController implements Express {
    27. private static final Logger log = LoggerFactory.getLogger(YdExpress.class);
    28. private static final String TRACK_SERVER_URL = "https://openapi.yundaex.com/openapi/outer/logictis/subscribe";
    29. private static final String SERVER_URL = "https://openapi.yundaex.com/openapi/outer/logictis/query";
    30. private static final String APP_KEY = "123456";
    31. private static final String APP_SECRET = "e10adc3949ba59abbe56e057f20f883e";
    32. @Resource
    33. private RedisTemplate redisTemplate;
    34. private static final String LOGISTICS_TRACK = "logistics::track:{}";
    35. @Override
    36. public String expressCode() {
    37. return "YD";
    38. }
    39. @Override
    40. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    41. log.info("韵达快递查询参数[{}]", JSON.toJSONString(request));
    42. JSONArray jsonArray = new JSONArray();
    43. String logisticsTrack = StrUtil.format(LOGISTICS_TRACK, request.getLogisticsNo());
    44. boolean isTrack = false;
    45. try {
    46. if (!redisTemplate.hasKey(logisticsTrack)) {
    47. //物流轨迹订阅
    48. String orderid = request.getOrderNo();
    49. String mailno = request.getLogisticsNo();
    50. String senderName = request.getReceiverName();
    51. String senderProvince = request.getProvinceName();
    52. String senderCity = request.getCityName();
    53. String senderCounty = request.getDistrictName();
    54. String senderAddress = request.getDetailAddress();
    55. String senderPhone = request.getReceiverMobile();
    56. String senderMobile = request.getReceiverMobile();
    57. String receiverName = request.getReceiverName();
    58. String receiverProvince = request.getProvinceName();
    59. String receiverCity = request.getCityName();
    60. String receiverCounty = request.getDistrictName();
    61. String receiverAddress = request.getDetailAddress();
    62. String receiverPhone = request.getReceiverMobile();
    63. String receiverMobile = request.getReceiverMobile();
    64. List orderInfoList = new ArrayList<>();
    65. OrderInfo orderInfo = new OrderInfo();
    66. orderInfo.setOrderid(orderid);
    67. orderInfo.setMailno(mailno);
    68. //发货人信息
    69. UserInfo userInfoSender = new UserInfo();
    70. userInfoSender.setName(senderName);
    71. userInfoSender.setProvince(senderProvince);
    72. userInfoSender.setCity(senderCity);
    73. userInfoSender.setCounty(senderCounty);
    74. userInfoSender.setAddress(senderAddress);
    75. userInfoSender.setPhone(senderPhone);
    76. userInfoSender.setMobile(senderMobile);
    77. orderInfo.setSender(userInfoSender);
    78. //接收人信息
    79. UserInfo userInfoReceiver = new UserInfo();
    80. userInfoReceiver.setName(receiverName);
    81. userInfoReceiver.setProvince(receiverProvince);
    82. userInfoReceiver.setCity(receiverCity);
    83. userInfoReceiver.setCounty(receiverCounty);
    84. userInfoReceiver.setAddress(receiverAddress);
    85. userInfoReceiver.setPhone(receiverPhone);
    86. userInfoReceiver.setMobile(receiverMobile);
    87. orderInfo.setReceiver(userInfoReceiver);
    88. orderInfoList.add(orderInfo);
    89. String orders = "{\"orders\":" + JSONObject.toJSONString(orderInfoList) + "}";
    90. String resTrack = doPostJson(TRACK_SERVER_URL, orders);
    91. JSONObject jsonObjTrack = JSON.parseObject(resTrack);
    92. if (jsonObjTrack.getBoolean("result")) {
    93. redisTemplate.expire(logisticsTrack, 60, TimeUnit.DAYS);
    94. isTrack = true;
    95. }
    96. }
    97. if (isTrack) {
    98. String sourceContent = "{\"mailno\":\"" + request.getLogisticsNo() + "\"}";
    99. String res = doPostJson(SERVER_URL, sourceContent);
    100. log.info("请求返回结果[{}]", res);
    101. JSONObject jsonObj = JSON.parseObject(res);
    102. if (jsonObj.containsKey("data")) {
    103. JSONObject json = jsonObj.getJSONObject("data");
    104. if (json.containsKey("steps")) {
    105. jsonArray = json.getJSONArray("steps");
    106. }
    107. }
    108. }
    109. } catch (Exception e) {
    110. log.error("韵达快递查询出错[{}]", e.getMessage());
    111. }
    112. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    113. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "description", "time")));
    114. return controller(expressSearchResponse, jsonArray, "description", "time");
    115. }
    116. /**
    117. * 发送HTTP请求
    118. *
    119. * @param apiUrl 请求URL
    120. * @param jsonParams 请求参数
    121. * @return String
    122. */
    123. private static String doPostJson(String apiUrl, String jsonParams) {
    124. StringBuffer sbResult = new StringBuffer();
    125. try {
    126. URL url = new URL(apiUrl);
    127. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    128. conn.setDoOutput(true);
    129. conn.setDoInput(true);
    130. conn.setUseCaches(false);
    131. conn.setRequestMethod("POST");
    132. conn.setRequestProperty("Connection", "Keep-Alive");
    133. conn.setRequestProperty("Charset", "UTF-8");
    134. byte[] data = jsonParams.getBytes(StandardCharsets.UTF_8);
    135. conn.setRequestProperty("Content-Length", String.valueOf(data.length));
    136. conn.setRequestProperty("Content-Type", "application/json");
    137. conn.setRequestProperty("app-key", YdExpress.APP_KEY);
    138. conn.setRequestProperty("req-time", String.valueOf(System.currentTimeMillis()));
    139. conn.setRequestProperty("sign", MD5(jsonParams + "_" + YdExpress.APP_SECRET));
    140. conn.connect();
    141. OutputStream out = new DataOutputStream(conn.getOutputStream());
    142. out.write(data);
    143. out.flush();
    144. out.close();
    145. if (200 == conn.getResponseCode()) {
    146. InputStream inputStream = conn.getInputStream();
    147. try {
    148. String readLine = null;
    149. BufferedReader responseReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
    150. while ((readLine = responseReader.readLine()) != null) {
    151. sbResult.append(readLine).append("\n");
    152. }
    153. responseReader.close();
    154. } catch (Exception var12) {
    155. var12.printStackTrace();
    156. }
    157. }
    158. } catch (Exception var13) {
    159. var13.printStackTrace();
    160. }
    161. return sbResult.toString();
    162. }
    163. /**
    164. * Md5加密算法
    165. *
    166. * @param str
    167. * @return
    168. * @throws Exception
    169. */
    170. private static String MD5(String str) throws Exception {
    171. MessageDigest md = MessageDigest.getInstance("MD5");
    172. md.update(str.getBytes(StandardCharsets.UTF_8));
    173. byte[] result = md.digest();
    174. StringBuffer sb = new StringBuffer(32);
    175. for (int i = 0; i < result.length; ++i) {
    176. int val = result[i] & 255;
    177. if (val <= 15) {
    178. sb.append("0");
    179. }
    180. sb.append(Integer.toHexString(val));
    181. }
    182. return sb.toString().toLowerCase();
    183. }
    184. }

    例2:AneExpress——>安能快递

    1. import cn.hutool.core.codec.Base64;
    2. import cn.hutool.crypto.SecureUtil;
    3. import cn.hutool.http.HttpRequest;
    4. import com.alibaba.fastjson.JSON;
    5. import com.alibaba.fastjson.JSONArray;
    6. import com.alibaba.fastjson.JSONObject;
    7. import ExpressSearchRequest;
    8. import ExpressSearchResponse;
    9. import org.slf4j.Logger;
    10. import org.slf4j.LoggerFactory;
    11. import org.springframework.stereotype.Service;
    12. import java.security.NoSuchAlgorithmException;
    13. /**
    14. * 安能
    15. **/
    16. @Service
    17. public class AneExpress extends ResponseController implements Express {
    18. private static final Logger log = LoggerFactory.getLogger(AneExpress.class);
    19. private static String URL = "http://opc.ane56.com/aneop/services/logisticsQuery/new/query";
    20. private static String APPKEY = "e10adc3949ba59abbe56e057f20f883e";
    21. private static String CODE = "ANENG";
    22. @Override
    23. public String expressCode() {
    24. return "ANE";
    25. }
    26. @Override
    27. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException {
    28. log.info("安能快递查询参数[{}]", JSON.toJSONString(request));
    29. JSONArray jsonArray = new JSONArray();
    30. try {
    31. JSONObject jsonObject = new JSONObject();
    32. JSONObject params = new JSONObject();
    33. params.put("ewbNo", request.getLogisticsNo());
    34. jsonObject.put("params", params.toJSONString());
    35. String digest = Base64.encode(SecureUtil.md5("{\"ewbNo\":\"" + request.getLogisticsNo() + "\"}" + CODE + APPKEY));
    36. jsonObject.put("digest", digest);
    37. jsonObject.put("code", CODE);
    38. String timestamp = Long.toString(System.currentTimeMillis());
    39. jsonObject.put("timestamp", timestamp);
    40. String res = HttpRequest.post(URL).header("Content-type", "application/json").body(jsonObject.toJSONString()).execute().body();
    41. log.info("请求返回结果[{}]", res);
    42. JSONObject resObject = JSONObject.parseObject(res);
    43. jsonArray = resObject.getJSONObject("resultInfo").getJSONArray("traces");
    44. } catch (Exception e) {
    45. log.error("安能快递查询出错[{}]", e.getMessage());
    46. }
    47. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    48. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "desc", "operateTime")));
    49. return controller(expressSearchResponse, jsonArray, "desc", "operateTime");
    50. }
    51. }

    例3:BestExpress——>百世快递

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import org.slf4j.Logger;
    7. import org.slf4j.LoggerFactory;
    8. import org.springframework.stereotype.Service;
    9. import javax.annotation.Resource;
    10. import java.util.HashMap;
    11. import java.util.Map;
    12. /**
    13. * 百世
    14. */
    15. @Service
    16. public class BestExpress extends ResponseController implements Express {
    17. private static final Logger log = LoggerFactory.getLogger(BestExpress.class);
    18. private static String url = "http://edi-q9.ns.800best.com/kd/api/process";
    19. private static String partnerKey = "49ba59abbe56";
    20. private static String partnerID = "12345";
    21. private static String serviceType = "KD_TRACE_QUERY";
    22. @Resource
    23. HttpClientUtils httpClientUtils;
    24. @Override
    25. public String expressCode() {
    26. return "HTKY";
    27. }
    28. @Override
    29. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    30. log.info("百世快递查询参数[{}]", JSON.toJSONString(request));
    31. JSONArray jsonArr = null;
    32. ExpressSearchResponse expressSearchResponse = null;
    33. try {
    34. //拼接请求头
    35. Map headers = new HashMap<>(4);
    36. headers.put("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
    37. headers.put("connection", "keep-alive");
    38. headers.put("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
    39. headers.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
    40. //组建数据格式
    41. String bizData = "{\"mailNos\": {\"mailNo\": [\"" + request.getLogisticsNo() + "\"]}}";
    42. String sign = Md5Utils.hash(bizData + partnerKey);
    43. String requestData = "partnerID=" + partnerID + "&serviceType=" + serviceType + "&bizData=" + bizData + "&sign=" + sign;
    44. //发送请求并接受返回
    45. String res = httpClientUtils.post(url, requestData, headers);
    46. log.info("请求返回结果[{}]", res);
    47. JSONObject json = JSONObject.parseObject(res);
    48. jsonArr = json.getJSONArray("traceLogs");
    49. //处理返回结果
    50. jsonArr = jsonArr.getJSONObject(0).getJSONObject("traces").getJSONArray("trace");
    51. } catch (Exception e) {
    52. log.error("百世快递查询出错[{}]", e.getMessage());
    53. }
    54. expressSearchResponse = checkResult(jsonArr, request);
    55. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "remark", "acceptTime")));
    56. return controller(expressSearchResponse, jsonArr, "remark", "acceptTime");
    57. }
    58. }

    例4:中国邮政快递——>ChinaPostExpress【线下联系邮政快递人员开通账号信息】

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import org.slf4j.Logger;
    7. import org.slf4j.LoggerFactory;
    8. import org.springframework.stereotype.Service;
    9. import javax.annotation.Resource;
    10. import java.util.HashMap;
    11. import java.util.Map;
    12. /**
    13. * 中国邮政
    14. */
    15. @Service
    16. public class ChinaPostExpress extends ResponseController implements Express {
    17. private static final Logger log = LoggerFactory.getLogger(ChinaPostExpress.class);
    18. @Resource
    19. HttpClientUtils httpClientUtils;
    20. @Override
    21. public String expressCode() {
    22. return "YZPY";
    23. }
    24. @Override
    25. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    26. log.info("邮政快递包裹查询参数[{}]", JSON.toJSONString(request));
    27. JSONArray jsonArray = null;
    28. try {
    29. String url = "http://211.156.193.140:8000/cotrackapi/api/track/mail/";
    30. //拼接请求头
    31. Map headers = new HashMap<>(2);
    32. headers.put("Version", "ems_track_cn_1.0");
    33. headers.put("authenticate", "E10ADC3949BA59ABBE56E057F20F883E");
    34. //组建数据格式
    35. url = url + request.getLogisticsNo();
    36. //发送请求并接受返回
    37. String res = httpClientUtils.get(url, headers);
    38. //处理返回结果
    39. log.info("请求返回结果[{}]", res);
    40. JSONObject json = JSONObject.parseObject(res);
    41. jsonArray = json.getJSONArray("traces");
    42. } catch (Exception e) {
    43. log.error("邮政快递包裹查询出错[{}]", e.getMessage());
    44. }
    45. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    46. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "remark", "acceptTime")));
    47. return controller(expressSearchResponse, jsonArray, "remark", "acceptTime");
    48. }
    49. }

    例5:EMS——>EmsExpress【线下联系邮政快递人员开通账号信息】

    1. import ExpressSearchRequest;
    2. import ExpressSearchResponse;
    3. import org.springframework.stereotype.Service;
    4. import javax.annotation.Resource;
    5. /**
    6. * EMS
    7. */
    8. @Service
    9. public class EmsExpress extends ResponseController implements Express {
    10. @Resource
    11. ChinaPostExpress chinaPostExpress;
    12. @Override
    13. public String expressCode() {
    14. return "EMS";
    15. }
    16. @Override
    17. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    18. return chinaPostExpress.logisticsSearch(request);
    19. }
    20. }

    例6:德邦快递——>DepponExpress

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import org.apache.commons.codec.binary.Base64;
    7. import org.apache.commons.codec.digest.DigestUtils;
    8. import org.slf4j.Logger;
    9. import org.slf4j.LoggerFactory;
    10. import org.springframework.stereotype.Service;
    11. import javax.annotation.Resource;
    12. import java.util.HashMap;
    13. import java.util.Map;
    14. /**
    15. * 德邦
    16. */
    17. @Service
    18. public class DepponExpress extends ResponseController implements Express {
    19. private static final Logger log = LoggerFactory.getLogger(DepponExpress.class);
    20. private static String url = "http://dpapi.deppon.com/dop-interface-sync/standard-query/newTraceQuery.action";
    21. private static String companyCode = "ABCDEFGHIJKLM";
    22. private static String appKey = "e10adc3949ba59abbe56e057f20f883e";
    23. @Resource
    24. HttpClientUtils httpClientUtils;
    25. @Override
    26. public String expressCode() {
    27. return "DBL";
    28. }
    29. @Override
    30. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    31. JSONArray jsonArray = null;
    32. log.info("德邦快递查询参数[{}]", JSON.toJSONString(request));
    33. try {
    34. //拼接请求头
    35. Map headers = new HashMap<>(1);
    36. headers.put("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
    37. //组建数据格式
    38. String timestamp = String.valueOf(System.currentTimeMillis());
    39. String params = "{\"mailNo\":\"" + request.getLogisticsNo() + "\"}";
    40. String digest = Base64.encodeBase64String(DigestUtils.md5Hex(params + appKey + timestamp).getBytes());
    41. String requestData = "params=" + params + "&digest=" + digest + "×tamp=" + timestamp + "&companyCode=" + companyCode;
    42. //发送请求并接受返回
    43. String res = httpClientUtils.post(url, requestData, headers);
    44. //处理返回结果
    45. log.info("请求返回结果[{}]", res);
    46. JSONObject json = JSONObject.parseObject(res);
    47. jsonArray = json.getJSONObject("responseParam").getJSONArray("trace_list");
    48. } catch (Exception e) {
    49. log.error("德邦快递查询出错[{}]", e.getMessage());
    50. }
    51. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    52. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "description", "time")));
    53. return controller(expressSearchResponse, jsonArray, "description", "time");
    54. }
    55. }

    例7:极兔快递——>JtExpress 

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import org.slf4j.Logger;
    7. import org.slf4j.LoggerFactory;
    8. import org.springframework.stereotype.Service;
    9. import org.apache.commons.codec.binary.Base64;
    10. import org.apache.commons.codec.digest.DigestUtils;
    11. import javax.annotation.Resource;
    12. import java.util.HashMap;
    13. import java.util.Map;
    14. /**
    15. * 极兔
    16. */
    17. @Service
    18. public class JtExpress extends ResponseController implements Express {
    19. private static final Logger log = LoggerFactory.getLogger(JtExpress.class);
    20. private static final String API_ACCOUNT = "178337126125932605";
    21. private static final String PRIVATE_KEY = "0258d71b55fc45e3ad7a7f38bf4b201a";
    22. private static final String SERVICE_URL = "https://openapi.jtexpress.com.cn/webopenplatformapi/api/logistics/trace";
    23. @Resource
    24. HttpClientUtils httpClientUtils;
    25. @Override
    26. public String expressCode() {
    27. return "JTSD";
    28. }
    29. @Override
    30. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    31. log.info("极兔查询参数[{}]", JSON.toJSONString(request));
    32. JSONArray jsonArray = new JSONArray();
    33. try {
    34. //查询参数
    35. String bizContent = "{\"billCodes\":\"" + request.getLogisticsNo() + "\"}";
    36. //拼接请求头
    37. Map headers = new HashMap<>();
    38. headers.put("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
    39. headers.put("apiAccount", API_ACCOUNT);
    40. headers.put("digest", digestForHead(bizContent));
    41. headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
    42. String requestData = "bizContent=" + bizContent;
    43. Map jsonMap = new HashMap<>();
    44. jsonMap.put("header", JSON.toJSONString(headers));
    45. jsonMap.put("body", requestData);
    46. log.info("请求参数digest[{}]", digestForHead(bizContent));
    47. log.info("请求参数headers[{}]", JSON.toJSONString(headers));
    48. log.info("请求参数body[{}]", requestData);
    49. log.info("请求jsonMap[{}]", JSON.toJSONString(jsonMap));
    50. //发送请求并接受返回
    51. String res = httpClientUtils.post(SERVICE_URL, requestData, headers);
    52. //处理返回结果
    53. log.info("请求返回结果[{}]", res);
    54. JSONObject json = JSONObject.parseObject(res);
    55. jsonArray = json.getJSONArray("data").getJSONObject(0).getJSONArray("details");
    56. } catch (Exception e) {
    57. log.error("极兔快递查询出错[{}]", e.getMessage());
    58. }
    59. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    60. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "desc", "scanTime")));
    61. return controller(expressSearchResponse, jsonArray, "desc", "scanTime");
    62. }
    63. private static String digestForHead(String json) {
    64. String signStr = json + JtExpress.PRIVATE_KEY;
    65. byte[] encode = (new Base64()).encode(DigestUtils.md5(signStr));
    66. return new String(encode);
    67. }
    68. }

     例8:顺丰快递——>SfExpress 【引用顺丰SDK】

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import com.sf.csim.express.service.CallExpressServiceTools;
    7. import com.sf.csim.express.service.HttpClientUtil;
    8. import org.slf4j.Logger;
    9. import org.slf4j.LoggerFactory;
    10. import org.springframework.stereotype.Service;
    11. import java.util.HashMap;
    12. import java.util.Map;
    13. import java.util.UUID;
    14. /**
    15. * 顺丰
    16. */
    17. @Service
    18. public class SfExpress extends ResponseController implements Express {
    19. private static final Logger log = LoggerFactory.getLogger(SfExpress.class);
    20. /**
    21. * 顾客编码
    22. */
    23. private static final String CLIENT_CODE = "ABCDEFGHIJKL";
    24. /**
    25. * 丰桥平台生产校验码
    26. */
    27. private static final String CHECK_WORD = "E10ADC3949BA59ABBE56E057F20F883E";
    28. /**
    29. * 接口服务代码
    30. */
    31. private static final String SERVICE_CODE = "EXP_RECE_SEARCH_ROUTES";
    32. /**
    33. * 生产环境的地址
    34. */
    35. private static final String CALL_URL_PROD = "https://sfapi.sf-express.com/std/service";
    36. @Override
    37. public String expressCode() {
    38. return "SF";
    39. }
    40. @Override
    41. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    42. log.info("顺丰查询参数[{}]", JSON.toJSONString(request));
    43. JSONArray jsonArray = new JSONArray();
    44. try {
    45. Map params = new HashMap<>();
    46. String msgData = "{" +
    47. " \"language\": 0," +
    48. " \"trackingType\": 1," +
    49. " \"trackingNumber\": [\"" + request.getLogisticsNo() + "\"]," +
    50. " \"methodType\": 1," +
    51. " \"checkPhoneNo\": \"" + request.getReceiverMobile().substring(7) + "\"" +
    52. "}";
    53. String timeStamp = String.valueOf(System.currentTimeMillis());
    54. params.put("partnerID", CLIENT_CODE);
    55. params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
    56. params.put("serviceCode", SERVICE_CODE);
    57. params.put("timestamp", timeStamp);
    58. params.put("msgData", msgData);
    59. params.put("msgDigest", CallExpressServiceTools.getMsgDigest(msgData, timeStamp, CHECK_WORD));
    60. System.out.println(params);
    61. String res = HttpClientUtil.post(CALL_URL_PROD, params);
    62. log.info("请求返回结果[{}]", res);
    63. JSONObject jsonObj = JSON.parseObject(res);
    64. if (jsonObj.containsKey("apiResultData")) {
    65. JSONObject json = jsonObj.getJSONObject("apiResultData");
    66. if (json.containsKey("msgData")) {
    67. json = json.getJSONObject("msgData").getJSONArray("routeResps").getJSONObject(0);
    68. if (json.containsKey("routes")) {
    69. jsonArray = json.getJSONArray("routes");
    70. }
    71. }
    72. }
    73. } catch (Exception e) {
    74. log.error("顺丰查询出错[{}]", e.getMessage());
    75. }
    76. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    77. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "remark", "acceptTime")));
    78. return controller(expressSearchResponse, jsonArray, "remark", "acceptTime");
    79. }
    80. }

      例9:申通快递——>StoExpress 【引用申通SDK】

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import com.sto.link.request.LinkRequest;
    7. import com.sto.link.util.LinkUtils;
    8. import org.slf4j.Logger;
    9. import org.slf4j.LoggerFactory;
    10. import org.springframework.stereotype.Service;
    11. import java.util.ArrayList;
    12. import java.util.List;
    13. /**
    14. * 申通
    15. */
    16. @Service
    17. public class StoExpress extends ResponseController implements Express {
    18. private static final Logger log = LoggerFactory.getLogger(StoExpress.class);
    19. private static String url = "https://cloudinter-linkgatewayonline.sto.cn/gateway/link.do";
    20. private static String api_name = "STO_TRACE_QUERY_COMMON";
    21. private static String from_appkey = "ABCDEFGHIJKLMNO";
    22. private static String from_code = "ABCDEFGHIJKLMNO";
    23. private static String to_appkey = "sto_trace_query";
    24. private static String to_code = "sto_trace_query";
    25. private static String secretKey = "E10ADC3949BA59ABBE56E057F20F883E";
    26. @Override
    27. public String expressCode() {
    28. return "STO";
    29. }
    30. @Override
    31. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    32. log.info("申通快递查询参数[{}]", JSON.toJSONString(request));
    33. JSONArray jsonArray = new JSONArray();
    34. try {
    35. LinkRequest data = new LinkRequest();
    36. data.setFromAppkey(from_appkey);
    37. data.setFromCode(from_code);
    38. data.setToAppkey(to_appkey);
    39. data.setToCode(to_code);
    40. data.setApiName(api_name);
    41. JSONObject jsonObject = new JSONObject();
    42. List ll = new ArrayList<>();
    43. ll.add(request.getLogisticsNo());
    44. jsonObject.put("waybillNoList", ll);
    45. data.setContent(jsonObject.toJSONString());
    46. String res = LinkUtils.request(data, url, secretKey);
    47. log.info("请求返回结果[{}]", res);
    48. jsonArray = JSONObject.parseObject(res).getJSONObject("data").getJSONArray(request.getLogisticsNo());
    49. } catch (Exception e) {
    50. log.error("申通快递查询出错[{}]", e.getMessage());
    51. }
    52. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    53. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "memo", "opTime")));
    54. return controller(expressSearchResponse, jsonArray, "memo", "opTime");
    55. }
    56. }

     例9:众邮快递——>ZyExpress 【引用众邮SDK】

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import com.jdwl.open.api.sdk.DefaultJdClient;
    5. import com.jdwl.open.api.sdk.JdClient;
    6. import com.jdwl.open.api.sdk.JdException;
    7. import com.jdwl.open.api.sdk.domain.zhongyouex.OrderTraceApi.CommonParam;
    8. import com.jdwl.open.api.sdk.request.zhongyouex.OrderFindTraceInfoByWaybillCodeLopRequest;
    9. import com.jdwl.open.api.sdk.response.zhongyouex.OrderFindTraceInfoByWaybillCodeResponse;
    10. import ExpressSearchRequest;
    11. import ExpressSearchResponse;
    12. import org.slf4j.Logger;
    13. import org.slf4j.LoggerFactory;
    14. import org.springframework.stereotype.Service;
    15. /**
    16. * 众邮
    17. */
    18. @Service
    19. public class ZyExpress extends ResponseController implements Express {
    20. private static final Logger log = LoggerFactory.getLogger(ZyExpress.class);
    21. private static String serverUrl = "https://api.zhongyouex.com/routerjson";
    22. private static String accessToken = "E10ADC3949BA59ABBE56E057F20F883E";
    23. private static String appKey = "E10ADC3949BA59ABBE56E057F20F883E";
    24. private static String appSecret = "E10ADC3949BA59ABBE56E057F20F883E";
    25. private static String appCode = "EXPRESS_100";
    26. private static String source = "1234";
    27. private static String userCode = "zhangsan123";
    28. @Override
    29. public String expressCode() {
    30. return "ZY";
    31. }
    32. @Override
    33. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    34. log.info("众邮快递查询参数[{}]", JSON.toJSONString(request));
    35. JSONArray jsonArray = new JSONArray();
    36. try {
    37. JdClient client = new DefaultJdClient(serverUrl, accessToken, appKey, appSecret);
    38. OrderFindTraceInfoByWaybillCodeLopRequest lopRequest = new OrderFindTraceInfoByWaybillCodeLopRequest();
    39. lopRequest.setWaybillCode(request.getLogisticsNo());
    40. CommonParam commonParam = new CommonParam();
    41. commonParam.setAppCode(appCode);
    42. commonParam.setSource(source);
    43. commonParam.setUserCode(userCode);
    44. lopRequest.setCommonParam(commonParam);
    45. OrderFindTraceInfoByWaybillCodeResponse response = client.execute(lopRequest);
    46. log.info("请求返回结果[{}]", response.getMsg());
    47. JSONObject jsonObject = JSONObject.parseObject(response.getMsg());
    48. jsonArray = jsonObject.getJSONObject("response").getJSONObject("content").getJSONArray("data");
    49. } catch (JdException e) {
    50. log.error("众邮快递查询出错[{}]", e.getErrMsg());
    51. }
    52. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    53. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "content", "operateTime")));
    54. return controller(expressSearchResponse, jsonArray, "content", "operateTime");
    55. }
    56. }

     例10:圆通快递——>YtoExpress

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import org.apache.commons.lang3.time.DateFormatUtils;
    7. import org.slf4j.Logger;
    8. import org.slf4j.LoggerFactory;
    9. import org.springframework.stereotype.Service;
    10. import javax.annotation.Resource;
    11. import java.net.URLEncoder;
    12. import java.util.Date;
    13. import java.util.HashMap;
    14. import java.util.Map;
    15. /**
    16. * 圆通
    17. */
    18. @Service
    19. public class YtoExpress extends ResponseController implements Express {
    20. private static final Logger log = LoggerFactory.getLogger(YtoExpress.class);
    21. private static String url = "http://openapi.yto.net.cn/service/waybill_query/v1/X1FKbA";
    22. private static String user_id = "YTOTEST";
    23. private static String app_key = "sF1Jzn";
    24. private static String secret_key = "1QLlIZ";
    25. private static String v = "1.01";
    26. private static String method = "yto.Marketing.WaybillTrace";
    27. @Resource
    28. HttpClientUtils httpClientUtils;
    29. @Override
    30. public String expressCode() {
    31. return "YTO";
    32. }
    33. @Override
    34. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
    35. log.info("圆通快递查询参数[{}]", JSON.toJSONString(request));
    36. JSONArray jsonArray = new JSONArray();
    37. try {
    38. JSONObject jsonObject = new JSONObject();
    39. jsonObject.put("Number", request.getLogisticsNo());
    40. String timestamp = DateFormatUtils.format(new Date(), "yyyy-mm-dd HH:mm:ss");
    41. String sign = secret_key + "app_key" + app_key + "formatJSONmethod" + method + "timestamp"
    42. + timestamp + "user_id" + user_id + "v" + v;
    43. sign = MD5.getInstance().getMD5String(sign).toUpperCase();
    44. String params = "sign=" + sign + "&app_key=" + app_key + "&format=JSON&method=" + method + "×tamp="
    45. + timestamp + "&user_id=" + user_id + "&v=" + v + "¶m=" + URLEncoder.encode(jsonObject.toJSONString(), "UTF-8");
    46. Map headers = new HashMap<>(1);
    47. headers.put("Content-Type", "application/x-www-form-urlencoded");
    48. String res = httpClientUtils.post(url, params, headers);
    49. log.info("请求返回结果[{}]", res);
    50. jsonArray = JSONObject.parseArray(res);
    51. } catch (Exception e) {
    52. log.error("圆通快递查询出错[{}]", e.getMessage());
    53. }
    54. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    55. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "processInfo", "upload_Time")));
    56. return controller(expressSearchResponse, jsonArray, "processInfo", "upload_Time");
    57. }
    58. }

     例11:中通快递——>ZtoExpress【旧版】

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import org.slf4j.Logger;
    7. import org.slf4j.LoggerFactory;
    8. import org.springframework.stereotype.Component;
    9. import org.springframework.util.Base64Utils;
    10. import javax.annotation.Resource;
    11. import java.net.URLEncoder;
    12. import java.security.NoSuchAlgorithmException;
    13. import java.util.HashMap;
    14. import java.util.Map;
    15. /**
    16. * 中通
    17. */
    18. @Component
    19. public class ZtoExpress extends ResponseController implements Express {
    20. private static final Logger log = LoggerFactory.getLogger(ZtoExpress.class);
    21. private static String url = "https://japi.zto.com/traceInterfaceNewTraces";
    22. private static String companyId = "e10adc3949ba59abbe56e057f20f883e";
    23. private static String key = "abcdefghijkl";
    24. private static String msg_type = "NEW_TRACES";
    25. @Resource
    26. HttpClientUtils httpClientUtils;
    27. @Override
    28. public String expressCode() {
    29. return "ZTO";
    30. }
    31. @Override
    32. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException {
    33. JSONArray jsonArray = null;
    34. log.info("中通快递查询参数[{}]", JSON.toJSONString(request));
    35. try {
    36. //组建数据格式
    37. String strToDigest = "data=['" + request.getLogisticsNo() + "']&company_id=" + companyId + "&msg_type=" + msg_type + key;
    38. String dataDigest = Base64Utils.encodeToString(MD5.getInstance().hash(strToDigest));
    39. String requestData = "data=" + URLEncoder.encode("['" + request.getLogisticsNo() + "']", "UTF-8") +
    40. "&company_id=" + companyId + "&msg_type=" + msg_type;
    41. //拼接请求头
    42. Map headers = new HashMap<>(3);
    43. headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
    44. headers.put("x-companyId", companyId);
    45. headers.put("x-dataDigest", dataDigest);
    46. //发送请求并接受返回
    47. String res = httpClientUtils.post(url, requestData, headers);
    48. //处理返回结果
    49. log.info("请求返回结果[{}]", res);
    50. JSONObject json = JSONObject.parseObject(res);
    51. jsonArray = json.getJSONArray("data").getJSONObject(0).getJSONArray("traces");
    52. } catch (Exception e) {
    53. log.error("中通快递查询出错[{}]", e.getMessage());
    54. }
    55. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    56. log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "desc", "scanDate")));
    57. return controller(expressSearchResponse, jsonArray, "desc", "scanDate");
    58. }
    59. }

    例12:中通快递——>ZtoExpress【新版】 

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONArray;
    3. import com.alibaba.fastjson.JSONObject;;
    4. import ExpressSearchRequest;
    5. import ExpressSearchResponse;
    6. import zop.EncryptionType;
    7. import zop.ZopClient;
    8. import zop.ZopPublicRequest;
    9. import org.slf4j.Logger;
    10. import org.slf4j.LoggerFactory;
    11. import org.springframework.stereotype.Component;
    12. import java.io.IOException;
    13. import java.security.NoSuchAlgorithmException;
    14. /**
    15. * 中通
    16. */
    17. @Component
    18. public class ZtoExpress extends ResponseController implements Express {
    19. private static final Logger log = LoggerFactory.getLogger(ZtoExpress.class);
    20. private static String url = "https://japi.zto.com/zto.merchant.waybill.track.query";
    21. private static String appKey = "ea8a706c4c34a168abcde";
    22. private static String appSecret = "827ccb0eea8a706c4c34a16891f84e7b";
    23. @Override
    24. public String expressCode() {
    25. return "ZTO";
    26. }
    27. @Override
    28. public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException {
    29. JSONArray jsonArray = null;
    30. log.info("中通快递查询参数[{}]", JSON.toJSONString(request));
    31. ZopClient client = new ZopClient(appKey, appSecret);
    32. ZopPublicRequest zopPublicRequest = new ZopPublicRequest();
    33. String mobilePhone = request.getReceiverMobile().substring(request.getReceiverMobile().length() - 4);
    34. zopPublicRequest.setBody("{\"billCode\":\"" + request.getLogisticsNo() + "\",\"mobilePhone\":\"" + mobilePhone + "\"}");
    35. zopPublicRequest.setUrl(url);
    36. zopPublicRequest.setBase64(true);
    37. zopPublicRequest.setEncryptionType(EncryptionType.MD5);
    38. zopPublicRequest.setTimestamp(null);
    39. try {
    40. String res = client.execute(zopPublicRequest);
    41. //处理返回结果
    42. log.info("请求返回结果[{}]", res);
    43. JSONObject json = JSONObject.parseObject(res);
    44. jsonArray = json.getJSONArray("result");
    45. log.info("请求返回结果jsonArray[{}]", jsonArray);
    46. } catch (IOException e) {
    47. log.error("中通快递查询出错[{}]", e.getMessage());
    48. }
    49. ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
    50. log.info("中通快递返回数据[{}]", JSON.toJSONString(controllerZto(expressSearchResponse, jsonArray, "desc", "scanDate")));
    51. return controllerZto(expressSearchResponse, jsonArray, "desc", "scanDate");
    52. }
    53. }

    zop :中通快递新版所需公共资源包

     

    zop 之 EncryptionType 枚举类

    1. public enum EncryptionType {
    2. MD5,
    3. SHA256,
    4. HmacSHA256
    5. }

     zop 之 HttpUtil 工具类

    1. import java.io.BufferedReader;
    2. import java.io.DataOutputStream;
    3. import java.io.IOException;
    4. import java.io.InputStreamReader;
    5. import java.net.HttpURLConnection;
    6. import java.net.URL;
    7. import java.nio.charset.Charset;
    8. import java.util.Map;
    9. public class HttpUtil {
    10. private static final int DEFAULT_TIMEOUT = 3000;
    11. public static String post(String interfaceUrl, Map headers, String queryString) throws IOException {
    12. URL url = new URL(interfaceUrl);
    13. HttpURLConnection con = (HttpURLConnection) url.openConnection();
    14. con.setRequestMethod("POST");
    15. con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
    16. con.setDoOutput(true);
    17. con.setConnectTimeout(DEFAULT_TIMEOUT);
    18. con.setReadTimeout(DEFAULT_TIMEOUT);
    19. for (Map.Entry e : headers.entrySet()) {
    20. con.setRequestProperty(e.getKey(), e.getValue());
    21. }
    22. DataOutputStream out = null;
    23. BufferedReader in = null;
    24. try {
    25. out = new DataOutputStream(con.getOutputStream());
    26. out.write(queryString.getBytes(Charset.forName("UTF-8")));
    27. out.flush();
    28. in = new BufferedReader(
    29. new InputStreamReader(con.getInputStream(), "UTF-8"));
    30. String inputLine;
    31. StringBuilder content = new StringBuilder();
    32. while ((inputLine = in.readLine()) != null) {
    33. content.append(inputLine);
    34. }
    35. return content.toString();
    36. } finally {
    37. if (out != null) {
    38. try {
    39. out.close();
    40. } catch (Exception ignored) {
    41. }
    42. }
    43. if (in != null) {
    44. try {
    45. in.close();
    46. } catch (Exception ignored) {
    47. }
    48. }
    49. }
    50. }
    51. public static String postJson(String interfaceUrl, Map headers, String json) throws IOException {
    52. URL url = new URL(interfaceUrl);
    53. HttpURLConnection con = (HttpURLConnection) url.openConnection();
    54. con.setRequestMethod("POST");
    55. con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
    56. con.setDoOutput(true);
    57. con.setConnectTimeout(DEFAULT_TIMEOUT);
    58. con.setReadTimeout(DEFAULT_TIMEOUT);
    59. for (Map.Entry e : headers.entrySet()) {
    60. con.setRequestProperty(e.getKey(), e.getValue());
    61. }
    62. DataOutputStream out = null;
    63. BufferedReader in = null;
    64. try {
    65. out = new DataOutputStream(con.getOutputStream());
    66. out.write(json.getBytes(Charset.forName("UTF-8")));
    67. out.flush();
    68. in = new BufferedReader(
    69. new InputStreamReader(con.getInputStream(), "UTF-8"));
    70. String inputLine;
    71. StringBuilder content = new StringBuilder();
    72. while ((inputLine = in.readLine()) != null) {
    73. content.append(inputLine);
    74. }
    75. return content.toString();
    76. } finally {
    77. if (out != null) {
    78. try {
    79. out.close();
    80. } catch (Exception ignored) {
    81. }
    82. }
    83. if (in != null) {
    84. try {
    85. in.close();
    86. } catch (Exception ignored) {
    87. }
    88. }
    89. }
    90. }
    91. }

      zop 之 ZopClient 工具类

    1. import java.io.IOException;
    2. import java.io.UnsupportedEncodingException;
    3. import java.net.URLEncoder;
    4. import java.util.HashMap;
    5. import java.util.Map;
    6. public class ZopClient {
    7. private final ZopProperties properties;
    8. public ZopClient(ZopProperties properties) {
    9. this.properties = properties;
    10. }
    11. public ZopClient(String appKey, String appSecret) {
    12. this.properties = new ZopProperties(appKey, appSecret);
    13. }
    14. public String execute(ZopPublicRequest request) throws IOException {
    15. String jsonBody = request.getBody();
    16. if (jsonBody == null) {
    17. Map params = request.getParams();
    18. StringBuilder queryBuilder = new StringBuilder();
    19. StringBuilder strToDigestBuilder = new StringBuilder();
    20. for (Map.Entry e : params.entrySet()) {
    21. strToDigestBuilder.append(e.getKey()).append("=").append(e.getValue()).append("&");
    22. queryBuilder.append(urlEncode(e.getKey())).append("=").append(urlEncode(e.getValue())).append("&");
    23. }
    24. String queryString = queryBuilder.substring(0, queryBuilder.length() - 1);
    25. String strToDigest = strToDigestBuilder.substring(0, strToDigestBuilder.length() - 1);
    26. strToDigest = strToDigest + properties.getKey();
    27. Map headers = new HashMap();
    28. headers.put("x-companyid", properties.getCompanyId());
    29. headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp(), request.getSecretKey()));
    30. if (request.getTimestamp() != null) {
    31. headers.put("x-timestamp", String.valueOf(request.getTimestamp()));
    32. }
    33. return HttpUtil.post(request.getUrl(), headers, queryString);
    34. } else {
    35. Map headers = new HashMap<>();
    36. String strToDigest = jsonBody + properties.getKey();
    37. headers.put("x-companyid", properties.getCompanyId());
    38. headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp(), request.getSecretKey()));
    39. if (request.getTimestamp() != null) {
    40. headers.put("x-timestamp", String.valueOf(request.getTimestamp()));
    41. }
    42. return HttpUtil.postJson(request.getUrl(), headers, jsonBody);
    43. }
    44. }
    45. private String urlEncode(String str) {
    46. try {
    47. return URLEncoder.encode(str, "UTF-8");
    48. } catch (UnsupportedEncodingException e) {
    49. return str;
    50. }
    51. }
    52. }

       zop 之 ZopDigestUtil 工具类

    1. import org.apache.commons.codec.binary.Base64;
    2. import org.apache.commons.codec.binary.Hex;
    3. import org.apache.commons.codec.digest.DigestUtils;
    4. import javax.crypto.Mac;
    5. import javax.crypto.SecretKey;
    6. import javax.crypto.spec.SecretKeySpec;
    7. import java.nio.charset.StandardCharsets;
    8. import java.security.InvalidKeyException;
    9. import java.security.NoSuchAlgorithmException;
    10. import java.util.Map;
    11. import java.util.Objects;
    12. import java.util.concurrent.ConcurrentHashMap;
    13. public class ZopDigestUtil {
    14. private static final String HMAC_SHA_256 = "HmacSHA256";
    15. private static final Map MAC_MAP = new ConcurrentHashMap<>();
    16. public static String digest(String str, Boolean isBase64, EncryptionType encryptionType, Long timestamp, String secretKey) {
    17. if (timestamp != null) {
    18. str = timestamp + str;
    19. }
    20. boolean base64 = isBase64 == null || isBase64;
    21. switch (encryptionType) {
    22. case SHA256:
    23. return base64 ? Base64.encodeBase64String(DigestUtils.sha256(str)) : DigestUtils.sha256Hex(str);
    24. case HmacSHA256:
    25. return base64 ? Base64.encodeBase64String(hmacSha256(secretKey, str)) : hmacSha256Str(secretKey, str);
    26. default:
    27. return base64 ? Base64.encodeBase64String(DigestUtils.md5(str)) : DigestUtils.md5Hex(str);
    28. }
    29. }
    30. public static String hmacSha256Str(String key, String body) {
    31. return Hex.encodeHexString(hmacSha256(key, body));
    32. }
    33. public static byte[] hmacSha256(String key, String body) {
    34. if (Objects.isNull(key)) {
    35. key = "";
    36. }
    37. Mac mac = MAC_MAP.get(key);
    38. if (mac == null) {
    39. try {
    40. mac = Mac.getInstance(HMAC_SHA_256);
    41. SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), HMAC_SHA_256);
    42. mac.init(secretKey);
    43. MAC_MAP.put(key, mac);
    44. } catch (NoSuchAlgorithmException | InvalidKeyException e) {
    45. throw new RuntimeException(e);
    46. }
    47. }
    48. return mac.doFinal(body.getBytes(StandardCharsets.UTF_8));
    49. }
    50. }

       zop 之 ZopProperties 配置类

    1. public class ZopProperties {
    2. private String companyId;
    3. private String key;
    4. public ZopProperties() {
    5. }
    6. public ZopProperties(String appKey, String appSecret) {
    7. this.companyId = appKey;
    8. this.key = appSecret;
    9. }
    10. public String getCompanyId() {
    11. return companyId;
    12. }
    13. public void setCompanyId(String companyId) {
    14. this.companyId = companyId;
    15. }
    16. public String getKey() {
    17. return key;
    18. }
    19. public void setKey(String key) {
    20. this.key = key;
    21. }
    22. }

        zop 之 ZopPublicRequest 请求类

    1. import com.alibaba.fastjson.JSON;
    2. import com.alibaba.fastjson.JSONObject;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. public class ZopPublicRequest {
    6. private String url;
    7. private Map params = new HashMap();
    8. // 如果body有值,表示使用application/json的方式传值
    9. private String body;
    10. /**
    11. * 签名是否需要base64
    12. */
    13. private Boolean isBase64;
    14. /**
    15. * 加密方式,MD5或者SHA256
    16. */
    17. private EncryptionType encryptionType;
    18. /**
    19. * HmacSHA256加密key
    20. */
    21. private String secretKey;
    22. /**
    23. * 时间戳,如果接口文档未标识使用时间戳请不要传值,否则会导致签名错误
    24. */
    25. private Long timestamp;
    26. public ZopPublicRequest() {
    27. }
    28. public void setBody(String body) {
    29. this.body = body;
    30. }
    31. public String getBody() {
    32. return body;
    33. }
    34. public void addParam(String k, String v) {
    35. params.put(k, v);
    36. }
    37. public void setData(String data) {
    38. try {
    39. JSONObject jsonObject = JSON.parseObject(data);
    40. for (Map.Entry entry : jsonObject.entrySet()) {
    41. params.put(entry.getKey(), entry.getValue().toString());
    42. }
    43. } catch (Exception e) {
    44. throw new RuntimeException("JSON格式不对,请检查数据", e);
    45. }
    46. }
    47. public void setDataObj(Map data) {
    48. params.putAll(data);
    49. }
    50. public void addParam(Map p) {
    51. for (Map.Entry entry : p.entrySet()) {
    52. params.put(entry.getKey(), entry.getValue());
    53. }
    54. }
    55. public String getUrl() {
    56. return url;
    57. }
    58. public void setUrl(String url) {
    59. this.url = url;
    60. }
    61. public Map getParams() {
    62. return params;
    63. }
    64. public void setParams(Map params) {
    65. this.params = params;
    66. }
    67. public Boolean getBase64() {
    68. return isBase64;
    69. }
    70. public void setBase64(Boolean base64) {
    71. isBase64 = base64;
    72. }
    73. public EncryptionType getEncryptionType() {
    74. return encryptionType;
    75. }
    76. public void setEncryptionType(EncryptionType encryptionType) {
    77. this.encryptionType = encryptionType;
    78. }
    79. public String getSecretKey() {
    80. return secretKey;
    81. }
    82. public void setSecretKey(String secretKey) {
    83. this.secretKey = secretKey;
    84. }
    85. public Long getTimestamp() {
    86. return timestamp;
    87. }
    88. public void setTimestamp(Long timestamp) {
    89. this.timestamp = timestamp;
    90. }
    91. }
  • 相关阅读:
    猜数字--
    2023全网最火的接口自动化框架对比 (建议收藏)
    软考高项——计算专题
    【元胞自动机】元胞自动机晶体生长【含Matlab源码 232期】
    FastJson解析对象出现 “$ref“:“$[0].portInfoBean“ 导致list数据错乱的解决方案
    每日一博 - 闲聊SQL Query Execution Order
    ZYNQ之FPGA学习----IIC协议驱动模块仿真实验
    全志F133(D1s)芯片 如何在Tina下进行显示旋转?
    这几个Python实战项目,让大家了解到它的神奇
    ubuntu 22.04安装cuda、cudnn、conda、pytorch
  • 原文地址:https://blog.csdn.net/netuser1937/article/details/126477495