package com.doumee.service.business.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.doumee.config.wx.WxPayProperties;
|
import com.doumee.config.wx.WxPayV3Service;
|
import com.doumee.core.constants.Constants;
|
import com.doumee.core.constants.ResponseStatus;
|
import com.doumee.core.exception.BusinessException;
|
import com.doumee.core.model.PageData;
|
import com.doumee.core.model.PageWrap;
|
import com.doumee.core.utils.Utils;
|
import com.doumee.dao.business.OrdersMapper;
|
import com.doumee.dao.business.OrdersRefundMapper;
|
import com.doumee.dao.business.model.Orders;
|
import com.doumee.dao.business.model.OrdersRefund;
|
import com.doumee.dao.dto.OrdersRefundPageDTO;
|
import com.doumee.dao.vo.OrdersRefundPageVO;
|
import com.doumee.service.business.OrdersRefundService;
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.CollectionUtils;
|
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* 订单退款记录Service实现
|
* @author rk
|
* @date 2026/04/13
|
*/
|
@Slf4j
|
@Service
|
public class OrdersRefundServiceImpl implements OrdersRefundService {
|
|
@Autowired
|
private OrdersRefundMapper ordersRefundMapper;
|
|
@Autowired
|
private OrdersMapper ordersMapper;
|
|
@Autowired
|
private WxPayV3Service wxPayV3Service;
|
|
@Autowired
|
private WxPayProperties wxPayProperties;
|
|
@Override
|
public Integer create(OrdersRefund ordersRefund) {
|
ordersRefundMapper.insert(ordersRefund);
|
return ordersRefund.getId();
|
}
|
|
@Override
|
public void deleteById(Integer id) {
|
ordersRefundMapper.deleteById(id);
|
}
|
|
@Override
|
public void delete(OrdersRefund ordersRefund) {
|
QueryWrapper<OrdersRefund> deleteWrapper = new QueryWrapper<>(ordersRefund);
|
ordersRefundMapper.delete(deleteWrapper);
|
}
|
|
@Override
|
public void deleteByIdInBatch(List<Integer> ids) {
|
if (CollectionUtils.isEmpty(ids)) {
|
return;
|
}
|
ordersRefundMapper.deleteBatchIds(ids);
|
}
|
|
@Override
|
public void updateById(OrdersRefund ordersRefund) {
|
ordersRefundMapper.updateById(ordersRefund);
|
}
|
|
@Override
|
public void updateByIdInBatch(List<OrdersRefund> ordersRefunds) {
|
if (CollectionUtils.isEmpty(ordersRefunds)) {
|
return;
|
}
|
for (OrdersRefund ordersRefund : ordersRefunds) {
|
this.updateById(ordersRefund);
|
}
|
}
|
|
@Override
|
public OrdersRefund findById(Integer id) {
|
return ordersRefundMapper.selectById(id);
|
}
|
|
@Override
|
public OrdersRefund findOne(OrdersRefund ordersRefund) {
|
QueryWrapper<OrdersRefund> wrapper = new QueryWrapper<>(ordersRefund);
|
return ordersRefundMapper.selectOne(wrapper);
|
}
|
|
@Override
|
public List<OrdersRefund> findList(OrdersRefund ordersRefund) {
|
QueryWrapper<OrdersRefund> wrapper = new QueryWrapper<>(ordersRefund);
|
return ordersRefundMapper.selectList(wrapper);
|
}
|
|
@Override
|
public PageData<OrdersRefund> findPage(PageWrap<OrdersRefund> pageWrap) {
|
IPage<OrdersRefund> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
|
QueryWrapper<OrdersRefund> queryWrapper = new QueryWrapper<>();
|
OrdersRefund model = pageWrap.getModel();
|
if (model != null) {
|
if (model.getOrderId() != null) {
|
queryWrapper.lambda().eq(OrdersRefund::getOrderId, model.getOrderId());
|
}
|
if (model.getType() != null) {
|
queryWrapper.lambda().eq(OrdersRefund::getType, model.getType());
|
}
|
}
|
for (PageWrap.SortData sortData : pageWrap.getSorts()) {
|
if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) {
|
queryWrapper.orderByDesc(sortData.getProperty());
|
} else {
|
queryWrapper.orderByAsc(sortData.getProperty());
|
}
|
}
|
return PageData.from(ordersRefundMapper.selectPage(page, queryWrapper));
|
}
|
|
@Override
|
public long count(OrdersRefund ordersRefund) {
|
QueryWrapper<OrdersRefund> wrapper = new QueryWrapper<>(ordersRefund);
|
return ordersRefundMapper.selectCount(wrapper);
|
}
|
|
@Override
|
public PageData<OrdersRefundPageVO> refundPage(PageWrap<OrdersRefundPageDTO> pageWrap) {
|
OrdersRefundPageDTO model = pageWrap.getModel();
|
IPage<OrdersRefund> page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity());
|
|
MPJLambdaWrapper<OrdersRefund> wrapper = new MPJLambdaWrapper<>();
|
wrapper.selectAll(OrdersRefund.class)
|
.select("o.code as orderCode")
|
.select("o.goods_info as goodsInfo")
|
.select("o.type as orderType")
|
.select("o.good_level as goodLevel")
|
.select("o.total_amount as totalAmount")
|
.select("o.pay_amount as payAmount")
|
.select("c2.name as goodLevelName")
|
.leftJoin("orders o on o.id = t.ORDER_ID and o.DELETED = 0")
|
.leftJoin("category c1 on c1.id = o.GOOD_TYPE and c1.DELETED = 0")
|
.leftJoin("category c2 on c2.id = c1.RELATION_ID and c2.DELETED = 0 and c2.TYPE = 3")
|
.eq(OrdersRefund::getDeleted, 0);
|
|
if (model != null) {
|
if (StringUtils.isNotBlank(model.getOrderCode())) {
|
wrapper.like("o.code", model.getOrderCode());
|
}
|
if (StringUtils.isNotBlank(model.getGoodsInfo())) {
|
wrapper.like("o.goods_info", model.getGoodsInfo());
|
}
|
if (model.getOrderType() != null) {
|
wrapper.eq("o.type", model.getOrderType());
|
}
|
if (model.getRefundStatus() != null) {
|
wrapper.eq(OrdersRefund::getStatus, model.getRefundStatus());
|
}
|
if (model.getCreateStartTime() != null) {
|
wrapper.ge(OrdersRefund::getCreateTime, model.getCreateStartTime());
|
}
|
if (model.getCreateEndTime() != null) {
|
wrapper.le(OrdersRefund::getCreateTime, model.getCreateEndTime());
|
}
|
}
|
|
wrapper.orderByDesc(OrdersRefund::getCreateTime);
|
|
IPage<OrdersRefund> refundPage = ordersRefundMapper.selectJoinPage(page, OrdersRefund.class, wrapper);
|
|
// 转换为 VO
|
List<OrdersRefundPageVO> voList = new ArrayList<>();
|
if (refundPage != null && refundPage.getRecords() != null) {
|
for (OrdersRefund r : refundPage.getRecords()) {
|
OrdersRefundPageVO vo = new OrdersRefundPageVO();
|
vo.setId(r.getId());
|
vo.setOrderId(r.getOrderId());
|
vo.setOrderCode(r.getOrderCode());
|
vo.setGoodsInfo(r.getGoodsInfo());
|
vo.setOrderType(r.getOrderType());
|
vo.setGoodLevelName(r.getGoodLevelName());
|
vo.setTotalAmount(r.getTotalAmount());
|
vo.setPayAmount(r.getPayAmount());
|
vo.setRefundAmount(r.getRefundAmount());
|
vo.setCreateTime(r.getCreateTime());
|
vo.setRefundStatus(r.getStatus());
|
voList.add(vo);
|
}
|
}
|
|
PageData<OrdersRefundPageVO> result = new PageData<>(
|
refundPage != null ? refundPage.getCurrent() : pageWrap.getPage(),
|
refundPage != null ? refundPage.getSize() : pageWrap.getCapacity());
|
result.setRecords(voList);
|
if (refundPage != null) {
|
result.setTotal(refundPage.getTotal());
|
}
|
return result;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void retryRefund(Integer id) {
|
// 1. 查询退款记录
|
OrdersRefund refundRecord = ordersRefundMapper.selectById(id);
|
if (refundRecord == null || Constants.ONE.equals(refundRecord.getDeleted())) {
|
throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "退款记录不存在");
|
}
|
if (!Constants.TWO.equals(refundRecord.getStatus())) {
|
throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅退款失败的记录可重新退款");
|
}
|
|
// 2. 查询关联订单
|
Orders order = ordersMapper.selectById(refundRecord.getOrderId());
|
if (order == null || Constants.ONE.equals(order.getDeleted())) {
|
throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "关联订单不存在");
|
}
|
if (StringUtils.isBlank(order.getOutTradeNo())) {
|
throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单缺少微信支付单号");
|
}
|
|
// 3. 发起微信退款
|
String outRefundNo = com.doumee.core.utils.ID.nextGUID();
|
com.wechat.pay.java.service.refund.model.Refund refundResult;
|
try {
|
refundResult = wxPayV3Service.refund(
|
outRefundNo,
|
order.getOutTradeNo(),
|
order.getPayAmount(),
|
refundRecord.getRefundAmount(),
|
"重新退款",
|
wxPayProperties.getV3RefundNotifyUrl());
|
} catch (Exception e) {
|
log.error("重新退款调用异常, refundRecordId={}", id, e);
|
throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "退款失败,请稍后重试");
|
}
|
|
// 4. 更新退款记录
|
Date now = new Date();
|
com.wechat.pay.java.service.refund.model.Status wxStatus = refundResult.getStatus();
|
OrdersRefund update = new OrdersRefund();
|
update.setId(id);
|
update.setRefundCode(outRefundNo);
|
update.setUpdateTime(now);
|
|
if (com.wechat.pay.java.service.refund.model.Status.SUCCESS.equals(wxStatus)) {
|
update.setStatus(Constants.ONE);
|
update.setRefundTime(now);
|
} else if (com.wechat.pay.java.service.refund.model.Status.PROCESSING.equals(wxStatus)) {
|
update.setStatus(Constants.ZERO);
|
} else {
|
update.setStatus(Constants.TWO);
|
update.setRefundRemark("重新退款仍然失败");
|
}
|
ordersRefundMapper.updateById(update);
|
}
|
}
|