Przeglądaj źródła

feat: 月结二维码相关逻辑;

hanchaolong 11 godzin temu
rodzic
commit
fb928c004a
19 zmienionych plików z 1131 dodań i 26 usunięć
  1. 39 10
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/front/controller/MonthQRCodeController.java
  2. 21 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/front/controller/WxMiniController.java
  3. 5 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/constant/RedisCacheConstants.java
  4. 105 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/BizMonthQrcodeRecordController.java
  5. 116 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/BizMonthQrcodeRecord.java
  6. 17 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/dto/MonthQRCodeDTO.java
  7. 61 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizMonthQrcodeRecordMapper.java
  8. 39 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/response/CommonOrderInfoResponse.java
  9. 73 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/response/Contact.java
  10. 61 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IBizMonthQrcodeRecordService.java
  11. 12 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/IMonthQRCodeTaskService.java
  12. 71 5
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/LogisticsOrderService.java
  13. 5 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/LogisticsService.java
  14. 96 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizMonthQrcodeRecordServiceImpl.java
  15. 65 11
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/JDLogisticsService.java
  16. 179 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/MonthQRCodeTaskServiceImpl.java
  17. 5 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/SFLogisticsService.java
  18. 69 0
      jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/QRCodeUtils.java
  19. 92 0
      jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizMonthQrcodeRecordMapper.xml

+ 39 - 10
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/front/controller/MonthQRCodeController.java

@@ -1,13 +1,19 @@
 package com.ruoyi.front.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderByMonthSettleQRV1.CommonMonthSettleQRQueryResponse;
+import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.web.controller.BaseController;
 import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.security.annotation.InnerAuth;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
+import com.ruoyi.logistics.response.CommonOrderInfoResponse;
+import com.ruoyi.logistics.service.IMonthQRCodeTaskService;
 import com.ruoyi.logistics.service.LogisticsOrderService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 /**
  * WX-月结二维码生成
@@ -16,18 +22,41 @@ import org.springframework.web.bind.annotation.RestController;
  * @date 2026-02-04
  */
 @RestController
-@RequestMapping("/front/qrcode")
-public class MonthQRCodeController {
+@RequestMapping("/callback/qrcode")
+public class MonthQRCodeController extends BaseController {
 
     @Autowired
     private LogisticsOrderService logisticsOrderService;
 
+    @Autowired
+    private IMonthQRCodeTaskService monthQRCodeService;
+
     @RequestMapping
-    public AjaxResult qrcode(@RequestParam("orderType") Integer orderType) {
-        JSONObject jsonObject = logisticsOrderService.getQRCode(orderType);
-        if(!jsonObject.getBooleanValue("success")){
-            throw new ServiceException("获取二维码失败! 原因:"+jsonObject.getString("msg"));
+    public AjaxResult qrcode(@RequestParam("source") Integer source, @RequestParam("waybillCode") String waybillCode) {
+        try{
+//            JSONObject jsonObject = logisticsOrderService.getQRCode(source);
+//            JSONObject jsonObject = logisticsOrderService.queryOrderDetailByWaybillCode(source, waybillCode);
+            JSONObject jsonObject = logisticsOrderService.queryOrderByQRCode(source, waybillCode);
+
+
+            CommonMonthSettleQRQueryResponse response = (CommonMonthSettleQRQueryResponse) jsonObject.get("msg");
+            // 返回完整的二维码信息,包括图片数据
+            return AjaxResult.success(response);
+        } catch (ServiceException e) {
+            return AjaxResult.error("获取二维码失败! 原因:"+e.getMessage());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @InnerAuth
+    @PostMapping("/consume")
+    public R<String> consume() {
+        try {
+            monthQRCodeService.consumeQRCode();
+            return R.ok();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
         }
-        return AjaxResult.success(jsonObject.getString("msg"));
     }
 }

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

@@ -2,7 +2,9 @@ package com.ruoyi.front.controller;
 
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.security.annotation.InnerAuth;
+import com.ruoyi.common.security.utils.SecurityUtils;
 import com.ruoyi.front.service.IWxService;
 import com.ruoyi.system.api.domain.SysUser;
 import com.ruoyi.system.api.model.LoginUser;
@@ -14,6 +16,9 @@ import org.springframework.web.bind.annotation.*;
 
 import java.util.Set;
 
+/**
+ * WX-用户信息管理
+ */
 @RestController
 @RequestMapping("/front/wxmini")
 public class WxMiniController {
@@ -72,4 +77,20 @@ public class WxMiniController {
         sysUserVo.setPermissions(permissions);
         return R.ok(sysUserVo);
     }
+
+
+    /**
+     * 获取用户信息
+     *
+     * @return 用户信息
+     */
+    @GetMapping("getInfo")
+    public AjaxResult getInfo()
+    {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        SysUser user = loginUser.getSysUser();
+        AjaxResult ajax = AjaxResult.success();
+        ajax.put("user", user);
+        return ajax;
+    }
 }

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

@@ -12,4 +12,9 @@ public class RedisCacheConstants {
      * 费用类型缓存KEY
      */
     public static final String FINANCIAL_FEE_ITEM_CACHE_KEY = "financial_fee_item_cache";
+
+    /**
+     * 月结二维码缓存KEY
+     */
+    public static final String MONTH_QRCODE_CACHE_KEY = "month:qrcode:cache:";
 }

+ 105 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/BizMonthQrcodeRecordController.java

@@ -0,0 +1,105 @@
+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;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+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.BizMonthQrcodeRecord;
+import com.ruoyi.logistics.service.IBizMonthQrcodeRecordService;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.core.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.web.page.TableDataInfo;
+
+/**
+ * 月结二维码使用记录Controller
+ * 
+ * @author RuiJing
+ * @date 2026-02-12
+ */
+@RestController
+@RequestMapping("/record")
+public class BizMonthQrcodeRecordController extends BaseController
+{
+    @Autowired
+    private IBizMonthQrcodeRecordService bizMonthQrcodeRecordService;
+
+    /**
+     * 查询月结二维码使用记录列表
+     */
+    @RequiresPermissions("system:record:list")
+    @GetMapping("/list")
+    public TableDataInfo list(BizMonthQrcodeRecord bizMonthQrcodeRecord)
+    {
+        startPage();
+        List<BizMonthQrcodeRecord> list = bizMonthQrcodeRecordService.selectBizMonthQrcodeRecordList(bizMonthQrcodeRecord);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出月结二维码使用记录列表
+     */
+    @RequiresPermissions("system:record:export")
+    @Log(title = "月结二维码使用记录", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BizMonthQrcodeRecord bizMonthQrcodeRecord)
+    {
+        List<BizMonthQrcodeRecord> list = bizMonthQrcodeRecordService.selectBizMonthQrcodeRecordList(bizMonthQrcodeRecord);
+        ExcelUtil<BizMonthQrcodeRecord> util = new ExcelUtil<BizMonthQrcodeRecord>(BizMonthQrcodeRecord.class);
+        util.exportExcel(response, list, "月结二维码使用记录数据");
+    }
+
+    /**
+     * 获取月结二维码使用记录详细信息
+     */
+    @RequiresPermissions("system:record:query")
+    @GetMapping(value = "/{qrcodeId}")
+    public AjaxResult getInfo(@PathVariable("qrcodeId") Long qrcodeId)
+    {
+        return success(bizMonthQrcodeRecordService.selectBizMonthQrcodeRecordByQrcodeId(qrcodeId));
+    }
+
+    /**
+     * 新增月结二维码使用记录
+     */
+    @RequiresPermissions("system:record:add")
+    @Log(title = "月结二维码使用记录", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BizMonthQrcodeRecord bizMonthQrcodeRecord)
+    {
+        return toAjax(bizMonthQrcodeRecordService.insertBizMonthQrcodeRecord(bizMonthQrcodeRecord));
+    }
+
+    /**
+     * 修改月结二维码使用记录
+     */
+    @RequiresPermissions("system:record:edit")
+    @Log(title = "月结二维码使用记录", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BizMonthQrcodeRecord bizMonthQrcodeRecord)
+    {
+        return toAjax(bizMonthQrcodeRecordService.updateBizMonthQrcodeRecord(bizMonthQrcodeRecord));
+    }
+
+    /**
+     * 删除月结二维码使用记录
+     */
+    @RequiresPermissions("system:record:remove")
+    @Log(title = "月结二维码使用记录", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{qrcodeIds}")
+    public AjaxResult remove(@PathVariable Long[] qrcodeIds)
+    {
+        return toAjax(bizMonthQrcodeRecordService.deleteBizMonthQrcodeRecordByQrcodeIds(qrcodeIds));
+    }
+}

+ 116 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/BizMonthQrcodeRecord.java

@@ -0,0 +1,116 @@
+package com.ruoyi.logistics.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.core.annotation.Excel;
+import com.ruoyi.common.core.web.domain.BaseEntity;
+
+/**
+ * 月结二维码使用记录对象 biz_month_qrcode_record
+ * 
+ * @author RuiJing
+ * @date 2026-02-12
+ */
+public class BizMonthQrcodeRecord extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 二维码id */
+    private Long qrcodeId;
+
+    /** 二维码内容 */
+    @Excel(name = "二维码内容")
+    private String qrcodeContent;
+
+    /** 用户id */
+    @Excel(name = "用户id")
+    private Long userId;
+
+    /** 供应商id */
+    @Excel(name = "供应商id")
+    private Long deptId;
+
+    /** 1.JD 2.SF */
+    @Excel(name = "1.JD 2.SF")
+    private Integer source;
+
+    /** 默认0 0未核销 1已核销 */
+    @Excel(name = "默认0 0未核销 1已核销")
+    private Integer isVerify;
+
+    public void setQrcodeId(Long qrcodeId) 
+    {
+        this.qrcodeId = qrcodeId;
+    }
+
+    public Long getQrcodeId() 
+    {
+        return qrcodeId;
+    }
+
+    public void setQrcodeContent(String qrcodeContent) 
+    {
+        this.qrcodeContent = qrcodeContent;
+    }
+
+    public String getQrcodeContent() 
+    {
+        return qrcodeContent;
+    }
+
+    public void setUserId(Long userId) 
+    {
+        this.userId = userId;
+    }
+
+    public Long getUserId() 
+    {
+        return userId;
+    }
+
+    public void setDeptId(Long deptId) 
+    {
+        this.deptId = deptId;
+    }
+
+    public Long getDeptId() 
+    {
+        return deptId;
+    }
+
+    public void setSource(Integer source) 
+    {
+        this.source = source;
+    }
+
+    public Integer getSource() 
+    {
+        return source;
+    }
+
+    public void setIsVerify(Integer isVerify) 
+    {
+        this.isVerify = isVerify;
+    }
+
+    public Integer getIsVerify() 
+    {
+        return isVerify;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("qrcodeId", getQrcodeId())
+            .append("qrcodeContent", getQrcodeContent())
+            .append("userId", getUserId())
+            .append("deptId", getDeptId())
+            .append("source", getSource())
+            .append("isVerify", getIsVerify())
+            .append("createTime", getCreateTime())
+            .append("createBy", getCreateBy())
+            .append("updateTime", getUpdateTime())
+            .append("updateBy", getUpdateBy())
+            .toString();
+    }
+}

+ 17 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/dto/MonthQRCodeDTO.java

@@ -0,0 +1,17 @@
+package com.ruoyi.logistics.dto;
+
+import lombok.Data;
+
+@Data
+public class MonthQRCodeDTO {
+
+    private Long qrcodeId;
+
+    private String qrCodeContent;
+
+    private Long userId;
+
+    private Long deptId;
+
+    private Integer source;
+}

+ 61 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/mapper/BizMonthQrcodeRecordMapper.java

@@ -0,0 +1,61 @@
+package com.ruoyi.logistics.mapper;
+
+import java.util.List;
+import com.ruoyi.logistics.domain.BizMonthQrcodeRecord;
+
+/**
+ * 月结二维码使用记录Mapper接口
+ * 
+ * @author RuiJing
+ * @date 2026-02-12
+ */
+public interface BizMonthQrcodeRecordMapper 
+{
+    /**
+     * 查询月结二维码使用记录
+     * 
+     * @param qrcodeId 月结二维码使用记录主键
+     * @return 月结二维码使用记录
+     */
+    public BizMonthQrcodeRecord selectBizMonthQrcodeRecordByQrcodeId(Long qrcodeId);
+
+    /**
+     * 查询月结二维码使用记录列表
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 月结二维码使用记录集合
+     */
+    public List<BizMonthQrcodeRecord> selectBizMonthQrcodeRecordList(BizMonthQrcodeRecord bizMonthQrcodeRecord);
+
+    /**
+     * 新增月结二维码使用记录
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 结果
+     */
+    public int insertBizMonthQrcodeRecord(BizMonthQrcodeRecord bizMonthQrcodeRecord);
+
+    /**
+     * 修改月结二维码使用记录
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 结果
+     */
+    public int updateBizMonthQrcodeRecord(BizMonthQrcodeRecord bizMonthQrcodeRecord);
+
+    /**
+     * 删除月结二维码使用记录
+     * 
+     * @param qrcodeId 月结二维码使用记录主键
+     * @return 结果
+     */
+    public int deleteBizMonthQrcodeRecordByQrcodeId(Long qrcodeId);
+
+    /**
+     * 批量删除月结二维码使用记录
+     * 
+     * @param qrcodeIds 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteBizMonthQrcodeRecordByQrcodeIds(Long[] qrcodeIds);
+}

+ 39 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/response/CommonOrderInfoResponse.java

@@ -0,0 +1,39 @@
+package com.ruoyi.logistics.response;
+
+import com.lop.open.api.sdk.internal.fastjson.annotation.JSONField;
+
+import java.io.Serializable;
+
+public class CommonOrderInfoResponse extends com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderInfoV1.CommonOrderInfoResponse implements Serializable {
+
+    private Contact receiverContact;
+    private Contact senderContact;
+
+    @JSONField(
+            name = "receiverContact"
+    )
+    public void setReceiverContact(Contact var1) {
+        this.receiverContact = var1;
+    }
+
+    @JSONField(
+            name = "receiverContact"
+    )
+    public Contact getReceiverContact() {
+        return this.receiverContact;
+    }
+
+    @JSONField(
+            name = "senderContact"
+    )
+    public void setSenderContact(Contact var1) {
+        this.senderContact = var1;
+    }
+
+    @JSONField(
+            name = "senderContact"
+    )
+    public Contact getSenderContact() {
+        return this.senderContact;
+    }
+}

+ 73 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/response/Contact.java

@@ -0,0 +1,73 @@
+package com.ruoyi.logistics.response;
+
+import com.lop.open.api.sdk.internal.fastjson.annotation.JSONField;
+
+import java.io.Serializable;
+
+public class Contact implements Serializable {
+
+    private String province;
+
+    private String city;
+
+    private String county;
+
+    private String town;
+
+
+    @JSONField(
+            name = "province"
+    )
+    public void setProvince(String var1) {
+        this.province = var1;
+    }
+
+    @JSONField(
+            name = "province"
+    )
+    public String getProvince() {
+        return this.province;
+    }
+
+    @JSONField(
+            name = "city"
+    )
+    public void setCity(String var1) {
+        this.city = var1;
+    }
+
+    @JSONField(
+            name = "city"
+    )
+    public String getCity() {
+        return this.city;
+    }
+
+    @JSONField(
+            name = "county"
+    )
+    public void setCounty(String var1) {
+        this.county = var1;
+    }
+
+    @JSONField(
+            name = "county"
+    )
+    public String getCounty() {
+        return this.county;
+    }
+
+    @JSONField(
+            name = "town"
+    )
+    public void setTown(String var1) {
+        this.town = var1;
+    }
+
+    @JSONField(
+            name = "town"
+    )
+    public String getTown() {
+        return this.town;
+    }
+}

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

@@ -0,0 +1,61 @@
+package com.ruoyi.logistics.service;
+
+import java.util.List;
+import com.ruoyi.logistics.domain.BizMonthQrcodeRecord;
+
+/**
+ * 月结二维码使用记录Service接口
+ * 
+ * @author RuiJing
+ * @date 2026-02-12
+ */
+public interface IBizMonthQrcodeRecordService 
+{
+    /**
+     * 查询月结二维码使用记录
+     * 
+     * @param qrcodeId 月结二维码使用记录主键
+     * @return 月结二维码使用记录
+     */
+    public BizMonthQrcodeRecord selectBizMonthQrcodeRecordByQrcodeId(Long qrcodeId);
+
+    /**
+     * 查询月结二维码使用记录列表
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 月结二维码使用记录集合
+     */
+    public List<BizMonthQrcodeRecord> selectBizMonthQrcodeRecordList(BizMonthQrcodeRecord bizMonthQrcodeRecord);
+
+    /**
+     * 新增月结二维码使用记录
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 结果
+     */
+    public int insertBizMonthQrcodeRecord(BizMonthQrcodeRecord bizMonthQrcodeRecord);
+
+    /**
+     * 修改月结二维码使用记录
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 结果
+     */
+    public int updateBizMonthQrcodeRecord(BizMonthQrcodeRecord bizMonthQrcodeRecord);
+
+    /**
+     * 批量删除月结二维码使用记录
+     * 
+     * @param qrcodeIds 需要删除的月结二维码使用记录主键集合
+     * @return 结果
+     */
+    public int deleteBizMonthQrcodeRecordByQrcodeIds(Long[] qrcodeIds);
+
+    /**
+     * 删除月结二维码使用记录信息
+     * 
+     * @param qrcodeId 月结二维码使用记录主键
+     * @return 结果
+     */
+    public int deleteBizMonthQrcodeRecordByQrcodeId(Long qrcodeId);
+}

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

@@ -0,0 +1,12 @@
+package com.ruoyi.logistics.service;
+
+/**
+ * 月结二维码业务
+ *
+ * @author RuiJing
+ * @date 2026-01-29
+ */
+public interface IMonthQRCodeTaskService {
+
+    void consumeQRCode();
+}

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

@@ -2,20 +2,33 @@ package com.ruoyi.logistics.service;
 
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.core.JsonProcessingException;
-import com.ruoyi.common.core.web.domain.AjaxResult;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.common.security.utils.SecurityUtils;
+import com.ruoyi.logistics.constant.RedisCacheConstants;
+import com.ruoyi.logistics.domain.BizMonthQrcodeRecord;
 import com.ruoyi.logistics.domain.BizWaybillOrder;
-import com.ruoyi.logistics.domain.LogisticsOrder;
+import com.ruoyi.logistics.dto.MonthQRCodeDTO;
 import com.ruoyi.logistics.service.factory.LogisticsFactory;
+import com.ruoyi.logistics.util.QRCodeUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.io.UnsupportedEncodingException;
+import java.util.concurrent.TimeUnit;
 
 @Service
 public class LogisticsOrderService {
     @Autowired
     private LogisticsFactory logisticsFactory;
 
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private IBizMonthQrcodeRecordService bizMonthQrcodeRecordService;
+
 
     public JSONObject precheckOrder(BizWaybillOrder bizWaybillOrder) throws UnsupportedEncodingException {
         // 根据订单中的物流公司类型获取对应服务
@@ -39,11 +52,57 @@ public class LogisticsOrderService {
         return cancelOrder;
     }
 
-    public JSONObject getQRCode(Integer orderType) {
+    public JSONObject getQRCode(Integer source) {
         // 根据订单中的物流公司类型获取对应服务
-        LogisticsService logisticsService = logisticsFactory.getLogisticsService(orderType==1?"JD":"SF");
+        LogisticsService logisticsService = logisticsFactory.getLogisticsService(source==1?"JD":"SF");
         JSONObject qrCode = logisticsService.getMonthQRCode();
-        return qrCode;
+
+        if(!qrCode.getBooleanValue("success")){
+            throw new ServiceException("获取二维码失败! 原因:"+qrCode.getString("msg"));
+        }
+
+        String qrcodeContent = qrCode.getString("msg");
+
+        BizMonthQrcodeRecord bizMonthQrcodeRecord = new BizMonthQrcodeRecord();
+        bizMonthQrcodeRecord.setQrcodeContent(qrcodeContent);
+        bizMonthQrcodeRecord.setUserId(SecurityUtils.getUserId());
+        bizMonthQrcodeRecord.setDeptId(SecurityUtils.getLoginUser().getSysUser().getDeptId());
+        bizMonthQrcodeRecord.setSource(source);
+        bizMonthQrcodeRecord.setIsVerify(0);
+        bizMonthQrcodeRecord.setCreateTime(DateUtils.getNowDate());
+        bizMonthQrcodeRecord.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
+
+        bizMonthQrcodeRecordService.insertBizMonthQrcodeRecord(bizMonthQrcodeRecord);
+
+        MonthQRCodeDTO monthQRCodeDTO = new MonthQRCodeDTO();
+        monthQRCodeDTO.setQrcodeId(bizMonthQrcodeRecord.getQrcodeId());
+        monthQRCodeDTO.setQrCodeContent(qrcodeContent);
+        monthQRCodeDTO.setUserId(SecurityUtils.getUserId());
+        monthQRCodeDTO.setDeptId(SecurityUtils.getLoginUser().getSysUser().getDeptId());
+        monthQRCodeDTO.setSource(source);
+
+        redisService.setCacheObject(RedisCacheConstants.MONTH_QRCODE_CACHE_KEY + bizMonthQrcodeRecord.getQrcodeId(), monthQRCodeDTO, 660L, TimeUnit.SECONDS);
+
+        // 生成二维码图片
+        String qrCodeContent = qrCode.getString("msg");
+        return getQRCodeImage(qrCodeContent);
+    }
+
+    public JSONObject getQRCodeImage(String content) {
+        // 生成二维码图片并返回Base64编码的图片数据
+        try {
+            String base64Image = QRCodeUtils.generateQRCodeBase64(content, 300, 300);
+            JSONObject result = new JSONObject();
+            result.put("success", true);
+            result.put("qrCodeImage", "data:image/png;base64," + base64Image);
+            result.put("msg", "二维码生成成功");
+            return result;
+        } catch (Exception e) {
+            JSONObject result = new JSONObject();
+            result.put("success", false);
+            result.put("msg", "生成二维码失败: " + e.getMessage());
+            return result;
+        }
     }
 
     public JSONObject queryOrderByQRCode(Integer orderType, String qrCode) {
@@ -59,5 +118,12 @@ public class LogisticsOrderService {
         JSONObject jsonObject = logisticsService.queryOrderDetailByWaybillCode(waybillCode);
         return jsonObject;
     }
+
+    public JSONObject queryOrderFeeInfoByWaybillCode(Integer orderType, String waybillCode) {
+        // 根据订单中的物流公司类型获取对应服务
+        LogisticsService logisticsService = logisticsFactory.getLogisticsService(orderType==1?"JD":"SF");
+        JSONObject jsonObject = logisticsService.queryOrderFeeInfo(waybillCode);
+        return jsonObject;
+    }
 }
 

+ 5 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/LogisticsService.java

@@ -57,4 +57,9 @@ public interface LogisticsService {
      */
     JSONObject queryOrderDetailByWaybillCode(String waybillCode);
 
+    /**
+     * 根据运单号查询订单费用信息
+     */
+    JSONObject queryOrderFeeInfo(String waybillCode);
+
 }

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

@@ -0,0 +1,96 @@
+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.BizMonthQrcodeRecordMapper;
+import com.ruoyi.logistics.domain.BizMonthQrcodeRecord;
+import com.ruoyi.logistics.service.IBizMonthQrcodeRecordService;
+
+/**
+ * 月结二维码使用记录Service业务层处理
+ * 
+ * @author RuiJing
+ * @date 2026-02-12
+ */
+@Service
+public class BizMonthQrcodeRecordServiceImpl implements IBizMonthQrcodeRecordService 
+{
+    @Autowired
+    private BizMonthQrcodeRecordMapper bizMonthQrcodeRecordMapper;
+
+    /**
+     * 查询月结二维码使用记录
+     * 
+     * @param qrcodeId 月结二维码使用记录主键
+     * @return 月结二维码使用记录
+     */
+    @Override
+    public BizMonthQrcodeRecord selectBizMonthQrcodeRecordByQrcodeId(Long qrcodeId)
+    {
+        return bizMonthQrcodeRecordMapper.selectBizMonthQrcodeRecordByQrcodeId(qrcodeId);
+    }
+
+    /**
+     * 查询月结二维码使用记录列表
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 月结二维码使用记录
+     */
+    @Override
+    public List<BizMonthQrcodeRecord> selectBizMonthQrcodeRecordList(BizMonthQrcodeRecord bizMonthQrcodeRecord)
+    {
+        return bizMonthQrcodeRecordMapper.selectBizMonthQrcodeRecordList(bizMonthQrcodeRecord);
+    }
+
+    /**
+     * 新增月结二维码使用记录
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 结果
+     */
+    @Override
+    public int insertBizMonthQrcodeRecord(BizMonthQrcodeRecord bizMonthQrcodeRecord)
+    {
+        bizMonthQrcodeRecord.setCreateTime(DateUtils.getNowDate());
+        return bizMonthQrcodeRecordMapper.insertBizMonthQrcodeRecord(bizMonthQrcodeRecord);
+    }
+
+    /**
+     * 修改月结二维码使用记录
+     * 
+     * @param bizMonthQrcodeRecord 月结二维码使用记录
+     * @return 结果
+     */
+    @Override
+    public int updateBizMonthQrcodeRecord(BizMonthQrcodeRecord bizMonthQrcodeRecord)
+    {
+        bizMonthQrcodeRecord.setUpdateTime(DateUtils.getNowDate());
+        return bizMonthQrcodeRecordMapper.updateBizMonthQrcodeRecord(bizMonthQrcodeRecord);
+    }
+
+    /**
+     * 批量删除月结二维码使用记录
+     * 
+     * @param qrcodeIds 需要删除的月结二维码使用记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteBizMonthQrcodeRecordByQrcodeIds(Long[] qrcodeIds)
+    {
+        return bizMonthQrcodeRecordMapper.deleteBizMonthQrcodeRecordByQrcodeIds(qrcodeIds);
+    }
+
+    /**
+     * 删除月结二维码使用记录信息
+     * 
+     * @param qrcodeId 月结二维码使用记录主键
+     * @return 结果
+     */
+    @Override
+    public int deleteBizMonthQrcodeRecordByQrcodeId(Long qrcodeId)
+    {
+        return bizMonthQrcodeRecordMapper.deleteBizMonthQrcodeRecordByQrcodeId(qrcodeId);
+    }
+}

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

@@ -10,6 +10,7 @@ import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCheckPreCreat
 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.domain.ECAP.CommonQueryOrderApi.commonGetActualFeeInfoV1.CommonActualFeeRequest;
 import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderByMonthSettleQRV1.CommonMonthSettleQRQueryRequest;
 import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderInfoV1.CommonOrderInfoRequest;
 import com.lop.open.api.sdk.plugin.LopPlugin;
@@ -19,10 +20,12 @@ import com.lop.open.api.sdk.response.ECAP.*;
 import com.ruoyi.common.core.exception.ServiceException;
 import com.ruoyi.common.core.utils.DateUtils;
 import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.bean.BeanUtils;
 import com.ruoyi.logistics.config.JDExpressConfig;
 import com.ruoyi.logistics.constant.JDDictConstants;
 import com.ruoyi.logistics.constant.SysConfigConstants;
 import com.ruoyi.logistics.domain.BizWaybillOrder;
+import com.ruoyi.logistics.response.CommonOrderInfoResponse;
 import com.ruoyi.logistics.service.LogisticsService;
 import com.ruoyi.system.service.ISysConfigService;
 import lombok.extern.slf4j.Slf4j;
@@ -544,7 +547,7 @@ public class JDLogisticsService  implements LogisticsService {
 
     @Override
     public JSONObject queryOrderByQRCode(String qrCode) {
-        log.info("京东开放平台根据二维码查询运单接口,入参:{}", qrCode);
+        log.info("京东开放平台根据二维码查询运单接口,入参:{}", qrCode);
         JSONObject result = new JSONObject();
         try {
             //设置接口域名(有的对接方案同时支持生产和沙箱环境,有的仅支持生产,具体以对接方案中的【API文档-请求地址】为准),生产域名:https://api.jdl.com 预发环境域名:https://uat-api.jdl.com
@@ -566,25 +569,25 @@ public class JDLogisticsService  implements LogisticsService {
             LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
             request.addLopPlugin(lopPlugin);
 
-            log.info("京东开放平台根据二维码查询运单接口,请求参数:{}", JSON.toJSONString(request));
+            log.info("京东开放平台根据二维码查询运单接口,请求参数:{}", JSON.toJSONString(request));
             CommonqueryorderapiCommongetorderbymonthsettleqrv1LopResponse response = client.execute(request);
-            log.info("京东开放平台根据二维码查询运单接口,响应结果:{}", JSON.toJSONString(response));
+            log.info("京东开放平台根据二维码查询运单接口,响应结果:{}", JSON.toJSONString(response));
 
             if (response.getCode().equals("0")) {
                 if (response.getResponse().getCode() == 0) {
                     result.put("success", true);
-                    result.put("msg", response.getResponse().getData().getWaybillQRVerifyInfoList());
+                    result.put("msg", response.getResponse().getData());
                 } else {
                     result.put("success", false);
-                    result.put("msg", "京东开放平台根据二维码查询运单接口!失败原因:" + response.getResponse().getMsg());
+                    result.put("msg", "京东开放平台根据二维码查询运单接口!失败原因:" + response.getResponse().getMsg());
                 }
             } else {
                 result.put("success", false);
-                result.put("msg", "京东开放平台根据二维码查询运单接口!失败原因:" + response.getMsg());
+                result.put("msg", "京东开放平台根据二维码查询运单接口!失败原因:" + response.getMsg());
             }
         } catch (LopException e) {
-            log.error("京东开放平台根据二维码查询运单接口异常:{}", e);
-            throw new ServiceException("京东开放平台根据二维码查询运单接口异常");
+            log.error("京东开放平台根据二维码查询运单接口异常:{}", e);
+            throw new ServiceException("京东开放平台根据二维码查询运单接口异常");
         }
         return result;
     }
@@ -620,7 +623,11 @@ public class JDLogisticsService  implements LogisticsService {
             if (response.getCode().equals("0")) {
                 if (response.getResult().getCode() == 0) {
                     result.put("success", true);
-                    result.put("msg", response.getResult().getData());
+                    JSONObject msgJson = JSON.parseObject(response.getMsg());
+                    JSONObject responseJson = msgJson.getJSONObject("response");
+                    JSONObject contentJson = responseJson.getJSONObject("content");
+                    CommonOrderInfoResponse commonOrderInfoResponse = JSON.parseObject(contentJson.getString("data"), CommonOrderInfoResponse.class);
+                    result.put("msg", commonOrderInfoResponse);
                 } else {
                     result.put("success", false);
                     result.put("msg", "京东开放平台根据运单号查询运单详情接口!失败原因:" + response.getResult().getMsg());
@@ -630,8 +637,55 @@ public class JDLogisticsService  implements LogisticsService {
                 result.put("msg", "京东开放平台根据运单号查询运单详情接口!失败原因:" + response.getMsg());
             }
         } catch (LopException e) {
-            log.error("京东开放平台根据运单号查询运单详情接口:{}", e);
-            throw new ServiceException("京东开放平台获取商家二维码接口异常");
+            log.error("京东开放平台根据运单号查询运单详情接口异常:{}", e);
+            throw new ServiceException("京东开放平台根据运单号查询运单详情接口异常");
+        }
+        return result;
+    }
+
+    @Override
+    public JSONObject queryOrderFeeInfo(String waybillCode) {
+        log.info("京东开放平台根据运单号查询运单费用接口,入参:{}", waybillCode);
+        JSONObject result = new JSONObject();
+        try {
+            //设置接口域名(有的对接方案同时支持生产和沙箱环境,有的仅支持生产,具体以对接方案中的【API文档-请求地址】为准),生产域名:https://api.jdl.com 预发环境域名:https://uat-api.jdl.com
+            //DefaultDomainApiClient对象全局只需要创建一次
+            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);
+
+            //入参对象
+            EcapV1OrdersActualfeeQueryLopRequest request = new EcapV1OrdersActualfeeQueryLopRequest();
+
+            CommonActualFeeRequest requestDTO = new CommonActualFeeRequest();
+            requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
+            requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
+            requestDTO.setWaybillCode(waybillCode);
+
+            request.setRequest(requestDTO);
+
+            //设置插件,必须的操作,不同类型的应用入参不同,请看入参注释,公共参数按顺序分别为AppKey、AppSecret、AccessToken
+            //使用开放平台ISV/自研商家应用调用接口
+            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
+            request.addLopPlugin(lopPlugin);
+
+            log.info("京东开放平台根据运单号查询运单费用接口,请求参数:{}", JSON.toJSONString(request));
+            EcapV1OrdersActualfeeQueryLopResponse response = client.execute(request);
+            log.info("京东开放平台根据运单号查询运单费用接口,响应结果:{}", JSON.toJSONString(response));
+
+            if (response.getCode().equals("0")) {
+                if (response.getResult().getCode() == 0) {
+                    result.put("success", true);
+                    result.put("msg", response.getResult().getData());
+                } else {
+                    result.put("success", false);
+                    result.put("msg", "京东开放平台根据运单号查询运单费用接口!失败原因:" + response.getResult().getMsg());
+                }
+            } else {
+                result.put("success", false);
+                result.put("msg", "京东开放平台根据运单号查询运单费用接口!失败原因:" + response.getMsg());
+            }
+        } catch (LopException e) {
+            log.error("京东开放平台根据运单号查询运单费用接口异常:{}", e);
+            throw new ServiceException("京东开放平台根据运单号查询运单费用接口异常");
         }
         return result;
     }

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

@@ -0,0 +1,179 @@
+package com.ruoyi.logistics.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetActualFeeInfoV1.CommonActualFeeInfoDetailResponse;
+import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetActualFeeInfoV1.CommonActualFeeResponse;
+import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderByMonthSettleQRV1.CommonMonthSettleQRQueryResponse;
+import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderInfoV1.addedProducts;
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.redis.service.RedisIdGenerator;
+import com.ruoyi.common.redis.service.RedisService;
+import com.ruoyi.logistics.constant.RedisCacheConstants;
+import com.ruoyi.logistics.domain.BizFinancialFeeItems;
+import com.ruoyi.logistics.domain.BizWaybillCostDetails;
+import com.ruoyi.logistics.domain.BizWaybillOrder;
+import com.ruoyi.logistics.dto.MonthQRCodeDTO;
+import com.ruoyi.logistics.mapper.BizWaybillCostDetailsMapper;
+import com.ruoyi.logistics.mapper.BizWaybillOrderMapper;
+import com.ruoyi.logistics.response.CommonOrderInfoResponse;
+import com.ruoyi.logistics.service.*;
+import com.ruoyi.system.api.domain.SysDept;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Service
+public class MonthQRCodeTaskServiceImpl implements IMonthQRCodeTaskService {
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private LogisticsOrderService logisticsOrderService;
+
+    @Autowired
+    private FeeItemsCacheService feeItemsCacheService;
+
+    @Autowired
+    private BizWaybillOrderMapper bizWaybillOrderMapper;
+
+    @Autowired
+    private BizWaybillCostDetailsMapper bizWaybillCostDetailsMapper;
+
+    @Autowired
+    private SysDeptMapper sysDeptMapper;
+
+
+    @Autowired
+    private RedisIdGenerator redisIdGenerator;
+
+    @Override
+    public void consumeQRCode() {
+        Collection<String> keys = redisService.keys(RedisCacheConstants.MONTH_QRCODE_CACHE_KEY + "*");
+
+        keys.forEach(key -> {
+            MonthQRCodeDTO monthQRCodeDTO = redisService.getCacheObject(key);
+
+            SysDept sysDept = sysDeptMapper.selectDeptById(monthQRCodeDTO.getDeptId());
+
+            JSONObject waybillCode = logisticsOrderService.queryOrderByQRCode(1, monthQRCodeDTO.getQrCodeContent());
+
+            CommonMonthSettleQRQueryResponse response = JSON.parseObject(waybillCode.getString("msg"), CommonMonthSettleQRQueryResponse.class);
+
+            if (response.getWaybillQRVerifyInfoList() != null && response.getWaybillQRVerifyInfoList().size() > 0) {
+                log.info("用户:{} 扫描了二维码:{}", monthQRCodeDTO.getUserId(), monthQRCodeDTO.getQrCodeContent());
+
+                response.getWaybillQRVerifyInfoList().forEach(waybillQRVerifyInfo -> {
+                    JSONObject orderDetail = logisticsOrderService.queryOrderDetailByWaybillCode(1, waybillQRVerifyInfo.getWaybillCode());
+                    JSONObject orderFeeInfo = logisticsOrderService.queryOrderFeeInfoByWaybillCode(1, waybillQRVerifyInfo.getWaybillCode());
+
+                    CommonOrderInfoResponse orderInfo = (CommonOrderInfoResponse) orderDetail.get("msg");
+                    CommonActualFeeResponse actualFee = JSON.parseObject(orderFeeInfo.getString("msg"), CommonActualFeeResponse.class);
+
+                    BizWaybillOrder bizWaybillOrder = new BizWaybillOrder();
+                    bizWaybillOrder.setWaybillNo(redisIdGenerator.generateUniqueId("RJSD"));
+                    bizWaybillOrder.setExternalWaybillNo(orderInfo.getWaybillCode());
+                    bizWaybillOrder.setOrderType(1);
+//                    bizWaybillOrder.setSenderName(orderInfo.gets());
+//                    bizWaybillOrder.setSenderPhone(orderInfo.getSenderPhone());
+                    bizWaybillOrder.setSenderProvince(orderInfo.getSenderContact().getProvince());
+                    bizWaybillOrder.setSenderCity(orderInfo.getSenderContact().getCity());
+                    bizWaybillOrder.setSenderCounty(orderInfo.getSenderContact().getCounty());
+                    bizWaybillOrder.setSenderAddress(orderInfo.getSenderContact().getTown());
+//                    bizWaybillOrder.setReceiverName(orderInfo.getReceiverName());
+//                    bizWaybillOrder.setReceiverPhone(orderInfo.getReceiverPhone());
+                    bizWaybillOrder.setReceiverProvince(orderInfo.getReceiverContact().getProvince());
+                    bizWaybillOrder.setReceiverCity(orderInfo.getReceiverContact().getCity());
+                    bizWaybillOrder.setReceiverCounty(orderInfo.getReceiverContact().getCounty());
+                    bizWaybillOrder.setReceiverAddress(orderInfo.getReceiverContact().getTown());
+                    bizWaybillOrder.setGoodsName(orderInfo.getCargoes().get(0).getName());
+                    bizWaybillOrder.setGoodsWeight(new BigDecimal(orderInfo.getCargoes().get(0).getWeight()));
+                    bizWaybillOrder.setGoodsVolume(new BigDecimal(orderInfo.getCargoes().get(0).getVolume()));
+                    bizWaybillOrder.setGoodsQty(orderInfo.getCargoes().get(0).getQuantity().longValue());
+                    bizWaybillOrder.setOrderStatus(1);
+                    bizWaybillOrder.setPickupType(1);
+                    bizWaybillOrder.setSendStartTime(new Date(orderInfo.getShipmentInfo().getPickupStartTime()));
+                    bizWaybillOrder.setSendEndTime(new Date(orderInfo.getShipmentInfo().getPickupEndTime()));
+//                    bizWaybillOrder.setPickupTime(new Date(orderInfo.getShipmentInfo().geta()));
+//                    bizWaybillOrder.setDeliveryTime(waybillQRVerifyInfo.getDeliveryTime());
+//                    bizWaybillOrder.setSignTime(waybillQRVerifyInfo.getSignTime());
+                    bizWaybillOrder.setProductCode(orderInfo.getProducts().getProductCode());
+                    bizWaybillOrder.setAddedService(assembleAddedService(orderInfo.getProducts().getAddedProducts()));
+                    bizWaybillOrder.setCreateTime(DateUtils.getNowDate());
+                    bizWaybillOrder.setUserId(monthQRCodeDTO.getUserId());
+                    bizWaybillOrder.setDeptId(monthQRCodeDTO.getDeptId());
+
+                    bizWaybillOrderMapper.insertBizWaybillOrder(bizWaybillOrder);
+
+                    List<BizWaybillCostDetails> details = assembleCostDetails(sysDept, bizWaybillOrder, actualFee.getCommonActualFeeInfoDetails());
+
+                    details.forEach(detail -> {
+                        bizWaybillCostDetailsMapper.insertBizWaybillCostDetails(detail);
+                    });
+                });
+
+
+            }
+        });
+    }
+
+    private List<BizWaybillCostDetails> assembleCostDetails(SysDept sysDept, BizWaybillOrder bizWaybillOrder, List<CommonActualFeeInfoDetailResponse> commonActualFeeInfoDetails) {
+        List<BizWaybillCostDetails> details = new ArrayList<>();
+        commonActualFeeInfoDetails.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.getMoney());
+                costDetail.setRateAmount(item.getMoney().multiply(new BigDecimal(StringUtils.isNotBlank(sysDept.getRateValue()) ? sysDept.getRateValue() : "1")).setScale(2, BigDecimal.ROUND_HALF_UP));
+                costDetail.setDeptId(bizWaybillOrder.getDeptId());
+                costDetail.setUserId(bizWaybillOrder.getUserId());
+            }
+
+            details.add(costDetail);
+        });
+        return details;
+    }
+
+    private String assembleAddedService(List<addedProducts> addedProducts) {
+        JSONObject addedService = new JSONObject();
+
+        addedService.put("isPack", null);
+        addedService.put("isGuaranteeMoney", null);
+        addedService.put("isReceiptCollect", null);
+
+        List<String> collect = addedProducts.stream().map(com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderInfoV1.addedProducts::getProductCode).collect(Collectors.toList());
+
+        collect.forEach(item -> {
+            switch (item) {
+                case "ed-a-0011":
+                case "fr-a-0005":
+                    addedService.put("isPack", true);
+                    break;
+                case "ed-a-0002":
+                case "fr-a-0002":
+                    addedService.put("isGuaranteeMoney", true);
+                    break;
+                case "ed-a-0010":
+                case "fr-a-0007":
+                    addedService.put("isReceiptCollect", true);
+            }
+        });
+        return addedService.toJSONString();
+    }
+}

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

@@ -354,4 +354,9 @@ public class SFLogisticsService implements LogisticsService {
     public JSONObject queryOrderDetailByWaybillCode(String waybillCode) {
         return null;
     }
+
+    @Override
+    public JSONObject queryOrderFeeInfo(String waybillCode) {
+        return null;
+    }
 }

+ 69 - 0
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/util/QRCodeUtils.java

@@ -0,0 +1,69 @@
+package com.ruoyi.logistics.util;
+
+import cn.hutool.core.img.ImgUtil;
+import cn.hutool.extra.qrcode.QrCodeUtil;
+import cn.hutool.extra.qrcode.QrConfig;
+import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * 二维码工具类
+ * 
+ * @author RuiJing
+ * @date 2026-02-11
+ */
+public class QRCodeUtils {
+
+    /**
+     * 生成二维码图片并返回字节数组
+     * 
+     * @param content 二维码内容
+     * @param width 二维码宽度
+     * @param height 二维码高度
+     * @return 二维码图片字节数组
+     */
+    public static byte[] generateQRCodeBytes(String content, int width, int height) {
+        // 设置二维码配置
+        QrConfig config = new QrConfig();
+        config.setWidth(width);
+        config.setHeight(height);
+        // 设置容错级别
+        config.setErrorCorrection(ErrorCorrectionLevel.M);
+        // 设置边距
+        config.setMargin(1);
+        
+        // 生成二维码图片
+        BufferedImage image = QrCodeUtil.generate(content, config);
+        
+        // 将BufferedImage转换为字节数组
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        try {
+            ImgUtil.write(image, "png", outputStream);
+            return outputStream.toByteArray();
+        } catch (Exception e) {
+            throw new RuntimeException("生成二维码失败", e);
+        } finally {
+            try {
+                outputStream.close();
+            } catch (IOException e) {
+                // 忽略关闭流的异常
+            }
+        }
+    }
+
+    /**
+     * 生成二维码图片并返回Base64编码字符串
+     * 
+     * @param content 二维码内容
+     * @param width 二维码宽度
+     * @param height 二维码高度
+     * @return Base64编码的二维码图片字符串
+     */
+    public static String generateQRCodeBase64(String content, int width, int height) {
+        byte[] qrCodeBytes = generateQRCodeBytes(content, width, height);
+        return java.util.Base64.getEncoder().encodeToString(qrCodeBytes);
+    }
+}

+ 92 - 0
jd-logistics-modules/jd-logistics-system/src/main/resources/mapper/logistics/BizMonthQrcodeRecordMapper.xml

@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.logistics.mapper.BizMonthQrcodeRecordMapper">
+    
+    <resultMap type="BizMonthQrcodeRecord" id="BizMonthQrcodeRecordResult">
+        <result property="qrcodeId"    column="qrcode_id"    />
+        <result property="qrcodeContent"    column="qrcode_content"    />
+        <result property="userId"    column="user_id"    />
+        <result property="deptId"    column="dept_id"    />
+        <result property="source"    column="source"    />
+        <result property="isVerify"    column="is_verify"    />
+        <result property="createTime"    column="create_time"    />
+        <result property="createBy"    column="create_by"    />
+        <result property="updateTime"    column="update_time"    />
+        <result property="updateBy"    column="update_by"    />
+    </resultMap>
+
+    <sql id="selectBizMonthQrcodeRecordVo">
+        select qrcode_id, qrcode_content, user_id, dept_id, source, is_verify, create_time, create_by, update_time, update_by from biz_month_qrcode_record
+    </sql>
+
+    <select id="selectBizMonthQrcodeRecordList" parameterType="BizMonthQrcodeRecord" resultMap="BizMonthQrcodeRecordResult">
+        <include refid="selectBizMonthQrcodeRecordVo"/>
+        <where>  
+            <if test="qrcodeContent != null  and qrcodeContent != ''"> and qrcode_content = #{qrcodeContent}</if>
+            <if test="userId != null "> and user_id = #{userId}</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="source != null "> and source = #{source}</if>
+            <if test="isVerify != null "> and is_verify = #{isVerify}</if>
+        </where>
+    </select>
+    
+    <select id="selectBizMonthQrcodeRecordByQrcodeId" parameterType="Long" resultMap="BizMonthQrcodeRecordResult">
+        <include refid="selectBizMonthQrcodeRecordVo"/>
+        where qrcode_id = #{qrcodeId}
+    </select>
+
+    <insert id="insertBizMonthQrcodeRecord" parameterType="BizMonthQrcodeRecord" useGeneratedKeys="true" keyProperty="qrcodeId">
+        insert into biz_month_qrcode_record
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="qrcodeContent != null">qrcode_content,</if>
+            <if test="userId != null">user_id,</if>
+            <if test="deptId != null">dept_id,</if>
+            <if test="source != null">source,</if>
+            <if test="isVerify != null">is_verify,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="updateTime != null">update_time,</if>
+            <if test="updateBy != null">update_by,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="qrcodeContent != null">#{qrcodeContent},</if>
+            <if test="userId != null">#{userId},</if>
+            <if test="deptId != null">#{deptId},</if>
+            <if test="source != null">#{source},</if>
+            <if test="isVerify != null">#{isVerify},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+         </trim>
+    </insert>
+
+    <update id="updateBizMonthQrcodeRecord" parameterType="BizMonthQrcodeRecord">
+        update biz_month_qrcode_record
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="qrcodeContent != null">qrcode_content = #{qrcodeContent},</if>
+            <if test="userId != null">user_id = #{userId},</if>
+            <if test="deptId != null">dept_id = #{deptId},</if>
+            <if test="source != null">source = #{source},</if>
+            <if test="isVerify != null">is_verify = #{isVerify},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+        </trim>
+        where qrcode_id = #{qrcodeId}
+    </update>
+
+    <delete id="deleteBizMonthQrcodeRecordByQrcodeId" parameterType="Long">
+        delete from biz_month_qrcode_record where qrcode_id = #{qrcodeId}
+    </delete>
+
+    <delete id="deleteBizMonthQrcodeRecordByQrcodeIds" parameterType="String">
+        delete from biz_month_qrcode_record where qrcode_id in 
+        <foreach item="qrcodeId" collection="array" open="(" separator="," close=")">
+            #{qrcodeId}
+        </foreach>
+    </delete>
+</mapper>