Kaynağa Gözat

Merge remote-tracking branch 'origin/master'

颜琼丽 1 hafta önce
ebeveyn
işleme
3cadb7116e
63 değiştirilmiş dosya ile 2542 ekleme ve 393 silme
  1. 34 7
      jd-logistics-api/jd-logistics-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java
  2. 12 0
      jd-logistics-api/jd-logistics-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java
  3. 15 0
      jd-logistics-api/jd-logistics-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java
  4. 32 0
      jd-logistics-auth/src/main/java/com/ruoyi/auth/controller/WxMiniController.java
  5. 13 0
      jd-logistics-auth/src/main/java/com/ruoyi/auth/form/LoginBody.java
  6. 47 0
      jd-logistics-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java
  7. 24 1
      jd-logistics-modules/jd-logistics-system/pom.xml
  8. 1 1
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/config/WxMaConfig.java
  9. 1 1
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/config/WxMaProperties.java
  10. 68 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/front/controller/WxMiniController.java
  11. 1 1
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/enums/EnvVersion.java
  12. 2 2
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/IWxService.java
  13. 4 3
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/impl/WxMiniAppServiceImpl.java
  14. 78 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/JDPushOrderFeeCallback.java
  15. 64 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/JDPushOrderStatausCallback.java
  16. 107 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/SfFeePushCallback.java
  17. 115 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/SfPushOrderStatusCallback.java
  18. 9 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/constant/JDDictConstants.java
  19. 15 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/constant/RedisCacheConstants.java
  20. 9 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/constant/SysConfigConstants.java
  21. 15 16
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/BizInancialFeeItemsController.java
  22. 15 3
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/BizWaybillOrderController.java
  23. 1 1
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/BizInancialFeeItems.java
  24. 25 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/BizWaybillOrder.java
  25. 23 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/OrderStateDetail.java
  26. 13 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfApiResponse.java
  27. 36 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfFeeApiResponse.java
  28. 32 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfFeeInfo.java
  29. 22 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfFeePushRequest.java
  30. 18 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfPushOrderStateRequest.java
  31. 56 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/dto/JDOrderFeeRequestDTO.java
  32. 50 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/dto/JDOrderStatusRequestDTO.java
  33. 28 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/enums/OrderStatusEnum.java
  34. 7 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizAddressBookMapper.java
  35. 11 11
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizInancialFeeItemsMapper.java
  36. 7 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizWaybillOrderMapper.java
  37. 129 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/FeeItemsCacheService.java
  38. 68 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IBizFinancialFeeItemsService.java
  39. 0 61
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IBizInancialFeeItemsService.java
  40. 9 1
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IBizWaybillOrderService.java
  41. 21 5
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/LogisticsOrderService.java
  42. 37 9
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/LogisticsService.java
  43. 12 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizAddressBookServiceImpl.java
  44. 112 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizFinancialFeeItemsServiceImpl.java
  45. 0 96
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizInancialFeeItemsServiceImpl.java
  46. 39 2
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizWaybillOrderServiceImpl.java
  47. 104 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/FeePushService.java
  48. 360 26
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/JDLogisticsService.java
  49. 245 39
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/SFLogisticsService.java
  50. 35 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/Base64Util.java
  51. 36 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/MD5Util.java
  52. 126 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/SFExpressHttpUtil.java
  53. 110 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/SignUtil.java
  54. 1 31
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/controller/SysUserController.java
  55. 8 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
  56. 10 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
  57. 4 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
  58. 4 0
      jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizAddressBookMapper.xml
  59. 16 16
      jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizInancialFeeItemsMapper.xml
  60. 40 1
      jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizWaybillOrderMapper.xml
  61. 5 1
      jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/system/SysUserMapper.xml
  62. 1 1
      jd-logistics-ui-v3/.env.development
  63. 0 57
      jd-logistics-ui-v3/src/views/logistics/city/index.vue

+ 34 - 7
jd-logistics-api/jd-logistics-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java

@@ -1,12 +1,7 @@
 package com.ruoyi.system.api;
 
 import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.*;
 import com.ruoyi.common.core.constant.SecurityConstants;
 import com.ruoyi.common.core.constant.ServiceNameConstants;
 import com.ruoyi.common.core.domain.R;
@@ -43,7 +38,7 @@ public interface RemoteUserService
     public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
 
     /**
-     * 记录用户登录IP地址和登录时间
+     * 获取用户
      *
      * @param sysUser 用户信息
      * @param source 请求来源
@@ -51,4 +46,36 @@ public interface RemoteUserService
      */
     @PutMapping("/user/recordlogin")
     public R<Boolean> recordUserLogin(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
+
+    /**
+     * 获取用户
+     *
+     * @param jsCode 用户信息
+     * @param source 请求来源
+     * @return 结果
+     */
+    @GetMapping("/front/wxmini/getOpenId")
+    public R<String> getOpenId(@RequestParam("jsCode") String jsCode, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
+
+    /**
+     * 获取用户
+     *
+     * @param code 用户信息
+     * @param source 请求来源
+     * @return 结果
+     */
+    @GetMapping("/front/wxmini/getPhoneNumber")
+    public R<String> getPhoneNumber(@RequestParam("code") String code, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
+
+
+    /**
+     * 通过用户名和openId查询用户信息
+     *
+     * @param sysUser 用户名 openId
+     * @param source 请求来源
+     * @return 结果
+     */
+    @PostMapping("/front/wxmini/getUserByOpenId")
+    public R<LoginUser> getUserByOpenId(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
+
 }

+ 12 - 0
jd-logistics-api/jd-logistics-api-system/src/main/java/com/ruoyi/system/api/domain/SysUser.java

@@ -93,6 +93,9 @@ public class SysUser extends BaseEntity
     /** 角色ID */
     private Long roleId;
 
+    /** 微信openId */
+    private String openId;
+
     public SysUser()
     {
 
@@ -311,6 +314,14 @@ public class SysUser extends BaseEntity
         this.roleId = roleId;
     }
 
+    public String getOpenId() {
+        return openId;
+    }
+
+    public void setOpenId(String openId) {
+        this.openId = openId;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -334,6 +345,7 @@ public class SysUser extends BaseEntity
             .append("updateTime", getUpdateTime())
             .append("remark", getRemark())
             .append("dept", getDept())
+            .append("openId", getOpenId())
             .toString();
     }
 }

+ 15 - 0
jd-logistics-api/jd-logistics-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java

@@ -42,6 +42,21 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
             {
                 return R.fail("记录用户登录信息失败:" + throwable.getMessage());
             }
+
+            @Override
+            public R<String> getOpenId(String jsCode, String source) {
+                return R.fail("获取用户OpenId失败:" + throwable.getMessage());
+            }
+
+            @Override
+            public R<String> getPhoneNumber(String code, String source) {
+                return R.fail("获取用户手机号失败:" + throwable.getMessage());
+            }
+
+            @Override
+            public R<LoginUser> getUserByOpenId(SysUser sysUser, String source) {
+                return R.fail("获取用户信息失败:" + throwable.getMessage());
+            }
         };
     }
 }

+ 32 - 0
jd-logistics-auth/src/main/java/com/ruoyi/auth/controller/WxMiniController.java

@@ -0,0 +1,32 @@
+package com.ruoyi.auth.controller;
+
+import com.ruoyi.auth.form.LoginBody;
+import com.ruoyi.auth.service.SysLoginService;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.security.service.TokenService;
+import com.ruoyi.system.api.model.LoginUser;
+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;
+
+@RestController
+@RequestMapping("/wxmini")
+public class WxMiniController {
+
+    @Autowired
+    private SysLoginService sysLoginService;
+
+    @Autowired
+    private TokenService tokenService;
+
+    @PostMapping("login")
+    public R<?> login(@RequestBody LoginBody form) {
+        // 用户登录
+        LoginUser userInfo = sysLoginService.openIdLogin(form.getUsername(), form.getOpenId());
+        // 获取登录token
+        return R.ok(tokenService.createToken(userInfo));
+    }
+
+}

+ 13 - 0
jd-logistics-auth/src/main/java/com/ruoyi/auth/form/LoginBody.java

@@ -17,6 +17,11 @@ public class LoginBody
      */
     private String password;
 
+    /**
+     * 微信小程序openId
+     */
+    private String openId;
+
     public String getUsername()
     {
         return username;
@@ -36,4 +41,12 @@ public class LoginBody
     {
         this.password = password;
     }
+
+    public String getOpenId() {
+        return openId;
+    }
+
+    public void setOpenId(String openId) {
+        this.openId = openId;
+    }
 }

+ 47 - 0
jd-logistics-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java

@@ -153,4 +153,51 @@ public class SysLoginService
         }
         recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功");
     }
+
+
+    /**
+     * 登录
+     */
+    public LoginUser openIdLogin(String username, String openId)
+    {
+        // 用户名或密码为空 错误
+        if (StringUtils.isAnyBlank(username, openId))
+        {
+            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/openId必须填写");
+            throw new ServiceException("用户/openId必须填写");
+        }
+        // IP黑名单校验
+        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
+        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
+        {
+            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾,访问IP已被列入系统黑名单");
+            throw new ServiceException("很遗憾,访问IP已被列入系统黑名单");
+        }
+        // 查询用户信息
+        SysUser sysUser = new SysUser();
+        sysUser.setUserName(username);
+        sysUser.setOpenId(openId);
+        R<LoginUser> userResult = remoteUserService.getUserByOpenId(sysUser, SecurityConstants.INNER);
+
+        if (R.FAIL == userResult.getCode())
+        {
+            throw new ServiceException(userResult.getMsg());
+        }
+
+        LoginUser userInfo = userResult.getData();
+        SysUser user = userResult.getData().getSysUser();
+        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
+        {
+            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
+            throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
+        }
+        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
+        {
+            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
+            throw new ServiceException("对不起,您的账号:" + username + " 已停用");
+        }
+        recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
+        recordLoginInfo(user.getUserId());
+        return userInfo;
+    }
 }

+ 24 - 1
jd-logistics-modules/jd-logistics-system/pom.xml

@@ -58,7 +58,13 @@
             <groupId>com.ruoyi</groupId>
             <artifactId>ruoyi-common-datascope</artifactId>
         </dependency>
-        
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.11</version>
+        </dependency>
+
+
         <!-- RuoYi Common Log -->
         <dependency>
             <groupId>com.ruoyi</groupId>
@@ -78,6 +84,23 @@
             <type>jar</type>
             <version>2.1.7</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.jd</groupId>
+            <artifactId>lop-opensdk-support</artifactId>
+            <version>1.0.30</version>
+        </dependency>
+        <dependency>
+            <groupId>com.jd</groupId>
+            <artifactId>ECAP</artifactId>
+            <version>6.9</version>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+        </dependency>
+
+
     </dependencies>
 
     <build>

+ 1 - 1
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/config/WxMaConfig.java

@@ -1,4 +1,4 @@
-package com.ruoyi.system.config;
+package com.ruoyi.front.config;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;

+ 1 - 1
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/config/WxMaProperties.java

@@ -1,4 +1,4 @@
-package com.ruoyi.system.config;
+package com.ruoyi.front.config;
 
 
 import lombok.Data;

+ 68 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/front/controller/WxMiniController.java

@@ -0,0 +1,68 @@
+package com.ruoyi.front.controller;
+
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.security.annotation.InnerAuth;
+import com.ruoyi.front.service.IWxService;
+import com.ruoyi.system.api.domain.SysUser;
+import com.ruoyi.system.api.model.LoginUser;
+import com.ruoyi.system.service.ISysPermissionService;
+import com.ruoyi.system.service.ISysUserService;
+import me.chanjar.weixin.common.error.WxErrorException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Set;
+
+@RestController
+@RequestMapping("/front/wxmini")
+public class WxMiniController {
+
+    @Autowired
+    private IWxService wxService;
+
+    @Autowired
+    private ISysUserService sysUserService;
+
+    @Autowired
+    private ISysPermissionService permissionService;
+
+    @InnerAuth
+    @GetMapping("/getOpenId")
+    public String getOpenId(@RequestParam("jsCode") String jsCode) {
+        try {
+            return wxService.getOpenId(jsCode);
+        } catch (WxErrorException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @InnerAuth
+    @GetMapping("/getPhoneNumber")
+    public String getPhoneNumber(@RequestParam("code") String code) {
+        try {
+            return wxService.getPhoneNumber(code);
+        } catch (WxErrorException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @InnerAuth
+    @PostMapping("/getUserByOpenId")
+    public R<LoginUser> getUserByOpenId(@RequestBody SysUser sysUser) {
+        SysUser currentUser = sysUserService.selectUserByOpenId(sysUser);
+        if (StringUtils.isNull(sysUser))
+        {
+            return R.fail("用户名或密码错误");
+        }
+        // 角色集合
+        Set<String> roles = permissionService.getRolePermission(currentUser);
+        // 权限集合
+        Set<String> permissions = permissionService.getMenuPermission(currentUser);
+        LoginUser sysUserVo = new LoginUser();
+        sysUserVo.setSysUser(currentUser);
+        sysUserVo.setRoles(roles);
+        sysUserVo.setPermissions(permissions);
+        return R.ok(sysUserVo);
+    }
+}

+ 1 - 1
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/enums/EnvVersion.java

@@ -1,4 +1,4 @@
-package com.ruoyi.system.enums;
+package com.ruoyi.front.enums;
 
 import lombok.Getter;
 

+ 2 - 2
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/IWxService.java

@@ -1,6 +1,6 @@
-package com.ruoyi.system.service;
+package com.ruoyi.front.service;
 
-import com.ruoyi.system.enums.EnvVersion;
+import com.ruoyi.front.enums.EnvVersion;
 import me.chanjar.weixin.common.error.WxErrorException;
 
 import java.io.File;

+ 4 - 3
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/impl/WxMiniAppServiceImpl.java

@@ -1,9 +1,10 @@
-package com.ruoyi.system.service.impl;
+package com.ruoyi.front.service.impl;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
-import com.ruoyi.system.enums.EnvVersion;
+import com.ruoyi.front.enums.EnvVersion;
+import com.ruoyi.front.service.IWxService;
 import lombok.RequiredArgsConstructor;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
@@ -18,7 +19,7 @@ import java.io.File;
 @Service
 @RequiredArgsConstructor
 @ConditionalOnBean(WxMaService.class)
-public class WxMiniAppServiceImpl implements com.ruoyi.system.service.IWxService {
+public class WxMiniAppServiceImpl implements IWxService {
 
     private final WxMaService wxMaService;
 

+ 78 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/JDPushOrderFeeCallback.java

@@ -0,0 +1,78 @@
+package com.ruoyi.logistics.callback;
+
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.logistics.domain.BizFinancialFeeItems;
+import com.ruoyi.logistics.domain.BizWaybillCostDetails;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
+import com.ruoyi.logistics.dto.JDOrderFeeRequestDTO;
+import com.ruoyi.logistics.service.FeeItemsCacheService;
+import com.ruoyi.logistics.service.IBizWaybillCostDetailsService;
+import com.ruoyi.logistics.service.IBizWaybillOrderService;
+import com.ruoyi.system.api.domain.SysDept;
+import com.ruoyi.system.service.ISysDeptService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+@RequestMapping("/callback/jd")
+public class JDPushOrderFeeCallback {
+
+    @Autowired
+    private IBizWaybillOrderService bizWaybillOrderService;
+
+    @Autowired
+    private IBizWaybillCostDetailsService bizWaybillCostDetailsService;
+
+    @Autowired
+    private ISysDeptService sysDeptService;
+
+    @Autowired
+    private FeeItemsCacheService feeItemsCacheService;
+
+    @RequestMapping("/fee")
+    public AjaxResult fee(@RequestBody JDOrderFeeRequestDTO request) {
+
+        // 根据运单号查询订单
+        BizWaybillOrder query = new BizWaybillOrder();
+        query.setExternalWaybillNo(request.getWaybillCode());
+        BizWaybillOrder bizWaybillOrder = bizWaybillOrderService.selectBizWaybillOrderByQuery(query);
+        if (bizWaybillOrder == null) {
+            return AjaxResult.error("订单不存在");
+        }
+        SysDept sysDept = sysDeptService.selectDeptById(bizWaybillOrder.getDeptId());
+
+        List<BizWaybillCostDetails> details = new ArrayList<>();
+        request.getCommonActualFeeInfoDetails().forEach(item -> {
+            BizWaybillCostDetails costDetail = new BizWaybillCostDetails();
+            costDetail.setWaybillId(bizWaybillOrder.getWaybillId());
+            costDetail.setExternalWaybillNo(bizWaybillOrder.getExternalWaybillNo());
+
+            // 匹配费用类型项
+            BizFinancialFeeItems feeItemByExtFeeCode = feeItemsCacheService.getFeeItemByExtFeeCode(item.getFeeType());
+            if (feeItemByExtFeeCode != null) {
+                costDetail.setFeeItemCode(feeItemByExtFeeCode.getFeeItemCode());
+                costDetail.setFeeItemName(feeItemByExtFeeCode.getFeeItemName());
+                costDetail.setFeeName(item.getFeeTypeName());
+                costDetail.setAmount(item.getStandardAmount());
+                costDetail.setRateAmount(item.getStandardAmount().multiply(new BigDecimal(sysDept.getRateValue())).setScale(2, BigDecimal.ROUND_HALF_UP));
+                costDetail.setDeptId(bizWaybillOrder.getDeptId());
+                costDetail.setUserId(bizWaybillOrder.getUserId());
+            }
+
+            details.add(costDetail);
+        });
+
+        details.forEach(detail -> {
+            bizWaybillCostDetailsService.insertBizWaybillCostDetails(detail);
+        });
+
+        return AjaxResult.success().put("message", "成功");
+    }
+}

+ 64 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/JDPushOrderStatausCallback.java

@@ -0,0 +1,64 @@
+package com.ruoyi.logistics.callback;
+
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
+import com.ruoyi.logistics.dto.JDOrderStatusRequestDTO;
+import com.ruoyi.logistics.enums.OrderStatusEnum;
+import com.ruoyi.logistics.service.IBizWaybillOrderService;
+import lombok.extern.slf4j.Slf4j;
+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;
+
+@Slf4j
+@RestController
+@RequestMapping("/callback/jd")
+public class JDPushOrderStatausCallback {
+
+    @Autowired
+    private IBizWaybillOrderService bizWaybillOrderService;
+
+    @PostMapping("/orderStatus")
+    public AjaxResult orderStatus(@RequestBody JDOrderStatusRequestDTO request) {
+        log.info("京东物流运单状态回调,参数:{}", request.toString());
+
+        // 根据运单号查询订单
+        BizWaybillOrder query = new BizWaybillOrder();
+        query.setWaybillNo(request.getOrderId());
+        query.setExternalWaybillNo(request.getWaybillCode());
+        BizWaybillOrder bizWaybillOrder = bizWaybillOrderService.selectBizWaybillOrderByQuery(query);
+        if (bizWaybillOrder == null) {
+            return AjaxResult.error("订单不存在");
+        }
+        Boolean update = Boolean.FALSE;
+        switch (request.getState()) {
+            case "200001"://揽收
+                bizWaybillOrder.setOrderStatus(OrderStatusEnum.ORDER_STATUS_1.getCode());
+                bizWaybillOrder.setPickupTime(DateUtils.getNowDate());
+                update = Boolean.TRUE;
+                break;
+            case "200075"://运输
+                bizWaybillOrder.setOrderStatus(OrderStatusEnum.ORDER_STATUS_3.getCode());
+                update = Boolean.TRUE;
+                break;
+            case "11000"://派送
+                bizWaybillOrder.setOrderStatus(OrderStatusEnum.ORDER_STATUS_4.getCode());
+                bizWaybillOrder.setDeliveryTime(DateUtils.getNowDate());
+                update = Boolean.TRUE;
+                break;
+            case "10034"://妥投
+                bizWaybillOrder.setOrderStatus(OrderStatusEnum.ORDER_STATUS_5.getCode());
+                bizWaybillOrder.setSignTime(DateUtils.getNowDate());
+                update = Boolean.TRUE;
+                break;
+        }
+        if (update) {
+            bizWaybillOrderService.updateBizWaybillOrder(bizWaybillOrder);
+        }
+
+        return AjaxResult.success();
+    }
+}

+ 107 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/SfFeePushCallback.java

@@ -0,0 +1,107 @@
+package com.ruoyi.logistics.callback;
+import com.ruoyi.logistics.service.impl.FeePushService;
+import org.springframework.web.bind.annotation.*;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.logistics.domain.SfFeeApiResponse;
+import com.ruoyi.logistics.domain.SfFeePushRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+
+
+
+/**
+ * 顺丰物流费用清单回调
+ * 目前涉及的回调有:
+ * 1.订单状态回调
+ * 2.费用清单回调
+ *
+ * @author zxf
+ * @date 2026-02-03
+ */
+@RestController
+@RequestMapping("/feecallback")
+public class SfFeePushCallback {
+    private static final Logger logger = LoggerFactory.getLogger(SfFeePushCallback.class);
+
+    private final ObjectMapper objectMapper;
+    private final FeePushService feePushService;
+
+    public SfFeePushCallback(ObjectMapper objectMapper, FeePushService feePushService) {
+        this.objectMapper = objectMapper;
+        this.feePushService = feePushService;
+    }
+
+    /**
+     * 接收顺丰运费清单推送
+     * 注意:接口整体报文为form表单格式,但content参数是JSON数据
+     * @param sign 数字签名
+     * @param content 业务数据JSON字符串
+     * @return 标准响应
+     */
+    @PostMapping("/feePush")
+    public ResponseEntity<SfFeeApiResponse> receiveFeePush(
+            @RequestParam("sign") String sign,
+            @RequestParam("content") String content) {
+
+        logger.info("收到顺丰运费清单推送,sign: {}", sign);
+
+        try {
+          /*  // 1. 验证签名(根据顺丰文档实现)
+            if (!verifySignature(sign, content)) {
+                logger.error("签名验证失败");
+                return ResponseEntity.ok(SfFeeApiResponse.error("签名验证失败"));
+            }*/
+
+            // 2. 解析JSON数据
+            SfFeePushRequest feePushRequest = objectMapper.readValue(content, SfFeePushRequest.class);
+
+            // 3. 参数验证
+            if (feePushRequest.getWaybillNo() == null || feePushRequest.getWaybillNo().isEmpty()) {
+                return ResponseEntity.ok(SfFeeApiResponse.error("运单号不能为空"));
+            }
+            if (feePushRequest.getOrderNo() == null || feePushRequest.getOrderNo().isEmpty()) {
+                return ResponseEntity.ok(SfFeeApiResponse.error("订单号不能为空"));
+            }
+
+            // 4. 处理业务逻辑
+            boolean success = feePushService.processFeePush(feePushRequest);
+
+            if (success) {
+                logger.info("运费清单处理成功,运单号: {}, 订单号: {}",
+                        feePushRequest.getWaybillNo(), feePushRequest.getOrderNo());
+                return ResponseEntity.ok(SfFeeApiResponse.success());
+            } else {
+                logger.error("运费清单处理失败,运单号: {}", feePushRequest.getWaybillNo());
+                return ResponseEntity.ok(SfFeeApiResponse.error("业务处理失败"));
+            }
+
+        } catch (com.fasterxml.jackson.core.JsonParseException e) {
+            logger.error("JSON解析失败: {}", e.getMessage());
+            return ResponseEntity.ok(SfFeeApiResponse.error("非法的JSON格式"));
+        } catch (Exception e) {
+            logger.error("处理运费清单推送异常: {}", e.getMessage(), e);
+            return ResponseEntity.ok(SfFeeApiResponse.error("系统发生数据错误或运行时异常"));
+        }
+    }
+
+    /**
+     * 验证签名
+     * 根据顺丰文档实现签名验证逻辑
+     */
+    /*private boolean verifySignature(String sign, String content) {
+        // 实际实现应根据顺丰提供的签名算法
+        // 通常使用checkword对content进行加密,然后与sign比较
+        // 这里简化处理,实际应按照文档实现
+        try {
+            // 示例:使用MD5或SHA256等算法
+             String calculatedSign = calculateSign(content, yourCheckword);
+             return calculatedSign.equals(sign);
+
+        } catch (Exception e) {
+            logger.error("签名验证异常: {}", e.getMessage());
+            return false;
+        }
+    }*/
+}

+ 115 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/callback/SfPushOrderStatusCallback.java

@@ -0,0 +1,115 @@
+package com.ruoyi.logistics.callback;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.ruoyi.logistics.domain.OrderStateDetail;
+import com.ruoyi.logistics.domain.SfApiResponse;
+import com.ruoyi.logistics.domain.SfPushOrderStateRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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.io.UnsupportedEncodingException;
+import java.util.List;
+
+/**
+ * 顺丰物流订单状态回调相关
+ * 目前涉及的回调有:
+ * 1.订单状态回调
+ * 2.费用清单回调
+ *
+ * @author zxf
+ * @date 2026-02-03
+ */
+@RestController
+@RequestMapping("/callback")
+public class SfPushOrderStatusCallback {
+    private static final Logger logger = LoggerFactory.getLogger(SfPushOrderStatusCallback.class);
+
+
+    /**
+     * 顺丰物流订单状态回调
+     * 说明:仅限于推送上门订单调度状态  非预约订单不推送
+     *
+     * @author zxf
+     * @date 2026-02-03
+     */
+    @PostMapping("/orderStatus")
+    public SfApiResponse orderStatus(@RequestBody SfPushOrderStateRequest pushRequest) throws UnsupportedEncodingException, JsonProcessingException {
+        logger.info("收到顺丰订单状态推送,requestId: {}", pushRequest.getRequestId());
+
+        // 1.订单状态为空直接返给顺丰
+        if (pushRequest.getOrderState() == null || pushRequest.getOrderState().isEmpty()) {
+            logger.error("订单状态数据为空");
+            return createErrorResponse("订单状态数据为空");
+        }
+
+        // 2. 处理每条订单状态更新
+        List<OrderStateDetail> stateList = pushRequest.getOrderState();
+        for (OrderStateDetail state : stateList) {
+            try {
+                processSingleOrderState(state);
+            } catch (Exception e) {
+                logger.error("处理订单状态失败,订单号: {}, 运单号: {}", state.getOrderNo(), state.getWaybillNo(), e);
+                // 可根据业务决定是记录日志后继续,还是直接返回失败
+            }
+        }
+
+        // 3. 返回成功响应(必须严格按此格式,否则顺丰可能认为推送失败)
+        SfApiResponse response = new SfApiResponse();
+        response.setSuccess("true");
+        response.setCode("0");
+        response.setMsg("");
+        logger.info("订单状态推送处理完成,requestId: {}", pushRequest.getRequestId());
+        return response;
+
+    }
+
+
+    /**
+            * 处理单个订单的状态更新
+     */
+    private void processSingleOrderState(OrderStateDetail state) {
+        logger.info("更新订单状态 - 订单号: {}, 运单号: {}, 状态码: {}, 状态描述: {}, 更新时间: {}",
+                state.getOrderNo(),
+                state.getWaybillNo(),
+                state.getOrderStateCode(),
+                state.getOrderStateDesc(),
+                state.getLastTime());
+        // 根据顺丰返回的状态吗进行系统状态变更  目前还没对
+        switch (state.getOrderStateCode()) {
+            case "04":
+
+                break;
+            case "04-40001":
+
+                break;
+            case "04-40037":
+
+                break;
+
+            default:
+                logger.info("收到未定义的状态码: {}", state.getOrderStateCode());
+        }
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+    private SfApiResponse createErrorResponse(String errorMsg) {
+        SfApiResponse response = new SfApiResponse();
+        response.setSuccess("false");
+        response.setMsg(errorMsg);
+        return response;
+    }
+}

+ 9 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/constant/JDDictConstants.java

@@ -0,0 +1,9 @@
+package com.ruoyi.logistics.constant;
+
+public class JDDictConstants {
+
+    //主产品类型
+    public static final String PRODUCT_CODE_ED_M_0001 = "ed-m-0001";
+    public static final String PRODUCT_CODE_ED_M_0002 = "ed-m-0002";
+    public static final String PRODUCT_CODE_FR_M_0004 = "fr-m-0004";
+}

+ 15 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/constant/RedisCacheConstants.java

@@ -0,0 +1,15 @@
+package com.ruoyi.logistics.constant;
+
+/**
+ * Redis缓存常量
+ * 
+ * @author lydgt
+ * @date 2026-02-04
+ */
+public class RedisCacheConstants {
+    
+    /**
+     * 费用类型缓存KEY
+     */
+    public static final String FINANCIAL_FEE_ITEM_CACHE_KEY = "financial_fee_item_cache";
+}

+ 9 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/constant/SysConfigConstants.java

@@ -0,0 +1,9 @@
+package com.ruoyi.logistics.constant;
+
+public class SysConfigConstants {
+
+    /**
+     * 京东客户编码
+     */
+    public static final String JD_LOGISTICS_CUSTOMERCODE = "jd.logistics.customercode";
+}

+ 15 - 16
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/BizInancialFeeItemsController.java

@@ -1,7 +1,6 @@
 package com.ruoyi.logistics.controller;
 
 import java.util.List;
-import java.io.IOException;
 import javax.servlet.http.HttpServletResponse;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -15,8 +14,8 @@ import org.springframework.web.bind.annotation.RestController;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
 import com.ruoyi.common.security.annotation.RequiresPermissions;
-import com.ruoyi.logistics.domain.BizInancialFeeItems;
-import com.ruoyi.logistics.service.IBizInancialFeeItemsService;
+import com.ruoyi.logistics.domain.BizFinancialFeeItems;
+import com.ruoyi.logistics.service.IBizFinancialFeeItemsService;
 import com.ruoyi.common.core.web.controller.BaseController;
 import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.core.utils.poi.ExcelUtil;
@@ -30,20 +29,20 @@ import com.ruoyi.common.core.web.page.TableDataInfo;
  */
 @RestController
 @RequestMapping("/inancialFee")
-public class BizInancialFeeItemsController extends BaseController
+public class BizFinancialFeeItemsController extends BaseController
 {
     @Autowired
-    private IBizInancialFeeItemsService bizInancialFeeItemsService;
+    private IBizFinancialFeeItemsService BizFinancialFeeItemsService;
 
     /**
      * 查询费用类型管理列表
      */
     @RequiresPermissions("system:inancialFee:list")
     @GetMapping("/list")
-    public TableDataInfo list(BizInancialFeeItems bizInancialFeeItems)
+    public TableDataInfo list(BizFinancialFeeItems bizFinancialFeeItems)
     {
         startPage();
-        List<BizInancialFeeItems> list = bizInancialFeeItemsService.selectBizInancialFeeItemsList(bizInancialFeeItems);
+        List<BizFinancialFeeItems> list = BizFinancialFeeItemsService.selectBizFinancialFeeItemsList(bizFinancialFeeItems);
         return getDataTable(list);
     }
 
@@ -53,10 +52,10 @@ public class BizInancialFeeItemsController extends BaseController
     @RequiresPermissions("system:inancialFee:export")
     @Log(title = "费用类型管理", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
-    public void export(HttpServletResponse response, BizInancialFeeItems bizInancialFeeItems)
+    public void export(HttpServletResponse response, BizFinancialFeeItems bizFinancialFeeItems)
     {
-        List<BizInancialFeeItems> list = bizInancialFeeItemsService.selectBizInancialFeeItemsList(bizInancialFeeItems);
-        ExcelUtil<BizInancialFeeItems> util = new ExcelUtil<BizInancialFeeItems>(BizInancialFeeItems.class);
+        List<BizFinancialFeeItems> list = BizFinancialFeeItemsService.selectBizFinancialFeeItemsList(bizFinancialFeeItems);
+        ExcelUtil<BizFinancialFeeItems> util = new ExcelUtil<BizFinancialFeeItems>(BizFinancialFeeItems.class);
         util.exportExcel(response, list, "费用类型管理数据");
     }
 
@@ -67,7 +66,7 @@ public class BizInancialFeeItemsController extends BaseController
     @GetMapping(value = "/{feeItemId}")
     public AjaxResult getInfo(@PathVariable("feeItemId") Long feeItemId)
     {
-        return success(bizInancialFeeItemsService.selectBizInancialFeeItemsByFeeItemId(feeItemId));
+        return success(BizFinancialFeeItemsService.selectBizFinancialFeeItemsByFeeItemId(feeItemId));
     }
 
     /**
@@ -76,9 +75,9 @@ public class BizInancialFeeItemsController extends BaseController
     @RequiresPermissions("system:inancialFee:add")
     @Log(title = "费用类型管理", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody BizInancialFeeItems bizInancialFeeItems)
+    public AjaxResult add(@RequestBody BizFinancialFeeItems bizFinancialFeeItems)
     {
-        return toAjax(bizInancialFeeItemsService.insertBizInancialFeeItems(bizInancialFeeItems));
+        return toAjax(BizFinancialFeeItemsService.insertBizFinancialFeeItems(bizFinancialFeeItems));
     }
 
     /**
@@ -87,9 +86,9 @@ public class BizInancialFeeItemsController extends BaseController
     @RequiresPermissions("system:inancialFee:edit")
     @Log(title = "费用类型管理", businessType = BusinessType.UPDATE)
     @PutMapping
-    public AjaxResult edit(@RequestBody BizInancialFeeItems bizInancialFeeItems)
+    public AjaxResult edit(@RequestBody BizFinancialFeeItems bizFinancialFeeItems)
     {
-        return toAjax(bizInancialFeeItemsService.updateBizInancialFeeItems(bizInancialFeeItems));
+        return toAjax(BizFinancialFeeItemsService.updateBizFinancialFeeItems(bizFinancialFeeItems));
     }
 
     /**
@@ -100,6 +99,6 @@ public class BizInancialFeeItemsController extends BaseController
 	@DeleteMapping("/{feeItemIds}")
     public AjaxResult remove(@PathVariable Long[] feeItemIds)
     {
-        return toAjax(bizInancialFeeItemsService.deleteBizInancialFeeItemsByFeeItemIds(feeItemIds));
+        return toAjax(BizFinancialFeeItemsService.deleteBizFinancialFeeItemsByFeeItemIds(feeItemIds));
     }
 }

+ 15 - 3
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/BizWaybillOrderController.java

@@ -1,8 +1,12 @@
 package com.ruoyi.logistics.controller;
 
+import java.io.UnsupportedEncodingException;
 import java.util.List;
 import java.io.IOException;
 import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.datascope.annotation.DataScope;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -40,6 +44,7 @@ public class BizWaybillOrderController extends BaseController
      */
     @RequiresPermissions("system:order:list")
     @GetMapping("/list")
+    @DataScope(deptAlias = "bwo", userAlias = "u")
     public TableDataInfo list(BizWaybillOrder bizWaybillOrder)
     {
         startPage();
@@ -76,9 +81,16 @@ public class BizWaybillOrderController extends BaseController
     @RequiresPermissions("system:order:add")
     @Log(title = "运单管理", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody BizWaybillOrder bizWaybillOrder)
-    {
-        return toAjax(bizWaybillOrderService.insertBizWaybillOrder(bizWaybillOrder));
+    public AjaxResult add(@RequestBody BizWaybillOrder bizWaybillOrder) {
+        try{
+            return toAjax(bizWaybillOrderService.insertBizWaybillOrder(bizWaybillOrder));
+          }
+         catch(ServiceException e){
+            return AjaxResult.error("下单失败! 原因:"+e.getMessage());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
     }
 
     /**

+ 1 - 1
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/BizInancialFeeItems.java

@@ -11,7 +11,7 @@ import com.ruoyi.common.core.web.domain.BaseEntity;
  * @author RuiJing
  * @date 2026-01-29
  */
-public class BizInancialFeeItems extends BaseEntity
+public class BizFinancialFeeItems extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
 

+ 25 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/BizWaybillOrder.java

@@ -152,6 +152,13 @@ public class BizWaybillOrder extends BaseEntity
     @Excel(name = "用户ID")
     private Long userId;
 
+    /** 产品类型 */
+    @Excel(name = "产品类型")
+    private String productCode;
+
+    /** 增值服务 */
+    private String addedService;
+
     public void setWaybillId(Long waybillId) 
     {
         this.waybillId = waybillId;
@@ -482,6 +489,22 @@ public class BizWaybillOrder extends BaseEntity
         return userId;
     }
 
+    public String getProductCode() {
+        return productCode;
+    }
+
+    public void setProductCode(String productCode) {
+        this.productCode = productCode;
+    }
+
+    public String getAddedService() {
+        return addedService;
+    }
+
+    public void setAddedService(String addedService) {
+        this.addedService = addedService;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -523,6 +546,8 @@ public class BizWaybillOrder extends BaseEntity
             .append("updateBy", getUpdateBy())
             .append("deptId", getDeptId())
             .append("userId", getUserId())
+            .append("productCode", getProductCode())
+            .append("addedService", getAddedService())
             .toString();
     }
 }

+ 23 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/OrderStateDetail.java

@@ -0,0 +1,23 @@
+package com.ruoyi.logistics.domain;
+
+
+import lombok.Data;
+/**
+ * 订单状态详情
+ * @author zxf
+ * @date 2026-02-03
+ */
+@Data
+public class OrderStateDetail {
+    private String orderNo;
+    private String waybillNo;
+    private String orderStateCode;
+    private String orderStateDesc;
+    private String empCode;
+    private String empPhone;
+    private String netCode;
+    private String lastTime;
+    private String bookTime;
+    private String carrierCode;
+    private String createTm;
+}

+ 13 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfApiResponse.java

@@ -0,0 +1,13 @@
+package com.ruoyi.logistics.domain;
+import lombok.Data;
+/**
+ * 顺丰标准响应体
+ * @author zxf
+ * @date 2026-02-03
+ */
+@Data
+public class SfApiResponse {
+    private String success; // 或使用Boolean类型
+    private String code;    // 成功时为"0"
+    private String msg;     //
+}

+ 36 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfFeeApiResponse.java

@@ -0,0 +1,36 @@
+package com.ruoyi.logistics.domain;
+
+import lombok.Data;
+
+/**
+ * 顺丰费用清单标准返回体
+ * @author zxf
+ * @date 2026-02-03
+ */
+@Data
+public class SfFeeApiResponse {
+    private Integer code;          // 200成功,400失败
+    private String partnerCode;    // 合作伙伴code
+    private String service;        // 服务code
+    private String msgData;        // 消息数据
+
+
+    public static SfFeeApiResponse success() {
+        SfFeeApiResponse response = new SfFeeApiResponse();
+        response.setCode(200);
+        response.setPartnerCode("yourPartnerCode");
+        response.setService("");
+        response.setMsgData("");
+        return response;
+    }
+
+    // 快速创建失败响应
+    public static SfFeeApiResponse error(String errorMsg) {
+        SfFeeApiResponse response = new SfFeeApiResponse();
+        response.setCode(400);
+        response.setPartnerCode("");
+        response.setService("");
+        response.setMsgData(errorMsg);
+        return response;
+    }
+}

+ 32 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfFeeInfo.java

@@ -0,0 +1,32 @@
+package com.ruoyi.logistics.domain;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 顺丰费用明细实体
+ * @author zxf
+ * @date 2026-02-03
+ */
+@Data
+public class SfFeeInfo {
+    private String bizOwnerZoneCode;
+    private String currencyCode;
+    private String customerAcctCode;
+    private BigDecimal feeAmt;
+    private BigDecimal feeAmtInd;
+    private Integer feeIndType;
+    private String feeTypeCode;
+    private String gatherEmpCode;
+    private String gatherZoneCode;
+    private String paymentChangeTypeCode;
+    private String paymentTypeCode;
+    private Integer serviceId;
+    private String settlementTypeCode;
+    private Integer versionNo;
+    private Integer waybillId;
+    private String waybillNo;
+    private Long inputTm;
+
+}

+ 22 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfFeePushRequest.java

@@ -0,0 +1,22 @@
+package com.ruoyi.logistics.domain;
+import lombok.Data;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 顺丰运费清单推送请求实体
+ * @author zxf
+ * @date 2026-02-03
+ */
+@Data
+public class SfFeePushRequest {
+    private String waybillNo;
+    private String customerAcctCode;
+    private String childNos;
+    private String orderNo;
+    private BigDecimal meterageWeightQty;
+    private BigDecimal volume;
+    private Integer quantity;
+    private List<SfFeeInfo> feeList;
+    private String productName;
+}

+ 18 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/SfPushOrderStateRequest.java

@@ -0,0 +1,18 @@
+package com.ruoyi.logistics.domain;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 顺丰订单状态回调接收参数
+ *
+ * @author RuiJing
+ * @date 2026-01-29
+ */
+@Data
+public class SfPushOrderStateRequest {
+    private String requestId;
+    private String timestamp;
+    private List<OrderStateDetail> orderState;
+}

+ 56 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/dto/JDOrderFeeRequestDTO.java

@@ -0,0 +1,56 @@
+package com.ruoyi.logistics.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+public class JDOrderFeeRequestDTO {
+
+    // 京东订单号
+    private String orderCode;
+    // 京东订单号
+    private String waybillCode;
+    // 币种 枚举:CNY(人民币)、USD(美元)、EUR(欧元)、JPY(日元)、HKD(港币)、GBP(英镑)
+    private String currencyCode;
+    // 计费重量
+    private BigDecimal weight;
+    // 计费重量单位KG
+    private String weightUnit;
+    // 下单重量
+    private String orderWeight;
+    // 下单体积
+    private String orderVolume;
+    // 实际重量
+    private String actualOrderWeight;
+    // 实际体积
+    private String actualOrderVolume;
+    // 包裹数量
+    private String packNum;
+    // 总标准价格
+    private BigDecimal totalStandardAmount;
+    // 折后总价格
+    private BigDecimal totalAfterBeforehandDiscount;
+    // 保价金额
+    private BigDecimal guaranteeMoney;
+    // 是否终态(拒收/妥投),是:true,否:空
+    private Boolean isFinalState;
+    // 费用明细列表
+    private List<CommonActualFeeInfoDetail> commonActualFeeInfoDetails;
+
+    @Data
+    public static class CommonActualFeeInfoDetail {
+
+        // 费用类型:122-快运运费;QIPSF-快递运费;QLBJ-快递保价费;QLDS-快递代收手续费;QLQDFH-快递签单返还;QLJZD-京尊达服务费;QLHCF-快递耗材;QLDZQD-快递电子签单,字段长度1-10
+        private String feeType;
+        // 费用类型名称:122-快运运费;QIPSF-快递运费;QLBJ-快递保价费;QLDS-快递代收手续费;QLQDFH-快递签单返还;QLJZD-京尊达服务费;QLHCF-快递耗材;QLDZQD-快递电子签单,长度1-20
+        private String feeTypeName;
+        // 标准金额
+        private BigDecimal standardAmount;
+        // 币种
+        private String currencyCode;
+        // 折后金额
+        private BigDecimal afterBeforehandDiscount;
+    }
+}

+ 50 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/dto/JDOrderStatusRequestDTO.java

@@ -0,0 +1,50 @@
+package com.ruoyi.logistics.dto;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class JDOrderStatusRequestDTO {
+
+    // 节点名称
+    private String operationTitle;
+    // 一级分类编码
+    private Integer category;
+    // 一级分类名称
+    private String categoryName;
+    // 签收类型
+    private String signTypeName;
+    // 节点编码
+    private String state;
+    // 路由详细地址
+    private String routeAddress;
+    // 路由 省
+    private String routeProvinceName;
+    // 路由 市
+    private String routeCityName;
+    // 路由 区
+    private String routeDistrictName;
+    // 路由 县
+    private String routeStreetName;
+    // 小哥名称
+    private String operatorName;
+    // 小哥电话
+    private String operatorPhone;
+    // 京东物流运单号
+    private String waybillCode;
+    // 商家订单号
+    private String orderId;
+    // 操作时间
+    private Date operationTime;
+    // 节点描述
+    private String operationRemark;
+    // 机构编码
+    private String operateSiteId;
+    // 机构编码名称
+    private String operateSite;
+    // 京东换单新运单号
+    private String newWaybillCode;
+    // 取消原因
+    private String cancelReason;
+}

+ 28 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/enums/OrderStatusEnum.java

@@ -0,0 +1,28 @@
+package com.ruoyi.logistics.enums;
+
+public enum OrderStatusEnum {
+
+    ORDER_STATUS_1(1, "待揽件"),
+    ORDER_STATUS_2(2, "已揽件"),
+    ORDER_STATUS_3(3, "运输中"),
+    ORDER_STATUS_4(4, "派送中"),
+    ORDER_STATUS_5(5, "已签收"),
+    ORDER_STATUS_6(6, "已取消");
+
+
+    private int code;
+    private String desc;
+
+    OrderStatusEnum(int code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+}

+ 7 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizAddressBookMapper.java

@@ -58,4 +58,11 @@ public interface BizAddressBookMapper
      * @return 结果
      */
     public int deleteBizAddressBookByAddressIds(Long[] addressIds);
+
+    /**
+     * 更新用户默认收货地址
+     * @param userId
+     * @return
+     */
+    public int updateBizAddressBookDefault(Long userId);
 }

+ 11 - 11
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizInancialFeeItemsMapper.java

@@ -1,7 +1,7 @@
 package com.ruoyi.logistics.mapper;
 
 import java.util.List;
-import com.ruoyi.logistics.domain.BizInancialFeeItems;
+import com.ruoyi.logistics.domain.BizFinancialFeeItems;
 
 /**
  * 费用类型管理Mapper接口
@@ -9,7 +9,7 @@ import com.ruoyi.logistics.domain.BizInancialFeeItems;
  * @author RuiJing
  * @date 2026-01-29
  */
-public interface BizInancialFeeItemsMapper 
+public interface BizFinancialFeeItemsMapper 
 {
     /**
      * 查询费用类型管理
@@ -17,31 +17,31 @@ public interface BizInancialFeeItemsMapper
      * @param feeItemId 费用类型管理主键
      * @return 费用类型管理
      */
-    public BizInancialFeeItems selectBizInancialFeeItemsByFeeItemId(Long feeItemId);
+    public BizFinancialFeeItems selectBizFinancialFeeItemsByFeeItemId(Long feeItemId);
 
     /**
      * 查询费用类型管理列表
      * 
-     * @param bizInancialFeeItems 费用类型管理
+     * @param bizFinancialFeeItems 费用类型管理
      * @return 费用类型管理集合
      */
-    public List<BizInancialFeeItems> selectBizInancialFeeItemsList(BizInancialFeeItems bizInancialFeeItems);
+    public List<BizFinancialFeeItems> selectBizFinancialFeeItemsList(BizFinancialFeeItems bizFinancialFeeItems);
 
     /**
      * 新增费用类型管理
      * 
-     * @param bizInancialFeeItems 费用类型管理
+     * @param bizFinancialFeeItems 费用类型管理
      * @return 结果
      */
-    public int insertBizInancialFeeItems(BizInancialFeeItems bizInancialFeeItems);
+    public int insertBizFinancialFeeItems(BizFinancialFeeItems bizFinancialFeeItems);
 
     /**
      * 修改费用类型管理
      * 
-     * @param bizInancialFeeItems 费用类型管理
+     * @param bizFinancialFeeItems 费用类型管理
      * @return 结果
      */
-    public int updateBizInancialFeeItems(BizInancialFeeItems bizInancialFeeItems);
+    public int updateBizFinancialFeeItems(BizFinancialFeeItems bizFinancialFeeItems);
 
     /**
      * 删除费用类型管理
@@ -49,7 +49,7 @@ public interface BizInancialFeeItemsMapper
      * @param feeItemId 费用类型管理主键
      * @return 结果
      */
-    public int deleteBizInancialFeeItemsByFeeItemId(Long feeItemId);
+    public int deleteBizFinancialFeeItemsByFeeItemId(Long feeItemId);
 
     /**
      * 批量删除费用类型管理
@@ -57,5 +57,5 @@ public interface BizInancialFeeItemsMapper
      * @param feeItemIds 需要删除的数据主键集合
      * @return 结果
      */
-    public int deleteBizInancialFeeItemsByFeeItemIds(Long[] feeItemIds);
+    public int deleteBizFinancialFeeItemsByFeeItemIds(Long[] feeItemIds);
 }

+ 7 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizWaybillOrderMapper.java

@@ -58,4 +58,11 @@ public interface BizWaybillOrderMapper
      * @return 结果
      */
     public int deleteBizWaybillOrderByWaybillIds(Long[] waybillIds);
+
+    /**
+     * 根据查询条件查询运单详情
+     * @param query
+     * @return
+     */
+    public BizWaybillOrder selectBizWaybillOrderByQuery(BizWaybillOrder query);
 }

+ 129 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/FeeItemsCacheService.java

@@ -0,0 +1,129 @@
+package com.ruoyi.logistics.service;
+
+import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.logistics.constant.RedisCacheConstants;
+import com.ruoyi.logistics.domain.BizFinancialFeeItems;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 费用类型缓存服务
+ * 
+ * @author lydgt
+ * @date 2026-02-04
+ */
+@Service
+public class FeeItemsCacheService {
+
+    private static final Logger log = LoggerFactory.getLogger(FeeItemsCacheService.class);
+
+    @Autowired
+    private IBizFinancialFeeItemsService BizFinancialFeeItemsService;
+
+    @Autowired
+    private RedisService redisService;
+
+    /**
+     * 初始化费用类型数据到Redis
+     */
+    @PostConstruct
+    public void initFeeItemsCache() {
+        loadFeeItemsToRedis();
+    }
+
+    /**
+     * 加载费用类型数据到Redis中
+     */
+    public void loadFeeItemsToRedis() {
+        try {
+            log.info("开始加载费用类型数据到Redis缓存...");
+            
+            // 查询所有费用类型数据
+            List<BizFinancialFeeItems> feeItemsList = BizFinancialFeeItemsService.selectAllBizFinancialFeeItems();
+            
+            if (feeItemsList != null && !feeItemsList.isEmpty()) {
+                // 创建Map用于存储费用类型数据,key为extFeeCode,value为BizFinancialFeeItems对象
+                Map<String, BizFinancialFeeItems> feeItemsMap = new HashMap<>();
+                
+                for (BizFinancialFeeItems feeItem : feeItemsList) {
+                    if (feeItem.getExtFeeCode() != null) {
+                        feeItemsMap.put(feeItem.getExtFeeCode(), feeItem);
+                    }
+                }
+                
+                // 清除旧的缓存数据
+                redisService.deleteObject(RedisCacheConstants.FINANCIAL_FEE_ITEM_CACHE_KEY);
+                
+                // 将费用类型数据保存到Redis中
+                if (!feeItemsMap.isEmpty()) {
+                    redisService.setCacheMap(RedisCacheConstants.FINANCIAL_FEE_ITEM_CACHE_KEY, feeItemsMap);
+                    log.info("成功加载{}条费用类型数据到Redis缓存", feeItemsMap.size());
+                } else {
+                    log.info("没有找到有效的费用类型数据");
+                }
+            } else {
+                log.info("没有找到费用类型数据");
+            }
+        } catch (Exception e) {
+            log.error("加载费用类型数据到Redis缓存失败", e);
+        }
+    }
+
+    /**
+     * 根据外部费用编码获取费用类型信息
+     * 
+     * @param extFeeCode 外部费用编码
+     * @return 费用类型信息
+     */
+    public BizFinancialFeeItems getFeeItemByExtFeeCode(String extFeeCode) {
+        if (extFeeCode == null) {
+            return null;
+        }
+        
+        Map<String, BizFinancialFeeItems> feeItemsMap = getFeeItemsMapFromRedis();
+        if (feeItemsMap != null) {
+            return feeItemsMap.get(extFeeCode);
+        }
+        
+        return null;
+    }
+
+    /**
+     * 从Redis获取费用类型Map
+     * 
+     * @return 费用类型Map
+     */
+    public Map<String, BizFinancialFeeItems> getFeeItemsMapFromRedis() {
+        return redisService.getCacheMap(RedisCacheConstants.FINANCIAL_FEE_ITEM_CACHE_KEY);
+    }
+
+    /**
+     * 更新缓存中的单个费用类型数据
+     * 
+     * @param extFeeCode 外部费用编码
+     * @param feeItem 费用类型对象
+     */
+    public void updateFeeItemInCache(String extFeeCode, BizFinancialFeeItems feeItem) {
+        if (extFeeCode != null && feeItem != null) {
+            redisService.setCacheMapValue(RedisCacheConstants.FINANCIAL_FEE_ITEM_CACHE_KEY, extFeeCode, feeItem);
+        }
+    }
+
+    /**
+     * 删除缓存中的费用类型数据
+     * 
+     * @param extFeeCode 外部费用编码
+     */
+    public void removeFeeItemFromCache(String extFeeCode) {
+        if (extFeeCode != null) {
+            redisService.deleteCacheMapValue(RedisCacheConstants.FINANCIAL_FEE_ITEM_CACHE_KEY, extFeeCode);
+        }
+    }
+}

+ 68 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IBizFinancialFeeItemsService.java

@@ -0,0 +1,68 @@
+package com.ruoyi.logistics.service;
+
+import java.util.List;
+import com.ruoyi.logistics.domain.BizFinancialFeeItems;
+
+/**
+ * 费用类型管理Service接口
+ * 
+ * @author RuiJing
+ * @date 2026-01-29
+ */
+public interface IBizFinancialFeeItemsService 
+{
+    /**
+     * 查询费用类型管理
+     * 
+     * @param feeItemId 费用类型管理主键
+     * @return 费用类型管理
+     */
+    public BizFinancialFeeItems selectBizFinancialFeeItemsByFeeItemId(Long feeItemId);
+
+    /**
+     * 查询费用类型管理列表
+     * 
+     * @param bizFinancialFeeItems 费用类型管理
+     * @return 费用类型管理集合
+     */
+    public List<BizFinancialFeeItems> selectBizFinancialFeeItemsList(BizFinancialFeeItems bizFinancialFeeItems);
+
+    /**
+     * 新增费用类型管理
+     * 
+     * @param bizFinancialFeeItems 费用类型管理
+     * @return 结果
+     */
+    public int insertBizFinancialFeeItems(BizFinancialFeeItems bizFinancialFeeItems);
+
+    /**
+     * 修改费用类型管理
+     * 
+     * @param bizFinancialFeeItems 费用类型管理
+     * @return 结果
+     */
+    public int updateBizFinancialFeeItems(BizFinancialFeeItems bizFinancialFeeItems);
+
+    /**
+     * 批量删除费用类型管理
+     * 
+     * @param feeItemIds 需要删除的费用类型管理主键集合
+     * @return 结果
+     */
+    public int deleteBizFinancialFeeItemsByFeeItemIds(Long[] feeItemIds);
+
+    /**
+     * 删除费用类型管理信息
+     * 
+     * @param feeItemId 费用类型管理主键
+     * @return 结果
+     */
+    public int deleteBizFinancialFeeItemsByFeeItemId(Long feeItemId);
+
+    /**
+     * 查询所有费用类型管理列表
+     * 
+     * @return 费用类型管理集合
+     */
+    public List<BizFinancialFeeItems> selectAllBizFinancialFeeItems();
+}

+ 0 - 61
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IBizInancialFeeItemsService.java

@@ -1,61 +0,0 @@
-package com.ruoyi.logistics.service;
-
-import java.util.List;
-import com.ruoyi.logistics.domain.BizInancialFeeItems;
-
-/**
- * 费用类型管理Service接口
- * 
- * @author RuiJing
- * @date 2026-01-29
- */
-public interface IBizInancialFeeItemsService 
-{
-    /**
-     * 查询费用类型管理
-     * 
-     * @param feeItemId 费用类型管理主键
-     * @return 费用类型管理
-     */
-    public BizInancialFeeItems selectBizInancialFeeItemsByFeeItemId(Long feeItemId);
-
-    /**
-     * 查询费用类型管理列表
-     * 
-     * @param bizInancialFeeItems 费用类型管理
-     * @return 费用类型管理集合
-     */
-    public List<BizInancialFeeItems> selectBizInancialFeeItemsList(BizInancialFeeItems bizInancialFeeItems);
-
-    /**
-     * 新增费用类型管理
-     * 
-     * @param bizInancialFeeItems 费用类型管理
-     * @return 结果
-     */
-    public int insertBizInancialFeeItems(BizInancialFeeItems bizInancialFeeItems);
-
-    /**
-     * 修改费用类型管理
-     * 
-     * @param bizInancialFeeItems 费用类型管理
-     * @return 结果
-     */
-    public int updateBizInancialFeeItems(BizInancialFeeItems bizInancialFeeItems);
-
-    /**
-     * 批量删除费用类型管理
-     * 
-     * @param feeItemIds 需要删除的费用类型管理主键集合
-     * @return 结果
-     */
-    public int deleteBizInancialFeeItemsByFeeItemIds(Long[] feeItemIds);
-
-    /**
-     * 删除费用类型管理信息
-     * 
-     * @param feeItemId 费用类型管理主键
-     * @return 结果
-     */
-    public int deleteBizInancialFeeItemsByFeeItemId(Long feeItemId);
-}

+ 9 - 1
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IBizWaybillOrderService.java

@@ -1,5 +1,6 @@
 package com.ruoyi.logistics.service;
 
+import java.io.UnsupportedEncodingException;
 import java.util.List;
 import com.ruoyi.logistics.domain.BizWaybillOrder;
 
@@ -33,7 +34,7 @@ public interface IBizWaybillOrderService
      * @param bizWaybillOrder 运单管理
      * @return 结果
      */
-    public int insertBizWaybillOrder(BizWaybillOrder bizWaybillOrder);
+    public int insertBizWaybillOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException;
 
     /**
      * 修改运单管理
@@ -58,4 +59,11 @@ public interface IBizWaybillOrderService
      * @return 结果
      */
     public int deleteBizWaybillOrderByWaybillId(Long waybillId);
+
+    /**
+     * 根据订单信息查询运单详情
+     * @param query
+     * @return
+     */
+    public BizWaybillOrder selectBizWaybillOrderByQuery(BizWaybillOrder query);
 }

+ 21 - 5
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/LogisticsOrderService.java

@@ -1,5 +1,8 @@
 package com.ruoyi.logistics.service;
 
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
 import com.ruoyi.logistics.domain.LogisticsOrder;
 import com.ruoyi.logistics.service.factory.LogisticsFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -12,15 +15,28 @@ public class LogisticsOrderService {
     @Autowired
     private LogisticsFactory logisticsFactory;
 
-    public String createOrder(LogisticsOrder logisticsOrder) throws UnsupportedEncodingException {
+
+    public JSONObject precheckOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException {
         // 根据订单中的物流公司类型获取对应服务
-        LogisticsService logisticsService = logisticsFactory.getLogisticsService(logisticsOrder.getOrderType());
-        String trackingNumber = logisticsService.createOrder(logisticsOrder);
+        LogisticsService logisticsService = logisticsFactory.getLogisticsService(bizWaybillOrder.getOrderType()==1?"JD":"SF");
+        JSONObject  precheckOrder= logisticsService.precheckOrder(bizWaybillOrder);
+        return precheckOrder;
+    }
+
 
-        // 保存订单... logisticsOrder.save();
-        return trackingNumber;
+    public JSONObject createOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException {
+        // 根据订单中的物流公司类型获取对应服务
+        LogisticsService logisticsService = logisticsFactory.getLogisticsService(bizWaybillOrder.getOrderType()==1?"JD":"SF");
+        JSONObject  createOrder= logisticsService.createOrder(bizWaybillOrder);
+        return createOrder;
     }
 
+    public JSONObject cancelOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException {
+        // 根据订单中的物流公司类型获取对应服务
+        LogisticsService logisticsService = logisticsFactory.getLogisticsService(bizWaybillOrder.getOrderType()==1?"JD":"SF");
+        JSONObject  cancelOrder= logisticsService.cancelOrder(bizWaybillOrder);
+        return cancelOrder;
+    }
 
 
 }

+ 37 - 9
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/LogisticsService.java

@@ -1,15 +1,43 @@
 package com.ruoyi.logistics.service;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
+/**
+ * 物流相关接口定义
+ *
+ * @author RuiJing
+ * @date 2026-02-02
+ */
+public interface LogisticsService {
 
-import com.ruoyi.logistics.domain.LogisticsOrder;
-
-import java.io.UnsupportedEncodingException;
 
-public interface LogisticsService {
+    /**
+     * 预下单  检验能否正常下单
+     *
+     * @author RuiJing
+     * @date 2026-02-02
+     */
+    JSONObject precheckOrder(BizWaybillOrder bizWaybillOrder);
+    /**
+     * 创建物流订单
+     *
+     * @author RuiJing
+     * @date 2026-02-02
+     */
+    JSONObject createOrder(BizWaybillOrder bizWaybillOrder) ;
 
-    //预下单
-    String precheckOrder();
-    //创建物流订单
-    String createOrder(LogisticsOrder logisticsOrder) throws UnsupportedEncodingException;
-    //取消物流订单
+    /**
+     * 取消物流订单
+     *
+     * @author RuiJing
+     * @date 2026-02-02
+     */
 
+    JSONObject cancelOrder(BizWaybillOrder bizWaybillOrder) ;
+    /**
+     *修改物流订单
+     *
+     * @author RuiJing
+     * @date 2026-02-02
+     */
+    JSONObject modifyOrder(BizWaybillOrder bizWaybillOrder) ;
 }

+ 12 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizAddressBookServiceImpl.java

@@ -2,6 +2,8 @@ package com.ruoyi.logistics.service.impl;
 
 import java.util.List;
 import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.security.utils.SecurityUtils;
+import com.ruoyi.system.api.model.LoginUser;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.logistics.mapper.BizAddressBookMapper;
@@ -41,6 +43,7 @@ public class BizAddressBookServiceImpl implements IBizAddressBookService
     @Override
     public List<BizAddressBook> selectBizAddressBookList(BizAddressBook bizAddressBook)
     {
+        bizAddressBook.setUserId(SecurityUtils.getLoginUser().getUserid());
         return bizAddressBookMapper.selectBizAddressBookList(bizAddressBook);
     }
 
@@ -53,7 +56,16 @@ public class BizAddressBookServiceImpl implements IBizAddressBookService
     @Override
     public int insertBizAddressBook(BizAddressBook bizAddressBook)
     {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+
+        bizAddressBook.setUserId(loginUser.getUserid());
+        bizAddressBook.setDeptId(loginUser.getSysUser().getDeptId());
         bizAddressBook.setCreateTime(DateUtils.getNowDate());
+
+        if ("1".equals(bizAddressBook.getDefaultFlag())) {
+            bizAddressBookMapper.updateBizAddressBookDefault(loginUser.getUserid());
+        }
+
         return bizAddressBookMapper.insertBizAddressBook(bizAddressBook);
     }
 

+ 112 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizFinancialFeeItemsServiceImpl.java

@@ -0,0 +1,112 @@
+package com.ruoyi.logistics.service.impl;
+
+import java.util.List;
+import com.ruoyi.common.core.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.logistics.mapper.BizFinancialFeeItemsMapper;
+import com.ruoyi.logistics.domain.BizFinancialFeeItems;
+import com.ruoyi.logistics.service.IBizFinancialFeeItemsService;
+import com.ruoyi.logistics.service.FeeItemsCacheService;
+
+/**
+ * 费用类型管理Service业务层处理
+ * 
+ * @author RuiJing
+ * @date 2026-01-29
+ */
+@Service
+public class BizFinancialFeeItemsServiceImpl implements IBizFinancialFeeItemsService 
+{
+    @Autowired
+    private BizFinancialFeeItemsMapper bizFinancialFeeItemsMapper;
+
+    /**
+     * 查询费用类型管理
+     * 
+     * @param feeItemId 费用类型管理主键
+     * @return 费用类型管理
+     */
+    @Override
+    public BizFinancialFeeItems selectBizFinancialFeeItemsByFeeItemId(Long feeItemId)
+    {
+        return bizFinancialFeeItemsMapper.selectBizFinancialFeeItemsByFeeItemId(feeItemId);
+    }
+
+    /**
+     * 查询费用类型管理列表
+     * 
+     * @param bizFinancialFeeItems 费用类型管理
+     * @return 费用类型管理
+     */
+    @Override
+    public List<BizFinancialFeeItems> selectBizFinancialFeeItemsList(BizFinancialFeeItems bizFinancialFeeItems)
+    {
+        return bizFinancialFeeItemsMapper.selectBizFinancialFeeItemsList(bizFinancialFeeItems);
+    }
+
+    /**
+     * 新增费用类型管理
+     * 
+     * @param bizFinancialFeeItems 费用类型管理
+     * @return 结果
+     */
+    @Override
+    public int insertBizFinancialFeeItems(BizFinancialFeeItems bizFinancialFeeItems)
+    {
+        bizFinancialFeeItems.setCreateTime(DateUtils.getNowDate());
+        int result = bizFinancialFeeItemsMapper.insertBizFinancialFeeItems(bizFinancialFeeItems);
+        return result;
+    }
+
+    /**
+     * 修改费用类型管理
+     * 
+     * @param bizFinancialFeeItems 费用类型管理
+     * @return 结果
+     */
+    @Override
+    public int updateBizFinancialFeeItems(BizFinancialFeeItems bizFinancialFeeItems)
+    {
+        bizFinancialFeeItems.setUpdateTime(DateUtils.getNowDate());
+        int result = bizFinancialFeeItemsMapper.updateBizFinancialFeeItems(bizFinancialFeeItems);
+        return result;
+    }
+
+    /**
+     * 批量删除费用类型管理
+     * 
+     * @param feeItemIds 需要删除的费用类型管理主键
+     * @return 结果
+     */
+    @Override
+    public int deleteBizFinancialFeeItemsByFeeItemIds(Long[] feeItemIds)
+    {
+        int result = bizFinancialFeeItemsMapper.deleteBizFinancialFeeItemsByFeeItemIds(feeItemIds);
+        return result;
+    }
+
+    /**
+     * 删除费用类型管理信息
+     * 
+     * @param feeItemId 费用类型管理主键
+     * @return 结果
+     */
+    @Override
+    public int deleteBizFinancialFeeItemsByFeeItemId(Long feeItemId)
+    {
+        int result = bizFinancialFeeItemsMapper.deleteBizFinancialFeeItemsByFeeItemId(feeItemId);
+        return result;
+    }
+
+    /**
+     * 查询所有费用类型管理列表
+     * 
+     * @return 费用类型管理集合
+     */
+    @Override
+    public List<BizFinancialFeeItems> selectAllBizFinancialFeeItems()
+    {
+        return bizFinancialFeeItemsMapper.selectBizFinancialFeeItemsList(new BizFinancialFeeItems());
+    }
+}

+ 0 - 96
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizInancialFeeItemsServiceImpl.java

@@ -1,96 +0,0 @@
-package com.ruoyi.logistics.service.impl;
-
-import java.util.List;
-import com.ruoyi.common.core.utils.DateUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import com.ruoyi.logistics.mapper.BizInancialFeeItemsMapper;
-import com.ruoyi.logistics.domain.BizInancialFeeItems;
-import com.ruoyi.logistics.service.IBizInancialFeeItemsService;
-
-/**
- * 费用类型管理Service业务层处理
- * 
- * @author RuiJing
- * @date 2026-01-29
- */
-@Service
-public class BizInancialFeeItemsServiceImpl implements IBizInancialFeeItemsService 
-{
-    @Autowired
-    private BizInancialFeeItemsMapper bizInancialFeeItemsMapper;
-
-    /**
-     * 查询费用类型管理
-     * 
-     * @param feeItemId 费用类型管理主键
-     * @return 费用类型管理
-     */
-    @Override
-    public BizInancialFeeItems selectBizInancialFeeItemsByFeeItemId(Long feeItemId)
-    {
-        return bizInancialFeeItemsMapper.selectBizInancialFeeItemsByFeeItemId(feeItemId);
-    }
-
-    /**
-     * 查询费用类型管理列表
-     * 
-     * @param bizInancialFeeItems 费用类型管理
-     * @return 费用类型管理
-     */
-    @Override
-    public List<BizInancialFeeItems> selectBizInancialFeeItemsList(BizInancialFeeItems bizInancialFeeItems)
-    {
-        return bizInancialFeeItemsMapper.selectBizInancialFeeItemsList(bizInancialFeeItems);
-    }
-
-    /**
-     * 新增费用类型管理
-     * 
-     * @param bizInancialFeeItems 费用类型管理
-     * @return 结果
-     */
-    @Override
-    public int insertBizInancialFeeItems(BizInancialFeeItems bizInancialFeeItems)
-    {
-        bizInancialFeeItems.setCreateTime(DateUtils.getNowDate());
-        return bizInancialFeeItemsMapper.insertBizInancialFeeItems(bizInancialFeeItems);
-    }
-
-    /**
-     * 修改费用类型管理
-     * 
-     * @param bizInancialFeeItems 费用类型管理
-     * @return 结果
-     */
-    @Override
-    public int updateBizInancialFeeItems(BizInancialFeeItems bizInancialFeeItems)
-    {
-        bizInancialFeeItems.setUpdateTime(DateUtils.getNowDate());
-        return bizInancialFeeItemsMapper.updateBizInancialFeeItems(bizInancialFeeItems);
-    }
-
-    /**
-     * 批量删除费用类型管理
-     * 
-     * @param feeItemIds 需要删除的费用类型管理主键
-     * @return 结果
-     */
-    @Override
-    public int deleteBizInancialFeeItemsByFeeItemIds(Long[] feeItemIds)
-    {
-        return bizInancialFeeItemsMapper.deleteBizInancialFeeItemsByFeeItemIds(feeItemIds);
-    }
-
-    /**
-     * 删除费用类型管理信息
-     * 
-     * @param feeItemId 费用类型管理主键
-     * @return 结果
-     */
-    @Override
-    public int deleteBizInancialFeeItemsByFeeItemId(Long feeItemId)
-    {
-        return bizInancialFeeItemsMapper.deleteBizInancialFeeItemsByFeeItemId(feeItemId);
-    }
-}

+ 39 - 2
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizWaybillOrderServiceImpl.java

@@ -1,7 +1,17 @@
 package com.ruoyi.logistics.service.impl;
 
+import java.io.UnsupportedEncodingException;
 import java.util.List;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.core.exception.ServiceException;
 import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.datascope.annotation.DataScope;
+import com.ruoyi.common.redis.service.RedisIdGenerator;
+import com.ruoyi.common.security.utils.SecurityUtils;
+import com.ruoyi.logistics.service.LogisticsOrderService;
+import com.ruoyi.system.api.model.LoginUser;
+import org.checkerframework.checker.units.qual.A;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.logistics.mapper.BizWaybillOrderMapper;
@@ -19,6 +29,11 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
 {
     @Autowired
     private BizWaybillOrderMapper bizWaybillOrderMapper;
+    @Autowired
+    LogisticsOrderService logisticsOrderService;
+
+    @Autowired
+    private RedisIdGenerator redisIdGenerator;
 
     /**
      * 查询运单管理
@@ -29,6 +44,7 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
     @Override
     public BizWaybillOrder selectBizWaybillOrderByWaybillId(Long waybillId)
     {
+
         return bizWaybillOrderMapper.selectBizWaybillOrderByWaybillId(waybillId);
     }
 
@@ -51,9 +67,23 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
      * @return 结果
      */
     @Override
-    public int insertBizWaybillOrder(BizWaybillOrder bizWaybillOrder)
-    {
+    public int insertBizWaybillOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException {
+
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        String orderId = redisIdGenerator.generateUniqueId("RJSD");
+        bizWaybillOrder.setWaybillNo(orderId);
+        //前置校验
+        JSONObject jsonObject= logisticsOrderService.precheckOrder(bizWaybillOrder);
+        if(!jsonObject.getBooleanValue("success")){
+            throw new ServiceException("下单前置校验未通过! 原因:"+jsonObject.getString("msg"));
+          }
+        JSONObject orderObject= logisticsOrderService.createOrder(bizWaybillOrder);
+        if(!orderObject.getBooleanValue("success")){
+            throw new ServiceException("下单失败! 原因:"+orderObject.getString("msg"));
+        }
         bizWaybillOrder.setCreateTime(DateUtils.getNowDate());
+        bizWaybillOrder.setUserId(loginUser.getUserid());
+        bizWaybillOrder.setDeptId(loginUser.getSysUser().getDeptId());
         return bizWaybillOrderMapper.insertBizWaybillOrder(bizWaybillOrder);
     }
 
@@ -67,6 +97,8 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
     public int updateBizWaybillOrder(BizWaybillOrder bizWaybillOrder)
     {
         bizWaybillOrder.setUpdateTime(DateUtils.getNowDate());
+
+
         return bizWaybillOrderMapper.updateBizWaybillOrder(bizWaybillOrder);
     }
 
@@ -93,4 +125,9 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
     {
         return bizWaybillOrderMapper.deleteBizWaybillOrderByWaybillId(waybillId);
     }
+
+    @Override
+    public BizWaybillOrder selectBizWaybillOrderByQuery(BizWaybillOrder query) {
+        return null;
+    }
 }

+ 104 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/FeePushService.java

@@ -0,0 +1,104 @@
+package com.ruoyi.logistics.service.impl;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.logistics.domain.*;
+import com.ruoyi.logistics.service.IBizFinancialFeeItemsService;
+import com.ruoyi.logistics.service.IBizWaybillCostDetailsService;
+import com.ruoyi.logistics.service.IBizWaybillOrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.math.BigDecimal;
+import java.util.List;
+
+
+/**
+ * 费用明细回调入库
+ *
+ * @author zxf
+ * @date 2026-02-03
+ */
+
+@Service
+public class FeePushService {
+
+    @Autowired
+    private IBizWaybillOrderService bizWaybillOrderService;
+    @Autowired
+    private IBizFinancialFeeItemsService BizFinancialFeeItemsService;
+
+    @Autowired
+    private IBizWaybillCostDetailsService bizWaybillCostDetailsService;
+    private static final Logger logger = LoggerFactory.getLogger(FeePushService.class);
+
+    public boolean processFeePush(SfFeePushRequest request) {
+        try {
+            String waybillNo = request.getWaybillNo();
+            String orderNo = request.getOrderNo();
+            BigDecimal totalWeight = request.getMeterageWeightQty();
+            Integer quantity = request.getQuantity();
+            String productName = request.getProductName();
+            List<SfFeeInfo> feeList = request.getFeeList();
+            logger.info("开始处理运费清单 - 运单号: {}, 订单号: {}, 产品: {}, 计费重量: {}kg",
+                    waybillNo, orderNo, productName, totalWeight);
+
+            // 1. 根据订单号查询本地订单 如果不存在该订单号  则不进行明细的入库
+            BizWaybillOrder bizWaybillOrder= new BizWaybillOrder();
+            bizWaybillOrder.setWaybillNo(orderNo);
+            bizWaybillOrder.setExternalWaybillNo(waybillNo);
+            List<BizWaybillOrder> orderList=bizWaybillOrderService.selectBizWaybillOrderList(bizWaybillOrder);
+            if (orderList.size()==0) {
+                logger.error("订单不存在: {}", orderNo);
+                return false;
+            }
+            //存在的话 就去拿到这个部门id 要知道这个供应商的费率
+            Long deptId=orderList.get(0).getDeptId();
+            //先写死
+            String  Rate="1.5";
+
+
+
+            // 2. 目前订单主表不涉及费用总计啥的  先不管
+
+
+            // 3. 处理费用明细
+            if (feeList != null && !feeList.isEmpty()) {
+                for (SfFeeInfo fee : feeList) {
+                    BigDecimal feeAmt = fee.getFeeAmt();
+                    //回调回来的 费用类型  还需与系统 费用类型表-biz_inancial_fee_items
+                    String feeTypeCode = fee.getFeeTypeCode();
+                    BizFinancialFeeItems bizFinancialFeeItems = new BizFinancialFeeItems();
+                    bizFinancialFeeItems.setFeeItemCategory("sf");
+                    bizFinancialFeeItems.setExtFeeCode(feeTypeCode);
+                    List<BizFinancialFeeItems> feeItemsList=BizFinancialFeeItemsService.selectBizFinancialFeeItemsList(bizFinancialFeeItems);
+                    BizWaybillCostDetails bizWaybillCostDetails= new BizWaybillCostDetails();
+                    //顺丰的费用类型代码无法在费用类型表中匹配 这里默认给值 给到外部叫什么名字
+                    bizWaybillCostDetails.setFeeName(feeItemsList.get(0).getExtFeeName());
+                    if(StringUtils.isBlank(feeItemsList.get(0).getFeeItemCode())){
+                        bizWaybillCostDetails.setFeeItemCode("00");
+                        bizWaybillCostDetails.setFeeItemName("瑞鲸-其他");
+                    }
+                    else{
+                        bizWaybillCostDetails.setFeeItemCode(feeItemsList.get(0).getFeeItemCode());
+                        bizWaybillCostDetails.setFeeItemName(feeItemsList.get(0).getFeeItemName());
+                    }
+                    bizWaybillCostDetails.setAmount(feeAmt);
+                    BigDecimal deptRate = new BigDecimal(Rate);
+                    BigDecimal result = feeAmt.multiply(deptRate);
+                    bizWaybillCostDetails.setRateAmount(result);
+                    bizWaybillCostDetails.setDeptId(deptId);
+                    // 记录费用明细
+                    bizWaybillCostDetailsService.insertBizWaybillCostDetails(bizWaybillCostDetails);
+                }
+            }
+            return true;
+
+        } catch (Exception e) {
+            logger.error("处理运费清单失败: {}", e.getMessage(), e);
+            return false;
+        }
+    }
+
+
+}

+ 360 - 26
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/JDLogisticsService.java

@@ -1,23 +1,42 @@
 package com.ruoyi.logistics.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.lop.open.api.sdk.DefaultDomainApiClient;
 import com.lop.open.api.sdk.LopException;
 import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCheckPreCreateOrderV1.CommonCreateOrderRequest;
 import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCheckPreCreateOrderV1.CommonProductInfo;
 import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCheckPreCreateOrderV1.Contact;
+import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonCargoInfo;
+import com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonCancelOrderV1.CommonOrderCancelRequest;
 import com.lop.open.api.sdk.plugin.LopPlugin;
 import com.lop.open.api.sdk.plugin.factory.OAuth2PluginFactory;
+import com.lop.open.api.sdk.request.ECAP.EcapV1OrdersCancelLopRequest;
 import com.lop.open.api.sdk.request.ECAP.EcapV1OrdersCreateLopRequest;
+import com.lop.open.api.sdk.request.ECAP.EcapV1OrdersModifyLopRequest;
 import com.lop.open.api.sdk.request.ECAP.EcapV1OrdersPrecheckLopRequest;
+import com.lop.open.api.sdk.response.ECAP.EcapV1OrdersCancelLopResponse;
 import com.lop.open.api.sdk.response.ECAP.EcapV1OrdersCreateLopResponse;
+import com.lop.open.api.sdk.response.ECAP.EcapV1OrdersModifyLopResponse;
 import com.lop.open.api.sdk.response.ECAP.EcapV1OrdersPrecheckLopResponse;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.logistics.config.JDExpressConfig;
-import com.ruoyi.logistics.domain.LogisticsOrder;
+import com.ruoyi.logistics.constant.JDDictConstants;
+import com.ruoyi.logistics.constant.SysConfigConstants;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
 import com.ruoyi.logistics.service.LogisticsService;
+import com.ruoyi.system.service.ISysConfigService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 @Slf4j
 @Service
 public class JDLogisticsService  implements LogisticsService {
@@ -25,27 +44,40 @@ public class JDLogisticsService  implements LogisticsService {
     @Autowired
     private JDExpressConfig jdExpressConfig;
 
+    @Autowired
+    private ISysConfigService sysConfigService;
+
     @Override
-    public String precheckOrder() {
-        log.info("调用京东开放平台订单预校验接口");
+    public JSONObject precheckOrder(BizWaybillOrder bizWaybillOrder) {
+        log.info("京东开放平台订单预校验接口,入参:{}", bizWaybillOrder);
+        JSONObject result = new JSONObject();
         try {
             //设置接口域名(有的对接方案同时支持生产和沙箱环境,有的仅支持生产,具体以对接方案中的【API文档-请求地址】为准),生产域名:https://api.jdl.com 预发环境域名:https://uat-api.jdl.com
             //DefaultDomainApiClient对象全局只需要创建一次
             DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);
 
-            //入参对象(请记得更换为自己要使用的接口入参对象)
+            //入参对象
             EcapV1OrdersPrecheckLopRequest request = new EcapV1OrdersPrecheckLopRequest();
 
-            //设置入参(请记得更换为自己要使用的接口入参)
+            //发货人
             Contact senderContact  = new Contact();
-            senderContact.setFullAddress("河北省廊坊市广阳区万庄镇中心小学");
+            senderContact.setName(bizWaybillOrder.getSenderName());
+            senderContact.setMobile(bizWaybillOrder.getSenderPhone());
+            senderContact.setFullAddress(bizWaybillOrder.getSenderProvince() + bizWaybillOrder.getSenderCity() + bizWaybillOrder.getSenderCounty() + bizWaybillOrder.getSenderAddress());
+
+            //收货人
             Contact receiverContact = new Contact();
-            receiverContact.setFullAddress("河北省廊坊市广阳区万庄镇中心小学");
+            receiverContact.setName(bizWaybillOrder.getReceiverName());
+            receiverContact.setMobile(bizWaybillOrder.getReceiverPhone());
+            receiverContact.setFullAddress(bizWaybillOrder.getReceiverProvince() + bizWaybillOrder.getReceiverCity() + bizWaybillOrder.getReceiverCounty() + bizWaybillOrder.getReceiverAddress());
+
             CommonCreateOrderRequest requestDTO = new  CommonCreateOrderRequest();
             requestDTO.setOrderOrigin(1);
-            requestDTO.setCustomerCode("010K****20");
+            requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
+
             CommonProductInfo productInfo = new CommonProductInfo();
-            productInfo.setProductCode("ed-m-0001");
+            productInfo.setProductCode(bizWaybillOrder.getProductCode());
+
             requestDTO.setProductsReq(productInfo);
             requestDTO.setReceiverContact(receiverContact);
             requestDTO.setSenderContact(senderContact);
@@ -56,36 +88,70 @@ public class JDLogisticsService  implements LogisticsService {
             LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
             request.addLopPlugin(lopPlugin);
 
+            log.info("京东开放平台订单预校验接口,请求参数:{}", request);
             EcapV1OrdersPrecheckLopResponse response = client.execute(request);
+            log.info("京东开放平台订单预校验接口,响应结果:{}", response);
+
+            if (response.getCode().equals("0")) {
+                result.put("success", true);
+                result.put("msg", "");
+            } else {
+                result.put("success", false);
+                result.put("msg", "京东开放平台订单预校验!失败原因:" + response.getMsg());
+            }
         } catch (LopException e) {
-            e.printStackTrace();
-        } catch (Exception e) {
-            e.printStackTrace();
+            log.error("京东开放平台订单预校验接口异常:{}", e);
+            throw new ServiceException("京东开放平台订单预校验接口异常");
         }
-        return "";
+        return result;
     }
 
     @Override
-    public String createOrder(LogisticsOrder logisticsOrder) {
-        log.info("调用京东开放平台订单预校验接口");
+    public JSONObject createOrder(BizWaybillOrder bizWaybillOrder) {
+        log.info("京东开放平台下单接口,入参:{}", bizWaybillOrder);
+        JSONObject result = new JSONObject();
         try {
             //设置接口域名(有的对接方案同时支持生产和沙箱环境,有的仅支持生产,具体以对接方案中的【API文档-请求地址】为准),生产域名:https://api.jdl.com 预发环境域名:https://uat-api.jdl.com
             //DefaultDomainApiClient对象全局只需要创建一次
             DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);
 
-            //入参对象(请记得更换为自己要使用的接口入参对象)
+            //入参对象
             EcapV1OrdersCreateLopRequest request = new EcapV1OrdersCreateLopRequest();
 
-            //设置入参(请记得更换为自己要使用的接口入参)
+            //发货人
             com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact senderContact  = new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact();
-            senderContact.setFullAddress("河北省廊坊市广阳区万庄镇中心小学");
+            senderContact.setFullAddress(bizWaybillOrder.getSenderProvince() + bizWaybillOrder.getSenderCity() + bizWaybillOrder.getSenderCounty() + bizWaybillOrder.getSenderAddress());
+
+            //收货人
             com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact receiverContact = new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact();
-            receiverContact.setFullAddress("河北省廊坊市广阳区万庄镇中心小学");
+            receiverContact.setFullAddress(bizWaybillOrder.getReceiverProvince() + bizWaybillOrder.getReceiverCity() + bizWaybillOrder.getReceiverCounty() + bizWaybillOrder.getReceiverAddress());
+
+            //订单信息
             com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonCreateOrderRequest requestDTO = new  com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonCreateOrderRequest();
-            requestDTO.setOrderOrigin(1);
-            requestDTO.setCustomerCode("010K****20");
+            requestDTO.setOrderId(bizWaybillOrder.getWaybillNo());
+            requestDTO.setOrderOrigin(getOrderOrigin(bizWaybillOrder.getProductCode()));
+            requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
+            requestDTO.setSettleType(3);
+            requestDTO.setPickupStartTime(bizWaybillOrder.getPickupTime().getTime());
+            requestDTO.setPickupEndTime(DateUtils.addHours(bizWaybillOrder.getPickupTime(), 1).getTime());
+            requestDTO.setPickupType(1);
+
+            //产品信息
             com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo productInfo = new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo();
-            productInfo.setProductCode("ed-m-0001");
+            productInfo.setProductCode(bizWaybillOrder.getProductCode());
+            productInfo.setAddedProducts(getAddedProducts(requestDTO.getOrderOrigin(), bizWaybillOrder.getAddedService()));
+
+
+            //货物信息
+            List<CommonCargoInfo> cargoes = new ArrayList<>();
+            CommonCargoInfo cargoInfo = new CommonCargoInfo();
+            cargoInfo.setName(bizWaybillOrder.getGoodsName());
+            cargoInfo.setQuantity(bizWaybillOrder.getGoodsQty().intValue());
+            cargoInfo.setWeight(bizWaybillOrder.getGoodsWeight());
+            cargoInfo.setVolume(bizWaybillOrder.getGoodsVolume());
+            cargoes.add(cargoInfo);
+
+            requestDTO.setCargoes(cargoes);
             requestDTO.setProductsReq(productInfo);
             requestDTO.setReceiverContact(receiverContact);
             requestDTO.setSenderContact(senderContact);
@@ -96,12 +162,280 @@ public class JDLogisticsService  implements LogisticsService {
             LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
             request.addLopPlugin(lopPlugin);
 
+            log.info("京东开放平台下单接口,请求参数:{}", request);
             EcapV1OrdersCreateLopResponse response = client.execute(request);
+            log.info("京东开放平台下单接口,响应结果:{}", response);
+
+            if (response.getCode().equals("0")) {
+                result.put("success", true);
+                result.put("msg", "");
+            } else {
+                result.put("success", false);
+                result.put("msg", "京东开放平台下单!失败原因:" + response.getMsg());
+            }
+        } catch (LopException e) {
+            log.error("京东开放平台下单接口异常:{}", e);
+            throw new ServiceException("京东开放平台下单接口异常");
+        }
+        return result;
+    }
+
+    @Override
+    public JSONObject cancelOrder(BizWaybillOrder bizWaybillOrder) {
+        log.info("京东开放平台取消订单接口,入参:{}", bizWaybillOrder);
+        JSONObject result = new JSONObject();
+        try {
+            //设置接口域名(有的对接方案同时支持生产和沙箱环境,有的仅支持生产,具体以对接方案中的【API文档-请求地址】为准),生产域名:https://api.jdl.com 预发环境域名:https://uat-api.jdl.com
+            //DefaultDomainApiClient对象全局只需要创建一次
+            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);
+
+            //入参对象
+            EcapV1OrdersCancelLopRequest request = new EcapV1OrdersCancelLopRequest();
+
+            //取消订单入参对象
+            CommonOrderCancelRequest commonOrderCancelRequest = new CommonOrderCancelRequest();
+            commonOrderCancelRequest.setWaybillCode(bizWaybillOrder.getExternalWaybillNo());
+            commonOrderCancelRequest.setCustomerOrderId(bizWaybillOrder.getWaybillNo());
+            commonOrderCancelRequest.setOrderOrigin(1);
+            commonOrderCancelRequest.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
+            commonOrderCancelRequest.setCancelReason("取消原因");
+            commonOrderCancelRequest.setCancelReasonCode("1");
+            commonOrderCancelRequest.setCancelType(1);
+
+            request.setRequest(commonOrderCancelRequest);
+
+            //设置插件,必须的操作,不同类型的应用入参不同,请看入参注释,公共参数按顺序分别为AppKey、AppSecret、AccessToken
+            //使用开放平台ISV/自研商家应用调用接口
+            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
+            request.addLopPlugin(lopPlugin);
+
+            log.info("京东开放平台取消订单接口,请求参数:{}", request);
+            EcapV1OrdersCancelLopResponse response = client.execute(request);
+            log.info("京东开放平台取消订单接口,响应结果:{}", response);
+
+            if (response.getCode().equals("0")) {
+                result.put("success", true);
+                result.put("msg", "");
+            } else {
+                result.put("success", false);
+                result.put("msg", "京东开放平台取消订单!失败原因:" + response.getMsg());
+            }
+        } catch (LopException e) {
+            log.error("京东开放平台取消订单接口异常:{}", e);
+            throw new ServiceException("京东开放平台取消订单接口异常");
+        }
+        return result;
+    }
+
+    @Override
+    public JSONObject modifyOrder(BizWaybillOrder bizWaybillOrder) {
+        log.info("京东开放平台修改订单接口,入参:{}", bizWaybillOrder);
+        JSONObject result = new JSONObject();
+        try {
+            //设置接口域名(有的对接方案同时支持生产和沙箱环境,有的仅支持生产,具体以对接方案中的【API文档-请求地址】为准),生产域名:https://api.jdl.com 预发环境域名:https://uat-api.jdl.com
+            //DefaultDomainApiClient对象全局只需要创建一次
+            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);
+
+            //入参对象
+            EcapV1OrdersModifyLopRequest request = new EcapV1OrdersModifyLopRequest();
+
+            //发货人
+            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact senderContact  = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact();
+            senderContact.setFullAddress(bizWaybillOrder.getSenderProvince() + bizWaybillOrder.getSenderCity() + bizWaybillOrder.getSenderCounty() + bizWaybillOrder.getSenderAddress());
+
+            //收货人
+            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact receiverContact = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact();
+            receiverContact.setFullAddress(bizWaybillOrder.getReceiverProvince() + bizWaybillOrder.getReceiverCity() + bizWaybillOrder.getReceiverCounty() + bizWaybillOrder.getReceiverAddress());
+
+            //订单信息
+            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonModifyCancelOrderRequest requestDTO = new  com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonModifyCancelOrderRequest();
+            requestDTO.setOrderId(bizWaybillOrder.getWaybillNo());
+            requestDTO.setOrderOrigin(1);
+            requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
+            requestDTO.setSettleType(3);
+            requestDTO.setPickupStartTime(bizWaybillOrder.getPickupTime().getTime());
+            requestDTO.setPickupEndTime(DateUtils.addHours(bizWaybillOrder.getPickupTime(), 1).getTime());
+
+            //产品信息
+            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonProductInfoRequest productInfo = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonProductInfoRequest();
+            productInfo.setProductCode(bizWaybillOrder.getProductCode());
+
+            //货物信息
+            List<com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonCargoInfo> cargoes = new ArrayList<>();
+            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonCargoInfo cargoInfo = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonCargoInfo();
+            cargoInfo.setName(bizWaybillOrder.getGoodsName());
+            cargoInfo.setQuantity(bizWaybillOrder.getGoodsQty().intValue());
+            cargoInfo.setWeight(bizWaybillOrder.getGoodsWeight());
+            cargoInfo.setVolume(bizWaybillOrder.getGoodsVolume());
+            cargoes.add(cargoInfo);
+
+            //扩展信息
+            Map<String, String> extendProps = new HashMap<>();
+            extendProps.put("autoSubscribe", "1");
+            extendProps.put("universalFeePush", "1");
+
+            requestDTO.setExtendProps(extendProps);
+            requestDTO.setCargoes(cargoes);
+            requestDTO.setProductsReq(productInfo);
+            requestDTO.setReceiverContact(receiverContact);
+            requestDTO.setSenderContact(senderContact);
+            request.setRequest(requestDTO);
+
+            //设置插件,必须的操作,不同类型的应用入参不同,请看入参注释,公共参数按顺序分别为AppKey、AppSecret、AccessToken
+            //使用开放平台ISV/自研商家应用调用接口
+            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
+            request.addLopPlugin(lopPlugin);
+
+            log.info("京东开放平台修改订单接口,请求参数:{}", request);
+            EcapV1OrdersModifyLopResponse response = client.execute(request);
+            log.info("京东开放平台修改订单接口,响应结果:{}", response);
+
+            if (response.getCode().equals("0")) {
+                result.put("success", true);
+                result.put("msg", "");
+            } else {
+                result.put("success", false);
+                result.put("msg", "京东开放平台修改订单!失败原因:" + response.getMsg());
+            }
         } catch (LopException e) {
-            e.printStackTrace();
-        } catch (Exception e) {
-            e.printStackTrace();
+            log.error("京东开放平台修改订单接口异常:{}", e);
+            throw new ServiceException("京东开放平台修改订单接口异常");
+        }
+        return result;
+    }
+
+    private Integer getOrderOrigin(String productCode) {
+        int orderOrigin = 1;
+        if (productCode.equals(JDDictConstants.PRODUCT_CODE_ED_M_0001) || productCode.equals(JDDictConstants.PRODUCT_CODE_ED_M_0002)) {
+            orderOrigin = 1;
+        } else if (productCode.equals(JDDictConstants.PRODUCT_CODE_FR_M_0004)) {
+            orderOrigin = 4;
+        }
+        return orderOrigin;
+    }
+
+    // 增值服务配置映射表
+    private static final Map<Integer, Map<String, ProductConfig>> SERVICE_CONFIG_MAP = new HashMap<>();
+    
+    static {
+        // 订单来源为1的配置
+        Map<String, ProductConfig> origin1Config = new HashMap<>();
+        origin1Config.put("isPack", new ProductConfig("ed-a-0002", true));
+        origin1Config.put("guaranteeMoney", new ProductConfig("ed-a-0010", true));
+        origin1Config.put("isReceiptCollect", new ProductConfig("ed-a-0011", false));
+        SERVICE_CONFIG_MAP.put(1, origin1Config);
+        
+        // 订单来源为4的配置
+        Map<String, ProductConfig> origin4Config = new HashMap<>();
+        origin4Config.put("isPack", new ProductConfig("fr-a-0002", true));
+        origin4Config.put("guaranteeMoney", new ProductConfig("fr-a-0007", true));
+        origin4Config.put("isReceiptCollect", new ProductConfig("fr-a-0005", false));
+        SERVICE_CONFIG_MAP.put(4, origin4Config);
+    }
+    
+    /**
+     * 产品配置类
+     */
+    private static class ProductConfig {
+        private final String productCode;
+        private final boolean hasAttrs;
+        
+        public ProductConfig(String productCode, boolean hasAttrs) {
+            this.productCode = productCode;
+            this.hasAttrs = hasAttrs;
+        }
+        
+        public String getProductCode() {
+            return productCode;
+        }
+        
+        public boolean isHasAttrs() {
+            return hasAttrs;
+        }
+    }
+    
+    /**
+     * 封装增值服务参数
+     * @param orderOrigin 订单来源
+     * @param addedService 增值服务JSON字符串
+     * @return 增值服务产品列表
+     */
+    private List<com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo> getAddedProducts(Integer orderOrigin, String addedService) {
+        if (StringUtils.isBlank(addedService)) {
+            return null;
+        }
+
+        JSONObject addedJson = JSON.parseObject(addedService);
+        List<com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo> addedProducts = new ArrayList<>();
+        
+        // 获取当前订单来源的配置
+        Map<String, ProductConfig> configMap = SERVICE_CONFIG_MAP.get(orderOrigin);
+        if (configMap == null) {
+            return addedProducts;
+        }
+        
+        // 遍历配置中的所有增值服务键
+        for (Map.Entry<String, ProductConfig> entry : configMap.entrySet()) {
+            String serviceKey = entry.getKey();
+            ProductConfig config = entry.getValue();
+            
+            // 检查JSON中是否包含该增值服务
+            if (addedJson.containsKey(serviceKey)) {
+                com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo addedProduct = 
+                    createProductInfo(config.getProductCode(), config.isHasAttrs() ? 
+                        addedJson.getString(serviceKey) : null);
+                addedProducts.add(addedProduct);
+            }
+        }
+
+        return addedProducts;
+    }
+    
+    /**
+     * 创建产品信息对象
+     * @param productCode 产品编码
+     * @param attrValue 属性值(可为空)
+     * @return 产品信息对象
+     */
+    private com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo 
+        createProductInfo(String productCode, String attrValue) {
+        com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo addedProduct = 
+            new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo();
+        addedProduct.setProductCode(productCode);
+        
+        // 如果需要设置属性,则添加属性
+        if (attrValue != null) {
+            addedProduct.setProductAttrs(getProductAttrs(productCode, attrValue));
+        }
+        
+        return addedProduct;
+    }
+
+    /**
+     * 获取产品属性
+     * @param productCode 产品编码
+     * @param value 属性值
+     * @return 产品属性映射
+     */
+    private Map<String, String> getProductAttrs(String productCode, String value) {
+        Map<String, String> productAttrs = new HashMap<>();
+        
+        switch (productCode) {
+            case "ed-a-0002":
+            case "fr-a-0002":
+                productAttrs.put("guaranteeMoney", value);
+                break;
+            case "ed-a-0010":
+                productAttrs.put("reReceiveMode", "[\"electronic\"]");
+                productAttrs.put("reReceiveType", "[\"electronicStubForm\"]");
+                break;
+            case "fr-a-0007":
+                productAttrs.put("reReceiveMode", "[\"electronic\"]");
+                break;
+            default:
+                return null;
         }
-        return "";
+        
+        return productAttrs;
     }
 }

+ 245 - 39
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/SFLogisticsService.java

@@ -1,49 +1,129 @@
 package com.ruoyi.logistics.service.impl;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.redis.service.RedisIdGenerator;
 import com.ruoyi.logistics.config.SFExpressConfig;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
 import com.ruoyi.logistics.domain.LogisticsOrder;
 import com.ruoyi.logistics.service.LogisticsService;
+import com.ruoyi.logistics.util.SFExpressHttpUtil;
+import com.ruoyi.system.controller.SysUserController;
 import com.sf.csim.express.service.CallExpressServiceTools;
 import com.sf.csim.express.service.HttpClientUtil;
 import com.sf.csim.express.service.IServiceCodeStandard;
 import com.sf.csim.express.service.code.ExpressServiceCodeEnum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.io.UnsupportedEncodingException;
 import java.util.*;
 
+
+/**
+ * 顺丰物流实现
+ *
+ * @author RuiJing
+ * @date 2026-02-02
+ */
 @Service
 public class SFLogisticsService implements LogisticsService {
+    private static final Logger log = LoggerFactory.getLogger(SFLogisticsService.class);
 
     @Autowired
     private SFExpressConfig sfExpressConfig;
-    @Autowired
-    private RedisIdGenerator redisIdGenerator;
+
+
+    /**
+     * 顺丰物流预下单接口
+     *
+     * @author zxf
+     * @date 2026-02-02
+     */
     @Override
-    public String createOrder(LogisticsOrder logisticsOrder) throws UnsupportedEncodingException {
-        IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER; //下订单
+    public JSONObject precheckOrder(BizWaybillOrder bizWaybillOrder) {
+        SFExpressHttpUtil sfExpressHttpUtil = new SFExpressHttpUtil(sfExpressConfig.getClientCode(), sfExpressConfig.getCheckWord(), sfExpressConfig.getCurrentApiUrl());
+        String serviceCode = "EXP_RECE_PRE_ORDER";
+        /* 物流预下单请求参数*/
+        JSONObject msgData = new JSONObject();
+        //预下单接口已拿到订单id 下单需要用到这个id
+
+        msgData.put("orderId", bizWaybillOrder.getWaybillNo());
+        msgData.put("cargoName", bizWaybillOrder.getGoodsName());
+        msgData.put("monthlyCard", sfExpressConfig.getMonthlyCord());
+        msgData.put("totalWeight", bizWaybillOrder.getGoodsWeight());
+       /* 快递产品类别  目前未定义  先写死
+        1 顺丰特快
+        2 顺丰标快
+        6 顺丰即日*/
+        msgData.put("expressTypeId", 1);
+        //包裹数  未定义  非必填
+        msgData.put("parcelQty", 1);
+        //收寄方地址参数
+        List<Map<String, Object>> contactInfoList = new ArrayList<>();
+        Map<String, Object> Consignor = new HashMap<>();
+        Consignor.put("contactType",1);
+        Consignor.put("mobile", bizWaybillOrder.getSenderPhone());
+        Consignor.put("province", bizWaybillOrder.getSenderProvince());
+        Consignor.put("city", bizWaybillOrder.getSenderCity());
+        Consignor.put("county", bizWaybillOrder.getSenderCounty());
+        Consignor.put("address", bizWaybillOrder.getSenderAddress());
+        contactInfoList.add(Consignor);
+        Map<String, Object> Consignee = new HashMap<>();
+        Consignee.put("contactType", 2);
+        Consignee.put("mobile", bizWaybillOrder.getReceiverPhone());
+        Consignee.put("province", bizWaybillOrder.getReceiverProvince());
+        Consignee.put("city", bizWaybillOrder.getReceiverCity());
+        Consignee.put("county", bizWaybillOrder.getReceiverCounty());
+        Consignee.put("address", bizWaybillOrder.getReceiverAddress());
+        contactInfoList.add(Consignee);
+        msgData.put("contactInfoList",contactInfoList);
+        String result = sfExpressHttpUtil.sendRequest(serviceCode, msgData.toJSONString());
+        JSONObject jsonObject = JSON.parseObject(result).getJSONObject("apiResultData");
+        JSONObject resultInfo = new JSONObject();
+        if (jsonObject != null && jsonObject.containsKey("success") && jsonObject.getBooleanValue("success")) {
+            resultInfo.put("success", true);
+            resultInfo.put("msg", "预下单校验成功!");
+            return resultInfo;
+        } else {
+            resultInfo.put("success", false);
+            resultInfo.put("msg", "预下单校验失败!失败原因:"+jsonObject.get("errorMsg"));
+            return resultInfo;
+        }
+
 
+    }
+    /**
+     * 顺丰物流下单接口
+     *
+     * @author zxf
+     * @date 2026-02-02
+     */
+    @Override
+    public JSONObject createOrder(BizWaybillOrder bizWaybillOrder) {
+        IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_CREATE_ORDER; //下订单
         CallExpressServiceTools tools=CallExpressServiceTools.getInstance();
         Map<String, String> params = new HashMap<String, String>();
         String timeStamp = String.valueOf(System.currentTimeMillis());
         Map<String,Object> orderData= new HashMap<>();
         orderData.put("language","zh_CN");
-        orderData.put("orderId",redisIdGenerator.generateUniqueId("RJSD"));//客户订单号,重复使用订单号时返回第一次下单成功时的运单信息
-        orderData.put("monthlyCard","7551234567");//月结账户
-        orderData.put("parcelQty",3);
+        //预下单 已返回订单id
+        orderData.put("orderId",bizWaybillOrder.getWaybillNo());
+        orderData.put("monthlyCard",sfExpressConfig.getMonthlyCord());//月结账户
+        //包裹数目前字段没有
+        orderData.put("parcelQty",1);
         //商品信息
         List<Map<String,Object>> cargoDetails = new ArrayList<>();
         Map cargo=new HashMap<>();
-        cargo.put("name","笔记本");
-        cargo.put("count",1);
-        cargo.put("unit","个");
-        cargo.put("weight",1.012);
-        cargo.put("amount",4999.189);
+        cargo.put("name",bizWaybillOrder.getGoodsName());
+        cargo.put("count",bizWaybillOrder.getGoodsQty());
+        cargo.put("weight",bizWaybillOrder.getGoodsWeight());
         cargoDetails.add(cargo);
         orderData.put("cargoDetails",cargoDetails);
+
         //增值服务信息 serviceList":[{"name":"INSURE","value":"500"}]
         List<Map<String,Object>> serviceList = new ArrayList<>();
         Map service=new HashMap<>();
@@ -53,48 +133,174 @@ public class SFLogisticsService implements LogisticsService {
         orderData.put("serviceList",serviceList);
         //收寄双方信息
         List<Map<String,Object>> contactInfoList = new ArrayList<>();
-        Map contactInfo1=new HashMap<>();
-        contactInfo1.put("address","河南省洛阳市洛龙区科技园街道和风雅叙");
-        contactInfo1.put("contact","张三");
-        contactInfo1.put("contactType",1);
-        contactInfo1.put("country","CN");
-        contactInfo1.put("postCode","580058");
-        contactInfo1.put("tel","15639072145");
-        contactInfoList.add(contactInfo1);
-        Map contactInfo=new HashMap<>();
-        contactInfo.put("address","河南省郑州市惠济区美景麟起城");
-        contactInfo.put("company","神州");
-        contactInfo.put("contact","小乔");
-        contactInfo.put("contactType",2);
-        contactInfo.put("country","CN");
-        contactInfo.put("tel","15539739074");
-        contactInfoList.add(contactInfo1);
-        contactInfoList.add(contactInfo);
+        Map<String,Object> Consignor= new HashMap<>();
+        Consignor.put("contactType","1");
+        Consignor.put("mobile",bizWaybillOrder.getSenderPhone());
+        Consignor.put("province",bizWaybillOrder.getSenderProvince());
+        Consignor.put("city",bizWaybillOrder.getSenderCity());
+        Consignor.put("county",bizWaybillOrder.getSenderCounty());
+        Consignor.put("address",bizWaybillOrder.getSenderAddress());
+        contactInfoList.add(Consignor);
+        Map<String,Object> Consignee= new HashMap<>();
+        Consignee.put("contactType","2");
+        Consignee.put("mobile",bizWaybillOrder.getReceiverPhone());
+        Consignee.put("province",bizWaybillOrder.getReceiverProvince());
+        Consignee.put("city",bizWaybillOrder.getReceiverCity());
+        Consignee.put("county",bizWaybillOrder.getReceiverCounty());
+        Consignee.put("address",bizWaybillOrder.getReceiverAddress());
+        contactInfoList.add(Consignee);
         orderData.put("contactInfoList",contactInfoList);
+        try {
+        String msgData =tools.packageMsgData(standardService);
+        msgData= JSON.toJSONString(orderData);
+        params.put("partnerID", sfExpressConfig.getClientCode());  // 顾客编码 ,对应丰桥上获取的clientCode
+        params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
+        params.put("serviceCode",standardService.getCode());// 接口服务码
+        params.put("timestamp", timeStamp);
+        params.put("msgData", msgData);
+        params.put("msgDigest", tools.getMsgDigest(msgData, timeStamp, sfExpressConfig.getCheckWord()));
+        String result = HttpClientUtil.post(sfExpressConfig.getCurrentApiUrl(), params);
+            JSONObject jsonObject = JSON.parseObject(result).getJSONObject("apiResultData");
+            JSONObject resultInfo = new JSONObject();
+            if (jsonObject != null && jsonObject.containsKey("success") && jsonObject.getBooleanValue("success")) {
+                resultInfo.put("success", true);
+                resultInfo.put("msg", "下单成功!");
+                return resultInfo;
+            } else {
+                resultInfo.put("success", false);
+                resultInfo.put("msg", "下单失败!失败原因:"+jsonObject.get("errorMsg"));
+                return resultInfo;
+            }
+
+        }catch(Exception e){
+            throw new RuntimeException();
+        }
+
 
+    }
+
+
+    /**
+     * 顺丰物流取消订单接口
+     * 客服描述 订单揽收前 可以进行取消订单或者修改订单信息
+     * @author zxf
+     * @date 2026-02-02
+     */
+    @Override
+    public JSONObject cancelOrder(BizWaybillOrder bizWaybillOrder) {
+        IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_UPDATE_ORDER;
+        CallExpressServiceTools tools=CallExpressServiceTools.getInstance();
+        Map<String, String> params = new HashMap<String, String>();
+        String timeStamp = String.valueOf(System.currentTimeMillis());
+        Map<String,Object> orderData= new HashMap<>();
+        orderData.put("language","zh_CN");
+        orderData.put("orderId",bizWaybillOrder.getWaybillNo());
+        orderData.put("dealType",2);
         String msgData =tools.packageMsgData(standardService);
         msgData= JSON.toJSONString(orderData);
+        try {
         params.put("partnerID", sfExpressConfig.getClientCode());  // 顾客编码 ,对应丰桥上获取的clientCode
         params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
         params.put("serviceCode",standardService.getCode());// 接口服务码
         params.put("timestamp", timeStamp);
         params.put("msgData", msgData);
         params.put("msgDigest", tools.getMsgDigest(msgData,timeStamp,sfExpressConfig.getCheckWord()));
+        String result = HttpClientUtil.post(sfExpressConfig.getCurrentApiUrl(), params);
+        JSONObject jsonObject = JSON.parseObject(result).getJSONObject("apiResultData");
+        JSONObject resultInfo = new JSONObject();
+            if (jsonObject != null && jsonObject.containsKey("success") && jsonObject.getBooleanValue("success")) {
 
-        // System.out.println(params.get("requestID"));
-        long startTime = System.currentTimeMillis();
+                resultInfo.put("success", true);
+                resultInfo.put("data", bizWaybillOrder);
+                resultInfo.put("msg", "订单取消成功!");
+                return resultInfo;
+            } else {
+                resultInfo.put("success", false);
+                resultInfo.put("msg", "订单取消失败!失败原因:"+jsonObject.get("errorMsg"));
+                return resultInfo;
+            }
+
+        }
+        catch(Exception e){
+            throw new RuntimeException();
+        }
+    }
+    /**
+     * 顺丰物流修改订单接口
+     *
+     * @author zxf
+     * @date 2026-02-02
+     */
+    @Override
+    public JSONObject modifyOrder(BizWaybillOrder bizWaybillOrder) {
+        IServiceCodeStandard standardService = ExpressServiceCodeEnum.EXP_RECE_UPDATE_ORDER;
+        CallExpressServiceTools tools=CallExpressServiceTools.getInstance();
+        Map<String, String> params = new HashMap<String, String>();
+        String timeStamp = String.valueOf(System.currentTimeMillis());
+        Map<String,Object> orderData= new HashMap<>();
+        orderData.put("language","zh_CN");
+        orderData.put("orderId",bizWaybillOrder.getWaybillNo());
+        orderData.put("dealType",1);
 
 
 
-        //  System.out.println("====调用请求:" + params.get("msgData"));
-        System.out.println("====调用实际请求:" + params);
-        String result = HttpClientUtil.post(sfExpressConfig.getCurrentApiUrl(), params);
 
-        System.out.println("====调用丰桥的接口服务代码:" + String.valueOf(standardService.getCode()) + " 接口耗时:"+ String.valueOf(System.currentTimeMillis()-startTime)+"====");
-        System.out.println("===调用地址 ==="+sfExpressConfig.getCurrentApiUrl());
-        System.out.println("===顾客编码 ==="+sfExpressConfig.getClientCode());
-        System.out.println("===返回结果:" +result);
 
-        return result;
+        String msgData =tools.packageMsgData(standardService);
+        msgData= JSON.toJSONString(orderData);
+        try {
+            params.put("partnerID", sfExpressConfig.getClientCode());  // 顾客编码 ,对应丰桥上获取的clientCode
+            params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
+            params.put("serviceCode",standardService.getCode());// 接口服务码
+            params.put("timestamp", timeStamp);
+            params.put("msgData", msgData);
+            params.put("msgDigest", tools.getMsgDigest(msgData,timeStamp,sfExpressConfig.getCheckWord()));
+            String result = HttpClientUtil.post(sfExpressConfig.getCurrentApiUrl(), params);
+            JSONObject jsonObject = JSON.parseObject(result).getJSONObject("apiResultData");
+            JSONObject resultInfo = new JSONObject();
+            if (jsonObject != null && jsonObject.containsKey("success") && jsonObject.getBooleanValue("success")) {
+
+                resultInfo.put("success", true);
+                resultInfo.put("data", bizWaybillOrder);
+                resultInfo.put("msg", "订单取消成功!");
+                return resultInfo;
+            } else {
+                resultInfo.put("success", false);
+                resultInfo.put("msg", "订单取消失败!失败原因:"+jsonObject.get("errorMsg"));
+                return resultInfo;
+            }
+
+        }
+        catch(Exception e){
+            throw new RuntimeException();
+        }
     }
+
+   /* @Override
+    public AjaxResult monthlyCode(LogisticsOrder logisticsOrder) {
+
+        SFExpressHttpUtil sfExpressHttpUtil= new SFExpressHttpUtil(sfExpressConfig.getClientCode(),sfExpressConfig.getCheckWord(),sfExpressConfig.getCurrentApiUrl());
+        String serviceCode="ACSP_CREATE_MONTHLY_CODE";
+        JSONObject msgData = new JSONObject();
+        msgData.put("monthCard",sfExpressConfig.getMonthlyCord());
+        msgData.put("needDynamicCode",true);
+        msgData.put("remak","月结码第一次测试");
+
+        String result= sfExpressHttpUtil.sendRequest(serviceCode,msgData.toJSONString());
+        return AjaxResult.success(result);
+    }
+
+    @Override
+    public AjaxResult queryOrder(LogisticsOrder logisticsOrder) {
+
+        SFExpressHttpUtil sfExpressHttpUtil= new SFExpressHttpUtil(sfExpressConfig.getClientCode(),sfExpressConfig.getCheckWord(),sfExpressConfig.getCurrentApiUrl());
+        String serviceCode="EXP_RECE_QUERY_SFWAYBILL";
+        JSONObject msgData = new JSONObject();
+        msgData.put("trackingType","1");
+        msgData.put("trackingNum","RJSD20260123000001");
+
+
+        String result= sfExpressHttpUtil.sendRequest(serviceCode,msgData.toJSONString());
+        return AjaxResult.success(result);
+    }*/
 }

+ 35 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/Base64Util.java

@@ -0,0 +1,35 @@
+package com.ruoyi.logistics.util;
+
+import java.io.UnsupportedEncodingException;
+import org.apache.commons.codec.binary.Base64;
+public class Base64Util {
+    private static final String ENCODING = "UTF-8";
+    public static String encode(String input) {
+        try {
+            input = new String(Base64.encodeBase64(input.getBytes(ENCODING)), ENCODING);
+        } catch (UnsupportedEncodingException e) {
+            input = "";
+        }
+        return input;
+    }
+
+    public static String encode(byte[] input) {
+        String ouput = "";
+        try {
+            ouput = new String(Base64.encodeBase64(input), ENCODING);
+        } catch (UnsupportedEncodingException e) {
+            ouput = "";
+        }
+        return ouput;
+    }
+
+    public static String decode(String input) {
+        String ouput = "";
+        try {
+            byte[] decodeBase64 = Base64.decodeBase64(input.getBytes(ENCODING));
+            ouput = new String(decodeBase64, ENCODING);
+        } catch (UnsupportedEncodingException e) {
+        }
+        return ouput;
+    }
+}

+ 36 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/MD5Util.java

@@ -0,0 +1,36 @@
+package com.ruoyi.logistics.util;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+public class MD5Util {
+    public static final String MD5 = "MD5";
+    public static final String ENCODING = "UTF-8";
+    public static String getMd5(String plainText) {
+        try {
+            MessageDigest md = MessageDigest.getInstance(MD5);
+            md.update(plainText.getBytes(ENCODING));
+            byte b[] = md.digest();
+            int i;
+            StringBuffer buf = new StringBuffer("");
+            for (int offset = 0; offset < b.length; offset++) {
+                i = b[offset];
+                if (i < 0)
+                    i += 256;
+                if (i < 16)
+                    buf.append("0");
+                buf.append(Integer.toHexString(i));
+            }
+            // 32位加密
+            return buf.toString();
+            // 16位的加密
+            // return buf.toString().substring(8, 24);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+            return null;
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+}

+ 126 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/SFExpressHttpUtil.java

@@ -0,0 +1,126 @@
+package com.ruoyi.logistics.util;
+import com.ruoyi.common.core.utils.uuid.UUID;
+import com.ruoyi.logistics.config.SFExpressConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.*;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.sf.csim.express.service.CallExpressServiceTools.getMsgDigest;
+
+public class SFExpressHttpUtil {
+    private String partnerID;
+    private String checkWord;
+    private String url;
+    public SFExpressHttpUtil(String partnerID, String checkWord,String url) {
+        this.partnerID = partnerID;
+        this.checkWord = checkWord;
+        this.url = url;
+
+    }
+    /**
+     * 生成MD5数字签名
+     */
+    public String generateMsgDigest(String msgData) {
+        try {
+            String timeStamp = String.valueOf(System.currentTimeMillis());
+          /*  String signStr = msgData + checkWord;
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            byte[] digest = md.digest(signStr.getBytes(StandardCharsets.UTF_8));
+            String md5Str = bytesToHex(digest);
+            return Base64.getEncoder().encodeToString(md5Str.getBytes(StandardCharsets.UTF_8));
+            */
+            return  getMsgDigest(msgData,timeStamp,checkWord);
+        } catch (Exception e) {
+            throw new RuntimeException("生成签名失败", e);
+        }
+    }
+/*
+
+    private String bytesToHex(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            sb.append(String.format("%02x", b));
+        }
+        return sb.toString();
+    }*/
+
+    /**
+     * 发送API请求
+     */
+    public String sendRequest(String serviceCode, String msgData) {
+        return sendRequest(serviceCode, msgData, null);
+    }
+
+    public String sendRequest(String serviceCode, String msgData, String requestId) {
+        try {
+            String requestID = requestId != null ? requestId : UUID.randomUUID().toString();
+            long timestamp = System.currentTimeMillis();
+            String msgDigest = generateMsgDigest(msgData);
+            Map<String, String> params = new HashMap<>();
+            params.put("partnerID", partnerID);
+            params.put("requestID", requestID);
+            params.put("serviceCode", serviceCode);
+            params.put("timestamp", String.valueOf(timestamp));
+            params.put("msgDigest", msgDigest);
+            params.put("msgData", msgData);
+            return doPost(url, params);
+        } catch (Exception e) {
+            throw new RuntimeException("调用顺丰API失败", e);
+        }
+    }
+
+    private String doPost(String url, Map<String, String> params) throws IOException {
+        HttpURLConnection connection = null;
+        try {
+            URL apiUrl = new URL(url);
+            connection = (HttpURLConnection) apiUrl.openConnection();
+            connection.setRequestMethod("POST");
+            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+            connection.setRequestProperty("Charset", "UTF-8");
+            connection.setConnectTimeout(30000);
+            connection.setReadTimeout(30000);
+            connection.setDoOutput(true);
+            connection.setDoInput(true);
+            StringBuilder postData = new StringBuilder();
+            for (Map.Entry<String, String> param : params.entrySet()) {
+                if (postData.length() != 0) postData.append('&');
+                postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
+                postData.append('=');
+                postData.append(URLEncoder.encode(param.getValue(), "UTF-8"));
+            }
+            try (OutputStream os = connection.getOutputStream()) {
+                byte[] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
+                os.write(postDataBytes);
+                os.flush();
+            }
+            int responseCode = connection.getResponseCode();
+            if (responseCode == HttpURLConnection.HTTP_OK) {
+                try (BufferedReader in = new BufferedReader(
+                        new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
+                    StringBuilder response = new StringBuilder();
+                    String line;
+                    while ((line = in.readLine()) != null) {
+                        response.append(line);
+                    }
+                    return response.toString();
+                }
+            } else {
+                throw new IOException("HTTP请求失败,状态码: " + responseCode);
+            }
+
+        } finally {
+            if (connection != null) {
+                connection.disconnect();
+            }
+        }
+    }
+
+}

+ 110 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/SignUtil.java

@@ -0,0 +1,110 @@
+/*
+package com.ruoyi.logistics.util;
+
+import java.util.Map;
+import java.util.TreeMap;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+*/
+/**
+ * 签名工具
+ *//*
+
+public class SignUtil {
+
+    public static final String SIGN_TYPE_0 = "0";//HmacSHA256
+    public static final String SIGN_TYPE_1 = "1";//MD5
+    public static final String HMAC_SHA256 = "HmacSHA256";
+    public static final String ENCODING = "UTF-8";
+    public static final String LF = "\n";
+    public static final String SPE1 = ",";
+    public static final String SPE2 = ":";
+    public static final String SPE3 = "&";
+    public static final String SPE4 = "=";
+    public static final String SPE5 = "?";
+
+    public static String sign(String signType, String appsecret, Map<String, String> querys) {
+        String signature = "";
+        try {
+            signType = StringUtils.validateStr(signType, SIGN_TYPE_0);//默认 HmacSHA256
+            if(SIGN_TYPE_0.equals(signType)){
+                Mac hmacSha256 = Mac.getInstance(HMAC_SHA256);
+                byte[] keyBytes = appsecret.getBytes(ENCODING);
+                hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, HMAC_SHA256));
+                signature = new String(Base64.encodeBase64(hmacSha256.doFinal(buildResource(querys).getBytes(ENCODING))),
+                        ENCODING);
+            }
+            if(SIGN_TYPE_1.equals(signType)){
+                querys.put("appsecret", appsecret);
+                signature = MD5Util.getMd5(buildResource2(querys)).toUpperCase();
+                querys.remove("appsecret");
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return signature;
+    }
+
+    private static String buildResource(Map<String, String> querys) {
+        StringBuilder sb = new StringBuilder();
+        Map<String, String> sortMap = new TreeMap<String, String>();
+        if (null != querys) {
+            for (Map.Entry<String, String> query : querys.entrySet()) {
+                if (!StringUtils.isBlank(query.getKey())) {
+                    sortMap.put(query.getKey(), query.getValue());
+                }
+            }
+        }
+
+        StringBuilder sbParam = new StringBuilder();
+        for (Map.Entry<String, String> item : sortMap.entrySet()) {
+            if (!StringUtils.isBlank(item.getKey())) {
+                if (0 < sbParam.length()) {
+                    sbParam.append(SPE3);
+                }
+                sbParam.append(item.getKey());
+                if (!StringUtils.isBlank(item.getValue())) {
+                    sbParam.append(SPE4).append(item.getValue());
+                }
+            }
+        }
+        if (0 < sbParam.length()) {
+            sb.append(SPE5);
+            sb.append(sbParam);
+        }
+        System.out.println(">>>>>>>>>>>>>>>>>>>>");
+        System.out.println(sb.toString());
+        System.out.println(">>>>>>>>>>>>>>>>>>>>");
+        return sb.toString();
+    }
+    private static String buildResource2(Map<String, String> querys) {
+        StringBuilder sb = new StringBuilder();
+        Map<String, String> sortMap = new TreeMap<String, String>();
+        if (null != querys) {
+            for (Map.Entry<String, String> query : querys.entrySet()) {
+                if (!StringUtils.isBlank(query.getKey())) {
+                    sortMap.put(query.getKey(), query.getValue());
+                }
+            }
+        }
+
+        StringBuilder sbParam = new StringBuilder();
+        for (Map.Entry<String, String> item : sortMap.entrySet()) {
+            if (!StringUtils.isBlank(item.getKey())) {
+                if (!StringUtils.isBlank(item.getValue())) {
+                    sbParam.append(item.getValue());
+                }
+            }
+        }
+        if (0 < sbParam.length()) {
+            sb.append(sbParam);
+        }
+        System.out.println(">>>>>>>>>>>>>>>>>>>>");
+        System.out.println(sb.toString());
+        System.out.println(">>>>>>>>>>>>>>>>>>>>");
+        return sb.toString();
+    }
+}
+*/

+ 1 - 31
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/controller/SysUserController.java

@@ -13,6 +13,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.common.core.utils.SpringUtils;
 import com.ruoyi.common.redis.service.RedisIdGenerator;
 import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
 import com.ruoyi.logistics.domain.LogisticsOrder;
 import com.ruoyi.logistics.service.LogisticsOrderService;
 import org.apache.commons.lang3.ArrayUtils;
@@ -382,35 +383,4 @@ public class SysUserController extends BaseController
         return success(deptService.selectDeptTreeList(dept));
     }
 
-
-    private static final Logger log = LoggerFactory.getLogger(SysUserController.class);
-
-
-        @Autowired
-        private RedisIdGenerator redisIdGenerator;
-         @Autowired
-         private LogisticsOrderService logisticsOrderService;
-    @PostMapping("/test")
-    public AjaxResult test(@RequestBody JSONObject json) throws UnsupportedEncodingException {
-
-        LogisticsOrder logisticsOrder= new LogisticsOrder();
-        logisticsOrder.setOrderType("SF");
-
-        System.out.println(logisticsOrderService.createOrder(logisticsOrder));
-       // String userId = redisIdGenerator.generateUniqueId("RJSD");
-        //String userI = SpringUtils.getBean(RedisIdGenerator.class).generateUniqueId("RJSD");
-
-       // System.out.println("生成订单ID: " + userId);
-       // log.info("生成订单ID: " + userId);
-        log.info("物流状态回调接口----状态"+json.get("orderState").toString());
-        return AjaxResult.success(json);
-    }
-
-
-    @PostMapping("/test1")
-    public AjaxResult test( @RequestParam Map<String,Object> content)
-    {
-        log.info("物流收费单据回调接口----"+content.get("content"));
-        return AjaxResult.success(content.get("content"));
-    }
 }

+ 8 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java

@@ -124,4 +124,12 @@ public interface SysUserMapper
      * @return 结果
      */
     public SysUser checkEmailUnique(String email);
+
+    /**
+     * 通过微信openId查询用户
+     *
+     * @param userName 用户名
+     * @return 用户对象信息
+     */
+    public SysUser selectUserByOpenId(@Param("userName") String userName, @Param("openId") String openId);
 }

+ 10 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/ISysUserService.java

@@ -203,4 +203,14 @@ public interface ISysUserService
      * @return 结果
      */
     public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
+
+
+    /**
+     * 通过用户名和OpenId查询用户
+     *
+     * @param userName 用户名
+     * @param openId 用户名
+     * @return 用户对象信息
+     */
+    public SysUser selectUserByOpenId( SysUser sysUser);
 }

+ 4 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java

@@ -548,4 +548,8 @@ public class SysUserServiceImpl implements ISysUserService
         return successMsg.toString();
     }
 
+    @Override
+    public SysUser selectUserByOpenId(SysUser sysUser) {
+        return userMapper.selectUserByOpenId(sysUser.getUserName(), sysUser.getOpenId());
+    }
 }

+ 4 - 0
jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizAddressBookMapper.xml

@@ -122,4 +122,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{addressId}
         </foreach>
     </delete>
+
+    <update id="updateBizAddressBookDefault" parameterType="Long">
+        update biz_address_book set default_flag = 0 where usre_id = #{userId} and default_flag = 1
+    </update>
 </mapper>

+ 16 - 16
jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizInancialFeeItemsMapper.xml

@@ -2,9 +2,9 @@
 <!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ruoyi.logistics.mapper.BizInancialFeeItemsMapper">
+<mapper namespace="com.ruoyi.logistics.mapper.BizFinancialFeeItemsMapper">
     
-    <resultMap type="com.ruoyi.logistics.domain.BizInancialFeeItems" id="BizInancialFeeItemsResult">
+    <resultMap type="com.ruoyi.logistics.domain.BizFinancialFeeItems" id="BizFinancialFeeItemsResult">
         <result property="feeItemId"    column="fee_item_id"    />
         <result property="feeItemCode"    column="fee_item_code"    />
         <result property="feeItemName"    column="fee_item_name"    />
@@ -21,12 +21,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="updateBy"    column="update_by"    />
     </resultMap>
 
-    <sql id="selectBizInancialFeeItemsVo">
-        select fee_item_id, fee_item_code, fee_item_name, fee_item_category, ext_fee_code, ext_fee_name, create_time, update_time, remark, dept_id, user_id, del_flag, create_by, update_by from biz_inancial_fee_items
+    <sql id="selectBizFinancialFeeItemsVo">
+        select fee_item_id, fee_item_code, fee_item_name, fee_item_category, ext_fee_code, ext_fee_name, create_time, update_time, remark, dept_id, user_id, del_flag, create_by, update_by from biz_financial_fee_items
     </sql>
 
-    <select id="selectBizInancialFeeItemsList" parameterType="com.ruoyi.logistics.domain.BizInancialFeeItems" resultMap="BizInancialFeeItemsResult">
-        <include refid="selectBizInancialFeeItemsVo"/>
+    <select id="selectBizFinancialFeeItemsList" parameterType="com.ruoyi.logistics.domain.BizFinancialFeeItems" resultMap="BizFinancialFeeItemsResult">
+        <include refid="selectBizFinancialFeeItemsVo"/>
         <where>  
             <if test="feeItemCode != null  and feeItemCode != ''"> and fee_item_code = #{feeItemCode}</if>
             <if test="feeItemName != null  and feeItemName != ''"> and fee_item_name like concat('%', #{feeItemName}, '%')</if>
@@ -38,13 +38,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
     </select>
     
-    <select id="selectBizInancialFeeItemsByFeeItemId" parameterType="Long" resultMap="BizInancialFeeItemsResult">
-        <include refid="selectBizInancialFeeItemsVo"/>
+    <select id="selectBizFinancialFeeItemsByFeeItemId" parameterType="Long" resultMap="BizFinancialFeeItemsResult">
+        <include refid="selectBizFinancialFeeItemsVo"/>
         where fee_item_id = #{feeItemId}
     </select>
 
-    <insert id="insertBizInancialFeeItems" parameterType="com.ruoyi.logistics.domain.BizInancialFeeItems" useGeneratedKeys="true" keyProperty="feeItemId">
-        insert into biz_inancial_fee_items
+    <insert id="insertBizFinancialFeeItems" parameterType="com.ruoyi.logistics.domain.BizFinancialFeeItems" useGeneratedKeys="true" keyProperty="feeItemId">
+        insert into biz_financial_fee_items
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="feeItemCode != null">fee_item_code,</if>
             <if test="feeItemName != null">fee_item_name,</if>
@@ -77,8 +77,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          </trim>
     </insert>
 
-    <update id="updateBizInancialFeeItems" parameterType="com.ruoyi.logistics.domain.BizInancialFeeItems">
-        update biz_inancial_fee_items
+    <update id="updateBizFinancialFeeItems" parameterType="com.ruoyi.logistics.domain.BizFinancialFeeItems">
+        update biz_financial_fee_items
         <trim prefix="SET" suffixOverrides=",">
             <if test="feeItemCode != null">fee_item_code = #{feeItemCode},</if>
             <if test="feeItemName != null">fee_item_name = #{feeItemName},</if>
@@ -97,12 +97,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where fee_item_id = #{feeItemId}
     </update>
 
-    <delete id="deleteBizInancialFeeItemsByFeeItemId" parameterType="Long">
-        delete from biz_inancial_fee_items where fee_item_id = #{feeItemId}
+    <delete id="deleteBizFinancialFeeItemsByFeeItemId" parameterType="Long">
+        delete from biz_financial_fee_items where fee_item_id = #{feeItemId}
     </delete>
 
-    <delete id="deleteBizInancialFeeItemsByFeeItemIds" parameterType="String">
-        delete from biz_inancial_fee_items where fee_item_id in 
+    <delete id="deleteBizFinancialFeeItemsByFeeItemIds" parameterType="String">
+        delete from biz_financial_fee_items where fee_item_id in 
         <foreach item="feeItemId" collection="array" open="(" separator="," close=")">
             #{feeItemId}
         </foreach>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 40 - 1
jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizWaybillOrderMapper.xml


+ 5 - 1
jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -219,5 +219,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  			#{userId}
         </foreach> 
  	</delete>
-	
+
+    <select id="selectUserByOpenId" parameterType="String" resultMap="SysUserResult">
+        <include refid="selectUserVo"/>
+        where u.user_name = #{userName} and u.open_id = #{openId} and u.del_flag = '0'
+    </select>
 </mapper> 

+ 1 - 1
jd-logistics-ui-v3/.env.development

@@ -7,4 +7,4 @@ VITE_APP_ENV = 'development'
 # 瑞鲸速达平台/开发环境
 VITE_APP_BASE_API = '/dev-api'
 
-VITE_APP_API_BASE_URL = 'http://192.168.100.246:8080'
+VITE_APP_API_BASE_URL = 'http://localhost:8080'

+ 0 - 57
jd-logistics-ui-v3/src/views/logistics/city/index.vue

@@ -1,14 +1,6 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="城市id" prop="cityId">
-        <el-input
-          v-model="queryParams.cityId"
-          placeholder="请输入城市id"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
       <el-form-item label="省市级别" prop="level">
         <el-input
           v-model="queryParams.level"
@@ -17,22 +9,6 @@
           @keyup.enter="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="父级id" prop="parentId">
-        <el-input
-          v-model="queryParams.parentId"
-          placeholder="请输入父级id"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="区号" prop="areaCode">
-        <el-input
-          v-model="queryParams.areaCode"
-          placeholder="请输入区号"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
       <el-form-item label="名称" prop="name">
         <el-input
           v-model="queryParams.name"
@@ -41,38 +17,6 @@
           @keyup.enter="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="合并名称" prop="mergerName">
-        <el-input
-          v-model="queryParams.mergerName"
-          placeholder="请输入合并名称"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="经度" prop="lng">
-        <el-input
-          v-model="queryParams.lng"
-          placeholder="请输入经度"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="纬度" prop="lat">
-        <el-input
-          v-model="queryParams.lat"
-          placeholder="请输入纬度"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
-      <el-form-item label="是否展示" prop="isShow">
-        <el-input
-          v-model="queryParams.isShow"
-          placeholder="请输入是否展示"
-          clearable
-          @keyup.enter="handleQuery"
-        />
-      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
         <el-button icon="Refresh" @click="resetQuery">重置</el-button>
@@ -123,7 +67,6 @@
 
     <el-table v-loading="loading" :data="cityList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="id" align="center" prop="id" />
       <el-table-column label="城市id" align="center" prop="cityId" />
       <el-table-column label="省市级别" align="center" prop="level" />
       <el-table-column label="父级id" align="center" prop="parentId" />