一.接口对接
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.kdapi.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 快递鸟使用接口对接
*
* @author liuqiyu
* @see: https://kdniao.com/api-eorder
* @date 2022/3/1 11:16
*/
@Slf4j
public class KdApiInterfaceUtil {
public static void main(String[] args) {
try {
KdApiInterfaceUtil api = new KdApiInterfaceUtil();
//System.out.println(orderOnline(api.getOrderOnlineData()));
System.out.println(orderOnlineByJson());
//System.out.println(api.orderCancelOnline("SF","012657018199","900008664480","123456",""));
//System.out.println(api.orderQueryOnline("UC","3001","福田网点","123456","c0bfe0ba86b66bae5426303c53db0a81"));
//System.out.println(api.timelyInquiryOrderOnline(null,null,"YTO","YT00003618100"));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 测试 电子面单参数信息封装
*
* @author liuqiyu
* @date 2022/3/1 11:16
*/
public KdOrderDTO getOrderOnlineData() {
KdOrderDTO kdOrderDTO = new KdOrderDTO();
kdOrderDTO.setOrderCode("012657016331");
kdOrderDTO.setShipperCode("YTO");
kdOrderDTO.setCustomerName("testyto");
kdOrderDTO.setCustomerPwd("");
kdOrderDTO.setMonthCode("testytomonthcode");
kdOrderDTO.setSendSite("");
kdOrderDTO.setPayType(1);
kdOrderDTO.setExpType(1);
kdOrderDTO.setWeight(1.0);
kdOrderDTO.setIsReturnPrintTemplate("1");
kdOrderDTO.setRemark("小心轻放");
kdOrderDTO.setVolume(0.0);
kdOrderDTO.setQuantity(1);
KdOrderSenderDTO sender = new KdOrderSenderDTO();
sender.setCompany("lv");
sender.setName("Taylor");
sender.setMobile("15018442396");
sender.setProvinceName("上海");
sender.setCityName("上海市");
sender.setExpAreaName("青浦区");
sender.setAddress("明珠路");
kdOrderDTO.setSender(sender);
KdOrderReceiverDTO receiver = new KdOrderReceiverDTO();
receiver.setCompany("GCCUI");
receiver.setName("Yann");
receiver.setMobile("15018442396");
receiver.setProvinceName("北京");
receiver.setCityName("北京市");
receiver.setExpAreaName("朝阳区");
receiver.setAddress("三里屯街道");
kdOrderDTO.setReceiver(receiver);
List<KdOrderAddServiceDTO> addServiceList = new ArrayList<>();
KdOrderAddServiceDTO COD = new KdOrderAddServiceDTO();
COD.setCustomerId("1234567890");
COD.setName("COD");
COD.setValue("1020");
addServiceList.add(COD);
KdOrderAddServiceDTO INSURE = new KdOrderAddServiceDTO();
INSURE.setName("INSURE");
INSURE.setValue("1000");
addServiceList.add(INSURE);
kdOrderDTO.setAddServiceList(addServiceList);
KdOrderCommodityDTO xiezi = new KdOrderCommodityDTO();
xiezi.setGoodsName("鞋子");
xiezi.setGoodsQuantity("1");
xiezi.setGoodsWeight("1.0");
KdOrderCommodityDTO yifu = new KdOrderCommodityDTO();
yifu.setGoodsName("鞋子");
yifu.setGoodsQuantity("1");
yifu.setGoodsWeight("1.0");
List<KdOrderCommodityDTO> kdOrderCommodityDTOList = new ArrayList<>();
kdOrderCommodityDTOList.add(xiezi);
kdOrderCommodityDTOList.add(yifu);
kdOrderDTO.setCommodityList(kdOrderCommodityDTOList);
// 组装应用级参数(未封装的)
String RequestData = "{" +
"'OrderCode': '012657018199'," +
"'ShipperCode': 'YTO'," +
"'CustomerName': '客户编码'," +
"'CustomerPwd': ''," +
"'MonthCode': '密钥'," +
"'SendSite': ''," +
"'PayType': 1," +
"'MonthCode': '1234567890'," +
"'ExpType': 1," +
"'Cost': 1.0," +
"'OtherCost': 1.0," +
"'Sender': {" +
"'Company': 'LV'," +
"'Name': 'Taylor'," +
"'Mobile': '15018442396'," +
"'ProvinceName': '上海'," +
"'CityName': '上海市'," +
"'ExpAreaName': '青浦区'," +
"'Address': '明珠路'" +
"}," +
"'Receiver': {" +
"'Company': 'GCCUI'," +
"'Name': 'Yann'," +
"'Mobile': '15018442396'," +
"'ProvinceName': '北京'," +
"'CityName': '北京市'," +
"'ExpAreaName': '朝阳区'," +
"'Address': '三里屯街道'" +
"}," +
"'Commodity': [" +
"{" +
"'GoodsName': '鞋子'," +
"'Goodsquantity': 1," +
"'GoodsWeight': 1.0" +
"}," +
"{" +
"'GoodsName': '衣服'," +
"'Goodsquantity': 1," +
"'GoodsWeight': 1.0" +
"}" +
"]," +
"'AddService': [" +
"{" +
"'Name': 'INSURE'," +
"'Value': '1000'" +
"}," +
"{" +
"'Name': 'COD'," +
"'Value': '1020'," +
"'CustomerID ': '1234567890'" +
"}" +
"]," +
"'Weight': 1.0," +
"'Quantity': 1," +
"'Volume': 0.0," +
"'IsReturnPrintTemplate':1," +
"'Remark': '小心轻放'" +
"}";
return kdOrderDTO;
}
/**
* 电子面单接口
* 此接口用于向快递/快运公司下发订单并获取快递单号,返回电子面单html模板,通知快递员上门取件。该功能支持情况需查看技术文档。
* 正式地址:https://api.kdniao.com/api/EOrderService
* <p>
* <p>
* 系统级参数
* RequestData String R 请求内容为JSON格式 详情可参考接口技术文档:https://www.kdniao.com/documents
* EBusinessID String R 用户ID
* RequestType String R 请求接口指令
* DataSign String R 数据内容签名,加密方法为:把(请求内容(未编码)+ApiKey)进行MD5加密--32位小写,然后Base64编码,最后进行URL(utf-8)编码
* DataType String R DataType=2,请求、返回数据类型均为JSON格式
* <p>
* 应用级参数
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
* Callback String(50) O 用户自定义回传字段
* CustomerName String(50) C 电子面单客户号,需要下载《快递鸟电子面单客户号参数对照表.xlsx》,参考对应字段传值 https://www.kdniao.com/documents
* CustomerPwd String(50) C 同上
* SendSite String(50) C 同上
* SendStaff String(50) C 同上
* MonthCode String(20) C 同上
* CustomArea String(500) O 商家自定义区域,需查看技术文档说明
* WareHouseID String(30) C 发货仓编码(ShipperCode为JD或JDKY时必填)
* TransType Int(2) O 京东(ShipperCode为JD或JDKY)的产品类型,需查看技术文档说明
* ShipperCode String(10) R 快递公司编码详细编码参考《快递鸟接口支持快递公司编码.xlsx》 https://www.kdniao.com/documents
* LogisticCode String(30) O 快递单号(仅宅急送可用)
* OrderCode String(30) R 订单编号(自定义,不可重复)
* ThrOrderCode String(50) C 京东商城的订单号(ShipperCode为JD且ExpType为1时必填)
* PayType Int(1) R 运费支付方式:1-现付,2-到付,3-月结
* ExpType String(2) R 详细快递类型参考《快递公司快递业务类型.xlsx》 https://www.kdniao.com/documents
* IsReturnSignBill Int(1) O 是否要求签回单 0-不要求,1-要求
* Receiver.Company String(30) O 收件人公司
* Receiver.Name String(30) R 收件人
* Receiver.Tel String(20) R 电话(电话与手机,必填一个)
* Receiver.Mobile String(20) R 手机(电话与手机,必填一个)
* Receiver.PostCode String(10) C 收件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
* Receiver.ProvinceName String(20) R 收件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
* Receiver.CityName String(20) R 收件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
* Receiver.ExpAreaName String(20) R 收件区/县(如福田区,不要缺少“区”或“县”)
* Receiver.Address String(100) R 收件人详细地址(不用传省市区)
* Sender.Company String(30) O 发件人公司
* Sender.Name String(30) R 发件人
* Sender.Tel String(20) R 电话(电话与手机,必填一个)
* Sender.Mobile String(20) R 手机(电话与手机,必填一个)
* Sender.PostCode String(10) C 发件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
* Sender.ProvinceName String(20) R 发件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
* Sender.CityName String(20) R 发件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
* Sender.ExpAreaName String(20) R 发件区/县(如福田区,不要缺少“区”或“县”)
* Sender.Address String(100) R 发件人详细地址(不用传省市区)
* IsNotice Int(1) O 是否通知快递员上门揽件 0-通知,1-不通知,不填则默认为1
* StartDate String(32) O 上门揽件时间段,格式:YYYY-MM-DD HH24:MM:SS
* EndDate String(32) O 上门揽件时间段,格式:YYYY-MM-DD HH24:MM:SS
* Weight Double(10,3) C 包裹总重量kg 1、当为快运的订单时必填;2、ShipperCode为JD时必填;
* Quantity Int(2) R 包裹数(最多支持300件)一个包裹对应一个运单号,如果是大于1个包裹,返回则按照子母件的方式返回母运单号和子运单号
* Volume Double(20,3) C 包裹总体积m3 1、当为快运的订单时必填;2、ShipperCode为JD时必填;
* Remark String(60) O 备注
* AddService.Name String(20) C 增值服务名称(数组形式,可以有多个增值服务)
* AddService.Value String(30) C 增值服务值
* AddService.CustomerID String(30) O 客户标识
* Commodity.GoodsName String(100) R 商品名称(数组形式)
* IsReturnPrintTemplate String(1) O 是否返回电子面单模板:0-不需要,1-需要
* IsSendMessage Int(1) O 是否订阅短信:0-不需要,1-需要
* IsSubscribe String(1) O 是否订阅轨迹推送 0-不订阅,1-订阅,不填默认为1
* TemplateSize String(10) O 模板规格,需查看技术文档说明
* PackingType Int(2) C 包装类型(快运字段),需查看技术文档说明
* DeliveryMethod Int(1) C 送货方式/派送类型/配送方式(快运字段),需查看技术文档说明
* CurrencyCode String(10) C 货物单价的币种:CNY: 人民币 HKD: 港币 NTD: 新台币 MOP: 澳门元 (ShipperCode为SF且收件地址为港澳台地区,必填)
* Dutiable.DeclaredValue Number(15,3) C 申报价值:订单货物总声明价值,包含子母件,精确到小数点后3位 (ShipperCode为SF且收件地址为港澳台地区,必填)
*/
public static JSONObject orderOnline(KdOrderDTO kdOrder) {
try {
// 组装应用级参数(只传必填信息)
String requestData = "{" +
"'CustomerName': '" + kdOrder.getCustomerName() + "'," +
"'CustomerPwd': '" + kdOrder.getCustomerPwd() + "'," +
"'MonthCode': '" + kdOrder.getMonthCode() + "'," +
"'SendSite': '" + kdOrder.getSendSite() + "'," +
"'SendStaff': '" + kdOrder.getSendStaff() + "'," +
"'ShipperCode': '" + kdOrder.getShipperCode() + "',";
//发货仓编码(ShipperCode为JD或JDKY时必填)
if ("JD".equals(kdOrder.getShipperCode()) || "JDKY".equals(kdOrder.getShipperCode())) {
requestData = requestData + "'WareHouseID': '" + kdOrder.getWareHouseId() + "',";
}
//第三方订单号 (ShipperCode为JD且ExpType为1时必填)
if ("JD".equals(kdOrder.getShipperCode()) && "1".equals(kdOrder.getExpType().toString())) {
requestData = requestData + "'ThrOrderCode': '" + kdOrder.getThrOrderCode() + "',";
}
requestData = requestData + "'OrderCode': '" + kdOrder.getOrderCode() + "'," +
"'PayType': " + kdOrder.getPayType() + "," +
"'ExpType': " + kdOrder.getExpType() + "," +
"'IsReturnPrintTemplate': 1 ," +
// 物流轨迹轨迹订阅,不需要在单独调用订阅接口
"'IsSubscribe': 1 ," +
"'IsNotice': 0 ,";
if ("JD".equals(kdOrder.getShipperCode())) {
//包裹总重量 kg 1、当为快运的订单时必填;2、ShipperCode 为 JD 时必填;2、顺丰微小件、陆运微小件,Weight传值必须小于等于0.5
requestData = requestData + "'Weight': " + kdOrder.getWeight() + ",";
//包裹总体积 m3 1、 当为快运的订单时必填;2、 ShipperCode 为 JD 时必填;
requestData = requestData + "'Volume':" + kdOrder.getVolume() + ",";
}
//(必填)包裹数(最多支持 300 件)一个包裹对应一个运单号,如果是大于 1 个包裹,返回则按照子母件的方式返回母运单号和子运单号
requestData = requestData + "'Quantity': " + kdOrder.getQuantity() + ",";
//送货方式/派送类型/配送方式
//(快运字段):0-自提1-送货上门(不含上楼)2-送货上楼
//当 ShipperCode 为 JTSD 时必填,支持以下传值:3-派送上门4-站点自提5-快递柜自提6-代收点自提
//当 ShipperCode 为 DBL 或DBLKY 时必填,支持以下传值:1-自提2-送货进仓3-送货(不含上楼)4-送货上楼5-大件上楼
//当 ShipperCode 为 ZYE 时必填,支持以下传值:1-送货上门2-自提
if ("JTSD".equals(kdOrder.getShipperCode()) || "DBL".equals(kdOrder.getShipperCode()) || "ZYE".equals(kdOrder.getShipperCode())) {
requestData = requestData + "'DeliveryMethod':" + kdOrder.getDeliveryMethod() + ",";
}
// 港澳台业务暂未做适配
//(ShipperCode 为 SF 且收件地址为港澳台地区,必填) 货物单价的币种:CNY: 人民币HKD: 港币NTD: 新台币 MOP: 澳门元
//requestData = requestData+ "'CurrencyCode':" + kdOrder.getCurrencyCode() + ",";
//if("SF".equals(kdOrder.getShipperCode())){
// //申报价值:订单货物总声明价值,包含子母件,精确到小数点后 3 位(ShipperCode 为 SF 且收件地址为港澳台地区,必填)
// requestData = requestData+ "'Dutiable': {" +
// "'DeclaredValue': '" + kdOrder.getSender().getName() + "'," +
// "}," ;
//}
// 发货人信息
requestData = requestData + "'Sender': {" +
"'Name': '" + kdOrder.getSender().getName() + "'," +
"'Mobile': '" + kdOrder.getSender().getMobile() + "'," +
"'ProvinceName': '" + kdOrder.getSender().getProvinceName() + "'," +
"'CityName': '" + kdOrder.getSender().getCityName() + "'," +
"'ExpAreaName': '" + kdOrder.getSender().getExpAreaName() + "'," +
"'Address': '" + kdOrder.getSender().getAddress() + "'";
if ("EMS".equals(kdOrder.getShipperCode()) || "YZPY".equals(kdOrder.getShipperCode()) || "YZBK".equals(kdOrder.getShipperCode())) {
//收件地邮编(ShipperCode 为EMS、YZPY、YZBK 时必填)
requestData = requestData + ",'PostCode': '" + kdOrder.getSender().getPostCode() + "'";
}
// 收货人信息
requestData = requestData + "}," +
"'Receiver': {" +
"'Name': '" + kdOrder.getReceiver().getName() + "'," +
"'Mobile': '" + kdOrder.getReceiver().getMobile() + "'," +
"'ProvinceName': '" + kdOrder.getReceiver().getProvinceName() + "'," +
"'CityName': '" + kdOrder.getReceiver().getCityName() + "'," +
"'ExpAreaName': '" + kdOrder.getReceiver().getExpAreaName() + "'," +
"'Address': '" + kdOrder.getReceiver().getAddress() + "'";
if ("EMS".equals(kdOrder.getShipperCode()) || "YZPY".equals(kdOrder.getShipperCode()) || "YZBK".equals(kdOrder.getShipperCode())) {
//收件地邮编(ShipperCode 为EMS、YZPY、YZBK 时必填)
requestData = requestData + ",'PostCode': '" + kdOrder.getSender().getPostCode() + "'";
}
requestData = requestData + "}," +
"'Commodity': [";
// 商品信息
for (int i = 0; i < kdOrder.getCommodityList().size(); i++) {
requestData = requestData + "{" +
"'GoodsName': '" + kdOrder.getCommodityList().get(i).getGoodsName() + "'," +
"}";
if (i < kdOrder.getCommodityList().size() - 1) {
requestData = requestData + ",";
}
}
requestData = requestData + "]";
// 增值信息
if (CollUtil.isNotEmpty(kdOrder.getAddServiceList())) {
requestData = requestData + ",'AddService': [";
for (int i = 0; i < kdOrder.getAddServiceList().size(); i++) {
requestData = requestData + "{" +
"'Name': '" + kdOrder.getAddServiceList().get(i).getName() + "'," +
"'Value': '" + kdOrder.getAddServiceList().get(i).getValue() + "'" +
"}";
if (i < kdOrder.getAddServiceList().size() - 1) {
requestData = requestData + ",";
}
}
requestData = requestData + "]";
}
requestData = requestData + "}";
// 组装系统级参数
Map<String, String> params = new HashMap<>();
params.put("RequestData", KdApiUtil.urlEncoder(requestData, "UTF-8"));
params.put("EBusinessID", KdApiUtil.EBusinessID);
params.put("RequestType", "1007");
String dataSign = KdApiUtil.encrypt(requestData, KdApiUtil.ApiKey, "UTF-8");
params.put("DataSign", KdApiUtil.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
String result = KdApiUtil.sendPost(KdApiUtil.ReqOrderURL, params);
JSONObject jsonObject = JSONUtil.parseObj(result);
if (!jsonObject.getBool("Success")) {
throw new ServiceException(jsonObject.getStr("Reason"));
}
return jsonObject;
} catch (ServiceException e) {
throw new ServiceException(e.getMessage());
}
catch (Exception e) {
log.error("电子面单下单失败===================={}", e.getMessage());
throw new ServiceException("电子面单下单失败,请查看配置信息是否正常");
}
}
/**
* 电子面单取消接口
* 此接口用于取消“电子面单接口”下单成功的订单,回收快递单号。该功能支持情况需查看技术文档。
* <p>
* 系统级参数
* RequestData String R 请求内容为JSON格式 详情可参考接口技术文档:https://www.kdniao.com/documents
* EBusinessID String R 用户ID
* RequestType String R 请求接口指令
* DataSign String R 数据内容签名,加密方法为:把(请求内容(未编码)+ApiKey)进行MD5加密--32位小写,然后Base64编码,最后进行URL(utf-8)编码
* DataType String R DataType=2,请求、返回数据类型均为JSON格式
* <p>
* <p>
* 应用级参数
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
* ShipperCode String(10) R 快递公司编码
* OrderCode String(30) R 订单编号
* ExpNo String(30) R 快递单号
* CustomerName String(50) R 电子面单客户号
* CustomerPwd String(30) R 电子面单密码(顺丰不需要)
*/
public static void orderCancelOnline(String shipperCode, String orderCode, String expNo, String customerName, String customerPwd){
try {
customerPwd = StringUtils.isEmpty(customerPwd) ? "" : customerPwd;
// 组装应用级参数
String requestData = "{" +
"'ShipperCode': '" + shipperCode + "'," +
"'OrderCode': '" + orderCode + "'," +
"'ExpNo': '" + expNo + "'," +
"'CustomerName': '" + customerName + "'," +
"'CustomerPwd': '" + customerPwd + "'" +
"}";
// 组装系统级参数
Map<String, String> params = new HashMap<>();
params.put("RequestData", KdApiUtil.urlEncoder(requestData, "UTF-8"));
params.put("EBusinessID", KdApiUtil.EBusinessID);
params.put("RequestType", "1147");
String dataSign = KdApiUtil.encrypt(requestData, KdApiUtil.ApiKey, "UTF-8");
params.put("DataSign", KdApiUtil.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
String result = KdApiUtil.sendPost(KdApiUtil.ReqOrderURL, params);
JSONObject jsonObject = JSONUtil.parseObj(result);
if (!jsonObject.getBool("Success")) {
throw new ServiceException(jsonObject.getStr("Reason"));
}
} catch (ServiceException e) {
throw new ServiceException(e.getMessage());
} catch (Exception e) {
log.error("快递鸟订单取消失败==============={}",e.getMessage());
throw new ServiceException("快递鸟订单取消失败");
}
}
/**
* 单号余量查询接口
* 此接口用于向快递公司查询电子面单客户号中剩余的可用单号数量。该功能支持情况需查看技术文档。
* 支持的公司:优速快递、中通快递、韵达速递、百世快递(暂不支持 TotalNum)
* <p>
* 系统级参数
* RequestData String R 请求内容为JSON格式 详情可参考接口技术文档:https://www.kdniao.com/documents
* EBusinessID String R 用户ID
* RequestType String R 请求接口指令
* DataSign String R 数据内容签名,加密方法为:把(请求内容(未编码)+ApiKey)进行MD5加密--32位小写,然后Base64编码,最后进行URL(utf-8)编码
* DataType String R DataType=2,请求、返回数据类型均为JSON格式
* <p>
* 应用级参数
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
* ShipperCode String(10) R 快递公司编码
* CustomerName String(50) R 电子面单客户号
* CustomerPwd String(30) R 电子面单密码
* StationCode String(30) R 网点编码
* StationName String(30) R 网点名称
*/
public static String orderQueryOnline(String shipperCode, String stationCode, String stationName, String customerName, String customerPwd) {
try {
// 组装应用级参数
String requestData = "{" +
"'ShipperCode': '" + shipperCode + "'," +
"'StationCode': '" + stationCode + "'," +
"'StationName': '" + stationName + "'," +
"'CustomerName': '" + customerName + "'," +
"'CustomerPwd': '" + customerPwd + "'" +
"}";
// 组装系统级参数
Map<String, String> params = new HashMap<>();
params.put("RequestData", KdApiUtil.urlEncoder(requestData, "UTF-8"));
params.put("EBusinessID", KdApiUtil.EBusinessID);
params.put("RequestType", "1127");
String dataSign = KdApiUtil.encrypt(requestData, KdApiUtil.ApiKey, "UTF-8");
params.put("DataSign", KdApiUtil.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
String result = KdApiUtil.sendPost(KdApiUtil.ReqOrderURL, params);
//根据公司业务处理返回的信息......
return result;
} catch (Exception e) {
log.error("快递鸟单号余量查询失败================{}", e.getMessage());
throw new ServiceException("快递鸟单号余量查询失败,请检查配置信息是否正确");
}
}
/**
* 即时查询接口
* 此接口用于向快递公司实时查询物流轨迹信息。该功能支持情况需查看技术文档。
* 正式地址:https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx
* <p>
* 增值版与非增值版区别:
* 增值版多了物流状态 StateEx 和所在城市 Location
* 支持查询的物流也不同,免费版只支持申通圆通百世和天天,其他快递都是增值版才有的,和时效方面也不同
* 物流查询没有沙箱环境,统一正式环境请求
* <p>
* 系统级参数
* RequestData String R 请求内容为JSON格式 详情可参考接口技术文档:https://www.kdniao.com/documents
* EBusinessID String R 用户ID
* RequestType String R 请求接口指令
* DataSign String R 数据内容签名,加密方法为:把(请求内容(未编码)+ApiKey)进行MD5加密--32位小写,然后Base64编码,最后进行URL(utf-8)编码
* DataType String R DataType=2,请求、返回数据类型均为JSON格式
* <p>
* 应用级参数
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
* OrderCode String(30) O 订单编号
* ShipperCode String(10) R 快递公司编码 详细编码参考《快递鸟接口支持快递公司编码.xlsx》 https://www.kdniao.com/documents
* LogisticCode String(30) R 快递单号
* CustomerName String(50) C ShipperCode为SF时必填,对应寄件人/收件人手机号后四位;ShipperCode为其他快递时,可不填或保留字段,不可传值
* <p>
* 请求示例
* ZTO请求示例:
* {
* "OrderCode": "",
* "ShipperCode": "ZTO",
* "LogisticCode": "638650888018",
* }
* <p>
* JD请求示例:
* {
* "OrderCode": "",
* "CustomerName": "",
* "ShipperCode": "JD",
* "LogisticCode": "JDVA00003618100",
* }
* <p>
* SF请求示例:
* {
* "OrderCode": "",
* "CustomerName": "1234",
* "ShipperCode": "SF",
* "LogisticCode": "SF00003618100",
* }
*/
public static JSONObject timelyInquiryOrderOnline(String orderCode, String customerName, String shipperCode, String logisticCode) {
try {
orderCode = StringUtils.isEmpty(orderCode) ? "" : orderCode;
customerName = StringUtils.isEmpty(customerName) ? "" : customerName;
// 组装应用级参数
String requestData = "{" ;
// ShipperCode为SF时必填,对应寄件人/收件人手机号后四位;ShipperCode为其他快递时,可不填或保留字段,不可传值
if("SF".equals(shipperCode)){
requestData=requestData+ "'CustomerName': '" + customerName + "'," ;
}
requestData=requestData+ "'OrderCode':'" + orderCode + "' ," +
"'ShipperCode': '" + shipperCode + "'," +
"'LogisticCode': '" + logisticCode + "'," +
"}";
// 组装系统级参数
Map<String, String> params = new HashMap<String, String>();
params.put("RequestData", KdApiUtil.urlEncoder(requestData, "UTF-8"));
params.put("EBusinessID", KdApiUtil.EBusinessID);
//免费即时查询接口指令1002/在途监控即时查询接口指令8001/地图版即时查询接口指令8003
params.put("RequestType", "1002");
String dataSign = KdApiUtil.encrypt(requestData, KdApiUtil.ApiKey, "UTF-8");
params.put("DataSign", KdApiUtil.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
String result = KdApiUtil.sendPost(KdApiUtil.TimelyInquiryURL, params);
JSONObject jsonObject = JSONUtil.parseObj(result);
if (!jsonObject.getBool("Success")) {
throw new ServiceException(jsonObject.getStr("Reason"));
}
return jsonObject;
} catch (ServiceException e) {
throw new ServiceException(e.getMessage());
} catch (Exception e){
log.error("轨迹查询失败========={}",e.getMessage());
throw new ServiceException("快递鸟轨迹查询失败");
}
}
/**
* 物流跟踪 订阅
* 应用级参数
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
* Callback String(50) O 用户自定义回传字段
* ShipperCode String(10) R 快递公司编码 详细编码参考《快递鸟接口支持快递公司编码.xlsx》
* LogisticCode String(30) R 快递单号
* CustomerName String(50) C ShipperCode为SF时必填,对应寄件人/收件人手机号后四位;ShipperCode为其他快递时,可不填或保留字段,不可传值
*
* @author liuqiyu
* @date 2022/3/8 13:14
* @return java.lang.String
*/
public static void orderTrackSubscribeOnline(String shipperCode,String logisticCode,String customerName){
try{
// 组装应用级参数
String requestData= "{";
// ShipperCode为SF时必填,对应寄件人/收件人手机号后四位;ShipperCode为其他快递时,可不填或保留字段,不可传值
if("SF".equals(shipperCode)){
requestData=requestData+ "'CustomerName': '" + customerName + "'," ;
}
requestData=requestData+ "'ShipperCode':'"+shipperCode+"',"+
"'LogisticCode':'"+logisticCode+"',"+
"}";
// 组装系统级参数
Map<String, String> params = new HashMap<>();
params.put("RequestData", KdApiUtil.urlEncoder(requestData, "UTF-8"));
params.put("EBusinessID", KdApiUtil.EBusinessID);
//免费订阅接口指令1008/在途监控订阅接口指令8008/地图版订阅接口指令8005
params.put("RequestType", "8008");
String dataSign = KdApiUtil.encrypt(requestData, KdApiUtil.ApiKey, "UTF-8");
params.put("DataSign", KdApiUtil.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
String result = KdApiUtil.sendPost(KdApiUtil.orderTrackSubscribeURL, params);
JSONObject jsonObject = JSONUtil.parseObj(result);
if (!jsonObject.getBool("Success")) {
throw new ServiceException(jsonObject.getStr("Reason"));
}
} catch (ServiceException e) {
throw new ServiceException(e.getMessage());
} catch (Exception e){
log.error("轨迹查询失败========={}",e.getMessage());
throw new ServiceException("快递鸟轨迹查询失败");
}
}
//轨迹推送接口 (用于模拟推送)
public static String orderOnlineByJson() throws Exception{
// 组装应用级参数
String RequestData= "{"+
"'EBusinessID': 'test1740043',"+
"'Count': '1',"+
"'PushTime': '2022-03-10 15:21:06',"+
"'Data': ["+
"{"+
"'EBusinessID': '1655797',"+
"'ShipperCode': 'YTO',"+
"'LogisticCode': '820070286166',"+
"'Success': true,"+
"'Reason': '',"+
"'State': '3',"+
"'CallBack': '0',"+
"'OrderCode': '1501799274345664512',"+
"'Traces': ["+
"{"+
"'AcceptTime': '2016-10-26 18:31:38',"+
"'AcceptStation': '【北京环铁站】的【互优图书】已收件',"+
"},"+
"{"+
"'AcceptTime': '2016-10-26 19:53:50',"+
"'AcceptStation': '快件在【北京环铁站】装车,正发往【北京分拨中心】',"+
" },"+
"{"+
"'AcceptTime': '2016-10-26 21:00:13',"+
"'AcceptStation': '快件到达【北京分拨中心】,上一站是【北京环铁站】',"+
"},"+
"{"+
"'AcceptTime': '2016-10-26 21:06:27',"+
"'AcceptStation': '快件在【北京分拨中心】装车,正发往【青州分拨中心】',"+
"},"+
"{"+
"'AcceptTime': '2016-10-27 11:04:43',"+
"'AcceptStation': '快件到达【北京分拨中心】,上一站是【】',"+
" },"+
"]"+
" }"+
"]"+
"}";
// 组装系统级参数
Map<String,String> params = new HashMap<String,String>();
params.put("RequestData", KdApiUtil.urlEncoder(RequestData, "UTF-8"));
params.put("EBusinessID", KdApiUtil.EBusinessID);
params.put("RequestType", "101"); //免费推送接口指令101/收费推送接口指令102
String dataSign=KdApiUtil.encrypt(RequestData, KdApiUtil.ApiKey, "UTF-8");
params.put("DataSign", KdApiUtil.urlEncoder(dataSign, "UTF-8"));
params.put("DataType", "2");
// 以form表单形式提交post请求,post请求体中包含了应用级参数和系统级参数
String result=KdApiUtil.sendPost("http://*****/api/kdOrder/callbackPushTrack", params);
//根据公司业务处理返回的信息......
return result;
}
}
二.公用工具类
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Map;
/**
* @description: 快递鸟对接使用共同方法
* @className: KdApiUtil
* @author: liuqiyu
* @date: 2022/3/1 10:59
* @version: 1.0
*/
public class KdApiUtil {
/**
* 用户ID,快递鸟提供,注意保管,不要泄漏
* 即用户ID,登录快递鸟官网会员中心获取 https://www.kdniao.com/UserCenter/v4/UserHome.aspx
*/
public static final String EBusinessID="*******";
/**
* API key,快递鸟提供,注意保管,不要泄漏
* 即API key,登录快递鸟官网会员中心获取 https://www.kdniao.com/UserCenter/v4/UserHome.aspx
*/
public static final String ApiKey="**************************";
/**
* 请求url, 正式环境地址
*/
//public static final String ReqOrderURL="https://api.kdniao.com/api/EOrderService";
public static final String ReqOrderURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
/**
* 及时查询请求url, 正式环境地址
*/
//public static final String TimelyInquiryURL="https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";
public static final String TimelyInquiryURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
/**
* 轨迹订阅接口
*/
public static final String orderTrackSubscribeURL="https://api.kdniao.com/api/dist";
//public static final String orderTrackSubscribeURL="http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
/**
* MD5加密
* str 内容
* charset 编码方式
* @throws Exception
*/
@SuppressWarnings("unused")
public static String MD5(String str, String charset) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes(charset));
byte[] result = md.digest();
StringBuffer sb = new StringBuffer(32);
for (int i = 0; i < result.length; i++) {
int val = result[i] & 0xff;
if (val <= 0xf) {
sb.append("0");
}
sb.append(Integer.toHexString(val));
}
return sb.toString().toLowerCase();
}
/**
* base64编码
* str 内容
* charset 编码方式
* @throws UnsupportedEncodingException
*/
public static String base64(String str, String charset) throws UnsupportedEncodingException {
return Base64.encode(str.getBytes(charset));
}
@SuppressWarnings("unused")
public static String urlEncoder(String str, String charset) throws UnsupportedEncodingException{
return URLEncoder.encode(str, charset);
}
/**
* 电商Sign签名生成
* content 内容
* keyValue ApiKey
* charset 编码方式
* @throws UnsupportedEncodingException ,Exception
* @return DataSign签名
*/
@SuppressWarnings("unused")
public static String encrypt (String content, String keyValue, String charset) throws UnsupportedEncodingException, Exception
{
if (keyValue != null)
{
return base64(MD5(content + keyValue, charset), charset);
}
return base64(MD5(content, charset), charset);
}
/**
* 向指定 URL 发送POST方法的请求
* url 发送请求的 URL
* params 请求的参数集合
* @return 远程资源的响应结果
*/
@SuppressWarnings("unused")
public static String sendPost(String url, Map<String, String> params) {
OutputStreamWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try {
URL realUrl = new URL(url);
HttpURLConnection conn =(HttpURLConnection) realUrl.openConnection();
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// POST方法
conn.setRequestMethod("POST");
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.connect();
// 获取URLConnection对象对应的输出流
out = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8);
// 发送请求参数
if (params != null) {
StringBuilder param = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if(param.length()>0){
param.append("&");
}
param.append(entry.getKey());
param.append("=");
param.append(entry.getValue());
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("param:"+param.toString());
out.write(param.toString());
}
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result.toString();
}
/**
* 判断是否从快递鸟进入的推送数据
* @param RequestData
* @param DataSign
* @return
*/
public static boolean isFromKdNiao(String RequestData,String DataSign){
try {
return encrypt(RequestData, ApiKey, "UTF-8").equals(DataSign);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
三.封装的类
package com.arpa.ntocc.common.common.util.kdapi.dto;
import lombok.Data;
import java.util.List;
/**
* @description: 电子面单DTO
* @className: KdOrderDTO
* @author: liuqiyu
* @date: 2022/3/1 15:50
* @version: 1.0
*
* 应用级参数
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
* Callback String(50) O 用户自定义回传字段
* CustomerName String(50) C 电子面单客户号,需要下载《快递鸟电子面单客户号参数对照表.xlsx》,参考对应字段传值 https://www.kdniao.com/documents
* CustomerPwd String(50) C 同上
* SendSite String(50) C 同上
* SendStaff String(50) C 同上
* MonthCode String(20) C 同上
* CustomArea String(500) O 商家自定义区域,需查看技术文档说明
* WareHouseID String(30) C 发货仓编码(ShipperCode为JD或JDKY时必填)
* TransType Int(2) O 京东(ShipperCode为JD或JDKY)的产品类型,需查看技术文档说明
* ShipperCode String(10) R 快递公司编码详细编码参考《快递鸟接口支持快递公司编码.xlsx》 https://www.kdniao.com/documents
* LogisticCode String(30) O 快递单号(仅宅急送可用)
* OrderCode String(30) R 订单编号(自定义,不可重复)
* ThrOrderCode String(50) C 京东商城的订单号(ShipperCode为JD且ExpType为1时必填)
* PayType Int(1) R 运费支付方式:1-现付,2-到付,3-月结
* ExpType String(2) R 详细快递类型参考《快递公司快递业务类型.xlsx》 https://www.kdniao.com/documents
* IsReturnSignBill Int(1) O 是否要求签回单 0-不要求,1-要求
* IsNotice Int(1) O 是否通知快递员上门揽件 0-通知,1-不通知,不填则默认为1
* StartDate String(32) O 上门揽件时间段,格式:YYYY-MM-DD HH24:MM:SS
* EndDate String(32) O 上门揽件时间段,格式:YYYY-MM-DD HH24:MM:SS
* Weight Double(10,3) C 包裹总重量kg 1、当为快运的订单时必填;2、ShipperCode为JD时必填;
* Quantity Int(2) R 包裹数(最多支持300件)一个包裹对应一个运单号,如果是大于1个包裹,返回则按照子母件的方式返回母运单号和子运单号
* Volume Double(20,3) C 包裹总体积m3 1、当为快运的订单时必填;2、ShipperCode为JD时必填;
* Remark String(60) O 备注
* Commodity.GoodsName String(100) R 商品名称(数组形式)
* IsReturnPrintTemplate String(1) O 是否返回电子面单模板:0-不需要,1-需要
* IsSendMessage Int(1) O 是否订阅短信:0-不需要,1-需要
* IsSubscribe String(1) O 是否订阅轨迹推送 0-不订阅,1-订阅,不填默认为1
* TemplateSize String(10) O 模板规格,需查看技术文档说明
* PackingType Int(2) C 包装类型(快运字段),需查看技术文档说明
* DeliveryMethod Int(1) C 送货方式/派送类型/配送方式(快运字段),需查看技术文档说明
* CurrencyCode String(10) C 货物单价的币种:CNY: 人民币 HKD: 港币 NTD: 新台币 MOP: 澳门元 (ShipperCode为SF且收件地址为港澳台地区,必填)
* Dutiable.DeclaredValue Number(15,3) C 申报价值:订单货物总声明价值,包含子母件,精确到小数点后3位 (ShipperCode为SF且收件地址为港澳台地区,必填)
*/
@Data
public class KdOrderDTO {
private String customerName;
private String customerPwd;
private String sendSite;
private String sendStaff;
private String monthCode;
private String customArea;
private String wareHouseId;
private Integer transType;
private String shipperCode;
private String logisticCode;
private String orderCode;
private String thrOrderCode;
private Integer payType;
private Integer expType;
private String isReturnSignBill;
private Integer isNotice;
private String startDate;
private String endDate;
private Double weight;
private Integer quantity;
private Double volume;
private String remark;
private String isReturnPrintTemplate;
private Integer isSendMessage;
private String isSubscribe;
private String templateSize;
private Integer packingType;
private Integer deliveryMethod;
private String currencyCode;
private String declaredValue;
private KdOrderReceiverDTO receiver;
private KdOrderSenderDTO sender;
private List<KdOrderCommodityDTO> commodityList;
private List<KdOrderAddServiceDTO> addServiceList;
public String getCustomerName() {
return customerName==null?"":customerName;
}
public String getCustomerPwd() {
return customerPwd==null?"":customerPwd;
}
public String getSendSite() {
return sendSite==null?"":sendSite;
}
public String getSendStaff() {
return sendStaff==null?"":sendStaff;
}
public String getMonthCode() {
return monthCode==null?"":monthCode;
}
public String getCustomArea() {
return customArea==null?"":customArea;
}
public String getWareHouseId() {
return wareHouseId==null?"":wareHouseId;
}
public Integer getTransType() {
return transType;
}
public String getShipperCode() {
return shipperCode==null?"":shipperCode;
}
public String getLogisticCode() {
return logisticCode==null?"":logisticCode;
}
public String getOrderCode() {
return orderCode==null?"":orderCode;
}
public String getThrOrderCode() {
return thrOrderCode==null?"":thrOrderCode;
}
public Integer getPayType() {
return payType;
}
public Integer getExpType() {
return expType;
}
public String getIsReturnSignBill() {
return isReturnSignBill==null?"":isReturnSignBill;
}
public Integer getIsNotice() {
return isNotice;
}
public String getStartDate() {
return startDate==null?"":startDate;
}
public String getEndDate() {
return endDate==null?"":endDate;
}
public Double getWeight() {
return weight;
}
public Integer getQuantity() {
return quantity;
}
public Double getVolume() {
return volume;
}
public String getRemark() {
return remark==null?"":remark;
}
public String getIsReturnPrintTemplate() {
return isReturnPrintTemplate==null?"":isReturnPrintTemplate;
}
public Integer getIsSendMessage() {
return isSendMessage;
}
public String getIsSubscribe() {
return isSubscribe==null?"":isSubscribe;
}
public String getTemplateSize() {
return templateSize==null?"":templateSize;
}
public Integer getPackingType() {
return packingType;
}
public Integer getDeliveryMethod() {
return deliveryMethod;
}
public String getCurrencyCode() {
return currencyCode==null?"CNY":currencyCode;
}
}
import lombok.Data;
/**
* @description: 发件方信息
* @className: KdOrderSenderDTO
* @author: liuqiyu
* @date: 2022/3/1 16:16
* @version: 1.0
*
* Sender.Company String(30) O 发件人公司
* Sender.Name String(30) R 发件人
* Sender.Tel String(20) R 电话(电话与手机,必填一个)
* Sender.Mobile String(20) R 手机(电话与手机,必填一个)
* Sender.PostCode String(10) C 发件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
* Sender.ProvinceName String(20) R 发件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
* Sender.CityName String(20) R 发件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
* Sender.ExpAreaName String(20) R 发件区/县(如福田区,不要缺少“区”或“县”)
* Sender.Address String(100) R 发件人详细地址(不用传省市区)
*/
@Data
public class KdOrderSenderDTO {
private String company;
private String name;
private String tel;
private String mobile;
private String postCode;
private String provinceName;
private String cityName;
private String expAreaName;
private String address;
}
import lombok.Data;
/**
* @description: 收件方信息
* @className: KdOrderReceiverDTO
* @author: liuqiyu
* @date: 2022/3/1 16:14
* @version: 1.0
*
* Receiver.Company String(30) O 收件人公司
* Receiver.Name String(30) R 收件人
* Receiver.Tel String(20) R 电话(电话与手机,必填一个)
* Receiver.Mobile String(20) R 手机(电话与手机,必填一个)
* Receiver.PostCode String(10) C 收件地邮编(ShipperCode为EMS、YZPY、YZBK时必填)
* Receiver.ProvinceName String(20) R 收件省(如广东省,不要缺少“省”;如是直辖市,请直接传北京、上海等;如是自治区,请直接传广西壮族自治区等)
* Receiver.CityName String(20) R 收件市(如深圳市,不要缺少“市;如是市辖区,请直接传北京市、上海市等”)
* Receiver.ExpAreaName String(20) R 收件区/县(如福田区,不要缺少“区”或“县”)
* Receiver.Address String(100) R 收件人详细地址(不用传省市区)
*/
@Data
public class KdOrderReceiverDTO {
private String company;
private String name;
private String tel;
private String mobile;
private String postCode;
private String provinceName;
private String cityName;
private String expAreaName;
private String address;
}
import lombok.Data;
/**
* @description: 商品部分信息
* @className: KdOrderCommodityDTO
* @author: liuqiyu
* @date: 2022/3/1 16:27
* @version: 1.0
* Commodity.GoodsName String(100) 是 商品名称
* Commodity.GoodsCode String(20)否 商品编码
* Commodity.Goodsquantity Int(5) 否 商品件数
* Commodity.GoodsPrice Double(10) 否 商品价格(当 ShipperCode 为BETWL时必填)
* Commodity.GoodsWeight Double(10,3) 否 商品重量 kg
* Commodity.GoodsDesc String(50) 否 商品描述
* Commodity.GoodsVol Double(15,3) 否 商品体积 m3
*/
@Data
public class KdOrderCommodityDTO {
private String goodsName;
private String goodsPrice;
private String goodsQuantity;
private String goodsWeight;
}
import lombok.Data;
/**
* @description: 增值服务信息
* @className: KdOrderAddServiceDTO
* @author: liuqiyu
* @date: 2022/3/1 16:09
* @version: 1.0
*
* R-必填(Required),O-可选(Optional),C-报文中该参数在一定条件下可选(Conditional)
* AddService.Name String(20) C 增值服务名称(数组形式,可以有多个增值服务)
* AddService.Value String(30) C 增值服务值
* AddService.CustomerID String(30) O 客户标识
*/
@Data
public class KdOrderAddServiceDTO {
private String name;
private String value;
private String customerId;
}
四.回调处理
接收回调
@ApiOperation(value = "快递鸟回调推送轨迹", notes = "快递鸟回调推送轨迹")
@PostMapping(value = "callbackPushTrack")
public Map<String, Object> callbackPushTrack(String RequestData, String RequestType, String DataSign, HttpServletRequest request) throws IOException {
//具体操作根据自身业务来,但记住,5s内必须给快递鸟发送相应,否则他会判断推送失败
log.info("RequestData:{}", RequestData);
log.info("requestType:{}", RequestType);
log.info("DataSign:{}", DataSign);
RequestData = Encodes.unescapeHtml(RequestData);
Map<String, Object> result = new HashMap<>();
//判断是从快递鸟进入
if (!(("101".equals(RequestType) || "102".equals(RequestType)) && KdApiUtil.isFromKdNiao(RequestData, DataSign))) {
result.put("Success", false);
result.put("Reason", "不是快递鸟推送来的数据。");
return result;
}
JSONObject jsonObj = new JSONObject(RequestData);
result.put("EBusinessID", jsonObj.getString("EBusinessID"));
result.put("UpdateTime", jsonObj.getString("PushTime"));
try {
// 进行业务处理
kdOrderService.callbackPushTrack(jsonObj);
result.put("Success", true);
result.put("Reason", "");
} catch (Exception e) {
result.put("Success", false);
result.put("Reason ", "解析数据失败。");
e.printStackTrace();
}
return result;
}
业务处理
@Override
@Transactional(rollbackFor = Exception.class)
public void callbackPushTrack(org.json.JSONObject jsonObj) {
/*
1.返回的物流轨迹信息按照发生时间的升序排列。
2.轨迹推送是异步推送的,系统拉取到轨迹后调用用户推送接口推送轨迹数据。
3.若 Data 接收到推送 Success 为 false,且 Reason 为三天无轨迹,需重新发起订阅。
4.若 Data 接收到推送 Success 为 false,且 Reason 为七天内无轨迹变化,需重新发起订阅。
5.若 Data 接收到推送 Success 为 false,且 State 为 0,属于正常推送,需耐心等待下次推送即可。
6.在没有返回信息或者返回不符合规定的情况下,会判断为推送失败。推送失败后会重试
推送 2 次,首次间隔 15 分钟,二次间隔半个小时,两次都失败就不会再推送,直到下次有轨迹更新才会再次推送,建议您严格按照技术文档进行返回
*/
JSONArray jsonArray = jsonObj.getJSONArray("Data");
for (int i = 0; i < jsonArray.length(); i++) {
jsonObj = jsonArray.getJSONObject(i);
// 根据快递鸟的快递号查询出信息,进行业务操作
OrderRelation orderRelation = orderRelationService.getOne(new QueryWrapper<OrderRelation>().lambda().eq(OrderRelation::getKdLogisticCode, jsonObj.getString("LogisticCode")));
if (!jsonObj.getBoolean("Success")) {
if ("0".equals(jsonObj.getString("State"))) {
continue;
}
if ("三天无轨迹".equals(jsonObj.getString("Reason")) || "七天内无轨迹变化".equals(jsonObj.getString("Reason"))) {
String customerName = null;
if ("SF".equals(orderRelation.getKdShipperCode())) {
PartyGroup partyGroup = partyGroupService.getByCode(orderRelation.getBranchCode());
String dispatcherMobile = partyGroup.getDispatcherMobile();
customerName = dispatcherMobile.substring(dispatcherMobile.length() - 4);
}
KdApiInterfaceUtil.orderTrackSubscribeOnline(jsonObj.getString("ShipperCode"), jsonObj.getString("LogisticCode"), customerName);
}
} else {
jsonObj.getString("ShipperCode");
jsonObj.getString("LogisticCode");
jsonObj.getString("State");
//jsonObj.getString("StateEx");
// 0-暂无轨迹信息不做处理
if ("1".equals(jsonObj.getString("State"))) {
//1-已揽收
} else if ("2".equals(jsonObj.getString("State"))) {
if (orderRelation.getStatus() == 2) {
continue;
}
} else if ("3".equals(jsonObj.getString("State"))) {
if (orderRelation.getStatus() == 3) {
continue;
}
//3-签收
} else if ("4".equals(jsonObj.getString("State"))) {
//4-问题件
}
}
}
}