这里只是记录一下。第三方都会提供很详细的demo和技术文档,或者安排专业人员进行联调。

第三方物流接口对比

快递查询API有即时查询和订阅查询两种,即时是请求即返回数据,订阅则是订阅快递单号到接口,有物流轨迹更新则全量返回数据。目前常用的有快递鸟、快递100、聚合数据、阿里云物流等。

快递鸟即时API可以查询3000次,3000以上接订阅接口,统一接口模式接入,常用快递均支持查询,还有订阅API、在线下单API、电子面单API,接口均不收取费用,没有要求用户添加外链,支持418家国内外快递物流查询。

快递100每天可以免费查询2000次,超过2000次收费,每次0.06~0.1元不等,如果查询的量大的话可以降低费用,免费的接口有几家常用快递不支持接口模式,只支持htmlAPI,要求用户添加外链,支持300多家国内外快递物流查询。

聚合数据按次数购买,1元100,300元20000次。

阿里云:【快递查询api,快递物流单号识别】近500+家全国快递查询API,1个单号,自动识别,稳定高效,包括:顺丰、申通、圆通、韵达、中通、汇通、EMS、天天、国通、德邦、宅急送等几百家快递物流查询接口。收费标准:按照次数购买。

接口示例

因为公司用的都是阿里云的产品,所以这里最后选择了阿里云的物流API。按照次数为单位购买的,可免费试用100次。

java pom 引入中通快递 java快递查询_API

JAVA接入

@Controller
@RequestMapping("/api/kdwl")
public class ApiKdwlController {

    private Logger logger = LoggerFactory.getLogger(ApiKdwlController.class);

    // 物流信息缓存间隔暂定3个小时
    private static final Long maxCacheTime = 1000 * 60 * 60 * 3L;

    /**
     快递物流查询接口
     商品购买地址:https://market.aliyun.com/products/56928004/cmapi022273.html
     String host = "http://kdwlcxf.market.alicloudapi.com"; //服务器
     String path = "/kdwlcx"; //接口地址
     */
    @RequestMapping("/q_wl_info")
    @ResponseBody
    public Map<String, Object> queryWlInfo(String no, String type) {
        if (StringUtils.isEmpty(no)) {
            throw new BusiException(E.INVALID_PARAMETER, "请传入运单号");
        }

        // no ="801132164062135036"
        // String host = "http://kdwlcxf.market.alicloudapi.com";
        // String path = "/kdwlcx";

        // String host = "https://wdexpress.market.alicloudapi.com";
        // String path = "/gxali";

        String host = "https://wuliu.market.alicloudapi.com";
        String path = "/kdi";

        String method = "GET";

        String appcode = "fadde964aead4dcabfbb7dfac600c4sd";  // !!! 替换这里填写你自己的AppCode 请在买家中心查看

        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + appcode); //格式为:Authorization:APPCODE 83359fd73fe11248385f570e3c139xxx
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("no", no);  // !!! 请求参数  运单号
        if (StringUtils.isNotEmpty(type)) {
            querys.put("type", type);// !!! 请求参数   快递公司
        }

        // 物流信息
        String returnStr = "";

        Jedis jedis = RedisPool.getJedis();
        Map<String, Object> returnMap = new HashMap<String, Object>();

        try {
            logger.info("---------开始查询运单号为{}的物流信息", no);

            // 只有当redis里面有缓存,且缓存时间不超过最大缓存时长,直接取缓存数据
            if (jedis.hexists(Rkey.KDWL_INFO_CACHE, no)) {

                // redis已经有缓存
                String kdwlInfo = jedis.hget(Rkey.KDWL_INFO_CACHE, no);
                if (StringUtils.isNotEmpty(kdwlInfo)) {
                    Map<String, Object> kdwlInfoToMap =  JsonUtils.toBean(kdwlInfo, new TypeReference<Map<String, Object>>() {
                    });
                    Long cacheBeginTime = (Long) kdwlInfoToMap.get("queryTime");
                    // 计算已经缓存时长
                    if (System.currentTimeMillis() - cacheBeginTime < maxCacheTime) {
                        // 直接取缓存
                        // kdwlInfoToMap.remove("queryTime");
                        logger.info("---------此次查询的物流信息来至于Redis缓存");
                        logger.info("---------查询运单号为{}的物流信息结束,物流信息:{}", no, kdwlInfo);
                        return kdwlInfoToMap;
                    } else {
                        // TODO: 2018/8/23 这里已经存过缓存时间 如果缓存数据得到的 物流的状态是已签收,是否需要重新查询??还是直接返回

                    }

                }
            }

            // 重新查询最新物流信息
            HttpResponse response = HttpUtils.doGet(host, path, method, headers, querys);

            // 从返回信息中拿到
            returnStr = EntityUtils.toString(response.getEntity());

            if (StringUtils.isEmpty(returnStr)) {
                throw new BusiException(E.INVALID_REQUEST, "查询物流信息失败");
            }

            // 重新缓存 [这里包含运单号输错 也缓存 避免有人故意调我们物流接口 次数用完]
            returnMap = JsonUtils.toBean(returnStr, new TypeReference<Map<String, Object>>() {
            });
            if (returnMap != null) {
                returnMap.put("queryTime", System.currentTimeMillis());
            }
            jedis.hset(Rkey.KDWL_INFO_CACHE, no, JsonUtils.toJson(returnMap));

            logger.info("---------此次查询的物流信息来至于重新查询");
            logger.info("---------查询运单号为{}的物流信息结束,物流信息:{}", no, returnStr);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            RedisPool.returnJedis(jedis);
        }

        return returnMap;
    }
}

接口说明:

########################################## 物流查询 #########################################################
1.根据运单号查询物流信息
url:
    api/kdwl/q_wl_info

param:
    no: 801132164062135036       // 运单号  (必传)
    type: zto        // 快递公司代码: 可不填自动识别,填了查询更快 (可不传) 

return:
    //  错误码 错误信息    描述
        201 快递单号错误  快递单号错误
        203 快递公司不存在 快递公司不存在
        204 快递公司识别失败    快递公司识别失败
        205 没有信息    没有信息
        207 该单号被限制,错误单号 该单号被限制,错误单号;一个单号对应多个快递公司,请求须指定快递公司

    // 订单号错误 或者其他情况
    {
      "status": "203",
      "msg": "快递公司不存在",
      "result": "",
      "queryTime": 1535013305603
    }

    // 正确结果
    {
      "status": "0",  // 请求状态码
      "msg": "ok",   // 返回信息
      "result": {
        "number": "801132164062135036",   // 运单号
        "type": "YTO",   // 快递公司代码
        "list": [{ //物流信息
            "time": "2018-03-09 11:59:26",
            "status": "【石家庄市】 快件已在 【长安三部】 签收,签收人: 本人, 感谢使用中通快递,期待再次为您服务!"
        }, {
            "time": "2018-03-09 09:03:10",
            "status": "【石家庄市】 快件已到达 【长安三部】(0311-85344265),业务员 容晓光(13081105270) 正在第1次派件, 请保持电话畅通,并耐心等待"
        }, {
            "time": "2018-03-08 23:43:44",
            "status": "【石家庄市】 快件离开 【石家庄】 发往 【长安三部】"
        }, {
            "time": "2018-03-08 21:00:44",
            "status": "【石家庄市】 快件到达 【石家庄】"
        }, {
            "time": "2018-03-07 01:38:45",
            "status": "【广州市】 快件离开 【广州中心】 发往 【石家庄】"
        }, {
            "time": "2018-03-07 01:36:53",
            "status": "【广州市】 快件到达 【广州中心】"
        }, {
            "time": "2018-03-07 00:40:57",
            "status": "【广州市】 快件离开 【广州花都】 发往 【石家庄中转】"
        }, {
            "time": "2018-03-07 00:01:55",
            "status": "【广州市】 【广州花都】(020-37738523) 的 马溪 (18998345739) 已揽收"
        }],
        "deliverystatus": "3",  /*  1.在途中 2.正在派件 3.已签收 4.派送失败  */
        "issign": "1",    /*  是否签收  1:已签收 0:未签收*/
        "expName": "圆通速递",   // 快递名称
        "expSite": "www.yto.net.cn ",    // 快递公司网址
        "expPhone": "95554"     // 快递公司联系电话 
      },
      "queryTime": 1535012513032   //请求时间 不管
    }

###############################################################################################################