doum
11 小时以前 59b1f0e9967902aa10f5e017d5a0bdfd1b60c9ea
server/services/src/main/java/com/doumee/service/business/impl/OrdersRefundServiceImpl.java
@@ -3,15 +3,31 @@
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;
/**
@@ -19,11 +35,21 @@
 * @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) {
@@ -110,4 +136,135 @@
        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);
    }
}