Spring Boot(四)—— 快递100查询物流信息

caroly 2020年08月18日 62次浏览

查询快递公司

配置文件

import lombok.Data;
import org.springframework.stereotype.Component;

@Data
@Component
public class SynConfig {
    public static String key = "xxxxxxx";                //贵司的授权key
    public static String customer = "xxxxxxxx";            //贵司的查询公司编号
    public static int resultv2 = 0;                //开启行政规划解析
    
    // 实时查询物流信息地址
    public static final String SYNQUERY_URL = "http://poll.kuaidi100.com/poll/query.do";

    // 查询快递公司地址
    public static final String SYNAUTONUMBER = "http://www.kuaidi100.com/autonumber/auto";
}

实体类封装

import lombok.Data;

@Data
public class ExpressVO {
    private String message;//无意义,请忽略

    private String nu;//物流单号

    private String ischeck;//无意义,请忽略

    private String condition;//无意义,请忽略

    private String com;//物流公司编号

    private String comCode;//公司简码

    /**
     * 查询结果状态:
     * 0:物流单暂无结果,
     * 1:查询成功,实际测试发现查询成功返回的是200
     * 2:接口出现异常,
     */
    private String status;

    /**
     * 快递单当前的状态 :
     * 0:在途,即货物处于运输过程中;
     * 1:揽件,货物已由快递公司揽收并且产生了第一条跟踪信息;
     * 2:疑难,货物寄送过程出了问题;
     * 3:签收,收件人已签收;
     * 4:退签,即货物由于用户拒签、超区等原因退回,而且发件人已经签收;
     * 5:派件,即快递正在进行同城派件;
     * 6:退回,货物正处于退回发件人的途中;
     * 7:转投,货物转给其他快递公司邮寄;
     * 10:待清关,货物等待清关;
     * 11:清关中,货物正在清关流程中;
     * 12:已清关,货物已完成清关流程;
     * 13:清关异常,货物在清关过程中出现异常;
     * 14:收件人拒签,收件人明确拒收;
     */
    private String state;
}

查询快递公司实体类

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 物流实时查询请求
 *
 * @author Administrator
 */
public class SynQueryUtils {

    private String key;            //授权key
    private String customer;    //实时查询公司编号

    public SynQueryUtils(String key, String customer) {
        this.key = key;
        this.customer = customer;
    }

    /**
     * 查询快递公司
     *
     * @param num 物流单号
     * @return
     * @throws Exception
     */
    public static List<ExpressVO> queryGetKD(String num) {
        String postUrl = SynConfig.SYNAUTONUMBER + "?num=" + num + "&key=" + SynConfig.key;
        StringBuffer result = new StringBuffer();
        BufferedReader in = null;
        try {
            URL realUrl = new URL(postUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e);
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
            }
        }

        List<ExpressVO> list = new Gson().fromJson(result.toString(), new TypeToken<List<ExpressVO>>() {
        }.getType());
        return list;
    }
}

查询操作

List<ExpressVO> list = SynQueryUtils.queryGetKD(num);

快递100的智能单号识别功能依托于快递100大数据,对快递单号进行识别,准确率可达90%以上。但因目前快递单号各快递公司格式不一致,返回的数据是多个可能的快递公司列表,相似度高的快递公司排名靠前。


查询物流

工具类中新添方法

/**
 * 实时查询快递单号
 *
 * @param com      快递公司编码
 * @param num      快递单号
 * @param phone    手机号
 * @param resultv2 开通区域解析功能:0-关闭;1-开通
 * @return
 */
public String synQueryData(String com, String num, String phone, int resultv2) {

    StringBuilder param = new StringBuilder("{");
    param.append("\"com\":\"").append(com).append("\"");
    param.append(",\"num\":\"").append(num).append("\"");
    param.append(",\"phone\":\"").append(phone).append("\"");
    if (1 == resultv2) {
        param.append(",\"resultv2\":1");
    } else {
        param.append(",\"resultv2\":0");
    }
    param.append("}");

    Map<String, String> params = new HashMap<String, String>();
    params.put("customer", this.customer);
    String sign = MD5Utils.encode(param + this.key + this.customer);
    params.put("sign", sign);
    params.put("param", param.toString());

    return this.post(params);
}

/**
 * 发送post请求
 */
public String post(Map<String, String> params) {
    StringBuffer response = new StringBuffer("");

    BufferedReader reader = null;
    try {
        StringBuilder builder = new StringBuilder();
        for (Map.Entry<String, String> param : params.entrySet()) {
            if (builder.length() > 0) {
                builder.append('&');
            }
            builder.append(URLEncoder.encode(param.getKey(), "UTF-8"));
            builder.append('=');
            builder.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
        }
        byte[] bytes = builder.toString().getBytes("UTF-8");

        URL url = new URL(SynConfig.SYNQUERY_URL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(3000);
        conn.setReadTimeout(3000);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("accept", "*/*");
        conn.setRequestProperty("connection", "Keep-Alive");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("Content-Length", String.valueOf(bytes.length));
        conn.setDoOutput(true);
        conn.getOutputStream().write(bytes);

        reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

        String line = "";
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != reader) {
                reader.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return response.toString();
}

查询操作

SynQueryUtils util = new SynQueryUtils(SynConfig.key, SynConfig.customer);
String result = util.synQueryData(/*快递公司名缩写*/, /*物流单号*/, /*手机号后四位*/, SynConfig.resultv2);
ObjectMapper objectMapper= new ObjectMapper();
// 转换为格式化的json
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
// 如果json中有新增的字段并且是实体类类中不存在的,不报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JsonNode jsonNode= objectMapper.readTree(result);
ObjectNode objectNode= (ObjectNode) jsonNode;
return objectMapper.valueToTree(objectNode);

返回结果

{
    "message": "ok",
    "nu": "xxxxxxxx",
    "ischeck": "1",
    "condition": "D01",
    "com": "xx快递",
    "status": "200",
    "state": "3",
    "data": [
        {
            "time": "2020-07-31 18:57:13",
            "ftime": "2020-07-31 18:57:13",
            "context": "【代收点】您的快件已签收,签收人在【xxxxx(已签收签收人凭取货码签收)】领取。"
        },
        {
            "time": "2020-07-31 11:51:18",
            "ftime": "2020-07-31 11:51:18",
            "context": "【代收点】您的快件已送达 xxxxx 保管,地址:快件已暂存至xxxxx如有疑问请联系xxxxx,请及时领取,如有疑问请电联快递员:xxxxx【xxxxx】。"
        },
        {
            "time": "2020-07-31 09:16:04",
            "ftime": "2020-07-31 09:16:04",
            "context": "【xx市】xxxxx 快递员 xxxxx xxxxx 正在为您派件【xxxxx为xxxxx快递员外呼专属号码,请放心接听】"
        },
        {
            "time": "2020-07-31 08:01:00",
            "ftime": "2020-07-31 08:01:00",
            "context": "【xx市】已离开 xxxxx分拨分部;发往 xxxxx分部"
        },
        {
            "time": "2020-07-31 04:05:42",
            "ftime": "2020-07-31 04:05:42",
            "context": "【xx市】已离开 xxxxx;发往 xxxxx分部"
        },
        {
            "time": "2020-07-30 11:07:44",
            "ftime": "2020-07-30 11:07:44",
            "context": "【xx市】已离开 xxxxx;发往 xxxxx分部"
        },
        {
            "time": "2020-07-30 10:08:39",
            "ftime": "2020-07-30 10:08:39",
            "context": "【xx市】已到达 xxxxx"
        },
        {
            "time": "2020-07-29 02:30:06",
            "ftime": "2020-07-29 02:30:06",
            "context": "【xx市】已离开 xxxxx;发往 xxxxx"
        },
        {
            "time": "2020-07-29 02:20:23",
            "ftime": "2020-07-29 02:20:23",
            "context": "【xx市】已离开 xxxxx;发往 xxxxx"
        },
        {
            "time": "2020-07-29 02:09:05",
            "ftime": "2020-07-29 02:09:05",
            "context": "【xx市】已到达 xxxxx"
        },
        {
            "time": "2020-07-28 16:39:46",
            "ftime": "2020-07-28 16:39:46",
            "context": "【xx市】xxxxx 已揽收"
        }
    ]
}