From f1dfd35960d3cd67697746a09c6948cc98c94521 Mon Sep 17 00:00:00 2001
From: chen-xin-zhi <3588068430@qq.com>
Date: Fri, 7 Feb 2025 20:55:49 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E4=BC=98=E6=83=A0?=
 =?UTF-8?q?=E5=88=B8=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../controller/good/CouponController.java     | 43 ++-------
 .../controller/good/GoodController.java       |  2 +-
 .../controller/order/OrderController.java     | 88 +++++++++++--------
 .../controller/wx/WeChatPayController.java    | 30 +++++++
 .../heritage/mapper/RefundRecordMapper.java   |  7 ++
 .../model/dto/coupon/CouponAddRequest.java    | 10 ++-
 .../model/dto/coupon/CouponUpdateRequest.java |  6 ++
 .../dto/coupon/UsableCouponQueryRequest.java  |  4 +-
 .../GeneralGoodSingleBuyAddRequest.java       | 68 ++++++++++++++
 .../dto/refund/RefundRecordAddRequest.java    | 39 ++++++++
 .../heritage/model/entity/Coupon.java         |  6 ++
 .../heritage/model/entity/RefundRecord.java   | 68 ++++++++++++++
 .../heritage/model/vo/coupon/CouponVO.java    |  6 ++
 .../heritage/service/good/CouponService.java  | 14 +++
 .../service/good/impl/CouponServiceImpl.java  | 62 +++++++++++++
 .../heritage/service/order/OrderService.java  | 10 ++-
 .../service/order/RefundRecordService.java    |  7 ++
 .../service/order/impl/OrderServiceImpl.java  | 50 +++++++++--
 .../order/impl/RefundRecordServiceImpl.java   | 11 +++
 .../heritage/service/wx/WeChatService.java    |  5 ++
 .../service/wx/impl/WeChatServiceImpl.java    | 59 ++++++++++++-
 .../cultural/heritage/utils/RefundUtils.java  | 21 +++++
 src/main/resources/application.yml            |  4 +-
 .../resources/mapper/RefundRecordMapper.xml   |  7 ++
 24 files changed, 542 insertions(+), 85 deletions(-)
 create mode 100644 src/main/java/com/cultural/heritage/mapper/RefundRecordMapper.java
 create mode 100644 src/main/java/com/cultural/heritage/model/dto/order/capital/GeneralGoodSingleBuyAddRequest.java
 create mode 100644 src/main/java/com/cultural/heritage/model/dto/refund/RefundRecordAddRequest.java
 create mode 100644 src/main/java/com/cultural/heritage/model/entity/RefundRecord.java
 create mode 100644 src/main/java/com/cultural/heritage/service/order/RefundRecordService.java
 create mode 100644 src/main/java/com/cultural/heritage/service/order/impl/RefundRecordServiceImpl.java
 create mode 100644 src/main/java/com/cultural/heritage/utils/RefundUtils.java
 create mode 100644 src/main/resources/mapper/RefundRecordMapper.xml

diff --git a/src/main/java/com/cultural/heritage/controller/good/CouponController.java b/src/main/java/com/cultural/heritage/controller/good/CouponController.java
index 92db996..3e18ca6 100644
--- a/src/main/java/com/cultural/heritage/controller/good/CouponController.java
+++ b/src/main/java/com/cultural/heritage/controller/good/CouponController.java
@@ -1,8 +1,6 @@
 package com.cultural.heritage.controller.good;
 
 
-import cn.hutool.core.date.DateTime;
-import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -11,7 +9,6 @@ import com.cultural.heritage.annotation.AuthCheck;
 import com.cultural.heritage.common.BaseResponse;
 import com.cultural.heritage.common.ErrorCode;
 import com.cultural.heritage.common.ResultUtils;
-import com.cultural.heritage.constant.MqConstant;
 import com.cultural.heritage.constant.UserConstant;
 import com.cultural.heritage.exception.BusinessException;
 import com.cultural.heritage.exception.ThrowUtils;
@@ -30,14 +27,12 @@ import com.cultural.heritage.model.vo.coupon.UserCouponVO;
 import com.cultural.heritage.service.good.CouponService;
 import com.cultural.heritage.service.good.UserCouponService;
 import com.cultural.heritage.service.user.UserService;
-import com.cultural.heritage.utils.MultiDelayMessage;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.beans.BeanUtils;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
@@ -65,8 +60,6 @@ public class CouponController {
     private UserCouponService userCouponService;
 
 
-    @Resource
-    private RabbitTemplate rabbitTemplate;
 
 
     /**
@@ -100,18 +93,8 @@ public class CouponController {
         boolean result = couponService.save(coupon);
         ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "优惠券添加失败");
 
-        // 延迟检查优惠券是否过期
-        MultiDelayMessage<Long> msg = new MultiDelayMessage<>(coupon.getId());
-        rabbitTemplate.convertAndSend(MqConstant.DELAY_EXCHANGE,
-                MqConstant.DELAY_COUPON_ROUTING_KEY, msg, message -> {
-                    //计算优惠券截止日期和当前的时间差
-                    DateTime now = new DateTime();
-                    DateTime end = DateUtil.parse(coupon.getEndTime());
-                    long seconds = DateUtil.between(now, end, DateUnit.SECOND);
-                    // 添加延迟消息属性
-                    message.getMessageProperties().setDelay((int) (seconds * 1000));
-                    return message;
-                });
+        // 向消息队列中发送优惠券创建的消息
+        couponService.sendCouponCreateMessage(coupon);
 
         return ResultUtils.success(true);
     }
@@ -251,18 +234,8 @@ public class CouponController {
         boolean save = userCouponService.save(userCoupon);
         ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "兑换记录插入失败");
 
-        // 延迟检查优惠券是否过期
-        MultiDelayMessage<Long> msg = new MultiDelayMessage<>(userCoupon.getId());
-        rabbitTemplate.convertAndSend(MqConstant.DELAY_EXCHANGE,
-                MqConstant.DELAY_USER_COUPON_ROUTING_KEY, msg, message -> {
-                    //计算优惠券截止日期和当前的时间差
-                    DateTime now = new DateTime();
-                    DateTime end = DateUtil.parse(coupon.getEndTime());
-                    long seconds = DateUtil.between(now, end, DateUnit.SECOND);
-                    // 添加延迟消息属性
-                    message.getMessageProperties().setDelay((int) (seconds * 1000));
-                    return message;
-                });
+        // 向消息队列中发送用户优惠券创建的消息
+        couponService.sendUserCouponCreateMessage(userCoupon, coupon);
 
         // 更新用户积分
         loginUser.setPoints(loginUser.getPoints() - requirePoints);
@@ -388,8 +361,8 @@ public class CouponController {
         if (usableCouponQueryRequest == null) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR);
         }
-        BigDecimal conditionAmount = usableCouponQueryRequest.getConditionAmount();
-        if (conditionAmount.compareTo(BigDecimal.ZERO) <= 0) {
+        BigDecimal currentAmount = usableCouponQueryRequest.getCurrentAmount();
+        if (currentAmount.compareTo(BigDecimal.ZERO) <= 0) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR, "订单金额参数错误");
         }
         User loginUser = userService.getLoginUser(request);
@@ -403,9 +376,9 @@ public class CouponController {
         // 获取(不)可使用的优惠券
         List<UserCoupon> userCoupons = userCouponList.stream().filter(userCoupon -> {
             CouponVO couponVO = userCoupon.getCouponVO();
-            BigDecimal couponAmount = couponVO.getConditionAmount();
+            BigDecimal standardAmount = couponVO.getStandardAmount();
             Boolean isAvailable = usableCouponQueryRequest.getIsAvailable();
-            int result = conditionAmount.compareTo(couponAmount);
+            int result = currentAmount.compareTo(standardAmount);
             return isAvailable == (result >= 0);
         }).toList();
 
diff --git a/src/main/java/com/cultural/heritage/controller/good/GoodController.java b/src/main/java/com/cultural/heritage/controller/good/GoodController.java
index 250f6e1..de6d864 100644
--- a/src/main/java/com/cultural/heritage/controller/good/GoodController.java
+++ b/src/main/java/com/cultural/heritage/controller/good/GoodController.java
@@ -206,7 +206,7 @@ public class GoodController {
         }
         Long id = deleteRequest.getId();
 
-        //删除预约时间段表中与该商品关联的记录
+        // 删除预约时间段表中与该商品关联的记录
         QueryWrapper<AppointmentDate> dateQueryWrapper = new QueryWrapper<>();
         dateQueryWrapper.eq("goodId", id);
         List<AppointmentDate> appointmentDateList = appointmentDateService.list(dateQueryWrapper);
diff --git a/src/main/java/com/cultural/heritage/controller/order/OrderController.java b/src/main/java/com/cultural/heritage/controller/order/OrderController.java
index f5736f7..ac84798 100644
--- a/src/main/java/com/cultural/heritage/controller/order/OrderController.java
+++ b/src/main/java/com/cultural/heritage/controller/order/OrderController.java
@@ -7,7 +7,6 @@ import com.cultural.heritage.annotation.AuthCheck;
 import com.cultural.heritage.common.BaseResponse;
 import com.cultural.heritage.common.ErrorCode;
 import com.cultural.heritage.common.ResultUtils;
-import com.cultural.heritage.constant.MqConstant;
 import com.cultural.heritage.constant.OrderStatusConstant;
 import com.cultural.heritage.constant.UserConstant;
 import com.cultural.heritage.exception.BusinessException;
@@ -17,23 +16,23 @@ import com.cultural.heritage.model.dto.cart.CartOrderAddRequest;
 import com.cultural.heritage.model.dto.cart.CartOrderItemAddRequest;
 import com.cultural.heritage.model.dto.order.OrderQueryRequest;
 import com.cultural.heritage.model.dto.order.OrderUpdateRequest;
+import com.cultural.heritage.model.dto.order.capital.GeneralGoodSingleBuyAddRequest;
 import com.cultural.heritage.model.dto.order.capital.OrderItemMainInfoAddRequest;
 import com.cultural.heritage.model.dto.order.capital.OrderMainInfoAddRequest;
 import com.cultural.heritage.model.dto.snapshot.GoodSnapshot;
 import com.cultural.heritage.model.entity.*;
 import com.cultural.heritage.model.vo.order.OrderVO;
 import com.cultural.heritage.service.good.CartRecordService;
+import com.cultural.heritage.service.good.CouponService;
 import com.cultural.heritage.service.good.GoodService;
 import com.cultural.heritage.service.order.OrderItemService;
 import com.cultural.heritage.service.order.OrderService;
 import com.cultural.heritage.service.user.UserService;
-import com.cultural.heritage.utils.MultiDelayMessage;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.beans.BeanUtils;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -78,9 +77,10 @@ public class OrderController {
     private GoodService goodService;
 
 
-
     @Resource
-    private RabbitTemplate rabbitTemplate;
+    private CouponService couponService;
+
+
 
 
 
@@ -98,14 +98,14 @@ public class OrderController {
         User loginUser = userService.getLoginUser(request);
         Long userId = loginUser.getId();
 
-        // 封装成订单创建请求体
-        OrderMainInfoAddRequest orderMainInfoAddRequest = new OrderMainInfoAddRequest();
-        BeanUtils.copyProperties(cartOrderAddRequest, orderMainInfoAddRequest);
-
         // 校验购物车数据是否准确
         List<CartOrderItemAddRequest> cartOrderItemAddRequestList = cartOrderAddRequest.getCartOrderItemAddRequestList();
         boolean isAccurate = cartRecordService.validIsConsistent(cartOrderItemAddRequestList);
-        ThrowUtils.throwIf(!isAccurate, ErrorCode.SYSTEM_ERROR, "当前购物车中的某些商品已下架或者库存不足,无法生成订单");
+        ThrowUtils.throwIf(!isAccurate, ErrorCode.OPERATION_ERROR, "当前购物车中的某些商品已下架或者库存不足,无法生成订单");
+
+        // 封装成订单主要信息请求体
+        OrderMainInfoAddRequest orderMainInfoAddRequest = new OrderMainInfoAddRequest();
+        BeanUtils.copyProperties(cartOrderAddRequest, orderMainInfoAddRequest);
 
         // 获取购物车id列表
         List<Long> cartIds = cartOrderItemAddRequestList.stream().map(CartOrderItemAddRequest::getCartRecordId).toList();
@@ -140,6 +140,11 @@ public class OrderController {
             Integer quantity = map.get(cartRecordId);
             totalAmount = totalAmount.add(good.getPrice().multiply(BigDecimal.valueOf(quantity)));
         }
+        Long couponId = orderMainInfoAddRequest.getCouponId();
+        Coupon coupon = couponService.getById(couponId);
+        ThrowUtils.throwIf(coupon == null, ErrorCode.OPERATION_ERROR, "优惠券不存在");
+        BigDecimal conditionAmount = coupon.getConditionAmount();
+        totalAmount = totalAmount.subtract(conditionAmount);
 
         orderMainInfoAddRequest.setTotalAmount(totalAmount);
         // 封装成订单明细主要信息请求体列表
@@ -157,17 +162,8 @@ public class OrderController {
         // 创建通用订单(常规类和服务类商品)
         Long orderId = orderService.createCommonOrder(orderMainInfoAddRequest, userId, true, cartIds);
 
-        // 延迟检查订单状态信息
-        MultiDelayMessage<Long> msg = new MultiDelayMessage<>(orderId,
-                10000L, 10000L, 10000L, 15000L, 15000L, 30000L, 30000L, 60000L, 60000L, 120000L, 300000L, 600000L, 600000L);
-        // 10000L, 10000L, 10000L, 15000L, 15000L, 30000L, 30000L, 60000L, 60000L, 120000L, 300000L, 600000L, 600000L
-        int delayValue = msg.removeNextDelay().intValue();
-        rabbitTemplate.convertAndSend(MqConstant.DELAY_EXCHANGE,
-                MqConstant.DELAY_ORDER_ROUTING_KEY, msg, message -> {
-                    // 添加延迟消息属性
-                    message.getMessageProperties().setDelay(delayValue);
-                    return message;
-                });
+        // 向消息队列中发送订单创建的消息
+        orderService.sendCreateOrderMessage(orderId);
 
         return ResultUtils.success(orderId);
     }
@@ -176,38 +172,36 @@ public class OrderController {
 
     /**
      * 小程序端用户创建常规类商品订单
-     * @param orderMainInfoAddRequest 订单创建请求体
+     * @param generalGoodSingleBuyAddRequest 常规类类商品单独购买创建请求体
      * @return  是否创建成功
      */
     @PostMapping("/add")
     @Transactional(rollbackFor = Exception.class)
     @Operation(summary = "小程序端用户创建常规类商品订单", description = "参数:订单创建请求体,权限:所有人,方法名:addOrder")
-    public BaseResponse<Long> addOrder(@RequestBody OrderMainInfoAddRequest orderMainInfoAddRequest, HttpServletRequest request) {
-        if (orderMainInfoAddRequest == null) {
+    public BaseResponse<Long> addOrder(@RequestBody GeneralGoodSingleBuyAddRequest generalGoodSingleBuyAddRequest, HttpServletRequest request) {
+        if (generalGoodSingleBuyAddRequest == null) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR);
         }
         // 校验用户当前是否处于登录态
         User loginUser = userService.getLoginUser(request);
         Long userId = loginUser.getId();
+
         // 校验单独购买的商品数据是否准确
-        orderService.validSingleGoodOrder(orderMainInfoAddRequest);
+        orderService.validSingleGoodOrder(generalGoodSingleBuyAddRequest);
+
+        // 封装成订单主要信息请求体
+        OrderMainInfoAddRequest orderMainInfoAddRequest = new OrderMainInfoAddRequest();
+        BeanUtils.copyProperties(generalGoodSingleBuyAddRequest, orderMainInfoAddRequest);
+
         // 计算单个商品购买的总金额
         BigDecimal totalAmount = orderService.calculateTotalAmount(orderMainInfoAddRequest);
         orderMainInfoAddRequest.setTotalAmount(totalAmount);
         // 创建通用订单(常规类和服务类商品)
         Long orderId = orderService.createCommonOrder(orderMainInfoAddRequest, userId, false, null);
 
-        // 延迟检查订单状态信息
-        MultiDelayMessage<Long> msg = new MultiDelayMessage<>(orderId,
-                10000L, 10000L, 10000L, 15000L, 15000L, 30000L, 30000L, 60000L, 60000L, 120000L, 300000L, 600000L, 600000L);
-        // 10000L, 10000L, 10000L, 15000L, 15000L, 30000L, 30000L, 60000L, 60000L, 120000L, 300000L, 600000L, 600000L
-        int delayValue = msg.removeNextDelay().intValue();
-        rabbitTemplate.convertAndSend(MqConstant.DELAY_EXCHANGE,
-                MqConstant.DELAY_ORDER_ROUTING_KEY, msg, message -> {
-                    // 添加延迟消息属性
-                    message.getMessageProperties().setDelay(delayValue);
-                    return message;
-                });
+        // 向消息队列中发送订单创建的消息
+        orderService.sendCreateOrderMessage(orderId);
+
         return ResultUtils.success(orderId);
     }
 
@@ -282,11 +276,31 @@ public class OrderController {
         queryWrapper.eq("userId", id);
         queryWrapper.orderByDesc("id");
         List<Order> orders = orderService.list(queryWrapper);
+
+        QueryWrapper<OrderItems> myOrderItemsQueryWrapper = new QueryWrapper<>();
+        List<Long> orderIds = orders.stream().map(Order::getId).toList();
+        myOrderItemsQueryWrapper.in("orderId", orderIds);
+        List<OrderItems> myOrderItems = orderItemService.list(myOrderItemsQueryWrapper);
+
+        // 封装map集合(键:订单id, 值:订单明细列表)
+        Map<Long, List<OrderItems>> map = new HashMap<>();
+        for (OrderItems orderItems : myOrderItems) {
+            Long orderId = orderItems.getOrderId();
+
+            List<OrderItems> orderItemsArrayList = map.get(orderId);
+            if (orderItemsArrayList == null) {
+                orderItemsArrayList = new ArrayList<>();
+            }
+            orderItemsArrayList.add(orderItems);
+            map.put(orderId, orderItemsArrayList);
+        }
+
+
         List<OrderVO> orderVOS = orders.stream().map(order -> {
             Long orderId = order.getId();
             QueryWrapper<OrderItems> orderItemsQueryWrapper = new QueryWrapper<>();
             orderItemsQueryWrapper.eq("orderId", orderId);
-            List<OrderItems> orderItemsList = orderItemService.list(orderItemsQueryWrapper);
+            List<OrderItems> orderItemsList = map.get(orderId);
             OrderVO orderVO = new OrderVO();
             BeanUtils.copyProperties(order, orderVO);
             orderVO.setOrderItemList(orderItemsList);
diff --git a/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java b/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java
index ae26dfe..48a2eb5 100644
--- a/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java
+++ b/src/main/java/com/cultural/heritage/controller/wx/WeChatPayController.java
@@ -11,7 +11,9 @@ import com.cultural.heritage.exception.BusinessException;
 import com.cultural.heritage.exception.ThrowUtils;
 import com.cultural.heritage.model.dto.CommonRequest;
 import com.cultural.heritage.model.entity.Order;
+import com.cultural.heritage.model.entity.OrderItems;
 import com.cultural.heritage.model.entity.User;
+import com.cultural.heritage.service.order.OrderItemService;
 import com.cultural.heritage.service.order.OrderService;
 import com.cultural.heritage.service.user.UserService;
 import com.cultural.heritage.service.wx.WeChatService;
@@ -46,6 +48,10 @@ public class WeChatPayController {
     @Resource
     private WeChatService weChatService;
 
+    @Resource
+    private OrderItemService orderItemService;
+
+
 
     /**
      * JSAPI 下单
@@ -83,10 +89,14 @@ public class WeChatPayController {
 
     /**
      * 退款(仅管理员)
+     * @param commonRequest 订单id
      */
     @PostMapping("/refund/create")
     @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
     public BaseResponse<Refund> createRefund(@RequestBody CommonRequest commonRequest) {
+        if (commonRequest == null || commonRequest.getId() <= 0) {
+            throw new BusinessException(ErrorCode.PARAMS_ERROR);
+        }
         Long orderId = commonRequest.getId();
         Order order = ordersService.getById(orderId);
         ThrowUtils.throwIf(order == null, ErrorCode.NOT_FOUND_ERROR, "订单不存在");
@@ -94,6 +104,26 @@ public class WeChatPayController {
         return ResultUtils.success(refund);
     }
 
+
+    /**
+     * Web管理员退款订单明细
+     * @param commonRequest 订单明细id
+     */
+    @PostMapping("/refund/part/create")
+    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
+    public BaseResponse<Refund> createPartRefund(@RequestBody CommonRequest commonRequest) {
+        if (commonRequest == null || commonRequest.getId() <= 0) {
+            throw new BusinessException(ErrorCode.PARAMS_ERROR);
+        }
+        Long orderItemsId = commonRequest.getId();
+        OrderItems orderItems = orderItemService.getById(orderItemsId);
+        ThrowUtils.throwIf(orderItems == null, ErrorCode.OPERATION_ERROR, "订单明细不存在");
+
+        Refund refund = weChatService.refundPartPayment(String.valueOf(orderItemsId), orderItems.getItemTotalAmount());
+        return ResultUtils.success(refund);
+    }
+
+
     /**
      * 退款回调
      */
diff --git a/src/main/java/com/cultural/heritage/mapper/RefundRecordMapper.java b/src/main/java/com/cultural/heritage/mapper/RefundRecordMapper.java
new file mode 100644
index 0000000..49ee451
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/mapper/RefundRecordMapper.java
@@ -0,0 +1,7 @@
+package com.cultural.heritage.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cultural.heritage.model.entity.RefundRecord;
+
+public interface RefundRecordMapper extends BaseMapper<RefundRecord> {
+}
diff --git a/src/main/java/com/cultural/heritage/model/dto/coupon/CouponAddRequest.java b/src/main/java/com/cultural/heritage/model/dto/coupon/CouponAddRequest.java
index 2055e72..dc3ef31 100644
--- a/src/main/java/com/cultural/heritage/model/dto/coupon/CouponAddRequest.java
+++ b/src/main/java/com/cultural/heritage/model/dto/coupon/CouponAddRequest.java
@@ -9,7 +9,7 @@ import java.math.BigDecimal;
 
 @Data
 @Schema(description = "优惠券添加请求体", requiredProperties =
-        {"name", "conditionAmount", "requirePoints", "content",  "startTime", "endTime", "description"})
+        {"name", "standardAmount", "conditionAmount", "requirePoints", "content",  "startTime", "endTime", "description"})
 public class CouponAddRequest implements Serializable {
 
 
@@ -19,6 +19,14 @@ public class CouponAddRequest implements Serializable {
     @Schema(description = "优惠券名称", example = "满200减50")
     private String name;
 
+
+    /**
+     * 标准金额
+     */
+    @Schema(description = "标准金额", example = "200")
+    private BigDecimal standardAmount;
+
+
     /**
      * 满减金额
      */
diff --git a/src/main/java/com/cultural/heritage/model/dto/coupon/CouponUpdateRequest.java b/src/main/java/com/cultural/heritage/model/dto/coupon/CouponUpdateRequest.java
index 401e54d..a91e2c6 100644
--- a/src/main/java/com/cultural/heritage/model/dto/coupon/CouponUpdateRequest.java
+++ b/src/main/java/com/cultural/heritage/model/dto/coupon/CouponUpdateRequest.java
@@ -24,6 +24,12 @@ public class CouponUpdateRequest implements Serializable {
     @Schema(description = "优惠券名称", example = "满200减50")
     private String name;
 
+    /**
+     * 标准金额
+     */
+    @Schema(description = "标准金额", example = "200")
+    private BigDecimal standardAmount;
+
     /**
      * 满减金额
      */
diff --git a/src/main/java/com/cultural/heritage/model/dto/coupon/UsableCouponQueryRequest.java b/src/main/java/com/cultural/heritage/model/dto/coupon/UsableCouponQueryRequest.java
index 410d113..c558a57 100644
--- a/src/main/java/com/cultural/heritage/model/dto/coupon/UsableCouponQueryRequest.java
+++ b/src/main/java/com/cultural/heritage/model/dto/coupon/UsableCouponQueryRequest.java
@@ -9,7 +9,7 @@ import java.math.BigDecimal;
 
 @Data
 @Schema(description = "可用优惠券请求体", requiredProperties =
-        {"conditionAmount", "isAvailable"})
+        {"standardAmount", "isAvailable"})
 public class UsableCouponQueryRequest implements Serializable {
 
 
@@ -17,7 +17,7 @@ public class UsableCouponQueryRequest implements Serializable {
      * 订单金额
      */
     @Schema(description = "订单金额", example = "50")
-    private BigDecimal conditionAmount;
+    private BigDecimal currentAmount;
 
 
     /**
diff --git a/src/main/java/com/cultural/heritage/model/dto/order/capital/GeneralGoodSingleBuyAddRequest.java b/src/main/java/com/cultural/heritage/model/dto/order/capital/GeneralGoodSingleBuyAddRequest.java
new file mode 100644
index 0000000..2ed41f8
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/model/dto/order/capital/GeneralGoodSingleBuyAddRequest.java
@@ -0,0 +1,68 @@
+package com.cultural.heritage.model.dto.order.capital;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+
+
+@Data
+@Schema(description = "常规类商品单独购买创建请求体", requiredProperties = {"userId", "userName", "orderNumber", "addressId", "contactsId",
+        "couponId", "orderStatus", "note", "orderItemMainInfoAddRequestList"})
+public class GeneralGoodSingleBuyAddRequest implements Serializable {
+
+
+    /**
+     * 订单类别
+     */
+    @Schema(description = "订单类别", example = "product")
+    private String orderType;
+
+
+    /**
+     * 用户昵称
+     */
+    @Schema(description = "用户昵称", example = "Hello")
+    private String userName;
+
+
+    /**
+     * 地址id
+     */
+    @Schema(description = "地址id(id > 0)", example = "12")
+    private Long addressId;
+
+
+    /**
+     * 联系人id
+     */
+    @Schema(description = "联系人id(id > 0)", example = "3")
+    private Long contactsId;
+
+
+    /**
+     * 优惠券id
+     */
+    @Schema(description = "优惠券id(id > 0)", example = "2")
+    private Long couponId;
+
+
+    /**
+     * 订单备注
+     */
+    @Schema(description = "订单备注", example = "希望能完整体验非遗文化,保持产品原貌,妥善包装")
+    private String note;
+
+    /**
+     * 订单主要明细信息
+     */
+    @Schema(description = "订单主要明细信息")
+    private List<OrderItemMainInfoAddRequest> orderItemMainInfoAddRequestList;
+
+
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/com/cultural/heritage/model/dto/refund/RefundRecordAddRequest.java b/src/main/java/com/cultural/heritage/model/dto/refund/RefundRecordAddRequest.java
new file mode 100644
index 0000000..53bb51b
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/model/dto/refund/RefundRecordAddRequest.java
@@ -0,0 +1,39 @@
+package com.cultural.heritage.model.dto.refund;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+@Schema(description = "退款记录添加请求体", requiredProperties = {"outTradeNo", "outRefundNo", "refundAmount"})
+public class RefundRecordAddRequest implements Serializable {
+
+
+    /**
+     * 商户单号
+     */
+    @Schema(description = "商户单号", example = "20250206220922442039734342343")
+    private String outTradeNo;
+
+
+    /**
+     * 退款单号
+     */
+    @Schema(description = "退款单号", example = "202502062209224420397")
+    private String outRefundNo;
+
+
+    /**
+     * 退款金额
+     */
+    @Schema(description = "退款金额", example = "100.00")
+    private BigDecimal refundAmount;
+
+
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/com/cultural/heritage/model/entity/Coupon.java b/src/main/java/com/cultural/heritage/model/entity/Coupon.java
index 6aa0a56..00f03a6 100644
--- a/src/main/java/com/cultural/heritage/model/entity/Coupon.java
+++ b/src/main/java/com/cultural/heritage/model/entity/Coupon.java
@@ -46,6 +46,12 @@ public class Coupon implements Serializable {
     private BigDecimal conditionAmount;
 
 
+    /**
+     * 标准金额
+     */
+    private BigDecimal standardAmount;
+
+
     /**
      * 需要的积分
      */
diff --git a/src/main/java/com/cultural/heritage/model/entity/RefundRecord.java b/src/main/java/com/cultural/heritage/model/entity/RefundRecord.java
new file mode 100644
index 0000000..e34776d
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/model/entity/RefundRecord.java
@@ -0,0 +1,68 @@
+package com.cultural.heritage.model.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+
+/**
+ * 退款记录表
+ * @TableName   refund_record
+ */
+@Data
+@TableName(value = "refund_record")
+@Schema(description = "退款记录", requiredProperties = {"id", "outTradeNo", "outRefundNo", "refundAmount"})
+public class RefundRecord implements Serializable {
+
+
+    /**
+     * 退款记录id
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+
+    /**
+     * 商户单号
+     */
+    private String outTradeNo;
+
+
+    /**
+     * 退款单号
+     */
+    private String outRefundNo;
+
+
+    /**
+     * 退款金额
+     */
+    private BigDecimal refundAmount;
+
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    /**
+     * 是否删除
+     */
+    private Integer isDelete;
+
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+}
diff --git a/src/main/java/com/cultural/heritage/model/vo/coupon/CouponVO.java b/src/main/java/com/cultural/heritage/model/vo/coupon/CouponVO.java
index 3dead69..1d8631d 100644
--- a/src/main/java/com/cultural/heritage/model/vo/coupon/CouponVO.java
+++ b/src/main/java/com/cultural/heritage/model/vo/coupon/CouponVO.java
@@ -28,6 +28,12 @@ public class CouponVO implements Serializable {
     private String content;
 
 
+    /**
+     * 标准金额
+     */
+    private BigDecimal standardAmount;
+
+
     /**
      * 满减金额
      */
diff --git a/src/main/java/com/cultural/heritage/service/good/CouponService.java b/src/main/java/com/cultural/heritage/service/good/CouponService.java
index 2fb0726..38af389 100644
--- a/src/main/java/com/cultural/heritage/service/good/CouponService.java
+++ b/src/main/java/com/cultural/heritage/service/good/CouponService.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.cultural.heritage.model.dto.coupon.CouponQueryRequest;
 import com.cultural.heritage.model.entity.Coupon;
+import com.cultural.heritage.model.entity.UserCoupon;
 
 public interface CouponService extends IService<Coupon> {
 
@@ -24,4 +25,17 @@ public interface CouponService extends IService<Coupon> {
      * 校验
      */
     void validCoupon(Coupon coupon, boolean update);
+
+
+    /**
+     * 向消息队列中发送优惠券创建的消息
+     */
+    void sendCouponCreateMessage(Coupon coupon);
+
+
+    /**
+     * 向消息队列中发送用户优惠券创建的消息
+     */
+    void sendUserCouponCreateMessage(UserCoupon userCoupon, Coupon coupon);
+
 }
diff --git a/src/main/java/com/cultural/heritage/service/good/impl/CouponServiceImpl.java b/src/main/java/com/cultural/heritage/service/good/impl/CouponServiceImpl.java
index afcbbb1..3a21dd0 100644
--- a/src/main/java/com/cultural/heritage/service/good/impl/CouponServiceImpl.java
+++ b/src/main/java/com/cultural/heritage/service/good/impl/CouponServiceImpl.java
@@ -1,17 +1,25 @@
 package com.cultural.heritage.service.good.impl;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUnit;
+import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cultural.heritage.common.ErrorCode;
 import com.cultural.heritage.constant.CommonConstant;
+import com.cultural.heritage.constant.MqConstant;
 import com.cultural.heritage.exception.BusinessException;
 import com.cultural.heritage.mapper.CouponMapper;
 import com.cultural.heritage.model.dto.coupon.CouponQueryRequest;
 import com.cultural.heritage.model.entity.Coupon;
+import com.cultural.heritage.model.entity.UserCoupon;
 import com.cultural.heritage.service.good.CouponService;
+import com.cultural.heritage.utils.MultiDelayMessage;
 import com.cultural.heritage.utils.SqlUtils;
+import jakarta.annotation.Resource;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -21,6 +29,10 @@ import java.util.Date;
 public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements CouponService {
 
 
+    @Resource
+    private RabbitTemplate rabbitTemplate;
+
+
     @Override
     public QueryWrapper<Coupon> getQueryWrapper(CouponQueryRequest couponQueryRequest) {
         if (couponQueryRequest == null) {
@@ -57,6 +69,7 @@ public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> impleme
         Long id = coupon.getId();
         String name = coupon.getName();
         BigDecimal conditionAmount = coupon.getConditionAmount();
+        BigDecimal standardAmount = coupon.getStandardAmount();
         Integer requirePoints = coupon.getRequirePoints();
         String startTime = coupon.getStartTime();
         String endTime = coupon.getEndTime();
@@ -69,9 +82,16 @@ public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> impleme
                 throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数id错误");
             }
         }
+        if (ObjectUtils.isEmpty(standardAmount) || standardAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            throw new BusinessException(ErrorCode.PARAMS_ERROR, "标准价格错误");
+        }
         if (ObjectUtils.isEmpty(conditionAmount) || conditionAmount.compareTo(BigDecimal.ZERO) <= 0) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR, "满减价格错误");
         }
+        if (conditionAmount.compareTo(standardAmount) > 0) {
+            throw new BusinessException(ErrorCode.PARAMS_ERROR, "满减价格不能超过标准价格");
+        }
+
         if (ObjectUtils.isEmpty(requirePoints) || requirePoints <= 0) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR, "积分参数错误");
         }
@@ -82,4 +102,46 @@ public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> impleme
             throw new BusinessException(ErrorCode.PARAMS_ERROR, "有效期开始时间晚于有效期截止时间");
         }
     }
+
+
+
+    /**
+     * 向消息队列中发送优惠券创建的消息
+     */
+    @Override
+    public void sendCouponCreateMessage(Coupon coupon) {
+        // 延迟检查优惠券是否过期
+        MultiDelayMessage<Long> msg = new MultiDelayMessage<>(coupon.getId());
+        rabbitTemplate.convertAndSend(MqConstant.DELAY_EXCHANGE,
+                MqConstant.DELAY_COUPON_ROUTING_KEY, msg, message -> {
+                    //计算优惠券截止日期和当前的时间差
+                    DateTime now = new DateTime();
+                    DateTime end = DateUtil.parse(coupon.getEndTime());
+                    long seconds = DateUtil.between(now, end, DateUnit.SECOND);
+                    // 添加延迟消息属性
+                    message.getMessageProperties().setDelay((int) (seconds * 1000));
+                    return message;
+                });
+    }
+
+
+
+    /**
+     * 向消息队列中发送用户优惠券创建的消息
+     */
+    @Override
+    public void sendUserCouponCreateMessage(UserCoupon userCoupon, Coupon coupon) {
+        // 延迟检查优惠券是否过期
+        MultiDelayMessage<Long> msg = new MultiDelayMessage<>(userCoupon.getId());
+        rabbitTemplate.convertAndSend(MqConstant.DELAY_EXCHANGE,
+                MqConstant.DELAY_USER_COUPON_ROUTING_KEY, msg, message -> {
+                    //计算优惠券截止日期和当前的时间差
+                    DateTime now = new DateTime();
+                    DateTime end = DateUtil.parse(coupon.getEndTime());
+                    long seconds = DateUtil.between(now, end, DateUnit.SECOND);
+                    // 添加延迟消息属性
+                    message.getMessageProperties().setDelay((int) (seconds * 1000));
+                    return message;
+                });
+    }
 }
diff --git a/src/main/java/com/cultural/heritage/service/order/OrderService.java b/src/main/java/com/cultural/heritage/service/order/OrderService.java
index a8091dd..e8b7681 100644
--- a/src/main/java/com/cultural/heritage/service/order/OrderService.java
+++ b/src/main/java/com/cultural/heritage/service/order/OrderService.java
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.cultural.heritage.model.dto.order.OrderAddRequest;
 import com.cultural.heritage.model.dto.order.OrderQueryRequest;
+import com.cultural.heritage.model.dto.order.capital.GeneralGoodSingleBuyAddRequest;
 import com.cultural.heritage.model.dto.order.capital.OrderMainInfoAddRequest;
 import com.cultural.heritage.model.entity.Order;
 
@@ -41,7 +42,7 @@ public interface OrderService extends IService<Order> {
     /**
      * 校验单独购买的商品数据是否准确
      */
-    void validSingleGoodOrder(OrderMainInfoAddRequest orderMainInfoAddRequest);
+    void validSingleGoodOrder(GeneralGoodSingleBuyAddRequest generalGoodSingleBuyAddRequest);
 
 
 
@@ -49,4 +50,11 @@ public interface OrderService extends IService<Order> {
      * 计算单个商品购买的总金额
      */
     BigDecimal calculateTotalAmount(OrderMainInfoAddRequest orderMainInfoAddRequest);
+
+
+    /**
+     * 向消息队列中发送订单创建的消息
+     */
+    void sendCreateOrderMessage(Long orderId);
+
 }
diff --git a/src/main/java/com/cultural/heritage/service/order/RefundRecordService.java b/src/main/java/com/cultural/heritage/service/order/RefundRecordService.java
new file mode 100644
index 0000000..4f6b86d
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/service/order/RefundRecordService.java
@@ -0,0 +1,7 @@
+package com.cultural.heritage.service.order;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cultural.heritage.model.entity.RefundRecord;
+
+public interface RefundRecordService extends IService<RefundRecord> {
+}
diff --git a/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java b/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java
index d8cbffe..b062e19 100644
--- a/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java
+++ b/src/main/java/com/cultural/heritage/service/order/impl/OrderServiceImpl.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cultural.heritage.common.ErrorCode;
 import com.cultural.heritage.constant.CommonConstant;
+import com.cultural.heritage.constant.MqConstant;
 import com.cultural.heritage.constant.OrderStatusConstant;
 import com.cultural.heritage.exception.BusinessException;
 import com.cultural.heritage.exception.ThrowUtils;
@@ -12,25 +13,30 @@ import com.cultural.heritage.mapper.*;
 import com.cultural.heritage.model.dto.order.OrderAddRequest;
 import com.cultural.heritage.model.dto.order.OrderItemAddRequest;
 import com.cultural.heritage.model.dto.order.OrderQueryRequest;
+import com.cultural.heritage.model.dto.order.capital.GeneralGoodSingleBuyAddRequest;
 import com.cultural.heritage.model.dto.order.capital.OrderItemMainInfoAddRequest;
 import com.cultural.heritage.model.dto.order.capital.OrderMainInfoAddRequest;
 import com.cultural.heritage.model.dto.snapshot.AddressSnapshot;
 import com.cultural.heritage.model.dto.snapshot.ContactsSnapshot;
 import com.cultural.heritage.model.dto.snapshot.CouponSnapshot;
 import com.cultural.heritage.model.dto.snapshot.GoodSnapshot;
+import com.cultural.heritage.model.entity.Coupon;
 import com.cultural.heritage.model.entity.Good;
 import com.cultural.heritage.model.entity.Order;
 import com.cultural.heritage.model.entity.OrderItems;
 import com.cultural.heritage.model.enums.GoodTypeEnum;
 import com.cultural.heritage.service.good.CartRecordService;
+import com.cultural.heritage.service.good.CouponService;
 import com.cultural.heritage.service.good.GoodService;
 import com.cultural.heritage.service.order.OrderItemService;
 import com.cultural.heritage.service.order.OrderService;
+import com.cultural.heritage.utils.MultiDelayMessage;
 import com.cultural.heritage.utils.OrderNumberUtils;
 import com.cultural.heritage.utils.SqlUtils;
 import jakarta.annotation.Resource;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
@@ -72,6 +78,14 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
     private CartRecordService cartRecordService;
 
 
+    @Resource
+    private RabbitTemplate rabbitTemplate;
+
+
+    @Resource
+    private CouponService couponService;
+
+
     /**
      * 获取查询条件
      */
@@ -255,12 +269,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
             good.setInventory(good.getInventory() - inventory);
         }
         boolean update = goodService.updateBatchById(goodList);
-        ThrowUtils.throwIf(!update, ErrorCode.SYSTEM_ERROR, "商品库存更新失败");
+        ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "商品库存更新失败");
 
         // 清空购物车
         if (isCartOrder) {
             boolean remove = cartRecordService.removeBatchByIds(cartIds);
-            ThrowUtils.throwIf(!remove, ErrorCode.SYSTEM_ERROR, "清空购物车失败");
+            ThrowUtils.throwIf(!remove, ErrorCode.OPERATION_ERROR, "清空购物车失败");
         }
         return id;
     }
@@ -271,8 +285,8 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
      * 校验单独购买的商品数据是否准确
      */
     @Override
-    public void validSingleGoodOrder(OrderMainInfoAddRequest orderMainInfoAddRequest) {
-        List<OrderItemMainInfoAddRequest> orderItemMainInfoAddRequestList = orderMainInfoAddRequest.getOrderItemMainInfoAddRequestList();
+    public void validSingleGoodOrder(GeneralGoodSingleBuyAddRequest generalGoodSingleBuyAddRequest) {
+        List<OrderItemMainInfoAddRequest> orderItemMainInfoAddRequestList = generalGoodSingleBuyAddRequest.getOrderItemMainInfoAddRequestList();
         if (orderItemMainInfoAddRequestList.size() != 1) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR, "购买了多种商品或未购买商品");
         }
@@ -293,13 +307,39 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
     public BigDecimal calculateTotalAmount(OrderMainInfoAddRequest orderMainInfoAddRequest) {
         List<OrderItemMainInfoAddRequest> orderItemMainInfoAddRequestList = orderMainInfoAddRequest.getOrderItemMainInfoAddRequestList();
         OrderItemMainInfoAddRequest orderItemMainInfoAddRequest = orderItemMainInfoAddRequestList.get(0);
+        Long couponId = orderMainInfoAddRequest.getCouponId();
+        Coupon coupon = couponService.getById(couponId);
+        ThrowUtils.throwIf(coupon == null, ErrorCode.OPERATION_ERROR, "优惠券不存在");
+        BigDecimal conditionAmount = coupon.getConditionAmount();
         Integer quantity = orderItemMainInfoAddRequest.getQuantity();
         Long goodId = orderItemMainInfoAddRequest.getGoodId();
         Good good = goodService.getById(goodId);
-        return good.getPrice().multiply(BigDecimal.valueOf(quantity));
+        return good.getPrice().multiply(BigDecimal.valueOf(quantity)).subtract(conditionAmount);
     }
 
 
+
+    /**
+     * 向消息队列中发送订单创建的消息
+     */
+    @Override
+    public void sendCreateOrderMessage(Long orderId) {
+        // 延迟检查订单状态信息
+        MultiDelayMessage<Long> msg = new MultiDelayMessage<>(orderId,
+                10000L, 10000L, 10000L, 15000L, 15000L, 30000L, 30000L, 60000L, 60000L, 120000L, 300000L, 600000L, 600000L);
+        // 10000L, 10000L, 10000L, 15000L, 15000L, 30000L, 30000L, 60000L, 60000L, 120000L, 300000L, 600000L, 600000L
+        int delayValue = msg.removeNextDelay().intValue();
+        rabbitTemplate.convertAndSend(MqConstant.DELAY_EXCHANGE,
+                MqConstant.DELAY_ORDER_ROUTING_KEY, msg, message -> {
+                    // 添加延迟消息属性
+                    message.getMessageProperties().setDelay(delayValue);
+                    return message;
+                });
+    }
+
+
+
+
     /**
      * 根据id获取订单(地址,联系人,优惠券,商品)信息
      */
diff --git a/src/main/java/com/cultural/heritage/service/order/impl/RefundRecordServiceImpl.java b/src/main/java/com/cultural/heritage/service/order/impl/RefundRecordServiceImpl.java
new file mode 100644
index 0000000..c8f8ad5
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/service/order/impl/RefundRecordServiceImpl.java
@@ -0,0 +1,11 @@
+package com.cultural.heritage.service.order.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cultural.heritage.mapper.RefundRecordMapper;
+import com.cultural.heritage.model.entity.RefundRecord;
+import com.cultural.heritage.service.order.RefundRecordService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class RefundRecordServiceImpl extends ServiceImpl<RefundRecordMapper, RefundRecord> implements RefundRecordService {
+}
diff --git a/src/main/java/com/cultural/heritage/service/wx/WeChatService.java b/src/main/java/com/cultural/heritage/service/wx/WeChatService.java
index fb4a2b4..8f3a79c 100644
--- a/src/main/java/com/cultural/heritage/service/wx/WeChatService.java
+++ b/src/main/java/com/cultural/heritage/service/wx/WeChatService.java
@@ -35,6 +35,11 @@ public interface WeChatService {
      */
     Refund refundPayment(String orderId, BigDecimal amount);
 
+    /**
+     * 退款申请
+     */
+    Refund refundPartPayment(String orderItemsId, BigDecimal amount);
+
     /**
      * 获取退款回调信息
      */
diff --git a/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java b/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java
index 9fce07d..364a4fc 100644
--- a/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java
+++ b/src/main/java/com/cultural/heritage/service/wx/impl/WeChatServiceImpl.java
@@ -12,6 +12,7 @@ import com.cultural.heritage.config.WxPayConfig;
 import com.cultural.heritage.constant.OrderStatusConstant;
 import com.cultural.heritage.exception.BusinessException;
 import com.cultural.heritage.exception.ThrowUtils;
+import com.cultural.heritage.model.dto.snapshot.CouponSnapshot;
 import com.cultural.heritage.model.dto.snapshot.GoodSnapshot;
 import com.cultural.heritage.model.entity.Good;
 import com.cultural.heritage.model.entity.Order;
@@ -19,7 +20,9 @@ import com.cultural.heritage.model.entity.OrderItems;
 import com.cultural.heritage.service.good.GoodService;
 import com.cultural.heritage.service.order.OrderItemService;
 import com.cultural.heritage.service.order.OrderService;
+import com.cultural.heritage.service.order.RefundRecordService;
 import com.cultural.heritage.service.wx.WeChatService;
+import com.cultural.heritage.utils.RefundUtils;
 import com.wechat.pay.java.core.notification.NotificationParser;
 import com.wechat.pay.java.core.notification.RequestParam;
 import com.wechat.pay.java.service.payments.jsapi.model.Amount;
@@ -40,6 +43,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.io.BufferedReader;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -67,6 +71,9 @@ public class WeChatServiceImpl implements WeChatService {
     @Resource
     private OrderItemService orderItemService;
 
+    @Resource
+    private RefundRecordService refundRecordService;
+
 
     /**
      * 请求参数
@@ -144,12 +151,14 @@ public class WeChatServiceImpl implements WeChatService {
         // 商户订单号
         createRequest.setOutTradeNo(orderNumber);
         // 商户退款单号
-        createRequest.setOutRefundNo(orderNumber);
+        String outRefundNo = RefundUtils.generateRefundNo();
+        createRequest.setOutRefundNo(outRefundNo);
         // 退款结果回调
         createRequest.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/refund/callback");
         // 退款金额
         AmountReq amountReq = new AmountReq();
         long refundAmount = amount.movePointRight(2).intValue();
+
         amountReq.setRefund(refundAmount);
         amountReq.setTotal(refundAmount);
         amountReq.setCurrency("CNY");
@@ -161,12 +170,60 @@ public class WeChatServiceImpl implements WeChatService {
         return refund;
     }
 
+
+    @Override
+    public Refund refundPartPayment(String orderItemsId, BigDecimal amount) {
+        // 获取订单明细
+        OrderItems orderItems = orderItemService.getById(orderItemsId);
+        ThrowUtils.throwIf(orderItemsId == null, ErrorCode.OPERATION_ERROR, "订单明细不存在");
+        // 获取订单明细所属的订单
+        Order order = orderService.getById(orderItems.getOrderId());
+        ThrowUtils.throwIf(order == null, ErrorCode.OPERATION_ERROR, "订单不存在");
+        String orderNumber = order.getOrderNumber();
+        // 退款请求
+        CreateRequest createRequest = new CreateRequest();
+        // 商户订单号
+        createRequest.setOutTradeNo(orderNumber);
+        // 商户退款单号
+        String outRefundNo = RefundUtils.generateRefundNo();
+        createRequest.setOutRefundNo(outRefundNo);
+        // 退款结果回调
+        createRequest.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/api/wechat/refund/callback");
+        // 退款金额
+        AmountReq amountReq = new AmountReq();
+
+        BigDecimal refundAmount;
+        CouponSnapshot couponSnapshot = order.getCouponSnapshot();
+        if (couponSnapshot == null) {
+            refundAmount = amount;
+        } else {
+            BigDecimal couponAmount = couponSnapshot.getConditionAmount();
+            BigDecimal totalAmount = order.getTotalAmount().add(couponAmount);
+            BigDecimal itemShare = amount.divide(totalAmount, 10, RoundingMode.HALF_UP);
+            BigDecimal itemCouponRefund = itemShare.multiply(couponAmount);
+            refundAmount = amount.subtract(itemCouponRefund);
+        }
+        refundAmount = refundAmount.movePointRight(2).setScale(0, RoundingMode.HALF_UP);
+        amountReq.setRefund(refundAmount.longValue());
+        amountReq.setTotal(order.getTotalAmount().movePointRight(2).longValue());
+        amountReq.setCurrency("CNY");
+        createRequest.setAmount(amountReq);
+        // 申请退款
+        System.out.println("退款请求:" + createRequest);
+        Refund refund = wxPayConfig.getRefundService().create(createRequest);
+        System.out.println("退款申请结果:" + refund);
+        return refund;
+    }
+
+
     @Override
     public RefundNotification getRefundInfo(HttpServletRequest request) {
         NotificationParser notificationParser = getNotificationParser(request);
         return notificationParser.parse(requestParam, RefundNotification.class);
     }
 
+
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public synchronized boolean refundCallback(RefundNotification refundNotification) {
diff --git a/src/main/java/com/cultural/heritage/utils/RefundUtils.java b/src/main/java/com/cultural/heritage/utils/RefundUtils.java
new file mode 100644
index 0000000..f90a9ef
--- /dev/null
+++ b/src/main/java/com/cultural/heritage/utils/RefundUtils.java
@@ -0,0 +1,21 @@
+package com.cultural.heritage.utils;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+
+public class RefundUtils {
+
+    // 生成唯一的退款单号,格式为 yyyyMMddHHmmssSSS + 随机数
+    public static String generateRefundNo() {
+        // 获取当前时间的时间戳
+        String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
+
+        // 生成一个 4 位随机数,保证每次退款单号不同
+        int randomNum = new Random().nextInt(9000) + 1000; // 生成1000到9999之间的随机数
+
+        // 拼接退款单号
+        return timestamp + randomNum;
+    }
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 0cfdc9d..2d55b57 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -94,8 +94,8 @@ wx:
     #商户APIv3密钥
     apiV3Key: fbemuj4Xql7CYlQJAoTEPYxvPSNgYT2t
     #通知地址
-#    notifyUrl: https://winning-mouse-internally.ngrok-free.app
-    notifyUrl: http://123.249.108.160:8888
+    notifyUrl: https://winning-mouse-internally.ngrok-free.app
+#    notifyUrl: http://123.249.108.160:8888
     #微信服务器地址
     domain: https://api.mch.weixin.qq.com
 
diff --git a/src/main/resources/mapper/RefundRecordMapper.xml b/src/main/resources/mapper/RefundRecordMapper.xml
new file mode 100644
index 0000000..6057893
--- /dev/null
+++ b/src/main/resources/mapper/RefundRecordMapper.xml
@@ -0,0 +1,7 @@
+<?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.cultural.heritage.model.dto.refund.RefundRecordAddRequest">
+
+</mapper>
\ No newline at end of file