Jelajahi Sumber

feat(charge): 新增用户余额判断实现起充价校验

- 新增AppletChargeController中的接口,实现校验用户余额是否满足起充价要求
- 从字典表中读取起充价配置,查询用户账户余额进行对比判断
- 用户余额不足时返回提示信息,满足则返回成功状态

feat(charging): 实现优惠首单逻辑并调整订单服务费计算

- 判断当前订单是否为用户首单,存在首单活动时关联优惠信息到订单
- 根据优惠金额调整平台服务费和优惠金额字段,结算订单实际费用
- 优惠金额与平台服务费分开计算并存储

feat(refund): 实现退款订单异步查询及自动状态更新

- 新增定时任务QueryRefundOrderJob,定时查询不为SUCCESS的退款订单结果并更新状态
- 修改WFTOrderService退款流程,支持异步查询退款接口,更新退款记录状态和时间
- 退款记录新增状态SUCCESS和PROCESSING标识,并支持异步更新退款状态和完成时间

refactor(database): 增加逻辑删除与乐观锁字段完善实体类

- 为ChargeOrderInfo、Coupon、CouponTemplate、DiscountsActivity、UserAccountLog、UserExchangeIntegralRule、UserRefundsOrderInfo实体添加逻辑删除字段@TableLogic
- ChargeOrderInfo新增乐观锁版本字段@Version实现并发控制

feat(userRefunds): 优化用户退款订单分页查询增加时间筛选

- 扩展UserRefundsOrderInfoQuery,支持用户ID和起止时间筛选参数
- 更新UserRefundsOrderInfoMapper及XML查询,增加退款时间条件过滤和删除逻辑判断
- 调整UserRefundsOrderInfoController接口描述及查询逻辑

fix(mapper): 调整ChargeOrderInfoMapper停止原因字段与条件

- 移除对停止类型(stop_type)的查询条件,改为使用停止原因(stop_reason)增强语义清晰
- 删除停止类型对应字段映射及返回字段改为停止原因

fix(config): 调整Redis数据库索引和安全配置

- 修改application-dev.yml中redis数据库索引由9改为10
- 增加部分接口请求头安全检查配置

perf(session): 延长JWT令牌及刷新令牌有效期

- 调整application-prod.yml中JWT访问令牌有效期为3天,刷新令牌有效期为14天,提升用户体验

style(service): 调整WFTOrderService退款方法返回值及代码结构

- 将refundOrder方法返回值由void改为退款记录ID,便于异步任务处理关联
- 优化使用线程池异步执行退款状态查询,提升退款状态更新效率
- 增加代码注释及日志完善退款流程跟踪

test: 新增业务线程池与异步退款状态查询测试逻辑

- 添加CompletableFuture异步执行退款查询逻辑,使用@Qualifier注入业务线程池
- 添加日志输出当前执行线程,便于调试与性能监控

misc: 优化订单号前缀常量位置及实体import整理

- 移除冗余的ThirdPartyStationInfoMapper声明,清理未使用import
- 归类实体import,统一导入com.zsElectric.boot.business.model.entity.*包示例
- 调整部分代码空行和注释风格统一代码规范
wzq 3 minggu lalu
induk
melakukan
9874a9d0a1
22 mengubah file dengan 290 tambahan dan 38 penghapusan
  1. 1 2
      src/main/java/com/zsElectric/boot/business/controller/UserRefundsOrderInfoController.java
  2. 45 0
      src/main/java/com/zsElectric/boot/business/controller/applet/AppletChargeController.java
  3. 2 1
      src/main/java/com/zsElectric/boot/business/mapper/UserRefundsOrderInfoMapper.java
  4. 4 0
      src/main/java/com/zsElectric/boot/business/model/entity/ChargeOrderInfo.java
  5. 2 0
      src/main/java/com/zsElectric/boot/business/model/entity/Coupon.java
  6. 2 0
      src/main/java/com/zsElectric/boot/business/model/entity/CouponTemplate.java
  7. 2 0
      src/main/java/com/zsElectric/boot/business/model/entity/DiscountsActivity.java
  8. 7 0
      src/main/java/com/zsElectric/boot/business/model/entity/UserAccountLog.java
  9. 2 0
      src/main/java/com/zsElectric/boot/business/model/entity/UserExchangeIntegralRule.java
  10. 2 0
      src/main/java/com/zsElectric/boot/business/model/entity/UserRefundsOrderInfo.java
  11. 2 2
      src/main/java/com/zsElectric/boot/business/model/query/ChargeOrderInfoQuery.java
  12. 10 0
      src/main/java/com/zsElectric/boot/business/model/query/UserOrderInfoQuery.java
  13. 17 0
      src/main/java/com/zsElectric/boot/business/model/query/UserRefundsOrderInfoQuery.java
  14. 83 0
      src/main/java/com/zsElectric/boot/business/quartz/QueryRefundOrderJob.java
  15. 46 8
      src/main/java/com/zsElectric/boot/business/service/WFTOrderService.java
  16. 3 2
      src/main/java/com/zsElectric/boot/business/service/impl/ChargeOrderInfoServiceImpl.java
  17. 28 4
      src/main/java/com/zsElectric/boot/charging/service/impl/ChargingReceptionServiceImpl.java
  18. 2 2
      src/main/resources/application-dev.yml
  19. 2 3
      src/main/resources/application-prod.yml
  20. 4 14
      src/main/resources/mapper/business/ChargeOrderInfoMapper.xml
  21. 12 0
      src/main/resources/mapper/business/UserOrderInfoMapper.xml
  22. 12 0
      src/main/resources/mapper/business/UserRefundsOrderInfoMapper.xml

+ 1 - 2
src/main/java/com/zsElectric/boot/business/controller/UserRefundsOrderInfoController.java

@@ -32,9 +32,8 @@ public class UserRefundsOrderInfoController  {
 
     private final UserRefundsOrderInfoService userRefundsOrderInfoService;
 
-    @Operation(summary = "退款订单分页列表")
+    @Operation(summary = "获取用户退款订单分页列表")
     @GetMapping("/page")
-    @PreAuthorize("@ss.hasPerm('business:user-refunds-order-info:query')")
     public PageResult<UserRefundsOrderInfoVO> getUserRefundsOrderInfoPage(UserRefundsOrderInfoQuery queryParams ) {
         IPage<UserRefundsOrderInfoVO> result = userRefundsOrderInfoService.getUserRefundsOrderInfoPage(queryParams);
         return PageResult.success(result);

+ 45 - 0
src/main/java/com/zsElectric/boot/business/controller/applet/AppletChargeController.java

@@ -1,15 +1,24 @@
 package com.zsElectric.boot.business.controller.applet;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.zsElectric.boot.business.model.entity.UserAccount;
 import com.zsElectric.boot.business.model.form.applet.AppInvokeChargeForm;
 import com.zsElectric.boot.business.model.form.applet.AppStopChargeForm;
 import com.zsElectric.boot.business.model.query.applet.AppChargeOrderInfoQuery;
 import com.zsElectric.boot.business.model.vo.ChargeOrderInfoVO;
 import com.zsElectric.boot.business.model.vo.applet.AppChargeVO;
 import com.zsElectric.boot.business.service.ChargeOrderInfoService;
+import com.zsElectric.boot.business.service.UserAccountService;
 import com.zsElectric.boot.common.annotation.Log;
 import com.zsElectric.boot.common.enums.LogModuleEnum;
+import com.zsElectric.boot.core.exception.BusinessException;
 import com.zsElectric.boot.core.web.Result;
+import com.zsElectric.boot.security.util.SecurityUtils;
+import com.zsElectric.boot.system.mapper.DictItemMapper;
+import com.zsElectric.boot.system.model.entity.DictItem;
+import com.zsElectric.boot.system.service.DictItemService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.validation.Valid;
@@ -18,6 +27,10 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.poi.ss.formula.functions.T;
 import org.springframework.web.bind.annotation.*;
 
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
 @Tag(name = "充电订单相关接口")
 @Slf4j
 @RestController
@@ -26,6 +39,8 @@ import org.springframework.web.bind.annotation.*;
 public class AppletChargeController {
 
     private final ChargeOrderInfoService chargeOrderInfoService;
+    private final DictItemService dictItemService;
+    private final UserAccountService userAccountService;
 
     /**
      * 充电订单记录
@@ -53,6 +68,36 @@ public class AppletChargeController {
         return Result.success(infoVO);
     }
 
+    /**
+     * 校验用户余额是否满足起充价
+     * @return Boolean
+     */
+    @Operation(summary = "校验用户余额是否满足起充价")
+    @PostMapping("/checkUserAccount")
+    public Result<Map<String,Object>> checkUserAccount() {
+
+        Map<String,Object> map = new HashMap<>();
+
+        Long userId = SecurityUtils.getUserId();
+
+        //查询订单起充价
+        DictItem upRecharge = dictItemService.getOne(Wrappers.<DictItem>lambdaQuery()
+                .eq(DictItem::getDictCode, "up_recharge")
+                .last("limit 1")
+        );
+        if(ObjectUtil.isNotEmpty(upRecharge)){
+            BigDecimal chargeFee = new BigDecimal(upRecharge.getValue());
+            UserAccount one = userAccountService.getOne(Wrappers.lambdaQuery(UserAccount.class).eq(UserAccount::getUserId, userId).last("limit 1"));
+            if(one.getBalance().compareTo(chargeFee) < 0){
+                map.put("status",Boolean.FALSE);
+                map.put("message","用户余额低于起充值 "+chargeFee+" 元,请前往充值后再充电!");
+                return Result.success(map);
+            }
+        }
+        map.put("status",Boolean.TRUE);
+        return Result.success(map);
+    }
+
     /**
      * 启用充电
      *

+ 2 - 1
src/main/java/com/zsElectric/boot/business/mapper/UserRefundsOrderInfoMapper.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zsElectric.boot.business.model.query.UserRefundsOrderInfoQuery;
 import com.zsElectric.boot.business.model.vo.UserRefundsOrderInfoVO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * 退款订单Mapper接口
@@ -23,6 +24,6 @@ public interface UserRefundsOrderInfoMapper extends BaseMapper<UserRefundsOrderI
      * @param queryParams 查询参数
      * @return {@link Page<UserRefundsOrderInfoVO>} 退款订单分页列表
      */
-    Page<UserRefundsOrderInfoVO> getUserRefundsOrderInfoPage(Page<UserRefundsOrderInfoVO> page, UserRefundsOrderInfoQuery queryParams);
+    Page<UserRefundsOrderInfoVO> getUserRefundsOrderInfoPage(Page<UserRefundsOrderInfoVO> page,@Param("queryParams") UserRefundsOrderInfoQuery queryParams);
 
 }

+ 4 - 0
src/main/java/com/zsElectric/boot/business/model/entity/ChargeOrderInfo.java

@@ -1,5 +1,7 @@
 package com.zsElectric.boot.business.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.Version;
 import com.zsElectric.boot.common.base.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
@@ -195,9 +197,11 @@ public class ChargeOrderInfo extends BaseEntity {
     /**
      * 乐观锁
      */
+    @Version
     private Integer version;
     /**
      * 逻辑删除(0-未删除 1-已删除)
      */
+    @TableLogic
     private Integer isDeleted;
 }

+ 2 - 0
src/main/java/com/zsElectric/boot/business/model/entity/Coupon.java

@@ -1,5 +1,6 @@
 package com.zsElectric.boot.business.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.zsElectric.boot.common.base.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
@@ -80,5 +81,6 @@ public class Coupon extends BaseEntity {
     /**
      * 逻辑删除(0-未删除 1-已删除)
      */
+    @TableLogic
     private Integer isDeleted;
 }

+ 2 - 0
src/main/java/com/zsElectric/boot/business/model/entity/CouponTemplate.java

@@ -1,5 +1,6 @@
 package com.zsElectric.boot.business.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.zsElectric.boot.common.base.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
@@ -87,5 +88,6 @@ public class CouponTemplate extends BaseEntity {
     /**
      * 逻辑删除(0-未删除 1-已删除)
      */
+    @TableLogic
     private Integer isDeleted;
 }

+ 2 - 0
src/main/java/com/zsElectric/boot/business/model/entity/DiscountsActivity.java

@@ -1,5 +1,6 @@
 package com.zsElectric.boot.business.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.zsElectric.boot.common.base.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
@@ -51,5 +52,6 @@ public class DiscountsActivity extends BaseEntity {
     /**
      * 逻辑删除(0-未删除 1-已删除)
      */
+    @TableLogic
     private Integer isDeleted;
 }

+ 7 - 0
src/main/java/com/zsElectric/boot/business/model/entity/UserAccountLog.java

@@ -1,11 +1,13 @@
 package com.zsElectric.boot.business.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.zsElectric.boot.common.base.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
 import com.baomidou.mybatisplus.annotation.TableName;
 
 import java.math.BigDecimal;
+import java.time.LocalDateTime;
 
 /**
  * 个人账户变更记录实体对象
@@ -49,4 +51,9 @@ public class UserAccountLog extends BaseEntity {
      * 变更余额
      */
     private BigDecimal changeBalance;
+
+    @TableLogic
+    private Integer isDelete;
+
+
 }

+ 2 - 0
src/main/java/com/zsElectric/boot/business/model/entity/UserExchangeIntegralRule.java

@@ -1,5 +1,6 @@
 package com.zsElectric.boot.business.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.zsElectric.boot.common.base.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
@@ -47,5 +48,6 @@ public class UserExchangeIntegralRule extends BaseEntity {
     /**
      * 逻辑删除(0-未删除 1-已删除)
      */
+    @TableLogic
     private Integer isDeleted;
 }

+ 2 - 0
src/main/java/com/zsElectric/boot/business/model/entity/UserRefundsOrderInfo.java

@@ -1,5 +1,6 @@
 package com.zsElectric.boot.business.model.entity;
 
+import com.baomidou.mybatisplus.annotation.TableLogic;
 import com.zsElectric.boot.common.base.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
@@ -76,5 +77,6 @@ public class UserRefundsOrderInfo extends BaseEntity {
     /**
      * 逻辑删除(0-未删除 1-已删除)
      */
+    @TableLogic
     private Integer isDeleted;
 }

+ 2 - 2
src/main/java/com/zsElectric/boot/business/model/query/ChargeOrderInfoQuery.java

@@ -41,8 +41,8 @@ public class ChargeOrderInfoQuery extends BasePageQuery {
     @Schema(description = "第三方充电站ID")
     private Long thirdStationId;
 
-    @Schema(description = "1 主动停止 2 充满停止 3 余额不足停止, 4电桩按钮停止")
-    private Integer stopType;
+    @Schema(description = "停止原因")
+    private Integer stopReason;
 
     @Schema(description = "开始时间")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

+ 10 - 0
src/main/java/com/zsElectric/boot/business/model/query/UserOrderInfoQuery.java

@@ -42,4 +42,14 @@ public class UserOrderInfoQuery extends BasePageQuery {
     @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime endTime;
+
+    @Schema(description = "退款-开始时间")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime refundStartTime;
+
+    @Schema(description = "退款结束时间")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime refundEndTime;
 }

+ 17 - 0
src/main/java/com/zsElectric/boot/business/model/query/UserRefundsOrderInfoQuery.java

@@ -1,9 +1,13 @@
 package com.zsElectric.boot.business.model.query;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.zsElectric.boot.common.base.BasePageQuery;
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
 import lombok.Getter;
 import lombok.Setter;
+import org.springframework.format.annotation.DateTimeFormat;
+
 import java.time.LocalDateTime;
 import java.util.List;
 import java.math.BigDecimal;
@@ -19,4 +23,17 @@ import java.math.BigDecimal;
 @Setter
 public class UserRefundsOrderInfoQuery extends BasePageQuery {
 
+    @Schema(description = "用户ID")
+    @NotNull(message = "用户ID不能为空")
+    private Long userId;
+
+    @Schema(description = "开始时间")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime startTime;
+
+    @Schema(description = "结束时间")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime endTime;
 }

+ 83 - 0
src/main/java/com/zsElectric/boot/business/quartz/QueryRefundOrderJob.java

@@ -0,0 +1,83 @@
+package com.zsElectric.boot.business.quartz;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.zsElectric.boot.business.mapper.UserRefundsOrderInfoMapper;
+import com.zsElectric.boot.business.model.entity.Coupon;
+import com.zsElectric.boot.business.model.entity.UserRefundsOrderInfo;
+import com.zsElectric.boot.business.service.CouponService;
+import com.zsElectric.boot.business.service.UserRefundsOrderInfoService;
+import com.zsElectric.boot.business.service.WFTOrderService;
+import com.zsElectric.boot.business.service.impl.UserRefundsOrderInfoServiceImpl;
+import com.zsElectric.boot.common.util.SpringUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 退款订单定时任务
+ * 不为SUCCESS的退款订单任务查询结果
+ *
+ * @author zsElectric
+ * @since 2026-01-09
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class QueryRefundOrderJob {
+
+    private final UserRefundsOrderInfoService userRefundsOrderInfoService;
+
+    private final WFTOrderService wftOrderService;
+
+    /**
+     * 每天凌晨2点执行一次
+     * 不为SUCCESS的退款订单任务查询结果
+     */
+    @Scheduled(cron = "0 0 01 * * ?")
+    @Transactional(rollbackFor = Exception.class)
+    public void processExpiredCoupons() {
+        log.info("开始执行不为SUCCESS的退款订单任务");
+
+        try {
+            // 查询一周内不为SUCCESS的退款订单任务
+            List<UserRefundsOrderInfo> refundsOrderInfoList =
+                    userRefundsOrderInfoService.list(Wrappers.lambdaQuery(UserRefundsOrderInfo.class).ne(UserRefundsOrderInfo::getStatus, "SUCCESS"));
+            log.info("查询到{}条不为SUCCESS的退款订单任务", refundsOrderInfoList.size());
+
+
+
+            for (UserRefundsOrderInfo userRefundsOrderInfo : refundsOrderInfoList) {
+
+                if(ObjectUtil.isNotEmpty(userRefundsOrderInfo.getRefundId())){
+                    // 获取微信退款结果
+                    Map<String, Object> map = wftOrderService.queryRefund(null, null, null, userRefundsOrderInfo.getRefundId());
+
+                    // 获取微信退款结果状态
+                    List<Map<String, Object>> refundList = (List<Map<String, Object>>) map.get("refund_list");
+                    String refundStatus = refundList.get(0).get("refund_status").toString();
+                    if(ObjectUtil.isEmpty(userRefundsOrderInfo.getStatus())){
+                        userRefundsOrderInfo.setStatus(refundStatus);
+                    }
+                    if(ObjectUtil.isEmpty(userRefundsOrderInfo.getSuccessTime())){
+                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+                        LocalDateTime dateTime = LocalDateTime.parse(refundList.get(0).get("refund_time").toString(), formatter);
+                        userRefundsOrderInfo.setSuccessTime(dateTime);
+                    }
+                    userRefundsOrderInfoService.updateById(userRefundsOrderInfo);
+                    log.info("退款金额:{},退款状态:{}", refundList.get(0).get("refund_fee").toString(), refundStatus);
+                }
+            }
+
+        } catch (Exception e) {
+            log.error("执行查看不为SUCCESS的退款订单任务失败", e);
+        }
+    }
+}

+ 46 - 8
src/main/java/com/zsElectric/boot/business/service/WFTOrderService.java

@@ -20,6 +20,8 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.validation.Valid;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -30,6 +32,7 @@ import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
 
 /**
  * 威富通支付服务
@@ -800,7 +803,7 @@ public class WFTOrderService {
 
             if (canRefundMoney.compareTo(refundMoney) >= 0) {
                 //可退款金额大于等于待退款金额,则直接退全部待退款金额
-                refundOrder(userOrderInfo, refundMoney, "账户退款", type);
+                Long refundOrderId = refundOrder(userOrderInfo, refundMoney, "账户退款", type);
 
                 //计算本次退款后的累计退款金额
                 BigDecimal totalRefundMoney = alreadyRefundMoney.add(refundMoney);
@@ -812,7 +815,7 @@ public class WFTOrderService {
                         refundMoney,
                         SystemConstants.CHANGE_TYPE_REDUCE,
                         SystemConstants.ACCOUNT_LOG_REFUND_NOTE,
-                        userOrderInfo.getId()
+                        refundOrderId
                 );
 
                 //修改订单状态(判断是全额退款还是部分退款)
@@ -854,7 +857,7 @@ public class WFTOrderService {
         return "账户退款,预计3个工作日内分一笔或多笔退还!到期如未收到,请联系客服处理!";
     }
 
-    public void refundOrder(UserOrderInfo userOrderInfo, BigDecimal refundAmount, String reason, Integer type) throws Exception {
+    public Long refundOrder(UserOrderInfo userOrderInfo, BigDecimal refundAmount, String reason, Integer type) throws Exception {
         log.info("进入退款接口------>");
         log.info("执行操作的 原支付交易对应的商户订单号:{}", userOrderInfo.getOrderNo());
 
@@ -873,7 +876,12 @@ public class WFTOrderService {
 
         SortedMap<String, String> params = new TreeMap<>();
 
-        params.put("out_trade_no", userOrderInfo.getOrderNo());//商户订单号
+        if (ObjectUtil.isNotEmpty(userOrderInfo.getTransactionId())) {
+            params.put("transaction_id", userOrderInfo.getTransactionId());
+            params.put("out_trade_no", userOrderInfo.getOrderNo());//商户订单号
+        }else {
+            params.put("out_trade_no", userOrderInfo.getOutTradeNo());//1.0的商户订单号
+        }
         params.put("out_refund_no", out_refund_no);//商户退款单号
         params.put("attach", reason);//退款原因
         params.put("total_fee", amount_fee(userOrderInfo.getOrderMoney()));//原订单金额
@@ -905,12 +913,15 @@ public class WFTOrderService {
                 userOrderInfo.setRefundMoney(totalRefundMoney);
                 userOrderInfo.setRefundTime(LocalDateTime.now());
                 userOrderInfoMapper.updateById(userOrderInfo);
+                userRefundsOrderInfo.setStatus("SUCCESS");
+                userRefundsOrderInfo.setSuccessTime(LocalDateTime.now());
             } else {
                 log.info("退款处理中");
                 //修改订单状态
                 BigDecimal currentRefundMoney = userOrderInfo.getRefundMoney() == null ? BigDecimal.ZERO : userOrderInfo.getRefundMoney();
                 userOrderInfo.setRefundMoney(currentRefundMoney.add(refundAmount));
                 userOrderInfoMapper.updateById(userOrderInfo);
+                userRefundsOrderInfo.setStatus("PROCESSING");
             }
             //退款信息补充
             userRefundsOrderInfo.setRefundId(refund.get("refund_id"));
@@ -918,8 +929,34 @@ public class WFTOrderService {
             userRefundsOrderInfo.setTransactionId(userOrderInfo.getTransactionId());
             userRefundsOrderInfo.setAcceptedTime(LocalDateTime.now());
             userRefundsOrderInfoMapper.insert(userRefundsOrderInfo);
+
+            //异步执行查询退款订单,修改退款记录
+            executeTaskQueryRefundOrder(userRefundsOrderInfo,userRefundsOrderInfo.getRefundId());
         }
+        return userRefundsOrderInfo.getId();
+    }
 
+    @Autowired
+    @Qualifier("businessTaskExecutor")
+    private ThreadPoolTaskExecutor businessTaskExecutor;
+
+    public CompletableFuture<Void> executeTaskQueryRefundOrder(UserRefundsOrderInfo userRefundsOrderInfo,String refundId) {
+        // 使用 runAsync 并指定自定义线程池
+        return CompletableFuture.runAsync(() -> {
+
+            log.info("进入查询退款接口------>执行线程: " + Thread.currentThread().getName());
+
+            // 异步任务逻辑
+            Map<String, Object> map = queryRefund(null, null, null, refundId);
+            List<Map<String, Object>> refundList= (List<Map<String, Object>>)map.get("refund_list");
+            String refundStatus = refundList.get(0).get("refund_status").toString();
+            userRefundsOrderInfo.setStatus(refundStatus);
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
+            LocalDateTime dateTime = LocalDateTime.parse(refundList.get(0).get("refund_time").toString(), formatter);
+            userRefundsOrderInfo.setSuccessTime(dateTime);
+            userRefundsOrderInfoMapper.updateById(userRefundsOrderInfo);
+            log.info("退款金额:{},退款状态:{}",refundList.get(0).get("refund_fee").toString(),refundStatus);
+        }, businessTaskExecutor);
     }
 
     /**
@@ -1074,11 +1111,12 @@ public class WFTOrderService {
     public static void main(String[] args) throws IOException {
         SortedMap<String, String> params = new TreeMap<>();
         SwiftpassConfig swiftpassConfig = new SwiftpassConfig();
-        params.put("transaction_id", "2301202601062012554389");//商户订单号
-        params.put("out_refund_no", "TK2301202601062012554389");//商户退款单号
+        params.put("transaction_id", "2301202601062012757716");//商户订单号
+//        params.put("out_trade_no", "ZSWL20251201000000201343");//商户订单号
+        params.put("out_refund_no", "TK2301202601062012757716");//商户退款单号
         params.put("attach", "");//退款原因
-        params.put("total_fee", "5000");//原订单金额
-        params.put("refund_fee", "2000");//退款金额
+        params.put("total_fee", "3000");//原订单金额
+        params.put("refund_fee", "1566");//退款金额
         params.put("sign_type", "RSA_1_256");
         PayUtill payUtill = new PayUtill();
         swiftpassConfig.setKey("f5131b3f07acb965a59041b690a29911");

+ 3 - 2
src/main/java/com/zsElectric/boot/business/service/impl/ChargeOrderInfoServiceImpl.java

@@ -17,6 +17,7 @@ import com.zsElectric.boot.business.model.form.applet.AppStopChargeForm;
 import com.zsElectric.boot.business.model.query.ChargeOrderInfoQuery;
 import com.zsElectric.boot.business.model.query.applet.AppChargeOrderInfoQuery;
 import com.zsElectric.boot.business.model.vo.ChargeOrderInfoVO;
+import com.zsElectric.boot.business.model.vo.UserAccountVO;
 import com.zsElectric.boot.business.model.vo.applet.AppChargeVO;
 import com.zsElectric.boot.business.model.vo.applet.AppUserInfoVO;
 import com.zsElectric.boot.business.service.AppletHomeService;
@@ -32,6 +33,8 @@ import com.zsElectric.boot.common.constant.ConnectivityConstants;
 import com.zsElectric.boot.common.constant.SystemConstants;
 import com.zsElectric.boot.core.exception.BusinessException;
 import com.zsElectric.boot.security.util.SecurityUtils;
+import com.zsElectric.boot.system.mapper.DictItemMapper;
+import com.zsElectric.boot.system.model.entity.DictItem;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -70,8 +73,6 @@ public class ChargeOrderInfoServiceImpl extends ServiceImpl<ChargeOrderInfoMappe
 
     private final AppletHomeService appletHomeService;
 
-    private final ThirdPartyStationInfoMapper thirdPartyStationInfoMapper;
-
     //充电订单号前缀
     private final String ORDER_NO_PREFIX = "CD";
     //设备流水号前缀

+ 28 - 4
src/main/java/com/zsElectric/boot/charging/service/impl/ChargingReceptionServiceImpl.java

@@ -7,10 +7,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.zsElectric.boot.business.mapper.*;
-import com.zsElectric.boot.business.model.entity.ChargeOrderInfo;
-import com.zsElectric.boot.business.model.entity.PolicyFee;
-import com.zsElectric.boot.business.model.entity.UserAccount;
-import com.zsElectric.boot.business.model.entity.UserFirm;
+import com.zsElectric.boot.business.model.entity.*;
 import com.zsElectric.boot.business.service.ChargeOrderInfoService;
 import com.zsElectric.boot.charging.entity.*;
 import com.zsElectric.boot.charging.mapper.ThirdPartyChargeStatusMapper;
@@ -77,6 +74,7 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
     private final ChargingBusinessService chargingBusinessService;
     private final ThirdPartyStationInfoMapper thirdPartyStationInfoMapper;
     private final ThirdPartyPolicyInfoMapper thirdPartyPolicyInfoMapper;
+    private final DiscountsActivityMapper discountsActivityMapper;
 
 
     /**
@@ -156,6 +154,25 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
             //推送订单明细
             chargeOrderInfo.setChargeDetails(jsonNode.toString());
 
+            //优惠单价
+            BigDecimal discountPrice = BigDecimal.ZERO;
+
+            //判断当前订单是否为首单
+            Long userId = chargeOrderInfo.getUserId();
+            List<ChargeOrderInfo> list = chargeOrderInfoService.list(Wrappers.<ChargeOrderInfo>lambdaQuery().eq(ChargeOrderInfo::getUserId, userId).eq(ChargeOrderInfo::getStatus,
+                    SystemConstants.STATUS_THREE));
+            if(ObjectUtil.isEmpty(list)){
+                DiscountsActivity discountsActivity = discountsActivityMapper.selectOne(Wrappers.<DiscountsActivity>lambdaQuery()
+                        .eq(DiscountsActivity::getType, SystemConstants.STATUS_ONE)
+                        .eq(DiscountsActivity::getStatus, SystemConstants.STATUS_ONE)
+                        .last("LIMIT 1"));
+                if(ObjectUtil.isNotEmpty(discountsActivity)){
+                    chargeOrderInfo.setDiscountInfoId(discountsActivity.getId());
+                    chargeOrderInfo.setDiscountDesc(discountsActivity.getActivityDesc());
+                    discountPrice = discountsActivity.getDiscount();
+                }
+            }
+
             chargeOrderInfo.setStopReason(stopReason);
             chargeOrderInfo.setStartTime(startTime);
             chargeOrderInfo.setEndTime(endTime);
@@ -176,6 +193,8 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
 
             //平台服务费
             BigDecimal serviceFee = BigDecimal.ZERO;
+            //优惠金额
+            BigDecimal discountFee = BigDecimal.ZERO;
             JsonNode chargeDetails = jsonNode.get("ChargeDetails");
             if (ObjectUtil.isNotEmpty(chargeDetails)) {
                 for (JsonNode node : chargeDetails) {
@@ -189,13 +208,18 @@ public class ChargingReceptionServiceImpl implements ChargingReceptionService {
                             .last("LIMIT 1"));
                     if (ObjectUtil.isNotEmpty(policyFee)) {
                         BigDecimal opFee = policyFee.getOpFee();
+                        if(ObjectUtil.isNotEmpty(chargeOrderInfo.getDiscountInfoId())){
+                            opFee = opFee.subtract(discountPrice);
+                        }
                         log.info("策略费用:{}",opFee);
                         serviceFee = serviceFee.add(opFee.multiply(detailPower));
+                        discountFee = discountFee.add(discountPrice.multiply(detailPower));
                     }
                 }
             }
 
             log.info("计算后的平台服务费:{}", serviceFee);
+            chargeOrderInfo.setDiscountMoney(discountFee);
             chargeOrderInfo.setRealServiceCost(serviceFee.setScale(2, RoundingMode.HALF_UP));
             //订单结算:平台实际收取金额 = 互联互通金额 + 中数电动金额(平台总服务费)
             chargeOrderInfo.setRealCost(chargeOrderInfo.getRealServiceCost().add(chargeOrderInfo.getThirdPartyTotalCost()));

+ 2 - 2
src/main/resources/application-dev.yml

@@ -10,7 +10,7 @@ spring:
     password: 1KQaNI+vPz8^xfYcb%l6
   data:
     redis:
-      database: 9
+      database: 10
       host: 192.168.1.242
       port: 6379
       password: FaajjVy8rl(k
@@ -150,9 +150,9 @@ security:
       - /charge-business/v1/linkData/notification_stop_charge_result
       - /charge-business/v1/linkData/notification_stationStatus
       - /charge-business/v1/linkData/query_token
+      - /applet/v1/homePage/test  # 首页测试接口(包含加密数据)
     # 额外需要检查的请求头(默认已检查 User-Agent、Referer、X-Forwarded-For)
     check-headers:
-      - Referer
       - X-Forwarded-For
 
 okhttp:

+ 2 - 3
src/main/resources/application-prod.yml

@@ -90,8 +90,8 @@ async:
 security:
   session:
     type: jwt # 会话方式 jwt/redis-token
-    access-token-time-to-live: 7200 # 访问令牌 有效期(单位:秒),默认 2 小时,-1 表示永不过期
-    refresh-token-time-to-live: 604800 # 刷新令牌有效期(单位:秒),默认 7 天,-1 表示永不过期
+    access-token-time-to-live: 259200 # 访问令牌 有效期(单位:秒),默认 3 天,-1 表示永不过期
+    refresh-token-time-to-live: 1209600 # 刷新令牌有效期(单位:秒),默认 14 天,-1 表示永不过期
     jwt:
       secret-key: SecretKey012345678901234567890123456789012345678901234567890123456789 # JWT密钥(HS256算法至少32字符)
     redis-token:
@@ -304,7 +304,6 @@ wx:
   #同一支付请求地址
   req_url: https://eoap.cebbank.com/uiap/bcac/pay/pay/gateway
   #支付请求成功后的回调地址--需要配置正确的域名
-  #  notify_url: http://120.78.228.211:8880/orderApi/enditPay
 #  notify_url: https://13cd4c06.r28.cpolar.top/applet/v1/wft/order/notify
   notify_url: https://cd.admin.zswlgz.com/applet/v1/wft/order/notify
   #私钥

+ 4 - 14
src/main/resources/mapper/business/ChargeOrderInfoMapper.xml

@@ -21,7 +21,6 @@
         coi.total_charge,
         coi.real_cost,
         coi.real_service_cost,
-        coi.stop_type,
         ui.phone AS phoneNum,
         coi.plate_num,
         coi.stop_reason,
@@ -77,8 +76,8 @@
             <if test="queryParams.endTime != null">
                 AND coi.create_time <![CDATA[  <=  ]]> #{queryParams.endTime,jdbcType=DATE}
             </if>
-            <if test="queryParams.stopType != null">
-                AND coi.stop_type = #{queryParams.stopType}
+            <if test="queryParams.stopReason != null">
+                AND coi.stop_reason = #{queryParams.stopReason}
             </if>
             <if test="queryParams.orderType != null">
                 AND coi.order_type = #{queryParams.orderType}
@@ -115,7 +114,6 @@
         coi.stop_type,
         coi.phone_num,
         coi.plate_num,
-        coi.stop_reason,
         coi.charge_details,
         coi.third_party_station_id,
         coi.pre_amt,
@@ -187,7 +185,6 @@
         coi.total_charge,
         coi.real_cost,
         coi.real_service_cost,
-        coi.stop_type,
         ui.phone AS phoneNum,
         coi.plate_num,
         coi.stop_reason,
@@ -268,13 +265,6 @@
         a.discount_money,
         a.discount_desc,
         a.coupon_price,
-        CASE a.stop_type
-        WHEN 1 THEN '主动停止'
-        WHEN 2 THEN '充满停止'
-        WHEN 3 THEN '余额不足停止'
-        WHEN 4 THEN '电桩按钮停止'
-        ELSE ''
-        END AS stop_type_name,
         CASE a.stop_reason
         WHEN 0 THEN '用户手动停止充电'
         WHEN 1 THEN '客户归属地运营商平台停止充电'
@@ -311,8 +301,8 @@
             <if test="queryParams.endTime != null">
                 AND a.create_time <![CDATA[  <=  ]]> #{queryParams.endTime,jdbcType=DATE}
             </if>
-            <if test="queryParams.stopType != null">
-                AND a.stop_type = #{queryParams.stopType}
+            <if test="queryParams.stopReason != null">
+                AND a.stop_reason = #{queryParams.stopReason}
             </if>
             <if test="queryParams.orderType != null">
                 AND a.order_type = #{queryParams.orderType}

+ 12 - 0
src/main/resources/mapper/business/UserOrderInfoMapper.xml

@@ -49,6 +49,12 @@
             <if test="queryParams.endTime != null">
                 AND a.create_time <![CDATA[  <=  ]]> #{queryParams.endTime,jdbcType=DATE}
             </if>
+            <if test="queryParams.refundStartTime != null">
+                AND a.refund_time <![CDATA[  >=  ]]> #{queryParams.refundStartTime,jdbcType=DATE}
+            </if>
+            <if test="queryParams.refundEndTime != null">
+                AND a.refund_time <![CDATA[  <=  ]]> #{queryParams.refundEndTime,jdbcType=DATE}
+            </if>
         </where>
         ORDER BY a.create_time DESC
     </select>
@@ -106,6 +112,12 @@
             <if test="queryParams.endTime != null">
                 AND a.create_time <![CDATA[  <=  ]]> #{queryParams.endTime,jdbcType=DATE}
             </if>
+            <if test="queryParams.refundStartTime != null">
+                AND a.refund_time <![CDATA[  >=  ]]> #{queryParams.refundStartTime,jdbcType=DATE}
+            </if>
+            <if test="queryParams.refundEndTime != null">
+                AND a.refund_time <![CDATA[  <=  ]]> #{queryParams.refundEndTime,jdbcType=DATE}
+            </if>
         </where>
         ORDER BY a.create_time DESC
     </select>

+ 12 - 0
src/main/resources/mapper/business/UserRefundsOrderInfoMapper.xml

@@ -25,7 +25,19 @@
         FROM
             c_user_refunds_order_info
         <where>
+            is_deleted = 0
+            <if test="queryParams.userId != null">
+                AND user_id = #{queryParams.userId}
+            </if>
+            <if test="queryParams.startTime != null">
+                AND create_time <![CDATA[  >=  ]]> #{queryParams.startTime,jdbcType=DATE}
+            </if>
+            <if test="queryParams.endTime != null">
+                AND create_time <![CDATA[  <=  ]]> #{queryParams.endTime,jdbcType=DATE}
+            </if>
         </where>
+        ORDER BY
+        create_time DESC
     </select>
 
 </mapper>