[express 100] the express aging interface obtains the estimated arrival time of the express

Posted by salasilm on Thu, 06 Jan 2022 02:58:29 +0100

requirement analysis

At present, the company has launched the push interface of express 100. Now it needs to make an interface for the estimated arrival time of express.

This interface is mainly used for month end assessment of signing in and warehouse personnel. For example, an express signed in on the 15th, but only entered the warehouse on the 20th. This is dereliction of duty and should be punished.

However, the company's express orders are maintained by the purchasing department. They think it is troublesome to maintain the express order number and the company to which the express belongs. They are unwilling to maintain the departure city and destination city (these two fields are required for express time effective details query)

This increases the difficulty of background development.

The original idea was to sys again_ Enter and maintain the departure city (formCity) and destination city (toCity) in express, so that each time these express orders are detected, they will automatically go to express 100 to query the estimated arrival time.

Later, it was found that this scheme was not feasible.

Because the express time limit details interface also needs the express order time. If an express order is placed at 8:00 a.m., the procurement department doesn't remember to enter the express order until 17:00 p.m.

At this time, the personnel of the procurement department need to remember the order time of each express order, and it is best to enter it immediately after the order is placed, but this is unrealistic. The work of the procurement department is busy and it is easy to forget. Moreover, there are too many express orders and it is easy to neglect.

Then I came up with a solution.

The push interface we launched before can get the collection time of the express by pushing the express logistics track information. This time is the correct order time.

I asked the customer service of express 100. An express placed an order at 8:00 and officially collected it at 16:00. Which is the time of placing an order (the courier received the order at 8:00, but went to another place to collect it. He didn't return to the express site until 4:00 p.m. and was transported away by the express truck.)

From the interface level, the collection time is the real time for express delivery.

(during the double 11 promotion time, the order was placed on November 11, and it is likely that the collection began on November 14. If it is expected to arrive within two days, it is likely that it has arrived, and the express has not delivered yet.)

This solves the problem of ordering time (orderTime is provided by the push interface, which is obtained when the push interface is pushed for the first time, and the departure express 100 time effective details interface is queried at the same time)

However, the form city and the destination city are still unavailable. What should I do?

After thinking for a long time, we found that our supplier information and customer information are maintained in the system. When we know the supplier and customer information, we naturally know their address and know the departure city or destination city in disguise.

As for the form city and the destination city, it only needs a simple judgment.

The business scenario has been clarified, and the next step is to write code.

Official documents

Official documents: https://cloud.kuaidi100.com/platform/productdetail/32164353135.shtml


V1 is used to query a single express company, and V2 is used to query the list of express companies.

V2 is accurate to the hour level, but it has a BUG. com in the request parameter should be companyList (it's tired to say too much).

I don't know why the maintenance personnel of express 100 didn't change this error. It may be because there are few people using this interface.

tips: the authorization key, interface number and encryption signature in the request parameters can be obtained in the background.

service code

SysExpressServiceImpl.java

/**
     * Business processing
     * @param param Returned parameters
     * @param backResp
     */
    @Transactional
    public void handleResponse(String param,SubscribePushParamResp backResp) throws Exception {

        // Every push message should be put into storage to facilitate troubleshooting after problems occur
        String expressNum = backResp.getLastResult().getNu();
        SysExpressData expressData = new SysExpressData();
        expressData.setExpressNum(expressNum);
        expressData.setReceiveText(param);
        expressData.setType("1");
        expressData.setStatus("0");
        expressDataMapper.insertSysExpressData(expressData);

        // Business processing
        SysExpress express = expressMapper.selectSysExpressByNum(expressNum);

        // Update master table status
        if("abort".equals(backResp.getStatus().trim())){
            //When the message is "no record in 3 days" or "no change in 60 days" status= abort, the processing logic is to re subscribe to the push service
            express.setRemark("status= abort,Re subscribe to push service");
            List<SysExpress> expressList = new ArrayList<>();
            expressList.add(express);
            subscribe(expressList);
        }
        // shutdown indicates that the express is signed in and the push service is suspended
        if("shutdown".equals(backResp.getStatus().trim())){
            express.setStatus(3L);
            expressMapper.updateSysExpress(express);
        }

        // Get the data set, parse it and store it in the database
        List<SubscribePushData> dataList = backResp.getLastResult().getData();
        if(dataList != null && dataList.size() >0){
            if (StringUtils.isEmpty(express.getArriveTime())) {
                //arriveTime is null, indicating that the interface has not been called to obtain the estimated arrival time
                if(StringUtils.isNotEmpty(express.getFromCity()) && StringUtils.isNotEmpty(express.getToCity())){
                    // fromCity and toCity are not empty, indicating that they are express documents entered later
                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put("secret_key", secretKey);
                    paramMap.put("secret_code", secretCode);
                    // secretSign = SignUtils.sign(key+secretSecret)
                    paramMap.put("secret_sign", secretSign);
                    paramMap.put("from", express.getFromCity());
                    paramMap.put("to", express.getToCity());
                    paramMap.put("companyList", express.getCompanyCode());
                    paramMap.put("orderTime", dataList.get(dataList.size()-1).getFtime());

                    String sendText = new Gson().toJson(paramMap);
                    String response = getExpressVo(paramMap);
                    handleResponseAndSaveArriveTime(sendText, response, express);
                }
            }
            List<SysExpressInfo> infoList = new ArrayList<>();
            for (SubscribePushData data : dataList) {
                SysExpressInfo info = new SysExpressInfo();
                info.setCompanyCode(backResp.getLastResult().getCom());
                info.setContext(data.getContext());
                info.setExpressNum(expressNum);
                info.setStatus(data.getStatus());
                info.setTime(DateUtils.getUTCTime(data.getFtime()));
                infoList.add(info);
            }
            if(infoList.size() > 0){
                // Delete sys before warehousing_ express_ The data in the info table only keeps the latest data.
                expressInfoMapper.deleteSysExpressInfoByNum(expressNum);
                expressInfoMapper.insertSysExpressBatch(infoList);
            }
        }
    }
    /**
     * Get express time effective interface
     * @param params
     * @return
     */
    public String getExpressVo(Map<String, String> params) throws IOException {
        StringBuilder response = new StringBuilder("");
        BufferedReader reader = null;

        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(arriveUrl);
        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);
        }
        return response.toString();
    }
/**
     * @param sendText Send message through express detail interface
     * @param response  Express detail interface return message
     * @param express   Express entity class
     */
    private void handleResponseAndSaveArriveTime(String sendText,String response,SysExpress express) {

        // Return message of express aging details and warehousing operation
        SysExpressData expressData = new SysExpressData();
        expressData.setExpressNum(express.getExpressNum());
        expressData.setSendText(sendText);
        expressData.setReceiveText(response);
        expressData.setType("2");
        expressData.setStatus("0");
        expressDataMapper.insertSysExpressData(expressData);

        ExpressVo expressVo = new Gson().fromJson(response, ExpressVo.class);

        if ("200".equals(expressVo.getReturnCode())) {
            express.setArriveTime("Estimated arrival time missing");
            // 200 indicates that the data is returned successfully
            List<ExpressSupportResult> data = expressVo.getData();
            if(data != null && data.size() > 0){
                // Explain that the express is supported
                String arriveTime = data.get(0).getArrivalTime();
                express.setArriveTime(arriveTime);
            }else{
                // Express companies not supported by TODO can be warehoused. This interface will not be called next time
            }
            expressMapper.updateSysExpress(express);
        }
    }

Express aging details entity class: ExpressVo

@Data
public class ExpressVo {

    /**place of departure*/
    private String fromName;
    /**Origin code*/
    private String fromNum;
    /**destination*/
    private String toName;
    /**Destination code*/
    private String toNum;
    /**Order time */
    private String orderTime;
    /**The returned status code 200 indicates success*/
    private String returnCode;

    private boolean result;
    /**Return information (success, failure, signature verification failure, etc.)*/
    private String message;
    /**Statistical time information of each express company*/
    private List<ExpressSupportResult> data;
	}

Express estimated arrival time result set: ExpressSupportResult

@Data
public class ExpressSupportResult {

    /**Express company code*/
    private String com;
    /**Average time*/
    private String totalAvg;
    /**Business type 10: ordinary, 20: fast, 30: Express*/
    private String type;
    /**Predicted arrival time*/
    private String arrivalTime;
    /**Predicted departure time*/
    private String startTime;
    /**Estimated time*/
    private String mayExpendTime;
    }

Topics: Distribution