韵达快递、安能快递、百世快递、中国邮政快递、EMS、德邦快递、极兔快递、顺丰快递、申通快递、众邮快递、圆通快递、中通快递
Express接口类
- public interface Express {
- /**
- * 快递编码
- *
- * @return String
- */
- String expressCode();
-
- /**
- * 根据快递编码相关信息查询快递信息
- *
- * @param request 请求参数
- * @return ExpressSearchResponse
- * @throws NoSuchAlgorithmException
- */
- ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException;
- }
SelectExpress类
- import org.springframework.boot.CommandLineRunner;
- import org.springframework.context.ApplicationContext;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
- import java.util.HashMap;
- import java.util.Map;
-
- @Service
- public class SelectExpress implements CommandLineRunner {
- @Resource
- private ApplicationContext applicationContext;
-
- private Map
expressMap = new HashMap<>(); -
- /**
- * 根据名字返回相应的实现类
- *
- * @param code 快递公司编码
- * @return 实现类
- */
- public Express get(String code) {
- return expressMap.get(code);
- }
-
- @Override
- public void run(String... args) throws Exception {
- applicationContext.getBeansOfType(Express.class).values()
- .forEach(express -> expressMap.put(express.expressCode(), express));
- }
- }
ExpressSearchRequest请求类
- import io.swagger.annotations.ApiModelProperty;
- import lombok.Data;
-
- import java.io.Serializable;
-
- @Data
- public class ExpressSearchRequest implements Serializable {
- private static final long serialVersionUID = -880253965590928905L;
- @ApiModelProperty(value = "真实物流单号")
- private String logisticsNo;
- @ApiModelProperty(value = "物流公司名称", hidden = true)
- private String expressName;
- @ApiModelProperty(value = "物流公司编码", hidden = true)
- private String expressCode;
- @ApiModelProperty(value = "订单编码", hidden = true)
- private String orderNo;
- @ApiModelProperty(value = "收件人姓名", hidden = true)
- private String receiverName;
- @ApiModelProperty(value = "收件人手机号", hidden = true)
- private String receiverMobile;
- @ApiModelProperty(value = "收人地址:省份名称", hidden = true)
- private String provinceName;
- @ApiModelProperty(value = "收人地址:地市名称", hidden = true)
- private String cityName;
- @ApiModelProperty(value = "收人地址:区县名称", hidden = true)
- private String districtName;
- @ApiModelProperty(value = "收件人详细地址", hidden = true)
- private String detailAddress;
- }
ExpressSearchResponse返回类
- import io.swagger.annotations.ApiModelProperty;
- import lombok.Data;
-
- import java.io.Serializable;
- import java.util.ArrayList;
- import java.util.List;
-
- @Data
- public class ExpressSearchResponse implements Serializable {
- private static final long serialVersionUID = 8570085965157271803L;
- @ApiModelProperty("快递公司名称")
- private String logisticsName = "";
- @ApiModelProperty("快递单号")
- private String logisticsNo = "";
- @ApiModelProperty("描述")
- List
descList = new ArrayList<>(); - }
ExpressDescDTO返回类子类
- import io.swagger.annotations.ApiModelProperty;
- import lombok.Data;
-
- import java.io.Serializable;
-
- @Data
- public class ExpressDescDTO implements Serializable {
- private static final long serialVersionUID = 2774275564551643616L;
- @ApiModelProperty("轨迹描述")
- private String desc = "";
- @ApiModelProperty("日期")
- private String date = "";
- }
ResponseController返回结果封装类
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.jumi.microservice.warehouse.entity.dto.ExpressDescDTO;
- import com.jumi.microservice.warehouse.entity.dto.ExpressSearchRequest;
- import com.jumi.microservice.warehouse.entity.dto.ExpressSearchResponse;
-
- import java.text.SimpleDateFormat;
- import java.util.ArrayList;
- import java.util.Comparator;
- import java.util.Date;
- import java.util.List;
- import java.util.stream.Collectors;
-
- public class ResponseController {
-
- /**
- * 校验返回结果
- *
- * @param jsonArray json数组
- * @param request 请求参数
- * @return ExpressSearchResponse
- */
- public ExpressSearchResponse checkResult(JSONArray jsonArray, ExpressSearchRequest request) {
- ExpressSearchResponse expressSearchResponse = new ExpressSearchResponse();
- expressSearchResponse.setLogisticsName(request.getExpressName());
- expressSearchResponse.setLogisticsNo(request.getLogisticsNo());
- if (jsonArray == null || jsonArray.isEmpty()) {
- expressSearchResponse.setDescList(new ArrayList<>());
- }
- return expressSearchResponse;
- }
-
- /**
- * 组装返回实体类
- *
- * @param expressSearchResponse 返回信息
- * @param jsonArr json数组
- * @param descKey 描述
- * @param dateKey 时间
- * @return 组装返回实体类
- */
- public ExpressSearchResponse controller(ExpressSearchResponse expressSearchResponse, JSONArray jsonArr,
- String descKey, String dateKey) {
- if (jsonArr == null || jsonArr.isEmpty()) {
- return expressSearchResponse;
- }
- List
list = new ArrayList<>(); - for (Object j : jsonArr) {
- JSONObject json = JSONObject.parseObject(j.toString());
- ExpressDescDTO expressDescDTO = new ExpressDescDTO();
- if (json.getString(descKey) == null || json.getString(dateKey) == null) {
- return expressSearchResponse;
- }
- expressDescDTO.setDesc(json.getString(descKey));
- expressDescDTO.setDate(json.getString(dateKey));
- list.add(expressDescDTO);
- }
- list = list.stream().sorted(Comparator.comparing(ExpressDescDTO::getDate).reversed()).collect(Collectors.toList());
- expressSearchResponse.setDescList(list);
- return expressSearchResponse;
- }
-
- /**
- * 组装返回实体类
- *
- * @param expressSearchResponse 返回信息
- * @param jsonArr json数组
- * @param descKey 描述
- * @param dateKey 时间
- * @return 组装返回实体类
- */
- public ExpressSearchResponse controllerZto(ExpressSearchResponse expressSearchResponse, JSONArray jsonArr,
- String descKey, String dateKey) {
- if (jsonArr == null || jsonArr.isEmpty()) {
- return expressSearchResponse;
- }
- List
list = new ArrayList<>(); - for (Object j : jsonArr) {
- JSONObject json = JSONObject.parseObject(j.toString());
- ExpressDescDTO expressDescDTO = new ExpressDescDTO();
- if (json.getString(descKey) == null || json.getString(dateKey) == null) {
- return expressSearchResponse;
- }
- expressDescDTO.setDesc(json.getString(descKey));
- expressDescDTO.setDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(Long.parseLong(json.getString(dateKey)))));
- list.add(expressDescDTO);
- }
- list = list.stream().sorted(Comparator.comparing(ExpressDescDTO::getDate).reversed()).collect(Collectors.toList());
- expressSearchResponse.setDescList(list);
- return expressSearchResponse;
- }
- }
通用查询快递方法
- /**
- * 查询快递
- *
- * @param sn 快递单号
- * @param name 快递公司名称
- * @param code 快递公司编码
- * @return 结果
- */
- public ExpressSearchResponse queryExpress(String sn, String name, String code) {
-
- ExpressSearchResponse response;
- if (StringUtils.isBlank(sn)) {
- return new ExpressSearchResponse();
- }
- Express express = selectExpress.get(code);
- ExpressSearchRequest request = new ExpressSearchRequest();
- request.setExpressName(name);
- request.setLogisticsNo(sn);
- request.setExpressCode(code);
- return express.logisticsSearch(request);
- }
HttpClientUtils工具类
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpResponse;
- import org.apache.http.client.methods.HttpGet;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.entity.StringEntity;
- import org.apache.http.impl.client.HttpClients;
- import org.apache.http.util.EntityUtils;
- import org.springframework.stereotype.Component;
-
- import java.io.IOException;
- import java.util.Map;
- import java.util.Set;
-
- @Component
- public class HttpClientUtils {
- /**
- * http get
- *
- * @param url 可带参数的 url 链接
- * @param heads http 头信息
- */
- public String get(String url, Map
heads) { - org.apache.http.client.HttpClient httpClient = HttpClients.createDefault();
- HttpResponse httpResponse = null;
- String result = "";
- HttpGet httpGet = new HttpGet(url);
- if (heads != null) {
- Set
keySet = heads.keySet(); - for (String s : keySet) {
- httpGet.addHeader(s, heads.get(s));
- }
- }
- try {
- httpResponse = httpClient.execute(httpGet);
- HttpEntity httpEntity = httpResponse.getEntity();
- if (httpEntity != null) {
- result = EntityUtils.toString(httpEntity, "utf-8");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return result;
- }
-
- /**
- * http post
- */
- public String post(String url, String data, Map
heads) { - org.apache.http.client.HttpClient httpClient = HttpClients.createDefault();
- HttpResponse httpResponse = null;
- String result = "";
- HttpPost httpPost = new HttpPost(url);
- if (heads != null) {
- Set
keySet = heads.keySet(); - for (String s : keySet) {
- httpPost.addHeader(s, heads.get(s));
- }
- }
- try {
- StringEntity s = new StringEntity(data, "utf-8");
- httpPost.setEntity(s);
- httpResponse = httpClient.execute(httpPost);
- HttpEntity httpEntity = httpResponse.getEntity();
- if (httpEntity != null) {
- result = EntityUtils.toString(httpEntity, "utf-8");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return result;
- }
- }
MD5工具类
- import com.google.common.collect.Maps;
- import org.springframework.stereotype.Component;
-
- import java.nio.charset.StandardCharsets;
- import java.security.MessageDigest;
- import java.util.Map;
- import java.util.concurrent.locks.ReentrantLock;
-
-
- @Component
- public class MD5 {
- private static int DIGITS_SIZE = 16;
- private static char[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-
- private static Map
rDigits = Maps.newHashMapWithExpectedSize(16); -
- static {
- for (int i = 0; i < digits.length; ++i) {
- rDigits.put(digits[i], i);
- }
- }
-
- private static MD5 me = new MD5();
- private MessageDigest mHasher;
- private ReentrantLock opLock = new ReentrantLock();
-
- private MD5() {
- try {
- mHasher = MessageDigest.getInstance("md5");
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- }
-
- public static MD5 getInstance() {
- return me;
- }
-
- public String getMD5String(String content) {
- return bytes2string(hash(content));
- }
-
- public String getMD5String(byte[] content) {
- return bytes2string(hash(content));
- }
-
- public byte[] getMD5Bytes(byte[] content) {
- return hash(content);
- }
-
- /**
- * 对字符串进行md5
- *
- * @param str
- * @return md5 byte[16]
- */
- public byte[] hash(String str) {
- opLock.lock();
- try {
- byte[] bt = mHasher.digest(str.getBytes(StandardCharsets.UTF_8));
- if (null == bt || bt.length != DIGITS_SIZE) {
- throw new IllegalArgumentException("md5 need");
- }
- return bt;
- } finally {
- opLock.unlock();
- }
- }
-
- /**
- * 对二进制数据进行md5
- *
- * @param data
- * @return md5 byte[16]
- */
- public byte[] hash(byte[] data) {
- opLock.lock();
- try {
- byte[] bt = mHasher.digest(data);
- if (null == bt || bt.length != DIGITS_SIZE) {
- throw new IllegalArgumentException("md5 need");
- }
- return bt;
- } finally {
- opLock.unlock();
- }
- }
-
- /**
- * 将一个字节数组转化为可见的字符串
- *
- * @param bt
- * @return
- */
- public String bytes2string(byte[] bt) {
- int l = bt.length;
- char[] out = new char[l << 1];
- for (int i = 0, j = 0; i < l; i++) {
- out[j++] = digits[(0xF0 & bt[i]) >>> 4];
- out[j++] = digits[0x0F & bt[i]];
- }
- return new String(out);
- }
- }
MD5加密工具类
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
-
- import java.security.MessageDigest;
-
- @Component
- public class Md5Utils {
- private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
-
- private static byte[] md5(String s) {
- MessageDigest algorithm;
- try {
- algorithm = MessageDigest.getInstance("MD5");
- algorithm.reset();
- algorithm.update(s.getBytes("UTF-8"));
- byte[] messageDigest = algorithm.digest();
- return messageDigest;
- } catch (Exception e) {
- log.error("MD5 Error...", e);
- }
- return null;
- }
-
- private static final String toHex(byte hash[]) {
- if (hash == null) {
- return null;
- }
- StringBuffer buf = new StringBuffer(hash.length * 2);
- int i;
- for (i = 0; i < hash.length; i++) {
- if ((hash[i] & 0xff) < 0x10) {
- buf.append("0");
- }
- buf.append(Long.toString(hash[i] & 0xff, 16));
- }
- return buf.toString();
- }
-
- public static String hash(String s) {
- try {
- return new String(toHex(md5(s)).getBytes("UTF-8"), "UTF-8");
- } catch (Exception e) {
- log.error("not supported charset...{}", e);
- return s;
- }
- }
- }
pom.xml——>引入顺丰、申通、众邮快递SDK。引入谷歌工具包:调用com.google.common.collect.Maps。
- <dependency>
- <groupId>com.expressgroupId>
- <artifactId>lop-zhongyou-api-sdkartifactId>
- <version>2.0.0version>
- <scope>compilescope>
- dependency>
- <dependency>
- <groupId>com.expressgroupId>
- <artifactId>sf-csim-express-sdkartifactId>
- <version>2.0.0version>
- <scope>compilescope>
- dependency>
- <dependency>
- <groupId>com.expressgroupId>
- <artifactId>sto-link-sdkartifactId>
- <version>2.0.0version>
- <scope>compilescope>
- dependency>
- <dependency>
- <groupId>com.google.guavagroupId>
- <artifactId>guavaartifactId>
- <version>22.0version>
- dependency>
韵达快递——>接收OrderInfo类
- import lombok.Data;
-
- @Data
- public class OrderInfo {
- private String orderid;
- private String mailno;
- private UserInfo sender;
- private UserInfo receiver;
- }
韵达快递——>接收子类UserInfo类
- import lombok.Data;
-
- @Data
- public class UserInfo {
- private String name;
- private String province;
- private String city;
- private String county;
- private String address;
- private String phone;
- private String mobile;
- }
例1:YdExpress——>韵达快递
- import cn.hutool.core.util.StrUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import OrderInfo;
- import UserInfo;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
- import java.io.*;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.nio.charset.StandardCharsets;
- import java.security.MessageDigest;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.TimeUnit;
-
- /**
- * 韵达
- */
- @Service
- public class YdExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(YdExpress.class);
- private static final String TRACK_SERVER_URL = "https://openapi.yundaex.com/openapi/outer/logictis/subscribe";
- private static final String SERVER_URL = "https://openapi.yundaex.com/openapi/outer/logictis/query";
- private static final String APP_KEY = "123456";
- private static final String APP_SECRET = "e10adc3949ba59abbe56e057f20f883e";
- @Resource
- private RedisTemplate redisTemplate;
- private static final String LOGISTICS_TRACK = "logistics::track:{}";
-
- @Override
- public String expressCode() {
- return "YD";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("韵达快递查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = new JSONArray();
- String logisticsTrack = StrUtil.format(LOGISTICS_TRACK, request.getLogisticsNo());
- boolean isTrack = false;
- try {
- if (!redisTemplate.hasKey(logisticsTrack)) {
- //物流轨迹订阅
- String orderid = request.getOrderNo();
- String mailno = request.getLogisticsNo();
-
- String senderName = request.getReceiverName();
- String senderProvince = request.getProvinceName();
- String senderCity = request.getCityName();
- String senderCounty = request.getDistrictName();
- String senderAddress = request.getDetailAddress();
- String senderPhone = request.getReceiverMobile();
- String senderMobile = request.getReceiverMobile();
-
- String receiverName = request.getReceiverName();
- String receiverProvince = request.getProvinceName();
- String receiverCity = request.getCityName();
- String receiverCounty = request.getDistrictName();
- String receiverAddress = request.getDetailAddress();
- String receiverPhone = request.getReceiverMobile();
- String receiverMobile = request.getReceiverMobile();
-
- List
orderInfoList = new ArrayList<>(); - OrderInfo orderInfo = new OrderInfo();
- orderInfo.setOrderid(orderid);
- orderInfo.setMailno(mailno);
- //发货人信息
- UserInfo userInfoSender = new UserInfo();
- userInfoSender.setName(senderName);
- userInfoSender.setProvince(senderProvince);
- userInfoSender.setCity(senderCity);
- userInfoSender.setCounty(senderCounty);
- userInfoSender.setAddress(senderAddress);
- userInfoSender.setPhone(senderPhone);
- userInfoSender.setMobile(senderMobile);
- orderInfo.setSender(userInfoSender);
- //接收人信息
- UserInfo userInfoReceiver = new UserInfo();
- userInfoReceiver.setName(receiverName);
- userInfoReceiver.setProvince(receiverProvince);
- userInfoReceiver.setCity(receiverCity);
- userInfoReceiver.setCounty(receiverCounty);
- userInfoReceiver.setAddress(receiverAddress);
- userInfoReceiver.setPhone(receiverPhone);
- userInfoReceiver.setMobile(receiverMobile);
- orderInfo.setReceiver(userInfoReceiver);
- orderInfoList.add(orderInfo);
- String orders = "{\"orders\":" + JSONObject.toJSONString(orderInfoList) + "}";
- String resTrack = doPostJson(TRACK_SERVER_URL, orders);
- JSONObject jsonObjTrack = JSON.parseObject(resTrack);
- if (jsonObjTrack.getBoolean("result")) {
- redisTemplate.expire(logisticsTrack, 60, TimeUnit.DAYS);
- isTrack = true;
- }
- }
- if (isTrack) {
- String sourceContent = "{\"mailno\":\"" + request.getLogisticsNo() + "\"}";
- String res = doPostJson(SERVER_URL, sourceContent);
- log.info("请求返回结果[{}]", res);
- JSONObject jsonObj = JSON.parseObject(res);
- if (jsonObj.containsKey("data")) {
- JSONObject json = jsonObj.getJSONObject("data");
- if (json.containsKey("steps")) {
- jsonArray = json.getJSONArray("steps");
- }
- }
- }
- } catch (Exception e) {
- log.error("韵达快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "description", "time")));
- return controller(expressSearchResponse, jsonArray, "description", "time");
- }
-
- /**
- * 发送HTTP请求
- *
- * @param apiUrl 请求URL
- * @param jsonParams 请求参数
- * @return String
- */
- private static String doPostJson(String apiUrl, String jsonParams) {
- StringBuffer sbResult = new StringBuffer();
- try {
- URL url = new URL(apiUrl);
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- conn.setDoOutput(true);
- conn.setDoInput(true);
- conn.setUseCaches(false);
- conn.setRequestMethod("POST");
- conn.setRequestProperty("Connection", "Keep-Alive");
- conn.setRequestProperty("Charset", "UTF-8");
- byte[] data = jsonParams.getBytes(StandardCharsets.UTF_8);
- conn.setRequestProperty("Content-Length", String.valueOf(data.length));
- conn.setRequestProperty("Content-Type", "application/json");
- conn.setRequestProperty("app-key", YdExpress.APP_KEY);
- conn.setRequestProperty("req-time", String.valueOf(System.currentTimeMillis()));
- conn.setRequestProperty("sign", MD5(jsonParams + "_" + YdExpress.APP_SECRET));
- conn.connect();
- OutputStream out = new DataOutputStream(conn.getOutputStream());
- out.write(data);
- out.flush();
- out.close();
- if (200 == conn.getResponseCode()) {
- InputStream inputStream = conn.getInputStream();
- try {
- String readLine = null;
- BufferedReader responseReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
-
- while ((readLine = responseReader.readLine()) != null) {
- sbResult.append(readLine).append("\n");
- }
-
- responseReader.close();
- } catch (Exception var12) {
- var12.printStackTrace();
- }
- }
- } catch (Exception var13) {
- var13.printStackTrace();
- }
- return sbResult.toString();
- }
-
- /**
- * Md5加密算法
- *
- * @param str
- * @return
- * @throws Exception
- */
- private static String MD5(String str) throws Exception {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.update(str.getBytes(StandardCharsets.UTF_8));
- byte[] result = md.digest();
- StringBuffer sb = new StringBuffer(32);
- for (int i = 0; i < result.length; ++i) {
- int val = result[i] & 255;
- if (val <= 15) {
- sb.append("0");
- }
- sb.append(Integer.toHexString(val));
- }
- return sb.toString().toLowerCase();
- }
- }
例2:AneExpress——>安能快递
- import cn.hutool.core.codec.Base64;
- import cn.hutool.crypto.SecureUtil;
- import cn.hutool.http.HttpRequest;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- import java.security.NoSuchAlgorithmException;
-
- /**
- * 安能
- **/
- @Service
- public class AneExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(AneExpress.class);
- private static String URL = "http://opc.ane56.com/aneop/services/logisticsQuery/new/query";
- private static String APPKEY = "e10adc3949ba59abbe56e057f20f883e";
- private static String CODE = "ANENG";
-
- @Override
- public String expressCode() {
- return "ANE";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException {
- log.info("安能快递查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = new JSONArray();
- try {
- JSONObject jsonObject = new JSONObject();
- JSONObject params = new JSONObject();
- params.put("ewbNo", request.getLogisticsNo());
- jsonObject.put("params", params.toJSONString());
- String digest = Base64.encode(SecureUtil.md5("{\"ewbNo\":\"" + request.getLogisticsNo() + "\"}" + CODE + APPKEY));
- jsonObject.put("digest", digest);
- jsonObject.put("code", CODE);
- String timestamp = Long.toString(System.currentTimeMillis());
- jsonObject.put("timestamp", timestamp);
- String res = HttpRequest.post(URL).header("Content-type", "application/json").body(jsonObject.toJSONString()).execute().body();
- log.info("请求返回结果[{}]", res);
- JSONObject resObject = JSONObject.parseObject(res);
- jsonArray = resObject.getJSONObject("resultInfo").getJSONArray("traces");
- } catch (Exception e) {
- log.error("安能快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "desc", "operateTime")));
- return controller(expressSearchResponse, jsonArray, "desc", "operateTime");
- }
- }
例3:BestExpress——>百世快递
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 百世
- */
- @Service
- public class BestExpress extends ResponseController implements Express {
-
- private static final Logger log = LoggerFactory.getLogger(BestExpress.class);
- private static String url = "http://edi-q9.ns.800best.com/kd/api/process";
- private static String partnerKey = "49ba59abbe56";
- private static String partnerID = "12345";
- private static String serviceType = "KD_TRACE_QUERY";
- @Resource
- HttpClientUtils httpClientUtils;
-
- @Override
- public String expressCode() {
- return "HTKY";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("百世快递查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArr = null;
- ExpressSearchResponse expressSearchResponse = null;
- try {
- //拼接请求头
- Map
headers = new HashMap<>(4); - headers.put("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
- headers.put("connection", "keep-alive");
- headers.put("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
- headers.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
- //组建数据格式
- String bizData = "{\"mailNos\": {\"mailNo\": [\"" + request.getLogisticsNo() + "\"]}}";
- String sign = Md5Utils.hash(bizData + partnerKey);
- String requestData = "partnerID=" + partnerID + "&serviceType=" + serviceType + "&bizData=" + bizData + "&sign=" + sign;
- //发送请求并接受返回
- String res = httpClientUtils.post(url, requestData, headers);
- log.info("请求返回结果[{}]", res);
- JSONObject json = JSONObject.parseObject(res);
- jsonArr = json.getJSONArray("traceLogs");
- //处理返回结果
- jsonArr = jsonArr.getJSONObject(0).getJSONObject("traces").getJSONArray("trace");
- } catch (Exception e) {
- log.error("百世快递查询出错[{}]", e.getMessage());
- }
- expressSearchResponse = checkResult(jsonArr, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "remark", "acceptTime")));
- return controller(expressSearchResponse, jsonArr, "remark", "acceptTime");
- }
- }
例4:中国邮政快递——>ChinaPostExpress【线下联系邮政快递人员开通账号信息】
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 中国邮政
- */
- @Service
- public class ChinaPostExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(ChinaPostExpress.class);
- @Resource
- HttpClientUtils httpClientUtils;
-
- @Override
- public String expressCode() {
- return "YZPY";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("邮政快递包裹查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = null;
- try {
- String url = "http://211.156.193.140:8000/cotrackapi/api/track/mail/";
- //拼接请求头
- Map
headers = new HashMap<>(2); - headers.put("Version", "ems_track_cn_1.0");
- headers.put("authenticate", "E10ADC3949BA59ABBE56E057F20F883E");
- //组建数据格式
- url = url + request.getLogisticsNo();
- //发送请求并接受返回
- String res = httpClientUtils.get(url, headers);
- //处理返回结果
- log.info("请求返回结果[{}]", res);
- JSONObject json = JSONObject.parseObject(res);
- jsonArray = json.getJSONArray("traces");
- } catch (Exception e) {
- log.error("邮政快递包裹查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "remark", "acceptTime")));
- return controller(expressSearchResponse, jsonArray, "remark", "acceptTime");
- }
- }
例5:EMS——>EmsExpress【线下联系邮政快递人员开通账号信息】
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
-
- /**
- * EMS
- */
- @Service
- public class EmsExpress extends ResponseController implements Express {
- @Resource
- ChinaPostExpress chinaPostExpress;
-
- @Override
- public String expressCode() {
- return "EMS";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- return chinaPostExpress.logisticsSearch(request);
- }
- }
例6:德邦快递——>DepponExpress
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.apache.commons.codec.binary.Base64;
- import org.apache.commons.codec.digest.DigestUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 德邦
- */
- @Service
- public class DepponExpress extends ResponseController implements Express {
-
- private static final Logger log = LoggerFactory.getLogger(DepponExpress.class);
- private static String url = "http://dpapi.deppon.com/dop-interface-sync/standard-query/newTraceQuery.action";
- private static String companyCode = "ABCDEFGHIJKLM";
- private static String appKey = "e10adc3949ba59abbe56e057f20f883e";
- @Resource
- HttpClientUtils httpClientUtils;
-
- @Override
- public String expressCode() {
- return "DBL";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- JSONArray jsonArray = null;
- log.info("德邦快递查询参数[{}]", JSON.toJSONString(request));
- try {
- //拼接请求头
- Map
headers = new HashMap<>(1); - headers.put("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
- //组建数据格式
- String timestamp = String.valueOf(System.currentTimeMillis());
- String params = "{\"mailNo\":\"" + request.getLogisticsNo() + "\"}";
- String digest = Base64.encodeBase64String(DigestUtils.md5Hex(params + appKey + timestamp).getBytes());
- String requestData = "params=" + params + "&digest=" + digest + "×tamp=" + timestamp + "&companyCode=" + companyCode;
- //发送请求并接受返回
- String res = httpClientUtils.post(url, requestData, headers);
- //处理返回结果
- log.info("请求返回结果[{}]", res);
- JSONObject json = JSONObject.parseObject(res);
- jsonArray = json.getJSONObject("responseParam").getJSONArray("trace_list");
- } catch (Exception e) {
- log.error("德邦快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "description", "time")));
- return controller(expressSearchResponse, jsonArray, "description", "time");
- }
- }
例7:极兔快递——>JtExpress
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
- import org.apache.commons.codec.binary.Base64;
- import org.apache.commons.codec.digest.DigestUtils;
-
- import javax.annotation.Resource;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 极兔
- */
- @Service
- public class JtExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(JtExpress.class);
- private static final String API_ACCOUNT = "178337126125932605";
- private static final String PRIVATE_KEY = "0258d71b55fc45e3ad7a7f38bf4b201a";
- private static final String SERVICE_URL = "https://openapi.jtexpress.com.cn/webopenplatformapi/api/logistics/trace";
- @Resource
- HttpClientUtils httpClientUtils;
-
- @Override
- public String expressCode() {
- return "JTSD";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("极兔查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = new JSONArray();
- try {
- //查询参数
- String bizContent = "{\"billCodes\":\"" + request.getLogisticsNo() + "\"}";
- //拼接请求头
- Map
headers = new HashMap<>(); - headers.put("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
- headers.put("apiAccount", API_ACCOUNT);
- headers.put("digest", digestForHead(bizContent));
- headers.put("timestamp", String.valueOf(System.currentTimeMillis()));
- String requestData = "bizContent=" + bizContent;
- Map
jsonMap = new HashMap<>(); - jsonMap.put("header", JSON.toJSONString(headers));
- jsonMap.put("body", requestData);
- log.info("请求参数digest[{}]", digestForHead(bizContent));
- log.info("请求参数headers[{}]", JSON.toJSONString(headers));
- log.info("请求参数body[{}]", requestData);
- log.info("请求jsonMap[{}]", JSON.toJSONString(jsonMap));
- //发送请求并接受返回
- String res = httpClientUtils.post(SERVICE_URL, requestData, headers);
- //处理返回结果
- log.info("请求返回结果[{}]", res);
- JSONObject json = JSONObject.parseObject(res);
- jsonArray = json.getJSONArray("data").getJSONObject(0).getJSONArray("details");
- } catch (Exception e) {
- log.error("极兔快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "desc", "scanTime")));
- return controller(expressSearchResponse, jsonArray, "desc", "scanTime");
- }
-
- private static String digestForHead(String json) {
- String signStr = json + JtExpress.PRIVATE_KEY;
- byte[] encode = (new Base64()).encode(DigestUtils.md5(signStr));
- return new String(encode);
- }
- }
例8:顺丰快递——>SfExpress 【引用顺丰SDK】
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import com.sf.csim.express.service.CallExpressServiceTools;
- import com.sf.csim.express.service.HttpClientUtil;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- import java.util.HashMap;
- import java.util.Map;
- import java.util.UUID;
-
-
- /**
- * 顺丰
- */
- @Service
- public class SfExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(SfExpress.class);
- /**
- * 顾客编码
- */
- private static final String CLIENT_CODE = "ABCDEFGHIJKL";
- /**
- * 丰桥平台生产校验码
- */
- private static final String CHECK_WORD = "E10ADC3949BA59ABBE56E057F20F883E";
- /**
- * 接口服务代码
- */
- private static final String SERVICE_CODE = "EXP_RECE_SEARCH_ROUTES";
- /**
- * 生产环境的地址
- */
- private static final String CALL_URL_PROD = "https://sfapi.sf-express.com/std/service";
-
- @Override
- public String expressCode() {
- return "SF";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("顺丰查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = new JSONArray();
- try {
- Map
params = new HashMap<>(); - String msgData = "{" +
- " \"language\": 0," +
- " \"trackingType\": 1," +
- " \"trackingNumber\": [\"" + request.getLogisticsNo() + "\"]," +
- " \"methodType\": 1," +
- " \"checkPhoneNo\": \"" + request.getReceiverMobile().substring(7) + "\"" +
- "}";
- String timeStamp = String.valueOf(System.currentTimeMillis());
- params.put("partnerID", CLIENT_CODE);
- params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
- params.put("serviceCode", SERVICE_CODE);
- params.put("timestamp", timeStamp);
- params.put("msgData", msgData);
- params.put("msgDigest", CallExpressServiceTools.getMsgDigest(msgData, timeStamp, CHECK_WORD));
- System.out.println(params);
- String res = HttpClientUtil.post(CALL_URL_PROD, params);
- log.info("请求返回结果[{}]", res);
- JSONObject jsonObj = JSON.parseObject(res);
- if (jsonObj.containsKey("apiResultData")) {
- JSONObject json = jsonObj.getJSONObject("apiResultData");
- if (json.containsKey("msgData")) {
- json = json.getJSONObject("msgData").getJSONArray("routeResps").getJSONObject(0);
- if (json.containsKey("routes")) {
- jsonArray = json.getJSONArray("routes");
- }
- }
- }
- } catch (Exception e) {
- log.error("顺丰查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "remark", "acceptTime")));
- return controller(expressSearchResponse, jsonArray, "remark", "acceptTime");
- }
-
- }
例9:申通快递——>StoExpress 【引用申通SDK】
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import com.sto.link.request.LinkRequest;
- import com.sto.link.util.LinkUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * 申通
- */
- @Service
- public class StoExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(StoExpress.class);
- private static String url = "https://cloudinter-linkgatewayonline.sto.cn/gateway/link.do";
- private static String api_name = "STO_TRACE_QUERY_COMMON";
- private static String from_appkey = "ABCDEFGHIJKLMNO";
- private static String from_code = "ABCDEFGHIJKLMNO";
- private static String to_appkey = "sto_trace_query";
- private static String to_code = "sto_trace_query";
- private static String secretKey = "E10ADC3949BA59ABBE56E057F20F883E";
-
- @Override
- public String expressCode() {
- return "STO";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("申通快递查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = new JSONArray();
- try {
- LinkRequest data = new LinkRequest();
- data.setFromAppkey(from_appkey);
- data.setFromCode(from_code);
- data.setToAppkey(to_appkey);
- data.setToCode(to_code);
- data.setApiName(api_name);
- JSONObject jsonObject = new JSONObject();
- List
ll = new ArrayList<>(); - ll.add(request.getLogisticsNo());
- jsonObject.put("waybillNoList", ll);
- data.setContent(jsonObject.toJSONString());
- String res = LinkUtils.request(data, url, secretKey);
- log.info("请求返回结果[{}]", res);
- jsonArray = JSONObject.parseObject(res).getJSONObject("data").getJSONArray(request.getLogisticsNo());
- } catch (Exception e) {
- log.error("申通快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "memo", "opTime")));
- return controller(expressSearchResponse, jsonArray, "memo", "opTime");
- }
- }
例9:众邮快递——>ZyExpress 【引用众邮SDK】
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.jdwl.open.api.sdk.DefaultJdClient;
- import com.jdwl.open.api.sdk.JdClient;
- import com.jdwl.open.api.sdk.JdException;
- import com.jdwl.open.api.sdk.domain.zhongyouex.OrderTraceApi.CommonParam;
- import com.jdwl.open.api.sdk.request.zhongyouex.OrderFindTraceInfoByWaybillCodeLopRequest;
- import com.jdwl.open.api.sdk.response.zhongyouex.OrderFindTraceInfoByWaybillCodeResponse;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- /**
- * 众邮
- */
- @Service
- public class ZyExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(ZyExpress.class);
- private static String serverUrl = "https://api.zhongyouex.com/routerjson";
- private static String accessToken = "E10ADC3949BA59ABBE56E057F20F883E";
- private static String appKey = "E10ADC3949BA59ABBE56E057F20F883E";
- private static String appSecret = "E10ADC3949BA59ABBE56E057F20F883E";
- private static String appCode = "EXPRESS_100";
- private static String source = "1234";
- private static String userCode = "zhangsan123";
-
- @Override
- public String expressCode() {
- return "ZY";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("众邮快递查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = new JSONArray();
- try {
- JdClient client = new DefaultJdClient(serverUrl, accessToken, appKey, appSecret);
- OrderFindTraceInfoByWaybillCodeLopRequest lopRequest = new OrderFindTraceInfoByWaybillCodeLopRequest();
- lopRequest.setWaybillCode(request.getLogisticsNo());
- CommonParam commonParam = new CommonParam();
- commonParam.setAppCode(appCode);
- commonParam.setSource(source);
- commonParam.setUserCode(userCode);
- lopRequest.setCommonParam(commonParam);
- OrderFindTraceInfoByWaybillCodeResponse response = client.execute(lopRequest);
- log.info("请求返回结果[{}]", response.getMsg());
- JSONObject jsonObject = JSONObject.parseObject(response.getMsg());
- jsonArray = jsonObject.getJSONObject("response").getJSONObject("content").getJSONArray("data");
- } catch (JdException e) {
- log.error("众邮快递查询出错[{}]", e.getErrMsg());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "content", "operateTime")));
- return controller(expressSearchResponse, jsonArray, "content", "operateTime");
- }
- }
例10:圆通快递——>YtoExpress
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.apache.commons.lang3.time.DateFormatUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
-
- import javax.annotation.Resource;
- import java.net.URLEncoder;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 圆通
- */
- @Service
- public class YtoExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(YtoExpress.class);
- private static String url = "http://openapi.yto.net.cn/service/waybill_query/v1/X1FKbA";
- private static String user_id = "YTOTEST";
- private static String app_key = "sF1Jzn";
- private static String secret_key = "1QLlIZ";
- private static String v = "1.01";
- private static String method = "yto.Marketing.WaybillTrace";
- @Resource
- HttpClientUtils httpClientUtils;
-
- @Override
- public String expressCode() {
- return "YTO";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) {
- log.info("圆通快递查询参数[{}]", JSON.toJSONString(request));
- JSONArray jsonArray = new JSONArray();
- try {
- JSONObject jsonObject = new JSONObject();
- jsonObject.put("Number", request.getLogisticsNo());
- String timestamp = DateFormatUtils.format(new Date(), "yyyy-mm-dd HH:mm:ss");
- String sign = secret_key + "app_key" + app_key + "formatJSONmethod" + method + "timestamp"
- + timestamp + "user_id" + user_id + "v" + v;
- sign = MD5.getInstance().getMD5String(sign).toUpperCase();
- String params = "sign=" + sign + "&app_key=" + app_key + "&format=JSON&method=" + method + "×tamp="
- + timestamp + "&user_id=" + user_id + "&v=" + v + "¶m=" + URLEncoder.encode(jsonObject.toJSONString(), "UTF-8");
- Map
headers = new HashMap<>(1); - headers.put("Content-Type", "application/x-www-form-urlencoded");
- String res = httpClientUtils.post(url, params, headers);
- log.info("请求返回结果[{}]", res);
- jsonArray = JSONObject.parseArray(res);
- } catch (Exception e) {
- log.error("圆通快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "processInfo", "upload_Time")));
- return controller(expressSearchResponse, jsonArray, "processInfo", "upload_Time");
- }
- }
例11:中通快递——>ZtoExpress【旧版】
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
- import org.springframework.util.Base64Utils;
-
- import javax.annotation.Resource;
- import java.net.URLEncoder;
- import java.security.NoSuchAlgorithmException;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 中通
- */
- @Component
- public class ZtoExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(ZtoExpress.class);
- private static String url = "https://japi.zto.com/traceInterfaceNewTraces";
- private static String companyId = "e10adc3949ba59abbe56e057f20f883e";
- private static String key = "abcdefghijkl";
- private static String msg_type = "NEW_TRACES";
- @Resource
- HttpClientUtils httpClientUtils;
-
- @Override
- public String expressCode() {
- return "ZTO";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException {
- JSONArray jsonArray = null;
- log.info("中通快递查询参数[{}]", JSON.toJSONString(request));
- try {
- //组建数据格式
- String strToDigest = "data=['" + request.getLogisticsNo() + "']&company_id=" + companyId + "&msg_type=" + msg_type + key;
- String dataDigest = Base64Utils.encodeToString(MD5.getInstance().hash(strToDigest));
- String requestData = "data=" + URLEncoder.encode("['" + request.getLogisticsNo() + "']", "UTF-8") +
- "&company_id=" + companyId + "&msg_type=" + msg_type;
- //拼接请求头
- Map
headers = new HashMap<>(3); - headers.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
- headers.put("x-companyId", companyId);
- headers.put("x-dataDigest", dataDigest);
- //发送请求并接受返回
- String res = httpClientUtils.post(url, requestData, headers);
- //处理返回结果
- log.info("请求返回结果[{}]", res);
- JSONObject json = JSONObject.parseObject(res);
- jsonArray = json.getJSONArray("data").getJSONObject(0).getJSONArray("traces");
- } catch (Exception e) {
- log.error("中通快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("请求返回[{}]", JSON.toJSONString(controller(expressSearchResponse, jsonArray, "desc", "scanDate")));
- return controller(expressSearchResponse, jsonArray, "desc", "scanDate");
- }
- }
例12:中通快递——>ZtoExpress【新版】
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;;
- import ExpressSearchRequest;
- import ExpressSearchResponse;
- import zop.EncryptionType;
- import zop.ZopClient;
- import zop.ZopPublicRequest;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
-
- import java.io.IOException;
- import java.security.NoSuchAlgorithmException;
-
- /**
- * 中通
- */
- @Component
- public class ZtoExpress extends ResponseController implements Express {
- private static final Logger log = LoggerFactory.getLogger(ZtoExpress.class);
- private static String url = "https://japi.zto.com/zto.merchant.waybill.track.query";
- private static String appKey = "ea8a706c4c34a168abcde";
- private static String appSecret = "827ccb0eea8a706c4c34a16891f84e7b";
-
- @Override
- public String expressCode() {
- return "ZTO";
- }
-
- @Override
- public ExpressSearchResponse logisticsSearch(ExpressSearchRequest request) throws NoSuchAlgorithmException {
- JSONArray jsonArray = null;
- log.info("中通快递查询参数[{}]", JSON.toJSONString(request));
- ZopClient client = new ZopClient(appKey, appSecret);
- ZopPublicRequest zopPublicRequest = new ZopPublicRequest();
- String mobilePhone = request.getReceiverMobile().substring(request.getReceiverMobile().length() - 4);
- zopPublicRequest.setBody("{\"billCode\":\"" + request.getLogisticsNo() + "\",\"mobilePhone\":\"" + mobilePhone + "\"}");
- zopPublicRequest.setUrl(url);
- zopPublicRequest.setBase64(true);
- zopPublicRequest.setEncryptionType(EncryptionType.MD5);
- zopPublicRequest.setTimestamp(null);
- try {
- String res = client.execute(zopPublicRequest);
- //处理返回结果
- log.info("请求返回结果[{}]", res);
- JSONObject json = JSONObject.parseObject(res);
- jsonArray = json.getJSONArray("result");
- log.info("请求返回结果jsonArray[{}]", jsonArray);
- } catch (IOException e) {
- log.error("中通快递查询出错[{}]", e.getMessage());
- }
- ExpressSearchResponse expressSearchResponse = checkResult(jsonArray, request);
- log.info("中通快递返回数据[{}]", JSON.toJSONString(controllerZto(expressSearchResponse, jsonArray, "desc", "scanDate")));
- return controllerZto(expressSearchResponse, jsonArray, "desc", "scanDate");
- }
- }
zop :中通快递新版所需公共资源包

zop 之 EncryptionType 枚举类
- public enum EncryptionType {
- MD5,
- SHA256,
- HmacSHA256
- }
zop 之 HttpUtil 工具类
- import java.io.BufferedReader;
- import java.io.DataOutputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.net.HttpURLConnection;
- import java.net.URL;
- import java.nio.charset.Charset;
- import java.util.Map;
-
- public class HttpUtil {
- private static final int DEFAULT_TIMEOUT = 3000;
-
- public static String post(String interfaceUrl, Map
headers, String queryString) throws IOException { - URL url = new URL(interfaceUrl);
- HttpURLConnection con = (HttpURLConnection) url.openConnection();
- con.setRequestMethod("POST");
- con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
- con.setDoOutput(true);
- con.setConnectTimeout(DEFAULT_TIMEOUT);
- con.setReadTimeout(DEFAULT_TIMEOUT);
- for (Map.Entry
e : headers.entrySet()) { - con.setRequestProperty(e.getKey(), e.getValue());
- }
- DataOutputStream out = null;
- BufferedReader in = null;
- try {
- out = new DataOutputStream(con.getOutputStream());
- out.write(queryString.getBytes(Charset.forName("UTF-8")));
- out.flush();
- in = new BufferedReader(
- new InputStreamReader(con.getInputStream(), "UTF-8"));
- String inputLine;
- StringBuilder content = new StringBuilder();
- while ((inputLine = in.readLine()) != null) {
- content.append(inputLine);
- }
- return content.toString();
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (Exception ignored) {
- }
- }
- if (in != null) {
- try {
- in.close();
- } catch (Exception ignored) {
- }
- }
- }
- }
-
- public static String postJson(String interfaceUrl, Map
headers, String json) throws IOException { - URL url = new URL(interfaceUrl);
- HttpURLConnection con = (HttpURLConnection) url.openConnection();
- con.setRequestMethod("POST");
- con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
- con.setDoOutput(true);
- con.setConnectTimeout(DEFAULT_TIMEOUT);
- con.setReadTimeout(DEFAULT_TIMEOUT);
- for (Map.Entry
e : headers.entrySet()) { - con.setRequestProperty(e.getKey(), e.getValue());
- }
- DataOutputStream out = null;
- BufferedReader in = null;
- try {
- out = new DataOutputStream(con.getOutputStream());
- out.write(json.getBytes(Charset.forName("UTF-8")));
- out.flush();
- in = new BufferedReader(
- new InputStreamReader(con.getInputStream(), "UTF-8"));
- String inputLine;
- StringBuilder content = new StringBuilder();
- while ((inputLine = in.readLine()) != null) {
- content.append(inputLine);
- }
- return content.toString();
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (Exception ignored) {
- }
- }
- if (in != null) {
- try {
- in.close();
- } catch (Exception ignored) {
- }
- }
- }
- }
- }
zop 之 ZopClient 工具类
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.net.URLEncoder;
- import java.util.HashMap;
- import java.util.Map;
-
- public class ZopClient {
- private final ZopProperties properties;
-
- public ZopClient(ZopProperties properties) {
- this.properties = properties;
- }
-
- public ZopClient(String appKey, String appSecret) {
- this.properties = new ZopProperties(appKey, appSecret);
- }
-
- public String execute(ZopPublicRequest request) throws IOException {
- String jsonBody = request.getBody();
- if (jsonBody == null) {
- Map
params = request.getParams(); - StringBuilder queryBuilder = new StringBuilder();
- StringBuilder strToDigestBuilder = new StringBuilder();
- for (Map.Entry
e : params.entrySet()) { - strToDigestBuilder.append(e.getKey()).append("=").append(e.getValue()).append("&");
- queryBuilder.append(urlEncode(e.getKey())).append("=").append(urlEncode(e.getValue())).append("&");
- }
- String queryString = queryBuilder.substring(0, queryBuilder.length() - 1);
- String strToDigest = strToDigestBuilder.substring(0, strToDigestBuilder.length() - 1);
- strToDigest = strToDigest + properties.getKey();
- Map
headers = new HashMap(); - headers.put("x-companyid", properties.getCompanyId());
- headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp(), request.getSecretKey()));
- if (request.getTimestamp() != null) {
- headers.put("x-timestamp", String.valueOf(request.getTimestamp()));
- }
- return HttpUtil.post(request.getUrl(), headers, queryString);
- } else {
- Map
headers = new HashMap<>(); - String strToDigest = jsonBody + properties.getKey();
- headers.put("x-companyid", properties.getCompanyId());
- headers.put("x-datadigest", ZopDigestUtil.digest(strToDigest, request.getBase64(), request.getEncryptionType(), request.getTimestamp(), request.getSecretKey()));
- if (request.getTimestamp() != null) {
- headers.put("x-timestamp", String.valueOf(request.getTimestamp()));
- }
- return HttpUtil.postJson(request.getUrl(), headers, jsonBody);
- }
- }
-
- private String urlEncode(String str) {
- try {
- return URLEncoder.encode(str, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- return str;
- }
- }
- }
zop 之 ZopDigestUtil 工具类
- import org.apache.commons.codec.binary.Base64;
- import org.apache.commons.codec.binary.Hex;
- import org.apache.commons.codec.digest.DigestUtils;
-
- import javax.crypto.Mac;
- import javax.crypto.SecretKey;
- import javax.crypto.spec.SecretKeySpec;
- import java.nio.charset.StandardCharsets;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.util.Map;
- import java.util.Objects;
- import java.util.concurrent.ConcurrentHashMap;
-
- public class ZopDigestUtil {
- private static final String HMAC_SHA_256 = "HmacSHA256";
- private static final Map
MAC_MAP = new ConcurrentHashMap<>(); -
- public static String digest(String str, Boolean isBase64, EncryptionType encryptionType, Long timestamp, String secretKey) {
- if (timestamp != null) {
- str = timestamp + str;
- }
- boolean base64 = isBase64 == null || isBase64;
- switch (encryptionType) {
- case SHA256:
- return base64 ? Base64.encodeBase64String(DigestUtils.sha256(str)) : DigestUtils.sha256Hex(str);
- case HmacSHA256:
- return base64 ? Base64.encodeBase64String(hmacSha256(secretKey, str)) : hmacSha256Str(secretKey, str);
- default:
- return base64 ? Base64.encodeBase64String(DigestUtils.md5(str)) : DigestUtils.md5Hex(str);
- }
- }
-
- public static String hmacSha256Str(String key, String body) {
- return Hex.encodeHexString(hmacSha256(key, body));
- }
-
- public static byte[] hmacSha256(String key, String body) {
- if (Objects.isNull(key)) {
- key = "";
- }
- Mac mac = MAC_MAP.get(key);
- if (mac == null) {
- try {
- mac = Mac.getInstance(HMAC_SHA_256);
- SecretKey secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), HMAC_SHA_256);
- mac.init(secretKey);
- MAC_MAP.put(key, mac);
- } catch (NoSuchAlgorithmException | InvalidKeyException e) {
- throw new RuntimeException(e);
- }
- }
- return mac.doFinal(body.getBytes(StandardCharsets.UTF_8));
- }
- }
zop 之 ZopProperties 配置类
- public class ZopProperties {
- private String companyId;
- private String key;
-
- public ZopProperties() {
- }
-
- public ZopProperties(String appKey, String appSecret) {
- this.companyId = appKey;
- this.key = appSecret;
- }
-
- public String getCompanyId() {
- return companyId;
- }
-
- public void setCompanyId(String companyId) {
- this.companyId = companyId;
- }
-
- public String getKey() {
- return key;
- }
-
- public void setKey(String key) {
- this.key = key;
- }
- }
zop 之 ZopPublicRequest 请求类
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
-
- import java.util.HashMap;
- import java.util.Map;
-
- public class ZopPublicRequest {
-
- private String url;
-
- private Map
params = new HashMap(); -
- // 如果body有值,表示使用application/json的方式传值
- private String body;
-
- /**
- * 签名是否需要base64
- */
- private Boolean isBase64;
-
- /**
- * 加密方式,MD5或者SHA256
- */
- private EncryptionType encryptionType;
-
- /**
- * HmacSHA256加密key
- */
- private String secretKey;
-
- /**
- * 时间戳,如果接口文档未标识使用时间戳请不要传值,否则会导致签名错误
- */
- private Long timestamp;
-
- public ZopPublicRequest() {
- }
-
- public void setBody(String body) {
- this.body = body;
- }
-
-
- public String getBody() {
- return body;
- }
-
- public void addParam(String k, String v) {
- params.put(k, v);
- }
-
- public void setData(String data) {
- try {
- JSONObject jsonObject = JSON.parseObject(data);
- for (Map.Entry
entry : jsonObject.entrySet()) { - params.put(entry.getKey(), entry.getValue().toString());
- }
- } catch (Exception e) {
- throw new RuntimeException("JSON格式不对,请检查数据", e);
- }
- }
-
- public void setDataObj(Map
data) { - params.putAll(data);
- }
-
- public void addParam(Map
p) { - for (Map.Entry
entry : p.entrySet()) { - params.put(entry.getKey(), entry.getValue());
- }
- }
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public Map
getParams() { - return params;
- }
-
- public void setParams(Map
params) { - this.params = params;
- }
-
- public Boolean getBase64() {
- return isBase64;
- }
-
- public void setBase64(Boolean base64) {
- isBase64 = base64;
- }
-
- public EncryptionType getEncryptionType() {
- return encryptionType;
- }
-
- public void setEncryptionType(EncryptionType encryptionType) {
- this.encryptionType = encryptionType;
- }
-
- public String getSecretKey() {
- return secretKey;
- }
-
- public void setSecretKey(String secretKey) {
- this.secretKey = secretKey;
- }
-
- public Long getTimestamp() {
- return timestamp;
- }
-
- public void setTimestamp(Long timestamp) {
- this.timestamp = timestamp;
- }
- }