RefundServiceImpl.java 6.11 KB
package com.diligrp.rider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.diligrp.rider.common.exception.BizException;
import com.diligrp.rider.entity.OrderRefundReason;
import com.diligrp.rider.entity.OrderRefundRecord;
import com.diligrp.rider.entity.Orders;
import com.diligrp.rider.mapper.OrderRefundReasonMapper;
import com.diligrp.rider.mapper.OrderRefundRecordMapper;
import com.diligrp.rider.mapper.OrdersMapper;
import com.diligrp.rider.entity.*;
import com.diligrp.rider.mapper.*;
import com.diligrp.rider.service.RefundService;
import com.diligrp.rider.service.WebhookService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class RefundServiceImpl implements RefundService {

    private final OrderRefundReasonMapper reasonMapper;
    private final OrderRefundRecordMapper recordMapper;
    private final OrdersMapper ordersMapper;
    private final WebhookService webhookService;
    private final ObjectMapper objectMapper;

    @Override
    public List<OrderRefundReason> getReasons(int role) {
        return reasonMapper.selectList(new LambdaQueryWrapper<OrderRefundReason>()
                .eq(role > 0, OrderRefundReason::getRole, role)
                .orderByAsc(OrderRefundReason::getListOrder));
    }

    @Override
    @Transactional
    public void applyRefund(Long orderId, Long uid, int role, Long reasonId, String reason) {
        Orders order = ordersMapper.selectById(orderId);
        if (order == null) throw new BizException("订单不存在");

        // 用户申请:必须是自己的订单且已完成或服务中
        if (role == 1) {
            if (!uid.equals(order.getUid())) throw new BizException("订单信息错误");
            if (order.getStatus() < 3 || order.getStatus() == 10) throw new BizException("当前订单状态不可申请退款");
        }
        // 骑手申请:必须是自己接的单
        if (role == 2) {
            if (!uid.equals(order.getRiderId())) throw new BizException("订单信息错误");
            if (order.getStatus() != 3 && order.getStatus() != 4) throw new BizException("当前订单状态不可申请退款");
        }

        // 检查是否已有退款申请
        Long exists = recordMapper.selectCount(new LambdaQueryWrapper<OrderRefundRecord>()
                .eq(OrderRefundRecord::getOid, orderId)
                .ne(OrderRefundRecord::getStatus, 2));
        if (exists > 0) throw new BizException("该订单已有退款申请,请勿重复提交");

        // 更新订单状态为退款申请中
        ordersMapper.update(null, new LambdaUpdateWrapper<Orders>()
                .eq(Orders::getId, orderId)
                .set(Orders::getStatus, 7));

        // 写退款记录
        OrderRefundRecord record = new OrderRefundRecord();
        record.setOid(orderId);
        record.setOrderNo(order.getOrderNo());
        record.setUid(uid);
        record.setRole(role);
        record.setReasonId(reasonId);
        record.setReason(reason);
        record.setMoney(order.getMoneyDelivery());
        record.setStatus(0);
        record.setAddTime(System.currentTimeMillis() / 1000);
        recordMapper.insert(record);

        // 通知接入方
        notifyRefundEvent(order, "order.refund_apply");
    }

    @Override
    @Transactional
    public void handleRefund(Long recordId, int status, String remark) {
        OrderRefundRecord record = recordMapper.selectById(recordId);
        if (record == null) throw new BizException("退款记录不存在");
        if (record.getStatus() != 0) throw new BizException("该退款申请已处理");

        long now = System.currentTimeMillis() / 1000;
        recordMapper.update(null, new LambdaUpdateWrapper<OrderRefundRecord>()
                .eq(OrderRefundRecord::getId, recordId)
                .set(OrderRefundRecord::getStatus, status)
                .set(OrderRefundRecord::getRemark, remark)
                .set(OrderRefundRecord::getHandleTime, now));

        Orders order = ordersMapper.selectById(record.getOid());
        if (order == null) return;

        if (status == 1) {
            // 退款通过 → 订单状态改为退款成功
            ordersMapper.update(null, new LambdaUpdateWrapper<Orders>()
                    .eq(Orders::getId, record.getOid())
                    .set(Orders::getStatus, 8));
            notifyRefundEvent(order, "order.refund_success");
        } else {
            // 退款拒绝 → 订单状态改为退款拒绝
            ordersMapper.update(null, new LambdaUpdateWrapper<Orders>()
                    .eq(Orders::getId, record.getOid())
                    .set(Orders::getStatus, 9));
            notifyRefundEvent(order, "order.refund_reject");
        }
    }

    @Override
    public OrderRefundRecord getByOrderId(Long orderId) {
        return recordMapper.selectOne(new LambdaQueryWrapper<OrderRefundRecord>()
                .eq(OrderRefundRecord::getOid, orderId)
                .orderByDesc(OrderRefundRecord::getId)
                .last("LIMIT 1"));
    }

    private void notifyRefundEvent(Orders order, String event) {
        try {
            if (order.getAppKey() == null || order.getAppKey().isBlank()) return;
            Map<String, Object> payload = new HashMap<>();
            payload.put("event", event);
            payload.put("outOrderNo", order.getOutOrderNo());
            payload.put("deliveryOrderId", order.getId());
            payload.put("orderNo", order.getOrderNo());
            payload.put("status", order.getStatus());
            payload.put("timestamp", System.currentTimeMillis() / 1000);
            webhookService.send(event, order.getId(), objectMapper.writeValueAsString(payload));
        } catch (Exception e) {
            log.warn("退款事件通知失败 orderId={}", order.getId(), e);
        }
    }
}