更新了服务类订单模块

This commit is contained in:
chen-xin-zhi 2025-02-14 16:21:35 +08:00
parent 6a269c5dc1
commit 2b25ac503c
6 changed files with 194 additions and 33 deletions

View File

@ -37,6 +37,7 @@ import java.io.IOException;
@RestController @RestController
@Tag(name = "微信支付接口") @Tag(name = "微信支付接口")
@RequestMapping("/wechat") @RequestMapping("/wechat")
@Transactional(rollbackFor = Exception.class)
public class WeChatPayController { public class WeChatPayController {
@Resource @Resource
@ -108,6 +109,12 @@ public class WeChatPayController {
} }
/** /**
* Web管理员部分退款 * Web管理员部分退款
* @param commonRequest 订单明细id * @param commonRequest 订单明细id
@ -127,6 +134,29 @@ public class WeChatPayController {
} }
/**
* Web管理员剩余部分退款
* @param commonRequest 订单id
*/
@PostMapping("/refund/rest/create")
@AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
public BaseResponse<Refund> createRestRefund(@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.OPERATION_ERROR, "订单不存在");
Refund refund = weChatService.refundRestPayment(String.valueOf(orderId), order.getTotalAmount());
return ResultUtils.success(refund);
}
/** /**
* 全额退款回调 * 全额退款回调
*/ */

View File

@ -1,5 +1,7 @@
package com.cultural.heritage.model.entity; 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 com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@ -19,6 +21,7 @@ public class PendingServiceGood implements Serializable {
/** /**
* 服务类商品待处理id * 服务类商品待处理id
*/ */
@TableId(type = IdType.AUTO)
private Long id; private Long id;

View File

@ -1,5 +1,7 @@
package com.cultural.heritage.model.entity; 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 com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@ -20,6 +22,7 @@ public class PendingServiceOrder implements Serializable {
/** /**
* 服务类订单待处理id * 服务类订单待处理id
*/ */
@TableId(type = IdType.AUTO)
private Long id; private Long id;

View File

@ -156,7 +156,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
ThrowUtils.throwIf(orderTypeEnum == null, ErrorCode.PARAMS_ERROR); ThrowUtils.throwIf(orderTypeEnum == null, ErrorCode.PARAMS_ERROR);
AddressSnapshot addressSnapshot = null; AddressSnapshot addressSnapshot = null;
ContactsSnapshot contactsSnapshot = null; ContactsSnapshot contactsSnapshot = null;
CouponSnapshot couponSnapshot = new CouponSnapshot(); CouponSnapshot couponSnapshot = null;
// 获取订单地址信息 // 获取订单地址信息
if (orderTypeEnum.equals(GoodTypeEnum.PRODUCT)) { if (orderTypeEnum.equals(GoodTypeEnum.PRODUCT)) {
@ -171,7 +171,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
UserCoupon userCoupon = userCouponService.getById(couponId); UserCoupon userCoupon = userCouponService.getById(couponId);
ThrowUtils.throwIf(userCoupon == null || userCoupon.getCouponVO().getStatus().equals("已过期"), ErrorCode.OPERATION_ERROR, "用户优惠券不存在或者已过期"); ThrowUtils.throwIf(userCoupon == null || userCoupon.getCouponVO().getStatus().equals("已过期"), ErrorCode.OPERATION_ERROR, "用户优惠券不存在或者已过期");
CouponVO couponVO = userCoupon.getCouponVO(); CouponVO couponVO = userCoupon.getCouponVO();
couponSnapshot = new CouponSnapshot();
BeanUtils.copyProperties(couponVO, couponSnapshot); BeanUtils.copyProperties(couponVO, couponSnapshot);
couponSnapshot.setId(couponId);
} }
// 封装订单明细信息 // 封装订单明细信息
List<OrderItemAddRequest> orderItemAddRequestList = orderItemMainInfoAddRequestList.stream().map(orderItemMainInfoAddRequest -> { List<OrderItemAddRequest> orderItemAddRequestList = orderItemMainInfoAddRequestList.stream().map(orderItemMainInfoAddRequest -> {

View File

@ -40,6 +40,11 @@ public interface WeChatService {
*/ */
Refund refundPartPayment(String orderItemsId, BigDecimal amount); Refund refundPartPayment(String orderItemsId, BigDecimal amount);
/**
* 剩余退款申请
*/
Refund refundRestPayment(String orderId, BigDecimal totalAmount);
/** /**
* 获取退款回调信息 * 获取退款回调信息
*/ */
@ -55,6 +60,12 @@ public interface WeChatService {
*/ */
boolean refundPartCallback(RefundNotification refundNotification); boolean refundPartCallback(RefundNotification refundNotification);
/**
* 剩余退款回调
*/
boolean refundRestCallback(RefundNotification refundNotification);
// /** // /**
// * 发送订阅模板消息 // * 发送订阅模板消息
// */ // */

View File

@ -8,10 +8,12 @@ import com.cultural.heritage.common.ErrorCode;
import com.cultural.heritage.config.WxOpenConfig; import com.cultural.heritage.config.WxOpenConfig;
import com.cultural.heritage.config.WxPayConfig; import com.cultural.heritage.config.WxPayConfig;
import com.cultural.heritage.constant.OrderStatusConstant; import com.cultural.heritage.constant.OrderStatusConstant;
import com.cultural.heritage.exception.BusinessException;
import com.cultural.heritage.exception.ThrowUtils; import com.cultural.heritage.exception.ThrowUtils;
import com.cultural.heritage.model.dto.snapshot.CouponSnapshot; import com.cultural.heritage.model.dto.snapshot.CouponSnapshot;
import com.cultural.heritage.model.dto.snapshot.GoodSnapshot; import com.cultural.heritage.model.dto.snapshot.GoodSnapshot;
import com.cultural.heritage.model.entity.*; import com.cultural.heritage.model.entity.*;
import com.cultural.heritage.service.common.CommonService;
import com.cultural.heritage.service.good.AppointmentDateService; import com.cultural.heritage.service.good.AppointmentDateService;
import com.cultural.heritage.service.good.GoodService; import com.cultural.heritage.service.good.GoodService;
import com.cultural.heritage.service.order.*; import com.cultural.heritage.service.order.*;
@ -77,6 +79,9 @@ public class WeChatServiceImpl implements WeChatService {
@Resource @Resource
private PendingServiceOrderService pendingServiceOrderService; private PendingServiceOrderService pendingServiceOrderService;
@Resource
private CommonService commonService;
/** /**
* 请求参数 * 请求参数
@ -179,6 +184,7 @@ public class WeChatServiceImpl implements WeChatService {
System.out.println("退款请求:" + createRequest); System.out.println("退款请求:" + createRequest);
Refund refund = wxPayConfig.getRefundService().create(createRequest); Refund refund = wxPayConfig.getRefundService().create(createRequest);
System.out.println("退款申请结果:" + refund); System.out.println("退款申请结果:" + refund);
return refund; return refund;
} }
@ -194,8 +200,8 @@ public class WeChatServiceImpl implements WeChatService {
public synchronized boolean refundCallback(RefundNotification refundNotification) { public synchronized boolean refundCallback(RefundNotification refundNotification) {
System.out.println("---------------------------微信退款回调(开始)-------------------------------"); System.out.println("---------------------------微信退款回调(开始)-------------------------------");
// 获取订单信息 // 获取订单信息
String orderIdByString = refundNotification.getOutTradeNo(); String orderNumber = refundNotification.getOutTradeNo();
Order order = getOrderInfoByOrderNumber(orderIdByString); Order order = getOrderInfoByOrderNumber(orderNumber);
// 修改订单状态 // 修改订单状态
modifyOrderStatus(order, OrderStatusConstant.PAYMENT_REFUNDED); modifyOrderStatus(order, OrderStatusConstant.PAYMENT_REFUNDED);
@ -209,7 +215,7 @@ public class WeChatServiceImpl implements WeChatService {
updatePendingServiceOrder(order.getOrderNumber(), OrderStatusConstant.PAYMENT_REFUNDED); updatePendingServiceOrder(order.getOrderNumber(), OrderStatusConstant.PAYMENT_REFUNDED);
} else { } else {
// 恢复商品库存 // 恢复商品库存
recoverGoodInventory(String.valueOf(order.getId())); recoverGoodInventory(order);
} }
System.out.println("---------------------------微信退款回调(结束)-------------------------------"); System.out.println("---------------------------微信退款回调(结束)-------------------------------");
return true; return true;
@ -230,7 +236,7 @@ public class WeChatServiceImpl implements WeChatService {
Order order = orderService.getById(orderItems.getOrderId()); Order order = orderService.getById(orderItems.getOrderId());
ThrowUtils.throwIf(order == null, ErrorCode.OPERATION_ERROR, "订单不存在"); ThrowUtils.throwIf(order == null, ErrorCode.OPERATION_ERROR, "订单不存在");
// 判断该订单明细是否已经退款 // 判断该订单明细是否已经退款
checkOrderItemStatus(orderItemsId); checkOrderItemStatus(orderItemsId, order);
String orderNumber = order.getOrderNumber(); String orderNumber = order.getOrderNumber();
// 退款请求 // 退款请求
@ -299,6 +305,78 @@ public class WeChatServiceImpl implements WeChatService {
boolean update = goodService.updateById(good); boolean update = goodService.updateById(good);
ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "商品库存恢复失败"); ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "商品库存恢复失败");
} }
System.out.println("---------------------------微信退款回调(结束)-------------------------------");
return true;
}
/**
* 剩余退款申请
*/
@Override
public Refund refundRestPayment(String orderId, BigDecimal totalAmount) {
// 获取订单号
Order order = orderService.getById(orderId);
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();
long refundAmount = totalAmount.movePointRight(2).intValue();
// 获取剩余退款的金额
BigDecimal restRefundAmount = this.getRestRefundAmount(order);
amountReq.setRefund(restRefundAmount.movePointRight(2).longValue());
amountReq.setTotal(refundAmount);
amountReq.setCurrency("CNY");
createRequest.setAmount(amountReq);
// 申请退款
System.out.println("退款请求:" + createRequest);
Refund refund = wxPayConfig.getRefundService().create(createRequest);
System.out.println("退款申请结果:" + refund);
return refund;
}
/**
* 剩余退款回调
*/
@Override
public boolean refundRestCallback(RefundNotification refundNotification) {
System.out.println("---------------------------微信退款回调(开始)-------------------------------");
// 获取订单信息
String orderNumber = refundNotification.getOutTradeNo();
Order order = getOrderInfoByOrderNumber(orderNumber);
// 修改订单状态
modifyOrderStatus(order, OrderStatusConstant.PAYMENT_REFUNDED);
// 生成退款记录
createRefundRecord(refundNotification);
boolean isGeneral = orderService.isGeneralGood(order.getOrderType());
if (!isGeneral) {
// 更新服务类订单待处理记录
updatePendingServiceOrder(order.getOrderNumber(), OrderStatusConstant.PAYMENT_REFUNDED);
} else {
// 恢复商品库存
recoverGoodInventory(order);
}
System.out.println("---------------------------微信退款回调(结束)-------------------------------");
return true; return true;
} }
@ -324,40 +402,48 @@ public class WeChatServiceImpl implements WeChatService {
/**
* 获取剩余退款的金额
*/
private BigDecimal getRestRefundAmount(Order order) {
QueryWrapper<RefundRecord> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("outTradeNo", order.getOrderNumber());
List<RefundRecord> refundRecordList = refundRecordService.list(queryWrapper);
BigDecimal totalRefund = new BigDecimal("0.00");
for (RefundRecord refundRecord : refundRecordList) {
totalRefund = totalRefund.add(refundRecord.getRefundAmount());
}
return order.getTotalAmount().subtract(totalRefund);
}
/** /**
* 判断当前订单明细是否已退款 * 判断当前订单明细是否已退款
*/ */
public void checkOrderItemStatus(String orderItemsId) { private void checkOrderItemStatus(String orderItemsId, Order order) {
QueryWrapper<PendingServiceOrder> pendingServiceOrderQueryWrapper = new QueryWrapper<>(); boolean isGeneral = orderService.isGeneralGood(order.getOrderType());
pendingServiceOrderQueryWrapper.eq("orderItemId", orderItemsId); if (isGeneral) {
PendingServiceOrder pendingServiceOrder = pendingServiceOrderService.getOne(pendingServiceOrderQueryWrapper); QueryWrapper<RefundRecord> queryWrapper = new QueryWrapper<>();
ThrowUtils.throwIf(pendingServiceOrder == null || !pendingServiceOrder.getOrderItemStatus() queryWrapper.eq("outTradeNo", order.getOrderNumber());
.equals(OrderStatusConstant.PENDING_SHIPMENT), ErrorCode.OPERATION_ERROR, "服务类订单待处理记录不存在或者当前订单明细状态错误"); List<RefundRecord> refundRecordList = refundRecordService.list(queryWrapper);
for (RefundRecord refundRecord : refundRecordList) {
String itemId = RefundUtils.parseRefundNoToItemId(refundRecord.getOutRefundNo());
System.out.println("订单明细id----------------------------------------------------------------------------------------------------->" + itemId);
if (orderItemsId.equals(itemId)) throw new BusinessException(ErrorCode.PARAMS_ERROR, "当前订单明细已退款");
}
} else {
QueryWrapper<PendingServiceOrder> pendingServiceOrderQueryWrapper = new QueryWrapper<>();
pendingServiceOrderQueryWrapper.eq("orderItemId", orderItemsId);
PendingServiceOrder pendingServiceOrder = pendingServiceOrderService.getOne(pendingServiceOrderQueryWrapper);
ThrowUtils.throwIf(pendingServiceOrder == null || !pendingServiceOrder.getOrderItemStatus()
.equals(OrderStatusConstant.PENDING_SHIPMENT), ErrorCode.OPERATION_ERROR, "服务类订单待处理记录不存在或者当前订单明细状态错误");
}
} }
/** /**
* 计算部分退款金额 * 计算部分退款金额
*/ */
@ -399,6 +485,7 @@ public class WeChatServiceImpl implements WeChatService {
/** /**
* 更新服务类商品订单待处理记录 * 更新服务类商品订单待处理记录
*/ */
@ -441,7 +528,7 @@ public class WeChatServiceImpl implements WeChatService {
RefundRecord refundRecord = new RefundRecord(); RefundRecord refundRecord = new RefundRecord();
refundRecord.setOutTradeNo(refundNotification.getOutTradeNo()); refundRecord.setOutTradeNo(refundNotification.getOutTradeNo());
refundRecord.setOutRefundNo(refundNotification.getOutRefundNo()); refundRecord.setOutRefundNo(refundNotification.getOutRefundNo());
refundRecord.setRefundAmount(BigDecimal.valueOf(refundNotification.getAmount().getRefund())); refundRecord.setRefundAmount(BigDecimal.valueOf(refundNotification.getAmount().getRefund()).movePointLeft(2));
boolean save = refundRecordService.save(refundRecord); boolean save = refundRecordService.save(refundRecord);
ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "退款记录生成失败"); ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "退款记录生成失败");
@ -449,6 +536,20 @@ public class WeChatServiceImpl implements WeChatService {
/**
* 生成退款记录
*/
private void createRefundRecord(String outTradeNo, String outRefundNo, long refundAmount) {
RefundRecord refundRecord = new RefundRecord();
refundRecord.setOutTradeNo(outTradeNo);
refundRecord.setOutRefundNo(outRefundNo);
refundRecord.setRefundAmount(BigDecimal.valueOf(refundAmount).movePointLeft(2));
boolean save = refundRecordService.save(refundRecord);
ThrowUtils.throwIf(!save, ErrorCode.OPERATION_ERROR, "退款记录生成失败");
}
@ -468,10 +569,21 @@ public class WeChatServiceImpl implements WeChatService {
/** /**
* 恢复商品库存 * 恢复商品库存
*/ */
private void recoverGoodInventory(String orderId) { private void recoverGoodInventory(Order order) {
QueryWrapper<OrderItems> orderItemsQueryWrapper = new QueryWrapper<>(); // 获取订单明细id列表
orderItemsQueryWrapper.eq("orderId", orderId); QueryWrapper<OrderItems> queryWrapper = new QueryWrapper<>();
List<OrderItems> orderItemsList = orderItemService.list(orderItemsQueryWrapper); queryWrapper.eq("orderId", order.getId());
List<OrderItems> orderItemsList = orderItemService.list(queryWrapper);
// 获取退款的订单明细id
QueryWrapper<RefundRecord> recordQueryWrapper = new QueryWrapper<>();
recordQueryWrapper.eq("outTradeNo", order.getOrderNumber());
List<RefundRecord> refundRecordList = refundRecordService.list(recordQueryWrapper);
List<Long> itemRefundIds = refundRecordList.stream().map(refundRecord ->
Long.parseLong(RefundUtils.parseRefundNoToItemId(refundRecord.getOutRefundNo()))).toList();
orderItemsList = orderItemsList.stream().filter(orderItems -> !itemRefundIds.contains(orderItems.getId())).toList();
// 获取商品id列表 // 获取商品id列表
List<Long> goodIds = orderItemsList.stream().map(orderItems -> { List<Long> goodIds = orderItemsList.stream().map(orderItems -> {
GoodSnapshot goodSnapshot = orderItems.getGoodSnapshot(); GoodSnapshot goodSnapshot = orderItems.getGoodSnapshot();