相关资料
顺丰统一接入平台 :https://freight.sf-express.com/api/api.html#id=28
顺丰在线查询物流信息地址: https://www.sf-express.com/cn/sc/dynamic_function/waybill/#search/bill-number/SF1193907051991
SF1193907051991] 为快递号 -> 修改为自己的即可
一、顺丰api 接口请求核心类
1、顺丰请求工具类 SFUtil
package com.ws.ldy.others.kuaidi.sf.util;
import com.alibaba.fastjson.JSON;
import com.ws.ldy.config.error.ErrorException;
import com.ws.ldy.others.kuaidi.sf.entity.SFReturnData;
import com.ws.ldy.others.kuaidi.sf.entity.SFReturnError;
import com.ws.ldy.others.kuaidi.sf.entity.cancel.request.RequestCancel;
import com.ws.ldy.others.kuaidi.sf.entity.cancel.response.ResponseCancel;
import com.ws.ldy.others.kuaidi.sf.entity.send.request.RequestCreate;
import com.ws.ldy.others.kuaidi.sf.entity.send.response.ResponseCreate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Encoder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* 顺丰快递 Api 接口对接, 官网文档-零担下单: https://freight.sf-express.com/api/api.html#id=30
* <P>
* 请求头必须添加: "Content-type","application/x-www-form-urlencoded;charset=UTF-8”
* </P>
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/9 0009 9:38
* @version 1.0.0
*/
@SuppressWarnings("all")
@Component
@Slf4j
public class SFUtil {
@Autowired
private RestTemplate restTemplate;
//测试地址
private static final String TEST_URL = "https://sfapi.sit.sf-express.com:45273/std/service";
private static final String TEST_PARTNER_ID = "fop_test";
private static final String TEST_MD5_KEY = "2Z7YPBNG2CKKBV17";
//正式地址 final
private static final String SF_URL = "https://sfapi.sf-express.com/std/service";
private static final String SF_PARTNER_ID = "fop_test";
private static final String SF_MD5_KEY = "2Z7YPBNG2CKKBV17";
/**
* 顺丰寄件下单
* @author wangsong
* @author requestCreate 下单参数
* @date 2020/9/15 0015 15:42
* @return ResponseCreate
* @version 1.0.0
*/
public ResponseCreate fopReceLtlCreateOrder(RequestCreate requestCreate) {
String mgsData = JSON.toJSONString(requestCreate);
//
SFReturnData sfReturnData = http("FOP_RECE_LTL_CREATE_ORDER", mgsData);
//
if (!"A1000".equals(sfReturnData.getApiResultCode())) {
//失败
log.info(sfReturnData.toString());
throw new ErrorException(10099, sfReturnData.getApiErrorMsg());
}
String apiResultData = sfReturnData.getApiResultData();
ResponseCreate responseCreate = JSON.parseObject(apiResultData, ResponseCreate.class);
if (!responseCreate.isSuccess()) {
//失败
log.info(sfReturnData.toString());
SFReturnError sfReturnError = JSON.parseObject(apiResultData, SFReturnError.class);
throw new ErrorException(10099, sfReturnError.getErrorMessage());
}
return responseCreate;
}
/**
* 顺丰取消订单
* @author wangsong
* @author cancel 下单参数
* @date 2020/9/15 0015 15:42
* @return 取消结果信息
* @version 1.0.0
*/
public ResponseCancel fopReceLtlCancelOrder(RequestCancel cancel) {
//
String mgsData = JSON.toJSONString(cancel);
//
SFReturnData sfReturnData = http("FOP_RECE_LTL_CANCEL_ORDER", mgsData);
if (!"A1000".equals(sfReturnData.getApiResultCode())) {
//失败
log.info(sfReturnData.toString());
throw new ErrorException(10099, sfReturnData.getApiErrorMsg());
}
String apiResultData = sfReturnData.getApiResultData();
ResponseCancel responseCancel = JSON.parseObject(apiResultData, ResponseCancel.class);
if (!responseCancel.getSuccess()) {
log.info(sfReturnData.toString());
SFReturnError sfReturnError = JSON.parseObject(apiResultData, SFReturnError.class);
throw new ErrorException(10099, sfReturnError.getErrorMessage());
}
return responseCancel;
}
/**
* 下单结果查询
* @author wangsong
* @author orderId 寄件商家的订单Id(非寄件单号)
* @date 2020/9/15 0015 15:42
* @return 同下单相同数据
* @version 1.0.0
*/
public ResponseCreate fopReceLtlGetOrderResult(String orderId) {
//
Map<String,String> param = new HashMap<>();
param.put("orderId",orderId);
String mgsData = JSON.toJSONString(param);
//
SFReturnData sfReturnData = http("FOP_RECE_LTL_GET_ORDER_RESULT", mgsData);
//
if (!"A1000".equals(sfReturnData.getApiResultCode())) {
//失败
log.info(sfReturnData.toString());
throw new ErrorException(10099, sfReturnData.getApiErrorMsg());
}
String apiResultData = sfReturnData.getApiResultData();
ResponseCreate responseCreate = JSON.parseObject(apiResultData, ResponseCreate.class);
if (!responseCreate.isSuccess()) {
//失败
log.info(sfReturnData.toString());
SFReturnError sfReturnError = JSON.parseObject(apiResultData, SFReturnError.class);
throw new ErrorException(10099, sfReturnError.getErrorMessage());
}
return responseCreate;
}
/**
*
* @param serviceCode 请求接口
* @param mgsData 请求参数: json 参数
* <P>
* // 1* 下快运订单 FOP_RECE_LTL_CREATE_ORDER
* // 2* 取消订单 FOP_RECE_LTL_CANCEL_ORDER
* // 3 筛单结果查询 FOP_RECE_LTL_SEARCH_ORDER
* // 4 路由查询 FOP_RECE_LTL_SEARCH_ROUTER
* // 5 路由推送 FOP_PUSH_LTL_ROUTER
* // 6 清单费用推送 FOP_PUSH_LTL_FEE
* // 7 清单费用查询 FOP_RECE_LTL_QUERY_FEE
* // 8* 下单结果查询 FOP_RECE_LTL_GET_ORDER_RESULT
* // 9 注册路由 FOP_RECE_LTL_REGISTER_ROUTER
* </P>
* @return SFReturnData
*/
private SFReturnData http(String serviceCode, String mgsData) {
String timestamp = System.currentTimeMillis() + "";
// 发送快递参数处理
MultiValueMap<String, Object> sendBody = new LinkedMultiValueMap<>();
sendBody.add("partnerID", TEST_PARTNER_ID); // 合作伙伴编码(由顺丰分配)
sendBody.add("requestID", UUID.randomUUID().toString()); // 请求唯一号UUID
sendBody.add("serviceCode", serviceCode); // 接口服务代码取消订单
sendBody.add("timestamp", timestamp); // 调用接口时间戳
sendBody.add("msgDigest", genDigest(timestamp, mgsData, TEST_MD5_KEY)); // 数字签名
sendBody.add("msgData", mgsData); // 业务数据报文
//设置请求头参数
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");
//发送请求
HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(sendBody, headers);
ResponseEntity<String> result = restTemplate.postForEntity(TEST_URL, formEntity, String.class);
//
SFReturnData sfReturnData = JSON.parseObject(result.getBody(), SFReturnData.class);
return sfReturnData;
}
/**
* 业务数据加密
* @param timestamp
* @param mgsData
* @param md5key
* @return
* @throws Exception
*/
private String genDigest(String timestamp, String mgsData, String md5key) {
//将业务报文+时间戳+秘钥组合成需加密的字符串(注意顺序)
String toVerifyText = mgsData + timestamp + md5key;
//因业务报文中可能包含加号、空格等特殊字符,需要urlEnCode处理
try {
toVerifyText = URLEncoder.encode(toVerifyText, "UTF-8");
//进行Md5加密
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(toVerifyText.getBytes("UTF-8"));
byte[] md = md5.digest();
//通过BASE64生成数字签名
String msgDigest = new String(new BASE64Encoder().encode(md));
return msgDigest;
} catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}
2、提供接口 SFService
/**
* 顺丰快递
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/15 0015 17:22
* @version 1.0.0
*/
public interface SFService {
public String sendSF(RequestCreate en, String productName);
public String cancelSF(String orderId);
public ResponseCreate getOrderSF(String orderId);
}
3、接口实现 SFServiceImpl
package com.ws.ldy.others.kuaidi.sf.service.impl;
import com.ws.ldy.others.kuaidi.sf.entity.cancel.request.RequestCancel;
import com.ws.ldy.others.kuaidi.sf.entity.cancel.response.ResponseCancel;
import com.ws.ldy.others.kuaidi.sf.entity.send.request.CargoList;
import com.ws.ldy.others.kuaidi.sf.entity.send.request.RequestCreate;
import com.ws.ldy.others.kuaidi.sf.entity.send.response.ResponseCreate;
import com.ws.ldy.others.kuaidi.sf.service.SFService;
import com.ws.ldy.others.kuaidi.sf.util.SFUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 顺丰
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/15 0015 17:24
* @version 1.0.0
*/
@Service
public class SFServiceImpl implements SFService {
@Autowired
private SFUtil sfUtil;
/**
* 顺丰下单 /返回单号
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/15 0015 19:36
* @version 1.0.0
*/
@Override
public String sendSF(RequestCreate en, String productName) {
// 付款方式(邮费): 1.寄方付 2.收方付 3.第三方付(默认收件方付)
en.setPayMethod("2");
// 货物明细
CargoList cargoList = new CargoList();
cargoList.setName(productName);
en.setCargoList(cargoList);
ResponseCreate responseCreate = sfUtil.fopReceLtlCreateOrder(en);
return responseCreate == null ? null : responseCreate.getObj().getWaybillNo();
}
/**
* 顺丰取消订单
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/15 0015 19:36
* @version 1.0.0
*/
@Override
public String cancelSF(String orderId) {
RequestCancel requestCancel = new RequestCancel();
requestCancel.setOrderid(orderId); //客户订单号
requestCancel.setCancelType("1"); //传1取消后,orderId可重复利用
ResponseCancel responseCancel = sfUtil.fopReceLtlCancelOrder(requestCancel);
return responseCancel == null ? null : responseCancel.getObj();
}
/**
* 顺丰查询订单
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/15 0015 19:36
* @version 1.0.0
*/
@Override
public ResponseCreate getOrderSF(String orderId) {
ResponseCreate responseCreate = sfUtil.fopReceLtlGetOrderResult(orderId);
return responseCreate;
}
}
4、提供测试接口
@ApiOperation("发货测试")
@RequestMapping(value = "/sendTest", method = RequestMethod.GET)
public R<String> findTable(String orderId) {
//
RequestCreate en = new RequestCreate();
en.setOrderid(orderId); // 订单Id
en.setSendContact("王松"); // 寄件方联系人
en.setSendMobile("17628689969"); // 寄件方电话
en.setSendProvince("四川省"); // 寄件方所在省级行政区名称,必须是标准的省级行政区名称,如:北京、广东省、广西壮族自治区等;
en.setSendCity("成都市"); // 寄件方所在地级行政区名称,必须是标准的城市称谓, 如:北京市、深圳市、大理白族自治州等;
en.setSendCounty("青羊区"); // 寄件人所在县/区级行政区名称必须是标准的县/区称谓, 如:福田区,南涧彝族自治县、准格尔旗等。
en.setSendAddress("新洲十一街万基商务大厦10楼。"); // 寄件人详细地址(请勿包含省市区), 如:新洲十一街万基商务大厦10楼。
//
en.setDeliveryContact("王松"); // 到件方联系人
en.setDeliveryMobile("17628689969");
en.setDeliveryProvince("四川省"); // 到件方所在省级行政区名称,必须是标准的省级行政区名称 如:北京、广东省、广西壮族自治区等;
en.setDeliveryCity("成都市"); // 到件方所在地级行政区名称,必须是标准的城市称谓
en.setDeliveryCounty("武侯区"); // 到件方所在县/区级行政区名称,必须是标准的县/区称谓, 如:福田区,南涧彝族自治县、准格尔旗等
en.setDeliveryAddress("新洲十一街万基商务大厦11楼");// 到件方详细地址(请勿包含省市区), 如:新洲十一街万基商务大厦10楼。
//
return R.success(sfService.sendSF(en, "测试商品"));
}
二、实体类封装
1、返回
1.1、正确统一返回 SFReturnError
package com.ws.ldy.others.kuaidi.sf.entity;
import com.ws.ldy.others.base.model.Convert;
import lombok.Data;
import lombok.ToString;
/**
* 统一返回正确获取对应数据时错误
* @author wangsong
* @mail 1720696548@qq.com`在这里插入代码片`
* @date 2020/9/15 0015 20:29
* @version 1.0.0
*/
@Data
@ToString
public class SFReturnError extends Convert {
private String errorCode;
private String errorMessage;
private Boolean success;
}
1.2、错误统一返回 SFReturnData
package com.ws.ldy.others.kuaidi.sf.entity;
import com.ws.ldy.others.base.model.Convert;
import lombok.Data;
import lombok.ToString;
/**
* 顺丰请求的-统一返回数据格式
*/
@Data
@ToString
public class SFReturnData extends Convert {
private String apiErrorMsg;
private String apiResponseID;
private String apiResultCode;
private String apiResultData;
}
2、寄件请求
2.1、请求必填参数 RequestCreate
/**
* Copyright 2020 bejson.com
*/
package com.ws.ldy.others.kuaidi.sf.entity.send.request;
import com.ws.ldy.others.base.model.Convert;
import lombok.Data;
import lombok.ToString;
/**
* 顺丰寄件必填参数的请求参数(当前系统使用参数)
* @author wangsong
* @date 2020/9/15 0015 16:05
* @return
* @version 1.0.0
*/
@Data
@ToString
public class RequestCreate extends Convert {
private String orderid; // 订单Id
// 寄件方
private String sendContact; // 寄件方联系人
private String sendMobile; // 寄件方电话
private String sendProvince; // 寄件方所在省级行政区名称,必须是标准的省级行政区名称,如:北京、广东省、广西壮族自治区等;
private String sendCity; // 寄件方所在地级行政区名称,必须是标准的城市称谓, 如:北京市、深圳市、大理白族自治州等;
private String sendCounty; // 寄件人所在县/区级行政区名称必须是标准的县/区称谓, 如:福田区,南涧彝族自治县、准格尔旗等。
private String sendAddress; // 寄件人详细地址(请勿包含省市区), 如:新洲十一街万基商务大厦10楼。
// 到件方
private String deliveryContact; // 到件方联系人
private String deliveryMobile; // 到件方电话
private String deliveryProvince; // 到件方所在省级行政区名称,必须是标准的省级行政区名称 如:北京、广东省、广西壮族自治区等;
private String deliveryCity; // 到件方所在地级行政区名称,必须是标准的城市称谓
private String deliveryCounty; // 到件方所在县/区级行政区名称,必须是标准的县/区称谓, 如:福田区,南涧彝族自治县、准格尔旗等
private String deliveryAddress; // 到件方详细地址(请勿包含省市区), 如:新洲十一街万基商务大厦10楼。
//
private String payMethod; // 付款方式(邮费): 1.寄方付 2.收方付 3.第三方付
private CargoList cargoList; // 货物明细,-非必填 参见Cargo
private String remark; // 下单备注
private String pickUpMode; // 取件方式 1. 客户自送 2 上门接货。默认为2上门接货。
private String expectedPickUpTime; // 希望上门取件时间。 格式:yyyy-MM-dd HH:mm:ss
}
2.2、请求必填- 子参数 CargoList
/**
* 货物信息
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/15 0015 20:13
* @version 1.0.0
*/
@Data
@ToString
public class CargoList {
private String name;
private int count;
private String unit;
private int length;
private int width;
private double amount;
private String currency;
private String sourcearea;
private String productrecordno;
private String goodPrepardNo;
private String taxNo;
private String hsCode;
private double volume;
private int boxno;
private int installcargotype;
private int height;
private int weight;
}
2.3、响应参数 ResponseCreate
/**
* 顺丰快递统一响应成功 SFReturnData 下的 apiResultData 内数据
* @author wangsong
* @mail 1720696548@qq.com
* @date 2020/9/15 0015 20:15
* @version 1.0.0
*/
@Data
@ToString
public class ResponseCreate extends Convert {
private Obj obj;
private boolean success;
}
2.4、响应子参数 Obj
@Data
@ToString
public class Obj extends Convert {
private String destCode;
private String filterResult;
private String orderId;
private RlsInfo rlsInfo;
private String waybillNo; //顺丰订单号
}
2.5、响应子参数 RlsDetail
@Data
@ToString
public class RlsDetail extends Convert {
private String abFlag;
private String cargoTypeCode;
private String codingMapping;
private String codingMappingOut;
private String deliveryMode;
private String destCityCode;
private String destDeptCode;
private String destDeptCodeMapping;
private String destRouteLabel;
private String destTeamCode;
private String destTeamCodeMapping;
private String destTransferCode;
private String destinationStationCode;
private String errMsg;
private String expressTypeCode;
private String fopIcon;
private String goodsNumber;
private String limitTypeCode;
private String newIcon;
private String printFlag;
private String printIcon;
private String proCode;
private String proName;
private String routeArray;
private String sendAreaCode;
private String sourceCityCode;
private String sourceDeptCode;
private String sourceTeamCode;
private String sourceTransferCode;
private String sxCompany;
private String twoDimensionCode;
private String waybillNo;
private String xbFlag;
}
2.6、响应子参数 RlsInfo
@Data
@ToString
public class RlsInfo extends Convert {
private RlsDetail rlsDetail;
}
3、取消寄件
3.1、请求 RequestCancel
@Data
@ToString
public class RequestCancel extends Convert {
private String orderid; // 客户订单号
private String cancelType; // 传1取消后,orderId可重复利用
}
3.2、响应 ResponseCancel
/**
* 顺丰快递统一响应成功 SFReturnData 下的 apiResultData 内数据
* @author wangsong
* @date 2020/9/15 0015 16:05
* @return
* @version 1.0.0
*/
@Data
@ToString
public class ResponseCancel extends Convert {
private String errorCode; // 错误代码
private String errorMessage; // 错误描述
private Boolean success; // 是否成功
private String obj; // 返回数据 //orderId String(64) R 客户订单号
}
-
个人开源项目(通用后台管理系统)–> https://gitee.com/wslxm/spring-boot-plus2 , 喜欢的可以看看
-
本文到此结束,如果觉得有用,动动小手点赞或关注一下呗,将不定时持续更新更多的内容…,感谢大家的观看!