京東物流對接
之前找資源的時候 在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() +
"×tamp=" + 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位址