更新了优惠券模块
This commit is contained in:
parent
9082882cab
commit
f1dfd35960
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退款回调
|
||||
*/
|
||||
|
|
|
@ -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> {
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* 满减金额
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,12 @@ public class CouponUpdateRequest implements Serializable {
|
|||
@Schema(description = "优惠券名称", example = "满200减50")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 标准金额
|
||||
*/
|
||||
@Schema(description = "标准金额", example = "200")
|
||||
private BigDecimal standardAmount;
|
||||
|
||||
/**
|
||||
* 满减金额
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -46,6 +46,12 @@ public class Coupon implements Serializable {
|
|||
private BigDecimal conditionAmount;
|
||||
|
||||
|
||||
/**
|
||||
* 标准金额
|
||||
*/
|
||||
private BigDecimal standardAmount;
|
||||
|
||||
|
||||
/**
|
||||
* 需要的积分
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -28,6 +28,12 @@ public class CouponVO implements Serializable {
|
|||
private String content;
|
||||
|
||||
|
||||
/**
|
||||
* 标准金额
|
||||
*/
|
||||
private BigDecimal standardAmount;
|
||||
|
||||
|
||||
/**
|
||||
* 满减金额
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
}
|
|
@ -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获取订单(地址,联系人,优惠券,商品)信息
|
||||
*/
|
||||
|
|
|
@ -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 {
|
||||
}
|
|
@ -35,6 +35,11 @@ public interface WeChatService {
|
|||
*/
|
||||
Refund refundPayment(String orderId, BigDecimal amount);
|
||||
|
||||
/**
|
||||
* 退款申请
|
||||
*/
|
||||
Refund refundPartPayment(String orderItemsId, BigDecimal amount);
|
||||
|
||||
/**
|
||||
* 获取退款回调信息
|
||||
*/
|
||||
|
|
|
@ -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) {
|
||||
|
|
21
src/main/java/com/cultural/heritage/utils/RefundUtils.java
Normal file
21
src/main/java/com/cultural/heritage/utils/RefundUtils.java
Normal file
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
7
src/main/resources/mapper/RefundRecordMapper.xml
Normal file
7
src/main/resources/mapper/RefundRecordMapper.xml
Normal file
|
@ -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>
|
Loading…
Reference in New Issue
Block a user