longz
2026-07-09 47c9a4de5451b06724ed3b5256f9592fffec8b76
DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/specialTrain/server/impl/OrderPrivateCarServiceImpl.java
@@ -18,6 +18,7 @@
import com.stylefeng.guns.modular.system.util.*;
import com.stylefeng.guns.modular.taxi.model.OrderTaxi;
import com.stylefeng.guns.modular.taxi.service.IOrderTaxiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
@@ -28,7 +29,7 @@
import java.math.RoundingMode;
import java.util.*;
@Slf4j
@Service
public class OrderPrivateCarServiceImpl extends ServiceImpl<OrderPrivateCarMapper, OrderPrivateCar> implements IOrderPrivateCarService {
@@ -955,21 +956,36 @@
            return;
        }
        PaymentRecord paymentRecord = paymentRecordService.query(1, orderPrivateCar.getUserId(), 1, orderPrivateCar.getId(), 1, orderPrivateCar.getPayType(), 2);
        if (paymentRecord == null || ToolUtil.isEmpty(paymentRecord.getCode())) {
            System.err.println("预支付退款数据异常(privateCarOrderId = " + orderPrivateCar.getId() + ")");
            return;
        }
        if (Integer.valueOf(1).equals(orderPrivateCar.getPayType())) {
            Map<String, String> map = payMoneyUtil.wxRefund(paymentRecord.getCode(), refundNo, paymentRecord.getAmount().toString(), refundMoney.toString(), "/base/prepayRefundWXPay");
            if (!"SUCCESS".equals(map.get("return_code"))) {
                System.err.println("专车预支付退款申请失败:" + map.get("return_msg"));
            String outRequestNo = orderPrivateCar.getPrepaySecondPayNo();
            if (ToolUtil.isEmpty(outRequestNo)) {
                System.err.println("快车微信先付订单缺少支付单号,无法关闭支付单(privateCarOrderId = " + orderPrivateCar.getId() + ")");
                return;
            }
            CbyzxPayUtil.ClosePayOrderRequest request = new CbyzxPayUtil.ClosePayOrderRequest();
            request.setOutRequestNo(outRequestNo);
            request.setRefundOutRequestNo(refundNo);
            request.setRefundAmount(toFen(refundMoney));
            request.setRefundDesc("快车预支付多退退款");
            JSONObject response = CbyzxPayUtil.closePayOrder(request);
            if (isPrepayRefundSuccess(response)) {
                String responseRefundNo = extractPrepayRefundNo(response);
                if (ToolUtil.isNotEmpty(responseRefundNo)) {
                    orderPrivateCar.setPrepayRefundNo(responseRefundNo);
                }
                finishPrepaidOrder(orderPrivateCar);
            } else {
                System.err.println("快车微信先付退款申请失败:" + extractPrepayRefundMessage(response));
            }
            return;
        }
        if (Integer.valueOf(2).equals(orderPrivateCar.getPayType())) {
            PaymentRecord paymentRecord = paymentRecordService.query(1, orderPrivateCar.getUserId(), 1, orderPrivateCar.getId(), 1, orderPrivateCar.getPayType(), 2);
            if (paymentRecord == null || ToolUtil.isEmpty(paymentRecord.getCode())) {
                System.err.println("预支付退款数据异常(privateCarOrderId = " + orderPrivateCar.getId() + ")");
                return;
            }
            try {
                Map<String, String> map = payMoneyUtil.aliRefund(paymentRecord.getCode(), refundMoney.toString());
                if ("10000".equals(map.get("code"))) {
@@ -1013,6 +1029,53 @@
    private String buildPrepayRefundNo(Integer orderType, Integer orderId) {
        return "PRF_" + orderType + "_" + orderId + "_" + System.currentTimeMillis();
    }
    private Integer toFen(Double amount) {
        return new BigDecimal(String.valueOf(amount)).multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP).intValue();
    }
    private boolean isPrepayRefundSuccess(JSONObject response) {
        if (response == null) {
            return false;
        }
        Object code = response.get("code");
        if (code == null || !"0".equals(String.valueOf(code))) {
            return false;
        }
        JSONObject data = response.getJSONObject("data");
        return data != null && Boolean.TRUE.equals(data.getBoolean("isSuccess"));
    }
    private String extractPrepayRefundNo(JSONObject response) {
        if (response == null) {
            return null;
        }
        JSONObject data = response.getJSONObject("data");
        if (data == null) {
            return null;
        }
        String refundNo = data.getString("merchantRefundSerialNo");
        if (ToolUtil.isNotEmpty(refundNo)) {
            return refundNo;
        }
        refundNo = data.getString("refundId");
        if (ToolUtil.isNotEmpty(refundNo)) {
            return refundNo;
        }
        return data.getString("gatewaySerialNo");
    }
    private String extractPrepayRefundMessage(JSONObject response) {
        if (response == null) {
            return "微信先付退款失败";
        }
        JSONObject data = response.getJSONObject("data");
        if (data != null && ToolUtil.isNotEmpty(data.getString("failReason"))) {
            return data.getString("failReason");
        }
        String msg = response.getString("msg");
        return ToolUtil.isNotEmpty(msg) ? msg : "微信先付退款失败";
    }
    private Double formatMoney(Double money) {
@@ -1244,9 +1307,11 @@
            double estimateMileage = (null == orderPrivateCar.getEstimateMileage() ? 0D : orderPrivateCar.getEstimateMileage());
            System.out.println("预估里程数"+estimateMileage);
            //在价格区间按照一口价算,不在区间按实时价格算
            if(d<estimateMileage+contentPrice.getDouble("num29")*1000 && d>estimateMileage-contentPrice.getDouble("num32")*1000){
            double exceedMileageInner = Optional.ofNullable(query1.get("exceedMileageInner")).map(Object::toString).map(Double::parseDouble).orElse(0d);
            double belowMileageInner = Optional.ofNullable(query1.get("belowMileageInner")).map(Object::toString).map(Double::parseDouble).orElse(0d);
            if(d<estimateMileage+exceedMileageInner*1000 && d>estimateMileage-belowMileageInner*1000) {
                System.out.println("在区间===============");
                orderPrivateCar = calculationPrice1(orderPrivateCar,contentPrice,jsonObject.getLongValue("num1"),jsonObject.getDouble("num2"),parkingFee,crossingFee);
                orderPrivateCar = calculationPrice(orderPrivateCar,contentPrice,jsonObject.getLongValue("num1"),jsonObject.getDouble("num2"),parkingFee,crossingFee);
                System.out.println("返回订单数据"+orderPrivateCar);
            }else{
                System.out.println("不在区间====================");
@@ -1285,6 +1350,181 @@
        return orderPrivateCar;
    }
    /**
     * sky
     * 公共费用计算
     * @param orderPrivateCar
     * @param rule  计费规则
     * @param wait  规则-等待时长
     * @param waitMoney 规则-等待单价
     * @param parkingFee    停车费
     * @param crossingFee   过路费
     * @return
     * @throws Exception
     */
    public OrderPrivateCar calculationPrice(OrderPrivateCar orderPrivateCar, JSONObject rule,
                                            long wait, Double waitMoney,
                                            Double parkingFee, Double crossingFee) throws Exception {
        orderPrivateCar.setChargeRule(rule.toJSONString());
        Date date = new Date();
        if (orderPrivateCar.getEndServiceTime() == null) {
            orderPrivateCar.setEndServiceTime(date);
        }
        double d  = (orderPrivateCar.getMileage() == null ? 0D : orderPrivateCar.getMileage()) / 1000;
        double t  = ((orderPrivateCar.getEndServiceTime().getTime()
                - orderPrivateCar.getStartServiceTime().getTime()) / 60000) + 1;
        double d1 = Math.max(0, d - rule.getDouble("num2"));
        double t1 = Math.max(0, t - rule.getDouble("num3"));
        double w  = ((orderPrivateCar.getStartServiceTime().getTime()
                - orderPrivateCar.getArriveTime().getTime()) / 60000) + 1;
        double w1 = (w - wait) < 0 ? 0
                : new BigDecimal(w - wait).setScale(0, BigDecimal.ROUND_UP).doubleValue();
        // 从 num14 开始,每 7 个为一组:numI=时间区间, +1=起步价, +2=里程费率,
        //   +3=时长费率, +4=远途1费率, +5=远途2费率, +6=远途3费率
        int startIndex = 14;
        boolean matched = false;
        while (rule.containsKey("num" + startIndex)) {
            // 必须保证后续 6 个参数都存在
            if (!rule.containsKey("num" + (startIndex + 6))) {
                break;
            }
            String timeRange = rule.getString("num" + startIndex);
            // 兼容 "HH:mm - HH:mm" 和 "HH:mm-HH:mm" 两种格式
            String[] parts = timeRange.split("\\s*-\\s*");
            if (parts.length != 2) {
                startIndex += 7;
                continue;
            }
            try {
                Calendar rangeStart = parseTimeToCalendar(date, parts[0].trim());
                Calendar rangeEnd   = parseTimeToCalendar(date, parts[1].trim());
                // 跨天处理(如 "20:00 - 02:00")
                if (rangeStart.getTimeInMillis() > rangeEnd.getTimeInMillis()) {
                    rangeEnd.add(Calendar.DAY_OF_YEAR, 1);
                }
                boolean inRange = date.getTime() > rangeStart.getTimeInMillis()
                        && date.getTime() < rangeEnd.getTimeInMillis();
                if (inRange) {
                    double qibujia  = rule.getDouble("num" + (startIndex + 1));
                    double lchengLv = rule.getDouble("num" + (startIndex + 2));
                    double schangLv = rule.getDouble("num" + (startIndex + 3));
                    double yt1Lv    = rule.getDouble("num" + (startIndex + 4));
                    double yt2Lv    = rule.getDouble("num" + (startIndex + 5));
                    double yt3Lv    = rule.getDouble("num" + (startIndex + 6));
                    applyPricing(orderPrivateCar, rule, d, d1, t1, w1,
                            waitMoney, parkingFee, crossingFee,
                            qibujia, lchengLv, schangLv, yt1Lv, yt2Lv, yt3Lv);
                    matched = true;
                    break;
                }
            } catch (Exception e) {
                // 时间解析异常时跳过该组,继续匹配下一组
            }
            startIndex += 7;
        }
        // 无任何时间组匹配,使用基础费率(num1 ~ num13)
        if (!matched) {
            applyPricing(orderPrivateCar, rule, d, d1, t1, w1,
                    waitMoney, parkingFee, crossingFee,
                    rule.getDouble("num1"),
                    rule.getDouble("num4"),
                    rule.getDouble("num5"),
                    rule.getDouble("num8"),
                    rule.getDouble("num11"),
                    rule.getDouble("num13"));
        }
        return orderPrivateCar;
    }
    /**
     * sky
     * 将 "HH:mm" 解析为基于 baseDate 当天的 Calendar
     */
    private Calendar parseTimeToCalendar(Date baseDate, String hhmm) {
        String[] hm = hhmm.split(":");
        Calendar cal = Calendar.getInstance();
        cal.setTime(baseDate);
        cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hm[0]));
        cal.set(Calendar.MINUTE,      Integer.parseInt(hm[1]));
        cal.set(Calendar.SECOND,      0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal;
    }
    /**
     * sky
     * 按指定费率计算远途费、各项费用,并写入 orderPrivateCar
     *
     * 远途分段逻辑(与原代码保持一致):
     *   段1:num6 < d < num7  → yt1 = yt1Lv * d
     *   段2:num9 < d < num10 → yt1 = yt1Lv * num7,  yt2 = yt2Lv * (d - num9)
     *   段3:d > num12        → yt1 = yt1Lv * num7,  yt2 = yt2Lv * (num10 - num9),  yt3 = yt3Lv * (d - num12)
     */
    private void applyPricing(OrderPrivateCar orderPrivateCar, JSONObject rule,
                              double d, double d1, double t1, double w1,
                              Double waitMoney, Double parkingFee, Double crossingFee,
                              double qibujia, double lchengLv, double schangLv,
                              double yt1Lv, double yt2Lv, double yt3Lv) {
        double num6  = rule.getDouble("num6");
        double num7  = rule.getDouble("num7");
        double num9  = rule.getDouble("num9");
        double num10 = rule.getDouble("num10");
        double num12 = rule.getDouble("num12");
        double yt1 = 0, yt2 = 0, yt3 = 0;
        if (d > num6 && d < num7) {
            yt1 = yt1Lv * d;
        }
        if (d > num9 && d < num10) {
            yt1 = yt1Lv * num7;
            yt2 = yt2Lv * (d - num9);
        }
        if (d > num12) {
            yt1 = yt1Lv * num7;
            yt2 = yt2Lv * (num10 - num9);
            yt3 = yt3Lv * (d - num12);
        }
        double mileageMoney  = new BigDecimal(d1 * lchengLv).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        double durationMoney = new BigDecimal(t1 * schangLv).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        double waitMoneyAmt  = new BigDecimal(w1 * waitMoney).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        double longDistMoney = new BigDecimal(yt1 + yt2 + yt3).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
        orderPrivateCar.setStartMileage(rule.getDouble("num2"));
        orderPrivateCar.setStartMoney(qibujia);
        orderPrivateCar.setMileageKilometers(new BigDecimal(d1).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
        orderPrivateCar.setMileageMoney(mileageMoney);
        orderPrivateCar.setDuration(new BigDecimal(t1).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
        orderPrivateCar.setDurationMoney(durationMoney);
        orderPrivateCar.setWait(new BigDecimal(w1).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
        orderPrivateCar.setWaitMoney(waitMoneyAmt);
        orderPrivateCar.setLongDistance(new BigDecimal(d > num6 ? d - num6 : 0).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
        orderPrivateCar.setLongDistanceMoney(longDistMoney);
        orderPrivateCar.setParkMoney(parkingFee);
        orderPrivateCar.setRoadTollMoney(crossingFee);
        orderPrivateCar.setRedPacketMoney(0D);
        orderPrivateCar.setCouponMoney(0D);
        orderPrivateCar.setDiscount(0D);
        orderPrivateCar.setPayMoney(0D);
        double amount = qibujia + mileageMoney + durationMoney + waitMoneyAmt + longDistMoney;
        orderPrivateCar.setOrderMoney(amount + parkingFee + crossingFee);
    }
    /**
     * 公共费用计算
@@ -1297,7 +1537,8 @@
     * @return
     * @throws Exception
     */
    public OrderPrivateCar  calculationPrice(OrderPrivateCar orderPrivateCar,JSONObject rule, long wait,Double waitMoney, Double parkingFee, Double crossingFee) throws Exception {
    @Deprecated
    public OrderPrivateCar  calculationPriceBack(OrderPrivateCar orderPrivateCar,JSONObject rule, long wait,Double waitMoney, Double parkingFee, Double crossingFee) throws Exception {
        orderPrivateCar.setChargeRule(rule.toJSONString());
        double amount = 0.0;
        //等待费