天天看點

京東物流對接京東物流對接怎麼使用:

京東物流對接

之前找資源的時候 在github 上面發現一個大佬封裝好的一個SDK

打開即用 可讀性非常高

怎麼使用:

1.引入依賴:

<dependency>
  <groupId>club.mrxiao</groupId>
  <artifactId>(不同子產品參考下文)</artifactId>
  <version>1.0.2</version>
</dependency>
           
  • 京東物流:

    express-java-jdl

  • 順豐物流:

    express-java-sf

2.将接口文檔中的請求參數、url等封裝成方法即可

就以下單為例 将請求參數、url 封裝成一個請求類即可響應同理

ReceiveOrderInfoRequest:

package com.plz.kd.jdl.bean.order;

import com.plz.kd.jdl.bean.BaseRequest;
import com.plz.kd.jdl.util.json.JdlGsonBuilder;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.List;

/**
 * <pre>
 * 下單接口請求對象
 * </pre>
 */
@Data
@Builder
@EqualsAndHashCode(callSuper = true)
public class ReceiveOrderInfoRequest extends BaseRequest {

    /**
     * 服務域
     */
    private static final String LOP_DN= "express";

    /**
     * code字段
     */
    private static final String CODE_FIELD = "resultCode";

    /**
     * 成功狀态碼
     */
    private static final Integer SUCCESS_CODE = 100;

    /**
     * API url
     */
    private static final String METHOD = "/WaybillJosService/receiveOrderInfo";


    /**
     * 運單資訊對象
     * <pre>
     * 是否必填:是
     * </pre>
     */
    private WaybillDTO waybillDTO;

    /**
     * 擷取傳回狀态碼字段
     * @return 傳回狀态碼字段
     */
    @Override
    public String getCodeField() {
        return CODE_FIELD;
    }

    /**
     * 擷取成功傳回狀态碼
     * @return 成功傳回狀态碼
     */
    @Override
    public Integer getSuccessCode() {
        return SUCCESS_CODE;
    }

    /**
     * 擷取請求json資料
     * @return 請求json資料
     */
    @Override
    public String getJsonParams() {
        List<WaybillDTO> list = new ArrayList<>();
        list.add(this.waybillDTO);
        return JdlGsonBuilder.create().toJson(list);
    }


    /**
     * 擷取服務域
     * @return 服務域
     */
    @Override
    public String getLopDn(){
        return LOP_DN;
    }

    /**
     * 擷取API url
     * @return API url
     */
    @Override
    public String getMethod(){
        return METHOD;
    }
}
           

ReceiveOrderInfoResponse:

package com.plz.kd.jdl.bean.order;

import lombok.Data;

/**
 * <pre>
 * 下單接口響應對象
 * </pre>
 */
@Data
public class ReceiveOrderInfoResponse {

    /**
     * 傳回碼
     */
    private Integer resultCode;

    /**
     * 傳回碼說明
     */
    private String resultMessage;


    private Boolean needRetry;

    /**
     * 商家訂單号(與入參相同)
     */
    private String orderId;

    /**
     * 京東運單号
     */
    private String deliveryId;

    /**
     * 實際時效産品類型(可能與入參不通,以京東實際運力計算結果為準)
     */
    private Integer promiseTimeType;

    /**
     * 錯誤碼(暫未啟用)
     */
    private Integer errorCode;

    /**
     * 錯誤碼說明(暫未啟用)
     */
    private String errorMessage;

    /**
     * 運輸類型 1:陸運 2:航空 不填或者超出範圍,預設是1
     */
    private Integer transType;

    private Integer expressOperationMode;

    /**
     * 預分揀結果資訊
     */
    private PreSortResult preSortResult;
}
           

mr-xiaoyu/express-java-tools: 京東物流、順豐物流api java封裝 (github.com)

JdlController:

package com.plz.kd.controller;


import club.mrxiao.common.error.ExpressErrorException;
import com.alibaba.fastjson.JSONObject;
import com.plz.kd.jdl.bean.order.*;
import com.plz.kd.jdl.bean.trace.*;
import com.plz.kd.service.JdlOrderService;
import com.plz.kd.service.JdlService;
import com.plz.kd.service.JdlTraceService;
import com.plz.kd.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RequestMapping("/jdl")
@RestController
public class JdlController {

    @Resource
    private JdlOrderService jdlOrderService;

    @Autowired
    private JdlService jdlService;


    @RequestMapping("/test")
    public R test() {
        return R.ok().put("test", "Test");
    }

    @RequestMapping("/receiveOrder")
    public ReceiveOrderInfoResponse receiveOrder(@RequestBody String json)  {
        WaybillDTO waybillDTO = JSONObject.parseObject(json, WaybillDTO.class);
        ReceiveOrderInfoRequest request = ReceiveOrderInfoRequest.builder().build();
        request.setWaybillDTO(waybillDTO);
        ReceiveOrderInfoResponse response = null;
        try {
            response = jdlOrderService.receiveOrder(request);
            return response;
        } catch (ExpressErrorException e) {
            throw new RuntimeException(e);
        }
    }

    @RequestMapping("/cancelOrder")
    //todo 修改取消訂單入參邏輯
    public CancelOrderResponse cancelOrder (@RequestBody String json) {
        CancelWaybillInterceptReq cancel = JSONObject.parseObject(json, CancelWaybillInterceptReq.class);
        cancel.setCancelOperator("happyLiu");
        cancel.setCancelTime(System.currentTimeMillis());
        cancel.setCancelReasonCode(1);
        cancel.setInterceptReason("使用者發起取消");
        CancelOrderRequest request = CancelOrderRequest.builder().cancelRequest(cancel).build();
        CancelOrderResponse response = null;
        try {
            response = jdlOrderService.cancelOrder(request);
            return response;
        } catch (ExpressErrorException e) {
            throw new RuntimeException(e);
        }
    }

    @RequestMapping("/queryOrder")
    public QueryTraceResponse queryOrder(@RequestBody String json) {
        //擷取京東物流軌迹api接口
        JdlTraceService jdlTraceService = jdlService.getJdlTraceService();
        TraceQueryDTO traceQueryDTO = JSONObject.parseObject(json, TraceQueryDTO.class);
        QueryTraceRequest request = QueryTraceRequest.builder().queryDTO(traceQueryDTO).build();
        QueryTraceResponse response = null;
        try {
            response = jdlTraceService.queryTrace(request);
            return response;
        } catch (ExpressErrorException e) {
            throw new RuntimeException(e);
        }
    }

    // 全程跟蹤查詢
    @RequestMapping("/queryDynamicTrace")
    public QueryTraceResponse queryDynamicTrace(@RequestBody String json) {
        //擷取京東物流軌迹api接口
        JdlTraceService jdlTraceService = jdlService.getJdlTraceService();
        TraceQueryDTO traceQueryDTO = JSONObject.parseObject(json, TraceQueryDTO.class);
        QueryDynamicTraceInfoRequest request = QueryDynamicTraceInfoRequest.builder().queryDTO(traceQueryDTO).build();
        QueryTraceResponse response = null;
        try {
            response = jdlTraceService.queryDynamicTrace(request);
            return response;
        } catch (ExpressErrorException e) {
            throw new RuntimeException(e);
        }
    }
    @RequestMapping("/queryWaybill")
    public QueryWaybillResponse queryWaybill(@RequestBody String json) {
        //查詢預估運費
        JdlOrderService jdlOrderService = jdlService.getJdlOrderService();
        QueryWaybill queryWaybill = JSONObject.parseObject(json, QueryWaybill.class);
        QueryWaybillRequest request = QueryWaybillRequest.builder().queryWaybill(queryWaybill).build();
        QueryWaybillResponse response = null;
        try {
            response = jdlOrderService.queryWaybillFreights(request);
            return response;
        } catch (ExpressErrorException e) {
            throw new RuntimeException(e);
        }
    }
    // 查詢物流軌迹(給消費者)
    @RequestMapping("/waybill2CTraceByWaybillCode")
    public GetWaybill2cTraceByWaybillCodeResponse Waybill2CTraceByWaybillCode (@RequestBody String json) {
        JdlTraceService jdlTraceService = jdlService.getJdlTraceService();
        Waybill2cTraceDTO waybill2cTraceDTO = JSONObject.parseObject(json, Waybill2cTraceDTO.class);
        GetWaybill2cTraceByWaybillCodeRequest request = GetWaybill2cTraceByWaybillCodeRequest.builder().waybill2cTraceDto(waybill2cTraceDTO).build();
        try {
            GetWaybill2cTraceByWaybillCodeResponse response = jdlTraceService.getWaybill2cTraceByWaybillCode(request);
            return response;
        } catch (ExpressErrorException e) {
            throw new RuntimeException(e);
        }
    }
}
           

JdlService:

package com.plz.kd.service;


import club.mrxiao.common.error.ExpressErrorException;
import com.plz.kd.jdl.bean.BaseRequest;
import com.plz.kd.jdl.config.JdlConfig;

/**
 * <pre>
 * 京東物流api接口
 * </pre>
 */
public interface JdlService {

    /**
     * 設定配置
     * @param config {@link JdlConfig} 配置
     * @throws ExpressErrorException {@link ExpressErrorException} 異常資訊
     */
    void setConfig(JdlConfig config) throws ExpressErrorException;

    /**
     * 擷取配置
     * @return {@link JdlConfig} 配置
     */
    JdlConfig getConfig();

    /**
     * 執行請求
     * @param request {@link BaseRequest} 統一請求對象
     * @param <T> 傳回對象
     * @param clazz 傳回對象
     * @return 請求結果
     * @throws ExpressErrorException {@link ExpressErrorException} 異常資訊
     */
    <T> T execute(BaseRequest request, Class<T> clazz) throws ExpressErrorException;

    /**
     * 擷取京東物流訂單api接口
     * @return 京東訂單api接口
     */
    JdlOrderService getJdlOrderService();

    /**
     * 擷取京東物流訂單軌迹api接口
     * @return 京東訂單軌迹api接口
     */
    JdlTraceService getJdlTraceService();

    /**
     * 擷取京東物流雲列印api接口
     * @return 京東物流雲列印api接口
     */
    JdlPrintService getJdlPrintService();
}
           

JdlServiceImpl:

package com.plz.kd.service.impl;



import club.mrxiao.common.error.ExpressError;
import club.mrxiao.common.error.ExpressErrorException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.google.gson.JsonObject;
import com.plz.kd.jdl.bean.BaseRequest;
import com.plz.kd.jdl.bean.token.TokenResult;
import com.plz.kd.jdl.config.JdlConfig;
import com.plz.kd.jdl.util.json.JdlGsonBuilder;
import com.plz.kd.service.JdlOrderService;
import com.plz.kd.service.JdlPrintService;
import com.plz.kd.service.JdlService;
import com.plz.kd.service.JdlTraceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import static com.plz.kd.jdl.util.sign.SignUtil.encode;
import static com.plz.kd.utils.MD5.md5;


/**
 * <pre>
 * 京東快遞api接口實作
 * </pre>
 */
@Service
public class JdlServiceImpl implements JdlService {

    /**
     * 錯誤傳回
     */
    private static final String ERROR_RESPONSE = "error_response";

    private final Log log = LogFactory.get(this.getClass().getName());


    @Autowired
    private JdlConfig config;
    private JdlOrderService jdlOrderService = new JdlOrderServiceImpl(this);
    private JdlTraceService jdlTraceService = new JdlTraceServiceImpl(this);
    private JdlPrintService jdlPrintService = new JdlPrintServiceImpl(this);


    @Override
    public void setConfig(JdlConfig config) throws ExpressErrorException {
        this.refreshToken(config);
    }

    @Override
    public JdlConfig getConfig() {
        return this.config;
    }

    @Override
    public JdlOrderService getJdlOrderService() {
        return this.jdlOrderService;
    }

    @Override
    public JdlTraceService getJdlTraceService() {
        return this.jdlTraceService;
    }

    @Override
    public JdlPrintService getJdlPrintService() {
        return this.jdlPrintService;
    }

    @Override
    public <T> T execute(BaseRequest request, Class<T> clazz) throws ExpressErrorException {
        try {
            String result = request.build(this.config).execute().body();
            if(StrUtil.isBlank(result)){
                throw new ExpressErrorException(ExpressError.builder().errorCode("9999").errorMsg("無響應内容").build());
            }
            if (result.contains(ERROR_RESPONSE)) {
                throw new ExpressErrorException(ExpressError.builder().json(result).build());
            }
//            this.resultSuccess(request,result);
            log.debug("【result】: {} \n",result);
            return JdlGsonBuilder.create().fromJson(result, clazz);
        }catch (HttpException e){
            throw new ExpressErrorException(ExpressError.builder().errorCode("9999").errorMsg("接口請求發生錯誤").build(),e);
        }

    }

    private void refreshToken(JdlConfig config) throws ExpressErrorException {

        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        String timestamp = dateFormat.format(new Date());

        String sign = md5(config.getAppSecret() + "app_key" + config.getAppKey() + "refresh_token" + config.getRefreshToken() + "timestamp" + timestamp + config.getAppSecret());

        String url = config.getUrl() +
                "/oauth/refresh_token_ext?LOP-DN=oauth.jdwl.com&app_key=" +
                config.getAppKey() +
                "&refresh_token=" + config.getRefreshToken() +
                "&timestamp=" + encode(timestamp) +
                "&sign=" + sign;
        try {
            String result = HttpRequest.post(url).execute().body();
            if(StrUtil.isBlank(result)){
                throw new ExpressErrorException(ExpressError.builder().errorCode("9999").errorMsg("無響應内容").build());
            }
            if (result.contains(ERROR_RESPONSE)) {
                throw new ExpressErrorException(ExpressError.builder().json(result).build());
            }
            TokenResult r = TokenResult.fromJson(result);
            if(!r.isSuccess()){
                throw new ExpressErrorException(ExpressError.builder()
                        .errorCode(r.getErrCode())
                        .errorMsg(r.getErrMsg())
                        .json(result)
                        .build());
            }
            config.setToken(r.getModel().getAccessToken());
            config.setPin(r.getModel().getSellerId());
            this.config = config;
        }catch (HttpException e){
            throw new ExpressErrorException(ExpressError.builder().errorCode("9999").errorMsg("接口請求發生錯誤").build(),e);
        }
    }

    private void resultSuccess(BaseRequest request,String result) throws ExpressErrorException {
        JsonObject obj = JdlGsonBuilder.create().fromJson(result, JsonObject.class);
        if(!obj.has(request.getCodeField())){
            throw new ExpressErrorException(ExpressError.builder()
                    .errorCode("9999")
                    .errorMsg("狀态碼不存在")
                    .json(result)
                    .build());
        }
        Integer code = obj.get(request.getCodeField()).getAsInt();
        if(!request.getSuccessCode().equals(code)){
            throw new ExpressErrorException(ExpressError.builder()
                    .errorCode(String.valueOf(code))
                    .json(result)
                    .build());
        }
    }
}
           

JdlOrderService:

package com.plz.kd.service;


import club.mrxiao.common.error.ExpressErrorException;
import com.plz.kd.jdl.bean.order.*;

/**
 * <pre>
 * 京東物流訂單api接口
 * </pre>
 */
public interface JdlOrderService {

    /**
     * 下單
     * @param request {@link ReceiveOrderInfoRequest} 下單接口請求對象
     * @return {@link ReceiveOrderInfoResponse} 下單接口響應對象
     * @throws ExpressErrorException {@link ExpressErrorException} 異常資訊
     */
    ReceiveOrderInfoResponse receiveOrder(ReceiveOrderInfoRequest request) throws ExpressErrorException;

    /**
     * 取消下單
     * @param request {@link CancelOrderRequest} 取消下單請求對象
     * @return {@link CancelOrderResponse} 取消下單響應對象
     * @throws ExpressErrorException {@link ExpressErrorException} 異常資訊
     */
    CancelOrderResponse cancelOrder(CancelOrderRequest request) throws ExpressErrorException;

    QueryWaybillResponse queryWaybillFreights(QueryWaybillRequest request) throws ExpressErrorException;

}
           

JdlOrderServiceImpl:

package com.plz.kd.service.impl;



import club.mrxiao.common.error.ExpressErrorException;
import com.plz.kd.jdl.bean.order.*;
import com.plz.kd.jdl.config.JdlConfig;
import com.plz.kd.service.JdlOrderService;
import com.plz.kd.service.JdlService;
import config.Config;
import jdk.nashorn.internal.ir.annotations.Reference;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

/**
 * <pre>
 * 京東訂單api接口實作
 * </pre>
 */
@Service
@AllArgsConstructor
public class JdlOrderServiceImpl implements JdlOrderService {

    /**
     * 服務接口
     */
    @Autowired
    private JdlService jdlService;

    @Override
    public ReceiveOrderInfoResponse receiveOrder(ReceiveOrderInfoRequest request) throws ExpressErrorException {
        JdlConfig config = this.jdlService.getConfig();
        request.getWaybillDTO().setJosPin(config.getPin());
        request.getWaybillDTO().setAppKey(config.getAppKey());
        request.getWaybillDTO().setCustomerCode(config.getCustomerCode());
        return this.jdlService.execute(request,ReceiveOrderInfoResponse.class);
    }

    @Override
    public CancelOrderResponse cancelOrder(CancelOrderRequest request) throws ExpressErrorException {
        JdlConfig config = this.jdlService.getConfig();
        request.getCancelRequest().setPin(config.getPin());
        request.getCancelRequest().setVendorCode(config.getCustomerCode());
        return this.jdlService.execute(request, CancelOrderResponse.class);
    }

    @Override
    public QueryWaybillResponse queryWaybillFreights(QueryWaybillRequest request) throws ExpressErrorException {
        JdlConfig config = this.jdlService.getConfig();
        request.getQueryWaybill().setVendorCode(config.getCustomerCode());
        return this.jdlService.execute(request, QueryWaybillResponse.class);
    }
}
           

JdlConfig:

package com.plz.kd.jdl.config;

import lombok.Data;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

/**
 * <pre>
 * 配置
 * </pre>
 */
@Data
public class JdlConfig {
    /**
     * 生産環境位址
     */
    private static final String PRO_URL = "https://api.jdl.com";

    /**
     * UAT環境位址
     */
    private static final String BOX_URL = "https://uat-api.jdl.com";


    /**
     * 是否生産環境
     */
    private Boolean pro = true;

    /**
     * 京東賬号
     */
    private String pin = "";

    /**
     * token 不用配置
     */
    private String token = "";
    

    /**
     * refresh_token
     */
    private String refreshToken = "";

    /**
     * app_key
     */
    private String appKey = "";

    /**
     * app_secret
     */
    private String appSecret = "";

    /**
     * 商家編碼
     */
    private String customerCode = "";

    /**
     * 标準模版連結
     */
    private String printTempUrl;

    /**
     * 頁面上下偏移量
     */
    private Integer printOffsetTop = 0;

    /**
     * 頁面左右偏移量
     */
    private Integer printOffsetLeft = 0;

    /**
     * 版本s
     */
    private String v = "2.0";


    /**
     * 擷取api位址
     *
     * @return api位址
     */
    public String getUrl() {
        if (this.pro) {
            return PRO_URL;
        }
        return BOX_URL;
    }
}
           

以上就是對接京東物流的核心代碼了 可以用作其他平台的接口的對接

毫不誇張的講 寫一個新接口隻需要 十分鐘二十分鐘 就可以寫好

非常好用! 贊一個

GitHub位址