基于顺丰同城接口编写sdk,java三方sdk编写思路

栏目: Java · 发布时间: 5年前

内容简介:由于公司外卖业务需要用到顺丰的配送体系,技术上需要对接顺丰 个人比较感兴趣,但是顺丰没有提供sdk,所以研究下自己写了一个完整代码已上传github :tada::三方sdk编写有两种实现方式

由于公司外卖业务需要用到顺丰的配送体系,技术上需要对接顺丰 个人比较感兴趣,但是顺丰没有提供sdk,所以研究下自己写了一个

完整代码已上传github :tada:: github.com/neatlife/sf…

技术选型

三方sdk编写有两种实现方式

  1. 不依赖框架,更通用,但是集成成本较高
  2. 依赖框架,比如spring boot,这样使用起来效率更高

为了提高使用效率,这里选择基于spring boot框架进行编写

前期准备

有很多基于spring boot的sdk了,骨架就不需要自行搭建了,找了下面几个进行参考

  1. github.com/jibaole/spr…
  2. github.com/spring-proj…

研究api文档

顺丰同城api文档地址: commit-openic.sf-express.com/open/api/do…

目前顺丰同城的开发者api个人可以注册,注册后可以设置回调地址

基于顺丰同城接口编写sdk,java三方sdk编写思路

找出文档中的关键点

在后续设计sdk上,考虑下这些点,可以让sdk更好用

顺丰状态回调可能会失败,通过定时调用查询订单状态接口可以补齐状态

基于顺丰同城接口编写sdk,java三方sdk编写思路

可以实时获取配送员的坐标,这个可用在app上实时显示配送员位置功能

基于顺丰同城接口编写sdk,java三方sdk编写思路

创建项目

虽然项目是作为和spring boot一起使用的,但是我们并不需要依赖完整的spring boot框架,所以创建一个maven项目就是ok的

基于顺丰同城接口编写sdk,java三方sdk编写思路

指定groupId, ArtifactId

基于顺丰同城接口编写sdk,java三方sdk编写思路

为了享受spring boot的自动配置,需要pom.xml里面加上spring-boot-autoconfigure库依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
复制代码

加上常用的http,lombok等库,最终pom文件内容如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.github.neatlife</groupId>
    <artifactId>sfcity</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.8</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
复制代码

自动配置api的密钥

把从顺丰api后台获取的配置信息写入配置文件:src/main/resources/application.properties 所有配置如下

sfcity.developer-id= xxx
sfcity.developer-key= xxx
sfcity.shop-id= xxx
sfcity.api-url= https://commit-openic.sf-express.com
复制代码

使用spring boot的自动配置机制,能够很方便的从配置文件中读取配置 核心代码如下

@ConfigurationProperties(prefix = "sfcity")
@Data
public class Properties {

    private Integer developerId;

    private String developerKey;

    private String shopId;

    private String apiUrl;

}
复制代码

参考:

  1. src/main/java/com/github/neatlife/AutoConfiguration.java
  2. src/main/java/com/github/neatlife/Properties.java

映射请求参数和响应参数

因为要做一个通用的sdk库,那么所有的请求参数和响应参数都需要映射,方便使用

这里为了演示就拿创建订单接口举例了

基于顺丰同城接口编写sdk,java三方sdk编写思路

创建订单请求实体

基于顺丰同城接口编写sdk,java三方sdk编写思路

响应实体

基于顺丰同城接口编写sdk,java三方sdk编写思路

还有一些关联的实体一并创建,最终实体效果如下:

基于顺丰同城接口编写sdk,java三方sdk编写思路

http处理 工具

使用resetTemplate进行请求,参考: juejin.im/post/5b88b1… 核心代码如下:

public static Response post(Integer appId, String appSecret, String url, Request request) {
    String content = JsonUtil.toJsonString(request);
    String sign = SignUtil.sign(appId.toString(), appSecret, content);

    url = url + "?sign=" + sign;

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

    HttpEntity<String> httpEntity = new HttpEntity<>(content, headers);
    ResponseEntity<String> httpResponse = restTemplate.postForEntity(url, httpEntity, String.class);

    Response response = JsonUtil.toObject(httpResponse.getBody(), Response.class);

    if (response.getErrorCode() != 0) {
        log.error("errorData: {}", response.getErrorData());
        throw new RuntimeException(response.getErrorMsg());
    }

    return response;
}
复制代码

json处理工具类

json处理工具类直接从自己编写的框架里拿,参考: github.com/neatlife/jf…

签名工具类

顺丰提供了 java 的签名示例代码

基于顺丰同城接口编写sdk,java三方sdk编写思路

在其基础上修改即可,核心代码如下

public static String sign(String appId, String appSecret, String content) {
    // 假设原始内容JSON为 {"hello":"kitty"}
    // content : "{\"hello\":\"kitty\"}"

    String toSign = content + "&" + appId + "&" + appSecret;
    // toSign : "{\"hello\":\"kitty\"}&1234567890&0123456789abcdef0123456789abcdef";

    String md5Result = md5(toSign.getBytes(StandardCharsets.UTF_8));
    // md5Result : "ef3435b1480e553480e19e3e162fb0be"

    // signResult : "ZWYzNDM1YjE0ODBlNTUzNDgwZTE5ZTNlMTYyZmIwYmU="

    return base64Encode(md5Result.getBytes(StandardCharsets.UTF_8));
}
复制代码

完整代码参考:src/main/java/com/github/neatlife/util/SignUtil.java

定义接口常量

把需要调用的接口地址放到统一的常量文件中,方便管理 核心代码如下:

public class ApiUrlConstant {

    private static final String CREATE_ORDER_URL = "/open/api/external/createorder";
    private static String sfCityHost;

    public static String getCreateOrderUrl() {
        return sfCityHost + CREATE_ORDER_URL;
    }

    public static void setSfCityHost(String sfCityHost) {
        ApiUrlConstant.sfCityHost = sfCityHost;
    }
}
复制代码

调用顺丰创建订单接口

上面步骤都准备完成后,进行到最重要的调用环节了,有了上面的准备,这一步也比较容易了 核心代码如下

public CreateOrderResponse createOrder(CreateOrderRequest createOrderRequest) {
    createOrderRequest.setDevId(developerId);
    createOrderRequest.setShopId(shopId);
    Response response = HttpUtil.post(
            developerId,
            developerKey,
            ApiUrlConstant.getCreateOrderUrl(),
            createOrderRequest
    );
    return JsonUtil.toObject(response.getResult(), CreateOrderResponse.class);
}
复制代码

编写自动测试

创建测试文件:src/test/java/com/github/neatlife/SfClientTest.java 填充测试数据 调用创建订单方法

@Test
public void createOrder() {
    CreateOrderResponse createOrderResponse = sfClient.createOrder(createOrderRequest());

    Assert.assertNotNull(createOrderResponse.getSfOrderId());
}

private CreateOrderRequest createOrderRequest() {
    CreateOrderRequest createOrderRequest = new CreateOrderRequest();
    createOrderRequest.setShopOrderId(System.currentTimeMillis() + "");
    createOrderRequest.setOrderSource("测试");
    createOrderRequest.setPayType(1);
    createOrderRequest.setOrderTime(DateUtil.currentSecond().intValue());
    createOrderRequest.setIsAppoint(0);
    createOrderRequest.setIsInsured(0);
    createOrderRequest.setRiderPickMethod(1);
    createOrderRequest.setPushTime(DateUtil.currentSecond().intValue());
    createOrderRequest.setVersion(17);
    createOrderRequest.setShop(
            Shop.builder()
                    .shopName("店铺名")
                    .shopPhone("13266666666")
                    .shopAddress("朝阳区高碑店镇四惠大厦F1-008")
                    .shopLng("116.514236")
                    .shopLat("39.905328")
                    .build()
    );
    createOrderRequest.setReceive(
            Receive.builder()
                    .userName("小明")
                    .userPhone("13288888888")
                    .userPhone("北京")
                    .userLng("116.3534196")
                    .userLat("40.0159778")
                    .userAddress("朝阳区高碑店镇四惠大厦F1-008")
                    .cityName("北京市")
                    .build()
    );
    createOrderRequest.setOrderDetail(
            OrderDetail.builder()
                    .totalPrice(100)
                    .productType(1)
                    .weightGram(500)
                    .productNum(1)
                    .productTypeNum(1)
                    .productDetail(
                            Stream.of(
                                    ProductDetail.builder()
                                            .productName("小炒肉")
                                            .productNum(1)
                                            .build()
                            ).collect(Collectors.toList())
                    )
                    .build()
    );
    return createOrderRequest;
}
复制代码

填充测试数据时注释对照顺丰文档,保证必填字段都有值

查看运行效果:

基于顺丰同城接口编写sdk,java三方sdk编写思路

顺丰返回了创建订单成功的响应:smile:

然后把jar包拷到需要的项目就可以使用了


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

复杂网络理论及其应用

复杂网络理论及其应用

汪小帆、李翔、陈关荣 / 清华大学出版社 / 2006 / 45.00元

国内首部复杂网络专著 【图书目录】 第1章 引论 1.1 引言 1.2 复杂网络研究简史 1.3 基本概念 1.4 本书内容简介 参考文献 第2章 网络拓扑基本模型及其性质 2.1 引言 2.2 规则网络 2.3 随机图 2.4 小世界网络模型 2.5 无标度网络模型 ......一起来看看 《复杂网络理论及其应用》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具