java接入顺丰快递api(有可运行demo)(包括下单、路由查询、路由推送、查询订单状态、取消订单)

故事发生的背景: 公司快递业务这一块之前接入的是快递100,由于快递100的推送的实时性没有达到公司的要求,而且公司全都用的顺丰快递,所以直接接入了顺丰快递的api。demo文章最后下载(新增了json格式请求)
首先, 申请接入流程不多说,这个是申请地址 ,先看一下我在平台申请的五个api(第一个是默认就有的,也是必须有的,下面四个是自己添加的),如下图:
顺丰api
我说明一下第一个下单接口和第五个路由推送接口,其他的照葫芦画瓢就搞定了,代码我会放在文章最后给需要的人下载。
重要提示: 下顺丰订单,肯定存在输入信息有误取消订单的情况。所以下顺丰订单传入的orderId,不要是你项目中的唯一的订单标识符,例如orderNo啊什么的,否则取消顺丰订单后,再次下单传入同一个orderId时,会下单失败的,提示:该订单已取消。
准备阶段: 顺丰这边给了一个jar包–>SF-CSIM-EXPRESS-SDK-V1.6.jar,主要用于加密和网络请求,其实打开看看,里面没啥技术含量的,加密和请求都可以自己写,没必要导包。想图省事的话直接拷贝出来放到自己项目就行了,注意我圈的三个文件,我就直接导入到项目中修改了一下就开始用了。
SF-CSIM-EXPRESS-SDK-V1.6.jar

下单接口

在开始测试前有个重点:这一点对于测试路由推送很重要,如下图
路由推送回调地址
把路由推送快递信息到的地址先配置一下。因为测试环境下,在我们下单成功后10分钟内(也有15分钟左右推送的)平台会给我们推送两条测试信息。 后面我会说明回调地址中的代码如何写。继续回到下单接口,下面我就直接上代码了,这个最直观。

/**
 * 获取下单请求体
 * @param expressOrder 快递信息实体类
 * @return
 */
public static String getOrderServiceRequestXml(ExpressOrder expressOrder) {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append("<?xml version='1.0' encoding='UTF-8'?>");
        strBuilder.append("<Request service='OrderService' lang='zh-CN'>");
        strBuilder.append("<Head>" + CLIENT_CODE + "</Head>");
        strBuilder.append("<Body>");
        strBuilder.append("<Order").append(" ");
        strBuilder.append("orderid='" + expressOrder.getOrderId() + "'").append(" ");
        //  1 代表顺丰标快 -- 详情查看平台 快件产品类别表,注意:标快支持子母单,速配不支持
        strBuilder.append("express_type='1'").append(" ");
        // 寄件方信息
        strBuilder.append("j_province='" + expressOrder.getjProvince() + "'").append(" ");
        strBuilder.append("j_city='" + expressOrder.getjCity() + "'").append(" ");
        strBuilder.append("j_county='" + expressOrder.getjCounty() + "'").append(" ");
        strBuilder.append("j_company='" + expressOrder.getjCompany() + "'").append(" ");
        strBuilder.append("j_contact='" + expressOrder.getjContact() + "'").append(" ");
        strBuilder.append("j_tel='" + expressOrder.getjTel() + "'").append(" ");
        strBuilder.append("j_address='" + expressOrder.getjAddress() + "'").append(" ");
        // 收件方信息
        strBuilder.append("d_province='" + expressOrder.getdProvince() + "'").append(" ");
        strBuilder.append("d_city='" + expressOrder.getdCity() + "'").append(" ");
        strBuilder.append("d_county='" + expressOrder.getdCounty() + "'").append(" ");
        strBuilder.append("d_company='" + expressOrder.getdCompany() + "'").append(" ");
        strBuilder.append("d_tel='" + expressOrder.getdTel() + "'").append(" ");
        strBuilder.append("d_contact='" + expressOrder.getdContact() + "'").append(" ");
        strBuilder.append("d_address='" + expressOrder.getdAddress() + "'").append(" ");
        if (!TextUtils.isEmpty(expressOrder.getRemark())) {
            strBuilder.append("remark='" + expressOrder.getRemark() + "'").append(" ");
        }
        // 货物信息
        // 这个参数是设置包裹数量n,n大于1是子母件,一个母单号,其他子单号,需要打印n张快递单
        strBuilder.append("parcel_quantity='1'").append(" ");
        strBuilder.append("pay_method='1'").append(" ");
        strBuilder.append("custid ='" + CallExpressServiceTools.CUST_ID + "'").append(" ");
        strBuilder.append("customs_batchs=''").append(" ");
        strBuilder.append("cargo='医药'").append(">");
        strBuilder.append("</Order>");
        strBuilder.append("</Body>");
        strBuilder.append("</Request>");
        return strBuilder.toString();
    }

写个测试方法:

@Test
public void testShunfengOrderService() {
    ExpressOrder expressOrder = new ExpressOrder();
    expressOrder.setOrderId("20190121181653954019");
    expressOrder.setjProvince("广东省");
    expressOrder.setjCity("深圳市");
    expressOrder.setjCounty("南山区");
    expressOrder.setjCompany("金草中医");
    expressOrder.setjContact("李大宝");
    expressOrder.setjTel("18777276920");
    expressOrder.setjAddress("龙珠四路金谷创业园c座611");
    expressOrder.setdProvince("广东省");
    expressOrder.setdCity("广州市");
    expressOrder.setdCounty("海珠区");
    expressOrder.setdCompany("个人");
    expressOrder.setdContact("滕大宝");
    expressOrder.setdTel("18938905541");
    expressOrder.setdAddress("宝芝林大厦701室");
    String requestXml = RequestXmlUtil.getOrderServiceRequestXml(expressOrder);
    System.out.println("请求报文:" + requestXml);
    String respXml= CallExpressServiceTools.callSfExpressServiceByCSIM(requestXml);
    System.out.println("响应报文:" + respXml);
}

测试方法运行后,一种方法可以打印响应报文,结合平台说明看是否成功。另一种方式是通过平台的我的沙盒查看,我建议第二钟方法,因为第二种可以看到更多信息,而且更直观。如下图:
在这里插入图片描述

路由推送

推送配置方面,我选择的form方式,
form方式
路由推送关键的部分是接收到推送的响应,必须为post。代码如下:

@RequestMapping(value="shunfeng/callback", method = RequestMethod.POST)
public @ResponseBody String shunFengCallback(String content) {
	LOGGER.info("顺丰路由推送响应参数 shunfeng/callback  content:{}", content);
	// 这里可以对接收到的content解析后进行操作
	ShunFengResponse response = XmlHelper.xmlToBeanForSF(content);
	
	return "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" +
			"<Response service=\"RoutePushService\">" +
			"<Head>OK</Head>" +
			"</Response>";
}

补充: 关于顺丰订单下成功以后打印面单的问题。下单成功后可以让顺丰那边上门取件由顺丰打印面单就可以了。也可以自己设计打印,比如我们公司需要用自己的包装盒,所以我们是自己打印面单的,我们使用二联的格式,布局时html画出来的,所需内容是自己下单填写的信息和下单成功后返回的信息。顺丰那边提供打印机和打印纸。
新增: demo中新增了json格式请求,已写好测试用例,直接运行即可。
demo结构
在这里插入图片描述

ok,文章到这里就结束了,有不对的地方和有疑问的道友们欢迎指正和评论,积分不够或者链接失效的话可以先在评论区留下邮箱。
代码下载地址

  • 14
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 89
    评论
如果你想使用`net.sf.json`库来将JSON字符串转换为List,你可以按照以下步骤进行操作: 1. 首先,确保你已经将`net.sf.json`库添加到你的项目依赖中。你可以在 Maven 或者 Gradle 的配置文件中添加如下依赖: ```xml <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> ``` 2. 接下来,使用`JSONArray`类将JSON字符串转换为JSONArray对象,然后通过遍历JSONArray对象将其转换为List。以下是一个示例代码: ```java import net.sf.json.JSONArray; import net.sf.json.JSONObject; import java.util.ArrayList; import java.util.List; public class JsonToListExample { public static void main(String[] args) { String jsonStr = "[{\"name\":\"John\",\"age\":30},{\"name\":\"Jane\",\"age\":25}]"; JSONArray jsonArray = JSONArray.fromObject(jsonStr); List<Person> personList = new ArrayList<>(); for (Object obj : jsonArray) { JSONObject jsonObject = (JSONObject) obj; Person person = (Person) JSONObject.toBean(jsonObject, Person.class); personList.add(person); } for (Person person : personList) { System.out.println("Name: " + person.getName()); System.out.println("Age: " + person.getAge()); } } static class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } } ``` 在上面的示例中,我们首先使用`JSONArray.fromObject()`方法将JSON字符串转换为JSONArray对象。然后,通过遍历JSONArray对象,我们将每个JSONObject转换为Person对象,并将其添加到List中。 请确保在使用`net.sf.json`库之前,将其添加到你的项目依赖中。
评论 89
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值