物流查询

做商城项目的,最好是可以直接在商城中查询订单的物流信息。所以新增物流查询功能。所用的物流查询,都由快递鸟提供。由于每天查询的次数不可预知,所以需要将查询的数据存放至数据库,避免重复查询,占用资源。

即时查询

使用情况:若从数据库查询不到物流消息时,则调用即时查询,将接收到的数据添加至数据库。作用情况:物流查询功能未更新之前的订单。 每日调用次数限制不超过3000次,API地址:http://www.kdniao.com/api-track 请求参数

  • 请求参数RequestData
    //OrderCode	订单编号--订单编号可以为空,不是必填
    private String OrderCode;
    //ShipperCode	快递公司编码
    private String ShipperCode;
    //LogisticCode	物流单号
    private String LogisticCode;
  • 即时查询方法,MD5加密和base64编码官方demo中有,所以不再重复贴
    //请求url
    private static final String ReqURL="http://api.kdniao.cc/Ebusiness/EbusinessOrderHandle.aspx";

    /**
     * 即时查询
     * @param ShipperCode  快递公司编码
     * @param LogisticCode 物流运单号
     * @throws Exception
     */
    public static String TrackQuery(String ShipperCode, String LogisticCode) throws Exception {
        TrackQueryRequestData trackQueryRequestData = new TrackQueryRequestData();
        trackQueryRequestData.setShipperCode(ShipperCode);
        trackQueryRequestData.setLogisticCode(LogisticCode);
        String requestData = JSONObject.fromObject(trackQueryRequestData).toString();
        Map<String, String> params = new HashMap<String, String>();
        params.put("RequestData", urlEncoder(requestData, "UTF-8"));
        params.put("EBusinessID", Commons.getKDNEBusinessID());
        params.put("RequestType", "1002");
        String dataSign = encrypt(requestData, Commons.getKDNAppKey(), "UTF-8");
        params.put("DataSign", urlEncoder(dataSign, "UTF-8"));
        params.put("DataType", "2");

        String result = sendPost(ReqURL, params);

        return result;
    }

物流查询

使用情况:没新增一个订单,发货时去订阅物流消息,并将快递公司编码和快递单号存放至数据库,当物流消息更新之后,接到快递鸟推送过来的信息,再将信息update至数据库。 适用于日查询量>3000次的网站和系统,请求参数同即时查询。

订阅

根据快递公司编码和快递单号,对物流信息进行订阅,可以进入调试平台进行调试,方法如下:

//请求url--正式
    private static final String ReqURL="http://api.kdniao.cc/api/dist";
    //请求url--测试
//    private static String ReqURL="http://testapi.kdniao.cc:8081/api/dist";

    /**
     * Json方式  物流追踪
     * @throws Exception
     */
    public static String SubscribeOrderTraces(String ShipperCode, String LogisticCode) throws Exception{
        SubscribeRequestData subscribeRequestData = new SubscribeRequestData();
        subscribeRequestData.setLogisticCode(LogisticCode);
        subscribeRequestData.setShipperCode(ShipperCode);
        String requestData = JSONObject.fromObject(subscribeRequestData).toString();
        Map<String, String> params = new HashMap<String, String>();
        params.put("RequestData", urlEncoder(requestData, "UTF-8"));
        params.put("EBusinessID", Commons.getKDNEBusinessID());
        params.put("RequestType", "1008");
        String dataSign=encrypt(requestData, Commons.getKDNAppKey(), "UTF-8");
        params.put("DataSign", urlEncoder(dataSign, "UTF-8"));
        params.put("DataType", "2");

        String result=sendPost(ReqURL, params);

        //根据公司业务处理返回的信息......

        return  result;
    }

订阅成功后,快递鸟会返回一个JSON数据,例如:

{
        "EBusinessID": "1151847",
        "UpdateTime": "2016-08-09 16:42:38",
        "Success": true,
        "Reason": ""
        }

success返回true,则表示订阅成功。

推送

订阅成功后,当物流信息有更新的时候,快递鸟会发送一条推送,需要一个借口去接收消息,并将接收到的消息更新至数据库。方法如下:

/**
     * 物流推送
     *  接收快递鸟推送过来的消息,并将消息存放至数据库
     * @param request
     */
    @RequestMapping(value="subscribeExpress")
    @ResponseBody
    public String subscribeExpress(HttpServletRequest request){
        JSONObject object = JSONObject.fromObject(request.getParameter("RequestData"));
        ExpressDetail expressDetail;
        JSONArray data = object.getJSONArray("Data");
        if (!Commons.isNull(data) && data.size() > 0){
            for (int i = 0; i < data.size(); i++) {
                JSONObject detail = data.getJSONObject(i);
                String shippercode = detail.getString("ShipperCode");
                String logisticcode = detail.getString("LogisticCode");
                ExpressDetail expressDetail1 = expressDetailService.selectByShipperAndLogistic(shippercode,logisticcode);
                if (Commons.isNull(expressDetail1)) {
                    expressDetail = new ExpressDetail();
                    expressDetail.setLogisticcode(logisticcode);
                    expressDetail.setShippercode(shippercode);
                    expressDetail.setEdittime(new Date());
                    if (detail.containsKey("State")){
                        expressDetail.setState(detail.getString("State"));
                    }else {
                        expressDetail.setState("4");
                    }
                    if (detail.getString("Traces") == null || "[]".equals(detail.getString("Traces"))){
                        expressDetail.setTracedetail("[{\"error\":\""+detail.getString("Reason")+"\"}]");
                    } else {
                        expressDetail.setTracedetail(detail.getString("Traces"));
                    }
                    expressDetailService.insert(expressDetail);
                } else {
                    expressDetail = new ExpressDetail();
                    expressDetail.setId(expressDetail1.getId());
                    expressDetail.setEdittime(new Date());
                    expressDetail.setState(detail.getString("State"));
                    expressDetail.setTracedetail(detail.getString("Traces"));
                    expressDetailService.updateById(expressDetail);
                }
            }
        }
        JSONObject result = new JSONObject();
        result.put("EBusinessID", Commons.getKDNEBusinessID());
        result.put("UpdateTime", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
        result.put("Success", true);
        result.put("Reason","");
        return result.toString();
    }

注意:接收到推送之后,一定要返回一个数据,告诉快递鸟接受推送成功。如果传递至快递鸟的订单数据有误,则返回的信息里面,可能没有state和traces的值,此时返回值中,Reason应有原因,这种情况需要进行处理。

以下是代码

  • 数据库字段
    private Long id;
    private String orderid;
    private String shippercode;
    private String logisticcode;
    //物流状态:0-无轨迹,1-已揽收, 2-在途中 201-到达派件城市,3-签收,4-问题件
    private String state;
    private Date edittime;
    private String tracedetail;
  • 新订单发货
//发货时去订阅物流消息
                        String shippercode = GetShipperCode.getShipperCode(deliverOrder.getExpress());
                        String detail = ExpresseSubscribe.SubscribeOrderTraces(shippercode,deliverOrder.getExpressno());
                        JSONObject obj = JSONObject.fromObject(detail);
                        if (obj.containsValue("true")) {
                            //订阅消息之后,将相应数据存入数据库
                            ExpressDetail expressDetail = new ExpressDetail();
                            expressDetail.setOrderid(String.valueOf(orderid));
                            expressDetail.setShippercode(shippercode);
                            expressDetail.setLogisticcode(deliverOrder.getExpressno());
                            expressDetail.setEdittime(new Date());
                            expressDetail.setTracedetail("暂时没有物流信息。");
                            expressDetailService.insert(expressDetail);
                        }
  • 获取数据库数据
/**
     * 获取物流详情
     */
    @RequestMapping(value = "getExpresseDetail",method = RequestMethod.POST)
    @ResponseBody
    public Result getExpresseDetail(@RequestBody Long orderid,HttpServletRequest request){
        DeliverOrder deliverOrder = orderDao.queryDeliverOrderByOrderId(orderid);
        if (deliverOrder==null){
            return new Result(Result.Status.ERROR, "deliverOrder为空");
        }
        if (deliverOrder.getExpress()==null){
            return new Result(Result.Status.ERROR, "快递为空");
        }
        if (deliverOrder.getExpressno()==null){
            return new Result(Result.Status.ERROR, "快递编号为空");
        }
        String shippercode = GetShipperCode.getShipperCode(deliverOrder.getExpress());
        ExpressDetail detail = expressDetailService.selectByShipperAndLogistic(shippercode,deliverOrder.getExpressno());
        if (Commons.isNull(detail)) {
            try {
                String result = ExpresseTrack.TrackQuery(shippercode,deliverOrder.getExpressno());
                JSONObject objDetail = JSONObject.fromObject(result);
                ExpressDetail expressDetail = new ExpressDetail();
                expressDetail.setOrderid(String.valueOf(orderid));
                expressDetail.setShippercode(shippercode);
                expressDetail.setLogisticcode(deliverOrder.getExpressno());
                expressDetail.setEdittime(new Date());
                if (objDetail.containsKey("State")){
                    expressDetail.setState(objDetail.getString("State"));
                }
                if (objDetail.getString("Traces")==null||objDetail.getString("Traces")=="[]"){
                    expressDetail.setTracedetail(objDetail.getString("Reason"));
                }
                expressDetail.setTracedetail(objDetail.getString("Traces"));
                expressDetailService.insert(expressDetail);
                detail = expressDetailService.selectByShipperAndLogistic(shippercode,deliverOrder.getExpressno());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return new Result(Result.Status.OK,JSONObject.fromObject(detail));
    }
  • 通过快递公司编码和快递单号查询,订单编号是可选字段,如需要也可加上订单编号
@Override
    public ExpressDetail selectByShipperAndLogistic(String shipperCode, String logisticCode) {
        ExpressDetail expressDetail = new ExpressDetail();
        expressDetail.setShippercode(shipperCode);
        expressDetail.setLogisticcode(logisticCode);
        ExpressDetail detail = expressDetailDao.selectOne(expressDetail);
        return detail;
    }
  • ctrl.js--ng的数据处理
/**
		 * 物流详情
		 */
		scope.expresseDetail = function(){
			var id = routeParams.id;
			orderService.getExpresseDetail(id,function(data){
				if (data.status == 'OK'){
					console.log(data.message);
					scope.expressDetail = data.message;
					scope.tracedetails = [];
					var detail = JSON.parse(scope.expressDetail.tracedetail);
					console.log(scope.expressDetail);
					//某事件内物流详情
					var tracedetail = {};
					//用于存放某天内的所有物流信息
					var traces = [];
					//用于存放整个物流所需多少天
					var traces1 = [];
					var dateForDay = {};
					for (var i = 0; i < detail.length; i++){
						var accepttime = detail[i].AcceptTime;
						var time = accepttime.split(" ");
						if (i == 0) {
							dateForDay.date = time[0];
							dateForDay.week = scope.getWeekName(new Date(time[0]).getDay());
							tracedetail = {};
							tracedetail.date = time[1];
							tracedetail.detail = detail[i].AcceptStation;
							traces1.push(tracedetail);
						} else {
							var upaccepttime = detail[i - 1].AcceptTime;
							var uptime = upaccepttime.split(" ");
							if (time[0] == uptime[0]) {
								tracedetail = {};
								tracedetail.date = time[1];
								tracedetail.detail = detail[i].AcceptStation;
								traces1.push(tracedetail);
								if (i == detail.length -1) {
									dateForDay.traces = traces1;
									traces.push(dateForDay);
								}
							} else {
								dateForDay.traces = traces1;
								traces.push(dateForDay);
								dateForDay = {};
								dateForDay.date = time[0];
								dateForDay.week = scope.getWeekName(new Date(time[0]).getDay());
								traces1 = [];
								tracedetail = {};
								tracedetail.date = time[1];
								tracedetail.detail = detail[i].AcceptStation;
								traces1.push(tracedetail);
								if (i == detail.length -1) {
									dateForDay.traces = traces1;
									traces.push(dateForDay);
								}
							}
						}
					}
					scope.traces = traces;
					console.log(scope.traces);
				}
			})
		};

		scope.getWeekName = function(index) {
            var result = "";
            switch (index){
                case 0:
                    result = "周日";
                    break;
                case 1:
                    result = "周一";
                    break;
                case 2:
                    result = "周二";
                    break;
                case 3:
                    result = "周三";
                    break;
                case 4:
                    result = "周四";
                    break;
                case 5:
                    result = "周五";
                    break;
                case 6:
                    result = "周六";
                    break;
            }
            return result;
        };
  • 配置文件设置
  1. Commons.java
	public static String getKDNEBusinessID(){
		String EBusinessID = ConfigurationHolder.getInstance().getProperty("kuaidiniao.ebusinessid");
		return EBusinessID;
	}

	public static String getKDNAppKey(){
		String AppKey = ConfigurationHolder.getInstance().getProperty("kuaidiniao.appkey");
		return AppKey;
	}

2.application.properties,具体用****代替

#快递鸟
kuaidiniao.ebusinessid=********
kuaidiniao.appkey=*******************************
  1. spring-mvc.xml
<mvc:exclude-mapping path="/expressdetail/subscribeExpress"/>

4.applicationContext-cluster.xml

<property name="filterChainDefinitions">
            <value>
                 /expressdetail/subscribeExpress = anon
            </value>
        </property>

最后

很多相似的内容就没有全部放上来。项目中设有拦截,所以配置文件中要做相应的处理。以上既是所有。

转载于:https://my.oschina.net/LYQ19941105/blog/855319

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值