瀏覽代碼

快递100

24282 2 年之前
父節點
當前提交
0e922f616d
共有 33 個文件被更改,包括 1173 次插入3 次删除
  1. 3 3
      hx-file/src/test/java/Main.java
  2. 35 0
      hx-kd100/pom.xml
  3. 10 0
      hx-kd100/src/main/java/com/fjhx/kd100/constant/Kd100Constant.java
  4. 57 0
      hx-kd100/src/main/java/com/fjhx/kd100/constant/LogisticsConstant.java
  5. 75 0
      hx-kd100/src/main/java/com/fjhx/kd100/controller/callback/CallbackConfig.java
  6. 40 0
      hx-kd100/src/main/java/com/fjhx/kd100/controller/company/CompanyInfoController.java
  7. 77 0
      hx-kd100/src/main/java/com/fjhx/kd100/controller/config/ConfigInfoController.java
  8. 17 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/company/dto/CompanyInfoSelectDto.java
  9. 43 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/company/po/CompanyInfo.java
  10. 17 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/company/vo/CompanyInfoVo.java
  11. 17 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/config/dto/ConfigInfoDto.java
  12. 17 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/config/dto/ConfigInfoSelectDto.java
  13. 53 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/config/po/ConfigInfo.java
  14. 17 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/config/vo/ConfigInfoVo.java
  15. 52 0
      hx-kd100/src/main/java/com/fjhx/kd100/entity/logistics/po/LogisticsInfo.java
  16. 20 0
      hx-kd100/src/main/java/com/fjhx/kd100/event/Kd100CallbackEvent.java
  17. 26 0
      hx-kd100/src/main/java/com/fjhx/kd100/mapper/company/CompanyInfoMapper.java
  18. 26 0
      hx-kd100/src/main/java/com/fjhx/kd100/mapper/config/ConfigInfoMapper.java
  19. 17 0
      hx-kd100/src/main/java/com/fjhx/kd100/mapper/logistics/LogisticsInfoMapper.java
  20. 25 0
      hx-kd100/src/main/java/com/fjhx/kd100/service/company/CompanyInfoService.java
  21. 33 0
      hx-kd100/src/main/java/com/fjhx/kd100/service/company/impl/CompanyInfoServiceImpl.java
  22. 46 0
      hx-kd100/src/main/java/com/fjhx/kd100/service/config/ConfigInfoService.java
  23. 59 0
      hx-kd100/src/main/java/com/fjhx/kd100/service/config/impl/ConfigInfoServiceImpl.java
  24. 17 0
      hx-kd100/src/main/java/com/fjhx/kd100/service/logistics/LogisticsInfoService.java
  25. 21 0
      hx-kd100/src/main/java/com/fjhx/kd100/service/logistics/impl/LogisticsInfoServiceImpl.java
  26. 55 0
      hx-kd100/src/main/java/com/fjhx/kd100/util/KD100Result.java
  27. 226 0
      hx-kd100/src/main/java/com/fjhx/kd100/util/KD100Util.java
  28. 15 0
      hx-kd100/src/main/resources/mapper/company/CompanyInfoMapper.xml
  29. 19 0
      hx-kd100/src/main/resources/mapper/config/ConfigInfoMapper.xml
  30. 4 0
      hx-kd100/src/main/resources/mapper/logistics/LogisticsInfoMapper.xml
  31. 1 0
      pom.xml
  32. 31 0
      ruoyi-common/src/main/java/com/ruoyi/common/config/HxConfig.java
  33. 2 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/BaseSourceConstant.java

+ 3 - 3
hx-file/src/test/java/Main.java

@@ -4,12 +4,12 @@ public class Main {
 
     public static void main(String[] args) {
         GeneratorApplication.builder()
-                .url("jdbc:mysql://36.134.91.96:17330/bytesailing_base?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true")
+                .url("jdbc:mysql://36.134.91.96:17330/bytesailing_kd100?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true")
                 .username("fjhx2012mysql")
                 .password("3PN-Mzn#vnP&q6d")
                 .port(9989)
-                .module("hx-flow")
-                .parent("com.fjhx.flow")
+                .module("hx-kd100")
+                .parent("com.fjhx.kd100")
                 .superServiceClass("com.ruoyi.common.core.service.BaseService")
                 .build();
     }

+ 35 - 0
hx-kd100/pom.xml

@@ -0,0 +1,35 @@
+<?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>
+    <parent>
+        <groupId>com.ruoyi</groupId>
+        <artifactId>ruoyi</artifactId>
+        <version>3.8.5</version>
+    </parent>
+
+    <artifactId>hx-kd100</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-framework</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.kuaidi100-api</groupId>
+            <artifactId>sdk</artifactId>
+            <version>1.0.11</version>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 10 - 0
hx-kd100/src/main/java/com/fjhx/kd100/constant/Kd100Constant.java

@@ -0,0 +1,10 @@
+package com.fjhx.kd100.constant;
+
+/**
+ * 快递100回调接口路径
+ */
+public interface Kd100Constant {
+
+    String CALLBACK_URL = "open/kd100/callback";
+
+}

+ 57 - 0
hx-kd100/src/main/java/com/fjhx/kd100/constant/LogisticsConstant.java

@@ -0,0 +1,57 @@
+package com.fjhx.kd100.constant;
+
+/**
+ * 物流常量
+ */
+public interface LogisticsConstant {
+
+    /**
+     * 状态
+     */
+    class Status {
+        // 未完成 / 未到货
+        public static final Integer STATUS_0 = 0;
+        // 已完成 / 已到货
+        public static final Integer STATUS_1 = 1;
+    }
+
+    /**
+     * 入库状态
+     */
+    class InStockStatus {
+        // 未入库
+        public static final Integer STATUS_10 = 10;
+        // 部分入库
+        public static final Integer STATUS_20 = 20;
+        // 已入库
+        public static final Integer STATUS_30 = 30;
+    }
+
+    /**
+     * 物流状态(快递100的状态)
+     */
+    class KD100Status {
+        // 未找到快递信息
+        public static final Integer STATUS_N = -1;
+        // 在途
+        public static final Integer STATUS_0 = 0;
+        // 揽收
+        public static final Integer STATUS_1 = 1;
+        // 疑难
+        public static final Integer STATUS_2 = 2;
+        // 签收
+        public static final Integer STATUS_3 = 3;
+        // 退签
+        public static final Integer STATUS_4 = 4;
+        // 派件
+        public static final Integer STATUS_5 = 5;
+        // 退回
+        public static final Integer STATUS_6 = 6;
+        // 转投
+        public static final Integer STATUS_7 = 7;
+        // 清关
+        public static final Integer STATUS_8 = 8;
+        // 拒签
+        public static final Integer STATUS_14 = 14;
+    }
+}

+ 75 - 0
hx-kd100/src/main/java/com/fjhx/kd100/controller/callback/CallbackConfig.java

@@ -0,0 +1,75 @@
+package com.fjhx.kd100.controller.callback;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.fjhx.kd100.entity.logistics.po.LogisticsInfo;
+import com.fjhx.kd100.event.Kd100CallbackEvent;
+import com.fjhx.kd100.service.logistics.LogisticsInfoService;
+import com.fjhx.kd100.util.KD100Util;
+import com.ruoyi.common.annotation.TenantIgnore;
+import com.ruoyi.common.constant.BaseSourceConstant;
+import io.seata.spring.annotation.GlobalTransactional;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+@DS(BaseSourceConstant.KD100)
+@TenantIgnore
+@RestController
+@RequestMapping("/open/kd100")
+public class CallbackConfig {
+
+    @Autowired
+    private LogisticsInfoService logisticsInfoService;
+
+    @Autowired
+    private ApplicationEventPublisher applicationEventPublisher;
+
+    /**
+     * 物流公司列表
+     */
+    @PostMapping("/callback")
+    @GlobalTransactional(rollbackFor = Exception.class)
+    public synchronized JSONObject callback(@RequestBody String data) {
+        // 解析回调参数
+        JSONObject result = KD100Util.parseCallbackData(data);
+
+        handleCallback(result);
+
+        JSONObject returnResult = new JSONObject();
+        returnResult.put("result", true);
+        returnResult.put("returnCode", 200);
+        returnResult.put("message", "成功");
+        return returnResult;
+    }
+
+    private void handleCallback(JSONObject result) {
+
+        // 快递公司编码
+        String com = result.getString("com");
+        // 	单号
+        String nu = result.getString("nu");
+        // 物流状态
+        Integer state = result.getInteger("state");
+
+        List<LogisticsInfo> logisticsInfoList = logisticsInfoService.list(
+                q -> q.eq(LogisticsInfo::getNumber, nu).eq(LogisticsInfo::getCompany, com));
+
+        if (logisticsInfoList.size() == 0) {
+            return;
+        }
+        
+        for (LogisticsInfo logisticsInfo : logisticsInfoList) {
+            logisticsInfo.setState(state);
+            applicationEventPublisher.publishEvent(new Kd100CallbackEvent(this, logisticsInfo));
+        }
+
+        logisticsInfoService.updateBatchById(logisticsInfoList);
+    }
+
+}

+ 40 - 0
hx-kd100/src/main/java/com/fjhx/kd100/controller/company/CompanyInfoController.java

@@ -0,0 +1,40 @@
+package com.fjhx.kd100.controller.company;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.fjhx.kd100.entity.company.dto.CompanyInfoSelectDto;
+import com.fjhx.kd100.entity.company.vo.CompanyInfoVo;
+import com.fjhx.kd100.service.company.CompanyInfoService;
+import com.ruoyi.common.constant.BaseSourceConstant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 物流公司 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2023-04-11
+ */
+@DS(BaseSourceConstant.KD100)
+@RestController
+@RequestMapping("/companyInfo")
+public class CompanyInfoController {
+
+    @Autowired
+    private CompanyInfoService companyInfoService;
+
+    /**
+     * 物流公司列表
+     */
+    @PostMapping("/list")
+    public List<CompanyInfoVo> list(@RequestBody CompanyInfoSelectDto dto) {
+        return companyInfoService.getList(dto);
+    }
+
+}

+ 77 - 0
hx-kd100/src/main/java/com/fjhx/kd100/controller/config/ConfigInfoController.java

@@ -0,0 +1,77 @@
+package com.fjhx.kd100.controller.config;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.kd100.entity.config.dto.ConfigInfoDto;
+import com.fjhx.kd100.entity.config.dto.ConfigInfoSelectDto;
+import com.fjhx.kd100.entity.config.vo.ConfigInfoVo;
+import com.fjhx.kd100.service.config.ConfigInfoService;
+import com.ruoyi.common.annotation.TenantIgnore;
+import com.ruoyi.common.constant.BaseSourceConstant;
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * 租户快递100账户配置 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2023-04-11
+ */
+@DS(BaseSourceConstant.KD100)
+@TenantIgnore
+@RestController
+@RequestMapping("/configInfo")
+public class ConfigInfoController {
+
+    @Autowired
+    private ConfigInfoService configInfoService;
+
+    /**
+     * 租户快递100账户配置分页
+     */
+    @PostMapping("/page")
+    public Page<ConfigInfoVo> page(@RequestBody ConfigInfoSelectDto dto) {
+        return configInfoService.getPage(dto);
+    }
+
+    /**
+     * 租户快递100账户配置明细
+     */
+    @PostMapping("/detail")
+    public ConfigInfoVo detail(@RequestBody BaseSelectDto dto) {
+        return configInfoService.detail(dto.getId());
+    }
+
+    /**
+     * 租户快递100账户配置新增
+     */
+    @PostMapping("/add")
+    public void add(@Validated @RequestBody ConfigInfoDto configInfoDto) {
+        configInfoService.add(configInfoDto);
+    }
+
+    /**
+     * 租户快递100账户配置编辑
+     */
+    @PostMapping("/edit")
+    public void edit(@RequestBody ConfigInfoDto configInfoDto) {
+        configInfoService.edit(configInfoDto);
+    }
+
+    /**
+     * 租户快递100账户配置删除
+     */
+    @PostMapping("/delete")
+    public void delete(@RequestBody BaseSelectDto dto) {
+        configInfoService.delete(dto.getId());
+    }
+
+}

+ 17 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/company/dto/CompanyInfoSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.kd100.entity.company.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 物流公司列表查询入参实体
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+public class CompanyInfoSelectDto extends BaseSelectDto {
+
+}

+ 43 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/company/po/CompanyInfo.java

@@ -0,0 +1,43 @@
+package com.fjhx.kd100.entity.company.po;
+
+import com.ruoyi.common.core.domain.BaseIdPo;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 物流公司
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+@TableName("company_info")
+public class CompanyInfo extends BaseIdPo {
+
+    /**
+     * 编码
+     */
+    private String code;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 类型
+     */
+    private String type;
+
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+}

+ 17 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/company/vo/CompanyInfoVo.java

@@ -0,0 +1,17 @@
+package com.fjhx.kd100.entity.company.vo;
+
+import com.fjhx.kd100.entity.company.po.CompanyInfo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 物流公司列表查询返回值实体
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+public class CompanyInfoVo extends CompanyInfo {
+
+}

+ 17 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/config/dto/ConfigInfoDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.kd100.entity.config.dto;
+
+import com.fjhx.kd100.entity.config.po.ConfigInfo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 租户快递100账户配置新增编辑入参实体
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+public class ConfigInfoDto extends ConfigInfo {
+
+}

+ 17 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/config/dto/ConfigInfoSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.kd100.entity.config.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 租户快递100账户配置列表查询入参实体
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+public class ConfigInfoSelectDto extends BaseSelectDto {
+
+}

+ 53 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/config/po/ConfigInfo.java

@@ -0,0 +1,53 @@
+package com.fjhx.kd100.entity.config.po;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.ruoyi.common.core.domain.BasePo;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * <p>
+ * 租户快递100账户配置
+ * </p>
+ *
+ * @author
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+@TableName("config_info")
+public class ConfigInfo extends BasePo {
+
+    /**
+     * 快递100 key
+     */
+    @NotNull
+    private String kdKey;
+
+    /**
+     * 快递100 customer
+     */
+    @NotNull
+    private String kdCustomer;
+
+    /**
+     * 快递100 secret
+     */
+    @NotNull
+    private String kdSecret;
+
+    /**
+     * 快递100 userId
+     */
+    @NotNull
+    private String kdUserId;
+
+    /**
+     * 租户id
+     */
+    @NotNull
+    private String tenantId;
+
+}

+ 17 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/config/vo/ConfigInfoVo.java

@@ -0,0 +1,17 @@
+package com.fjhx.kd100.entity.config.vo;
+
+import com.fjhx.kd100.entity.config.po.ConfigInfo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 租户快递100账户配置列表查询返回值实体
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+public class ConfigInfoVo extends ConfigInfo {
+
+}

+ 52 - 0
hx-kd100/src/main/java/com/fjhx/kd100/entity/logistics/po/LogisticsInfo.java

@@ -0,0 +1,52 @@
+package com.fjhx.kd100.entity.logistics.po;
+
+import com.ruoyi.common.core.domain.BasePo;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 快递监听信息
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Getter
+@Setter
+@TableName("logistics_info")
+public class LogisticsInfo extends BasePo {
+
+    /**
+     * 物流公司编号
+     */
+    private String company;
+
+    /**
+     * 物流单号
+     */
+    private String number;
+
+    /**
+     * -1未找到快递信息,0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转投,8清关,14拒签
+     */
+    private Integer state;
+
+    /**
+     * 业务id
+     */
+    private Long businessId;
+
+    /**
+     * 业务类型
+     */
+    private Integer businessType;
+
+    /**
+     * 表名
+     */
+    private String tableName;
+
+}

+ 20 - 0
hx-kd100/src/main/java/com/fjhx/kd100/event/Kd100CallbackEvent.java

@@ -0,0 +1,20 @@
+package com.fjhx.kd100.event;
+
+import com.fjhx.kd100.entity.logistics.po.LogisticsInfo;
+import lombok.Getter;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * 快递100回调触发事件
+ */
+public class Kd100CallbackEvent extends ApplicationEvent {
+
+    @Getter
+    private final LogisticsInfo logisticsInfo;
+
+    public Kd100CallbackEvent(Object source, LogisticsInfo logisticsInfo) {
+        super(source);
+        this.logisticsInfo = logisticsInfo;
+    }
+
+}

+ 26 - 0
hx-kd100/src/main/java/com/fjhx/kd100/mapper/company/CompanyInfoMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.kd100.mapper.company;
+
+import com.fjhx.kd100.entity.company.po.CompanyInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.kd100.entity.company.vo.CompanyInfoVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 物流公司 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+public interface CompanyInfoMapper extends BaseMapper<CompanyInfo> {
+
+    /**
+     * 物流公司列表
+     */
+    List<CompanyInfoVo> getList(@Param("ew") IWrapper<CompanyInfo> wrapper);
+
+}

+ 26 - 0
hx-kd100/src/main/java/com/fjhx/kd100/mapper/config/ConfigInfoMapper.java

@@ -0,0 +1,26 @@
+package com.fjhx.kd100.mapper.config;
+
+import com.fjhx.kd100.entity.config.po.ConfigInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.kd100.entity.config.vo.ConfigInfoVo;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.apache.ibatis.annotations.Param;
+
+
+/**
+ * <p>
+ * 租户快递100账户配置 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+public interface ConfigInfoMapper extends BaseMapper<ConfigInfo> {
+
+    /**
+     * 租户快递100账户配置分页
+     */
+    Page<ConfigInfoVo> getPage(@Param("page") Page<Object> page, @Param("ew") IWrapper<ConfigInfo> wrapper);
+
+}

+ 17 - 0
hx-kd100/src/main/java/com/fjhx/kd100/mapper/logistics/LogisticsInfoMapper.java

@@ -0,0 +1,17 @@
+package com.fjhx.kd100.mapper.logistics;
+
+import com.fjhx.kd100.entity.logistics.po.LogisticsInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+
+/**
+ * <p>
+ * 快递监听信息 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+public interface LogisticsInfoMapper extends BaseMapper<LogisticsInfo> {
+
+}

+ 25 - 0
hx-kd100/src/main/java/com/fjhx/kd100/service/company/CompanyInfoService.java

@@ -0,0 +1,25 @@
+package com.fjhx.kd100.service.company;
+
+import com.fjhx.kd100.entity.company.po.CompanyInfo;
+import com.ruoyi.common.core.service.BaseService;
+import com.fjhx.kd100.entity.company.vo.CompanyInfoVo;
+import com.fjhx.kd100.entity.company.dto.CompanyInfoSelectDto;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 物流公司 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+public interface CompanyInfoService extends BaseService<CompanyInfo> {
+
+    /**
+     * 物流公司列表
+     */
+    List<CompanyInfoVo> getList(CompanyInfoSelectDto dto);
+
+}

+ 33 - 0
hx-kd100/src/main/java/com/fjhx/kd100/service/company/impl/CompanyInfoServiceImpl.java

@@ -0,0 +1,33 @@
+package com.fjhx.kd100.service.company.impl;
+
+import com.fjhx.kd100.entity.company.po.CompanyInfo;
+import com.fjhx.kd100.mapper.company.CompanyInfoMapper;
+import com.fjhx.kd100.service.company.CompanyInfoService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+import com.fjhx.kd100.entity.company.vo.CompanyInfoVo;
+import com.fjhx.kd100.entity.company.dto.CompanyInfoSelectDto;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 物流公司 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Service
+public class CompanyInfoServiceImpl extends ServiceImpl<CompanyInfoMapper, CompanyInfo> implements CompanyInfoService {
+
+    @Override
+    public List<CompanyInfoVo> getList(CompanyInfoSelectDto dto) {
+        IWrapper<CompanyInfo> wrapper = getWrapper();
+        wrapper.orderByDesc("ci", CompanyInfo::getId);
+        List<CompanyInfoVo> list = this.baseMapper.getList(wrapper);
+        return list;
+    }
+
+}

+ 46 - 0
hx-kd100/src/main/java/com/fjhx/kd100/service/config/ConfigInfoService.java

@@ -0,0 +1,46 @@
+package com.fjhx.kd100.service.config;
+
+import com.fjhx.kd100.entity.config.po.ConfigInfo;
+import com.ruoyi.common.core.service.BaseService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fjhx.kd100.entity.config.vo.ConfigInfoVo;
+import com.fjhx.kd100.entity.config.dto.ConfigInfoSelectDto;
+import com.fjhx.kd100.entity.config.dto.ConfigInfoDto;
+
+
+/**
+ * <p>
+ * 租户快递100账户配置 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+public interface ConfigInfoService extends BaseService<ConfigInfo> {
+
+    /**
+     * 租户快递100账户配置分页
+     */
+    Page<ConfigInfoVo> getPage(ConfigInfoSelectDto dto);
+
+    /**
+     * 租户快递100账户配置明细
+     */
+    ConfigInfoVo detail(Long id);
+
+    /**
+     * 租户快递100账户配置新增
+     */
+    void add(ConfigInfoDto configInfoDto);
+
+    /**
+     * 租户快递100账户配置编辑
+     */
+    void edit(ConfigInfoDto configInfoDto);
+
+    /**
+     * 租户快递100账户配置删除
+     */
+    void delete(Long id);
+
+}

+ 59 - 0
hx-kd100/src/main/java/com/fjhx/kd100/service/config/impl/ConfigInfoServiceImpl.java

@@ -0,0 +1,59 @@
+package com.fjhx.kd100.service.config.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.kd100.entity.config.dto.ConfigInfoDto;
+import com.fjhx.kd100.entity.config.dto.ConfigInfoSelectDto;
+import com.fjhx.kd100.entity.config.po.ConfigInfo;
+import com.fjhx.kd100.entity.config.vo.ConfigInfoVo;
+import com.fjhx.kd100.mapper.config.ConfigInfoMapper;
+import com.fjhx.kd100.service.config.ConfigInfoService;
+import com.ruoyi.common.utils.wrapper.IWrapper;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * 租户快递100账户配置 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2023-04-11
+ */
+@Service
+public class ConfigInfoServiceImpl extends ServiceImpl<ConfigInfoMapper, ConfigInfo> implements ConfigInfoService {
+
+    @Override
+    public Page<ConfigInfoVo> getPage(ConfigInfoSelectDto dto) {
+        IWrapper<ConfigInfo> wrapper = getWrapper();
+        wrapper.orderByDesc("ci", ConfigInfo::getId);
+        Page<ConfigInfoVo> page = this.baseMapper.getPage(dto.getPage(), wrapper);
+        return page;
+    }
+
+    @Override
+    public ConfigInfoVo detail(Long id) {
+        ConfigInfo ConfigInfo = this.getById(id);
+        ConfigInfoVo result = BeanUtil.toBean(ConfigInfo, ConfigInfoVo.class);
+        return result;
+    }
+
+    @Override
+    public void add(ConfigInfoDto configInfoDto) {
+        nameDuplication(ConfigInfo::getTenantId, configInfoDto.getTenantId(), "租户配置已存在");
+        this.save(configInfoDto);
+    }
+
+    @Override
+    public void edit(ConfigInfoDto configInfoDto) {
+        configInfoDto.setTenantId(null);
+        this.updateById(configInfoDto);
+    }
+
+    @Override
+    public void delete(Long id) {
+        this.removeById(id);
+    }
+
+}

+ 17 - 0
hx-kd100/src/main/java/com/fjhx/kd100/service/logistics/LogisticsInfoService.java

@@ -0,0 +1,17 @@
+package com.fjhx.kd100.service.logistics;
+
+import com.fjhx.kd100.entity.logistics.po.LogisticsInfo;
+import com.ruoyi.common.core.service.BaseService;
+
+
+/**
+ * <p>
+ * 快递监听信息 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+public interface LogisticsInfoService extends BaseService<LogisticsInfo> {
+
+}

+ 21 - 0
hx-kd100/src/main/java/com/fjhx/kd100/service/logistics/impl/LogisticsInfoServiceImpl.java

@@ -0,0 +1,21 @@
+package com.fjhx.kd100.service.logistics.impl;
+
+import com.fjhx.kd100.entity.logistics.po.LogisticsInfo;
+import com.fjhx.kd100.mapper.logistics.LogisticsInfoMapper;
+import com.fjhx.kd100.service.logistics.LogisticsInfoService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * <p>
+ * 快递监听信息 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2023-04-11
+ */
+@Service
+public class LogisticsInfoServiceImpl extends ServiceImpl<LogisticsInfoMapper, LogisticsInfo> implements LogisticsInfoService {
+
+}

+ 55 - 0
hx-kd100/src/main/java/com/fjhx/kd100/util/KD100Result.java

@@ -0,0 +1,55 @@
+package com.fjhx.kd100.util;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class KD100Result {
+
+    /**
+     * 消息体
+     */
+    private String message;
+
+    /**
+     * 单号
+     */
+    private String nu;
+
+    /**
+     * 快递公司编码,一律用小写字母
+     */
+    private String com;
+
+    /**
+     * -1未找到快递信息,0在途,1揽收,2疑难,3签收,4退签,5派件,6退回,7转投,8清关,14拒签
+     *
+     * @link com.fjhx.kd100.constant.KD100Status
+     */
+    private Integer state;
+
+    /**
+     * 明细数据
+     */
+    private List<Data> data;
+
+    @Getter
+    @Setter
+    public static class Data {
+
+        /**
+         * 时间
+         */
+        private String ftime;
+
+        /**
+         * 提示
+         */
+        private String context;
+
+    }
+
+}

+ 226 - 0
hx-kd100/src/main/java/com/fjhx/kd100/util/KD100Util.java

@@ -0,0 +1,226 @@
+package com.fjhx.kd100.util;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.hutool.http.HttpStatus;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fjhx.kd100.constant.Kd100Constant;
+import com.fjhx.kd100.constant.LogisticsConstant;
+import com.fjhx.kd100.entity.config.po.ConfigInfo;
+import com.fjhx.kd100.entity.logistics.po.LogisticsInfo;
+import com.fjhx.kd100.service.config.ConfigInfoService;
+import com.fjhx.kd100.service.logistics.LogisticsInfoService;
+import com.kuaidi100.sdk.api.QueryTrack;
+import com.kuaidi100.sdk.api.Subscribe;
+import com.kuaidi100.sdk.contant.ApiInfoConstant;
+import com.kuaidi100.sdk.core.IBaseClient;
+import com.kuaidi100.sdk.pojo.HttpResult;
+import com.kuaidi100.sdk.request.*;
+import com.kuaidi100.sdk.utils.SignUtils;
+import com.ruoyi.common.config.HxConfig;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.lang3.StringUtils;
+
+import java.lang.annotation.Annotation;
+import java.net.URLDecoder;
+import java.util.Objects;
+
+@Log4j2
+public class KD100Util {
+
+    /**
+     * 实时快递查询接口
+     *
+     * @param com 快递公司编码
+     * @param num 快递单号
+     */
+    public static KD100Result queryTrack(String com, String num) {
+        HttpResult httpResult;
+
+        ConfigInfo configInfo = getConfigInfo();
+
+        try {
+            // 参数组合成的json对象
+            QueryTrackParam queryTrackParam = new QueryTrackParam();
+            queryTrackParam.setCom(com);
+            queryTrackParam.setNum(num);
+            String param = JSON.toJSONString(queryTrackParam);
+
+            // 快递100入参
+            QueryTrackReq queryTrackReq = new QueryTrackReq();
+            queryTrackReq.setParam(param);
+            queryTrackReq.setCustomer(configInfo.getKdCustomer());
+            queryTrackReq.setSign(SignUtils.querySign(param, configInfo.getKdKey(), configInfo.getKdCustomer()));
+
+            // 查询快递100
+            httpResult = new QueryTrack().execute(queryTrackReq);
+        } catch (Exception e) {
+            log.error("请求kd100发生异常", e);
+            throw new ServiceException("请求kd100发生异常,异常原因:" + e);
+        }
+
+        if (Objects.equals(httpResult.getStatus(), HttpStatus.HTTP_OK)) {
+            return JSON.parseObject(httpResult.getBody()).toJavaObject(KD100Result.class);
+        } else {
+            log.error("查询快递100失败,失败原因:{}", httpResult.getBody());
+            throw new ServiceException("查询快递100失败,失败原因:" + httpResult.getBody());
+        }
+    }
+
+    /**
+     * 获取快递状态并监听未到货快递
+     *
+     * @param com          快递公司编码
+     * @param num          快递单号
+     * @param businessId   业务id
+     * @param businessType 业务类型
+     * @param cls          数据库表映射实体
+     */
+    public static LogisticsInfo monitor(String com, String num, Long businessId, Integer businessType, Class<?> cls) {
+        // 查询快递100的物流信息
+        KD100Result result = KD100Util.queryTrack(com, num);
+        String message = result.getMessage();
+        if (Objects.equals(message, "查询无结果,请隔段时间再查")) {
+            return saveInfo(com, num, LogisticsConstant.KD100Status.STATUS_N, businessId, businessType, cls);
+        }
+        if (Objects.equals(message, "ok")) {
+            Integer state = result.getState();
+            if (!Objects.equals(state, LogisticsConstant.KD100Status.STATUS_3)) {
+                // 如果不是已签收状态,则开启订阅(物流状态跟踪并推送)
+                KD100Util.subscribe(com, num);
+            }
+            return saveInfo(com, num, state, businessId, businessType, cls);
+        } else {
+            throw new ServiceException("快递100异常:" + message);
+        }
+    }
+
+    /**
+     * 保存快递信息
+     */
+    private static LogisticsInfo saveInfo(String com, String num, Integer state, Long businessId, Integer businessType, Class<?> cls) {
+
+        LogisticsInfo logisticsInfo = new LogisticsInfo();
+        logisticsInfo.setCompany(com);
+        logisticsInfo.setNumber(num);
+        logisticsInfo.setState(state);
+        logisticsInfo.setBusinessId(businessId);
+        logisticsInfo.setBusinessType(businessType);
+        logisticsInfo.setTableName(getTableName(cls));
+
+        LogisticsInfoService logisticsInfoService = SpringUtil.getBean(LogisticsInfoService.class);
+        logisticsInfoService.save(logisticsInfo);
+        return logisticsInfo;
+    }
+
+    public static String getTableName(Class<?> cls) {
+        Annotation[] annotations = cls.getAnnotations();
+        TableName tableName = null;
+        for (Annotation annotation : annotations) {
+            if (annotation instanceof TableName) {
+                tableName = (TableName) annotation;
+                break;
+            }
+        }
+
+        if (tableName != null) {
+            return tableName.value();
+        } else {
+            String name = cls.getSimpleName();
+            return StrUtil.toUnderlineCase(name);
+        }
+    }
+
+    /**
+     * 订阅接口
+     *
+     * @param com 快递公司编码
+     * @param num 快递单号
+     */
+    public static void subscribe(String com, String num) {
+        HttpResult result;
+        ConfigInfo configInfo = getConfigInfo();
+        try {
+            SubscribeParameters subscribeParameters = new SubscribeParameters();
+            subscribeParameters.setCallbackurl(getCallbackUrl());
+
+            SubscribeParam subscribeParam = new SubscribeParam();
+            subscribeParam.setParameters(subscribeParameters);
+            subscribeParam.setCompany(com);
+            subscribeParam.setNumber(num);
+            subscribeParam.setKey(configInfo.getKdKey());
+
+            SubscribeReq subscribeReq = new SubscribeReq();
+            subscribeReq.setSchema(ApiInfoConstant.SUBSCRIBE_SCHEMA);
+            subscribeReq.setParam(JSON.toJSONString(subscribeParam));
+
+            IBaseClient subscribe = new Subscribe();
+            result = subscribe.execute(subscribeReq);
+        } catch (Exception e) {
+            log.error(e.toString());
+            throw new ServiceException("请求第三方快递订阅功能异常:" + e);
+        }
+
+        if (Objects.equals(result.getStatus(), HttpStatus.HTTP_OK)) {
+            JSONObject body = JSON.parseObject(result.getBody());
+            if (!Objects.equals(body.getBoolean("result"), Boolean.TRUE)) {
+                log.error("监听物流消息失败: com:{}, num:{}, message:{}", com, num, result.getBody());
+                throw new ServiceException("监听物流消息失败:" + result.getBody());
+            }
+        } else {
+            throw new ServiceException("监听物流消息失败:" + result.getError());
+        }
+    }
+
+    /**
+     * 解析数据:回调结果
+     *
+     * @param data 物流信息
+     */
+    public static JSONObject parseCallbackData(String data) {
+        log.info("快递100接口回调数据:{}", data);
+
+        if (StrUtil.isNotBlank(data) && StringUtils.indexOf(data, "param=") != -1) {
+            data = StringUtils.substringAfter(data, "param=");
+            try {
+                data = URLDecoder.decode(data, "UTF-8");
+            } catch (Exception e) {
+                throw new ServiceException("物流信息推送失败,参数解码异常!");
+            }
+
+            JSONObject object = JSON.parseObject(data);
+            if (ObjectUtil.isNotEmpty(object) && ObjectUtil.isNotEmpty(object.getJSONObject("lastResult"))) {
+                JSONObject body = object.getJSONObject("lastResult");
+                if (ObjectUtil.isNotEmpty(body.get("message")) && StrUtil.equalsIgnoreCase(body.getString("message"), "ok")) {
+                    return body;
+                } else {
+                    throw new ServiceException("物流信息推送失败,原因:物流信息【" + body.getString("message") + "】!");
+                }
+            } else {
+                throw new ServiceException("物流信息推送失败,参数解析异常!");
+            }
+        } else {
+            throw new ServiceException("物流信息推送失败!");
+        }
+    }
+
+    private static String getCallbackUrl() {
+        return HxConfig.getHttpUrl() + Kd100Constant.CALLBACK_URL;
+    }
+
+    private static ConfigInfo getConfigInfo() {
+        ConfigInfoService configInfoService = SpringUtil.getBean(ConfigInfoService.class);
+        String tenantId = SecurityUtils.getTenantId();
+        ConfigInfo configInfo = configInfoService.getOne(q -> q.eq(ConfigInfo::getTenantId, tenantId));
+        if (configInfo == null) {
+            throw new ServiceException("租户未配置快递100信息");
+        }
+        return configInfo;
+    }
+
+}

+ 15 - 0
hx-kd100/src/main/resources/mapper/company/CompanyInfoMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.kd100.mapper.company.CompanyInfoMapper">
+    <select id="getList" resultType="com.fjhx.kd100.entity.company.vo.CompanyInfoVo">
+        select
+            ci.id,
+            ci.code,
+            ci.name,
+            ci.type,
+            ci.sort
+        from company_info ci
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>

+ 19 - 0
hx-kd100/src/main/resources/mapper/config/ConfigInfoMapper.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.kd100.mapper.config.ConfigInfoMapper">
+    <select id="getPage" resultType="com.fjhx.kd100.entity.config.vo.ConfigInfoVo">
+        select
+            ci.id,
+            ci.kd_key,
+            ci.kd_customer,
+            ci.kd_secret,
+            ci.kd_user_id,
+            ci.create_user,
+            ci.create_time,
+            ci.update_user,
+            ci.update_time
+        from config_info ci
+            ${ew.customSqlSegment}
+    </select>
+
+</mapper>

+ 4 - 0
hx-kd100/src/main/resources/mapper/logistics/LogisticsInfoMapper.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.kd100.mapper.logistics.LogisticsInfoMapper">
+</mapper>

+ 1 - 0
pom.xml

@@ -206,6 +206,7 @@
         <module>hx-flow</module>
         <module>hx-tenant</module>
         <module>hx-area</module>
+        <module>hx-kd100</module>
     </modules>
     <packaging>pom</packaging>
 

+ 31 - 0
ruoyi-common/src/main/java/com/ruoyi/common/config/HxConfig.java

@@ -0,0 +1,31 @@
+package com.ruoyi.common.config;
+
+import cn.hutool.core.util.StrUtil;
+import com.ruoyi.common.exception.ServiceException;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConfigurationProperties(prefix = "hx")
+public class HxConfig {
+
+
+    private static String httpUrl;
+
+    public void setHttpUrl(String httpUrl) {
+        HxConfig.httpUrl = httpUrl;
+    }
+
+    public static String getHttpUrl() {
+        
+        if (StrUtil.isBlank(httpUrl)) {
+            throw new ServiceException("yml未配置 hx.httpUrl");
+        }
+
+        if (httpUrl.endsWith("/")) {
+            return httpUrl;
+        }
+
+        return httpUrl + "/";
+    }
+}

+ 2 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/BaseSourceConstant.java

@@ -7,4 +7,6 @@ public interface BaseSourceConstant {
 
     String BASE = "base";
 
+    String KD100 = "kd100";
+
 }