liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -4,6 +4,7 @@
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@@ -18,6 +19,9 @@
import com.xiaopeng.api.dto.account.UseUserCouponDto;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
import com.xiaopeng.api.dto.automaticPilot.VehicleEventDTO;
import com.xiaopeng.api.dto.frdXfipEvent.XpFrdXfipEventCouponLineDTO;
import com.xiaopeng.api.dto.frdXfipEvent.XpFrdXfipEventIngestContentDTO;
import com.xiaopeng.api.dto.frdXfipEvent.XpFrdXfipEventIngestReqDTO;
import com.xiaopeng.api.dto.map.OrderRouteAndFareDto;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
@@ -30,10 +34,12 @@
import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto;
import com.xiaopeng.api.feignClient.account.SysGroupMenuClient;
import com.xiaopeng.api.feignClient.account.UserResourcesClient;
import com.xiaopeng.api.feignClient.account.XpAppUserClient;
import com.xiaopeng.api.feignClient.account.XpAppUserCollectAddrClient;
import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.automaticPilot.VehicleBuriedPointClient;
import com.xiaopeng.api.feignClient.frdXfipEvent.XpFrdXfipEventClient;
import com.xiaopeng.api.feignClient.maintenance.XpTaskRuleClient;
import com.xiaopeng.api.feignClient.map.XpMapClient;
import com.xiaopeng.api.feignClient.map.XpStationClient;
@@ -44,6 +50,7 @@
import com.xiaopeng.api.feignClient.vehicleConvoy.*;
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.operation.*;
import com.xiaopeng.api.model.account.XpAppUser;
import com.xiaopeng.api.model.order.*;
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
@@ -57,6 +64,7 @@
import com.xiaopeng.api.vo.automaticPilot.protobuf.OrderOperationType;
import com.xiaopeng.api.vo.automaticPilot.protobuf.OrderStatus;
import com.xiaopeng.api.vo.automaticPilot.protobuf.TaskActionType;
import com.xiaopeng.api.vo.frdXfipEvent.XpFrdXfipEventIngestRespVO;
import com.xiaopeng.api.vo.operation.NearestNextVo;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.*;
@@ -82,6 +90,7 @@
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.common.security.utils.SecurityUtils;
import com.xiaopeng.order.config.MinistryTransportProperties;
import com.xiaopeng.order.constant.I18nKeyConstant;
import com.xiaopeng.order.dto.MileageDto;
import com.xiaopeng.order.dto.UserOrderListDto;
@@ -93,6 +102,9 @@
import com.xiaopeng.order.mapper.XpCruiseOrderMapper;
import com.xiaopeng.order.mapper.XpOrderDetailMapper;
import com.xiaopeng.order.mapper.XpOrderMapper;
import com.xiaopeng.order.model.dto.CreditPaySuccessCallDto;
import com.xiaopeng.order.model.dto.RegulationOrderCreateInfoDTO;
import com.xiaopeng.order.model.dto.RegulationOrderMatchInfoDTO;
import com.xiaopeng.order.model.dto.XpOrderCommentDto;
import com.xiaopeng.order.model.dto.XpOrderPayDto;
import com.xiaopeng.order.model.query.XpHistoryOrderListQuery;
@@ -100,6 +112,7 @@
import com.xiaopeng.order.model.query.XpOrderPageQuery;
import com.xiaopeng.order.model.vo.*;
import com.xiaopeng.order.service.*;
import com.xiaopeng.order.utils.MinistryOfTransportOrderReporter;
import com.xiaopeng.order.utils.*;
import com.xiaopeng.order.utils.holiday.HolidayUtil;
import com.xiaopeng.order.vo.*;
@@ -156,10 +169,12 @@
    private final UserResourcesClient userResourcesClient;
    private final XpPointClient xpPointClient;
    private final XpVehicleClient xpVehicleClient;
    private final XpAppUserClient xpAppUserClient;
    private final XpAppUserCouponClient xpAppUserCouponClient;
    private final XpFleetClient xpFleetClient;
    private final XpFleetVehicleClient xpFleetVehicleClient;
    private final UserVehicleClient userVehicleClient;
    private final MinistryTransportProperties ministryTransportProperties;
    @Lazy
    @Autowired
    private IXpOrderEvaluateService xpOrderEvaluateService;
@@ -184,13 +199,12 @@
    @Autowired
    private IXpTestOrderService xpTestOrderService;
    private final XpMapClient xpMapClient;
    private final MinistryOfTransportOrderReporter ministryOfTransportOrderReporter;
    @Resource
    private XpRoutePlanClient xpRoutePlanClient;
    @Resource
    @Lazy
    private BootCommonService bootCommonService;
    @Autowired
    private SysGroupMenuClient sysGroupMenuClient;
    @Autowired
    private XpCruiseOrderClient xpCruiseOrderClient;
@@ -218,6 +232,12 @@
    private XpPayFrontClient xpPayFrontClient;
    @Resource
    private XpStationClient xpStationClient;
    @Resource
    private XpFrdXfipEventClient xpFrdXfipEventClient;
    @Resource
    private XpTargetedServiceClient targetedServiceClient;
    @Value("${robotaxi.appId:xp_robotaxi_api}")
    private String appid;
@@ -510,7 +530,6 @@
        if (Objects.nonNull(query.getEndTime())) {
            wrapper.le(XpOrder::getCreateTime, LocalDateTime.of(query.getEndTime(), LocalTime.MAX));
        }
        wrapper.orderByDesc(XpOrder::getCreateTime);
        return wrapper;
    }
@@ -669,7 +688,7 @@
        if (Objects.nonNull(order.getAppUserId()) && userInfoMap != null && userInfoMap.containsKey(order.getAppUserId().toString())) {
            UcUserInfo userInfo = userInfoMap.get(order.getAppUserId().toString());
            vo.setNickName(userInfo.getNickName());
            if(!loginUser.getPhoneDesensitizationExempt()){
            if (!loginUser.getPhoneDesensitizationExempt()) {
                vo.setPhoneNumber(DesensitizedUtil.mobilePhone(userInfo.getMobile()));
            }
@@ -695,7 +714,9 @@
     * 取消订单
     */
    private void cancelOrder(XpOrder order) {
        redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
        if(StringUtils.isNotEmpty(order.getQueueName())){
            redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
        }
        Long userId = order.getAppUserId();
        Integer status = order.getStatus();
@@ -706,22 +727,26 @@
            baseMapper.updateById(order);
            order.setAppUserId(appUserId);
            bootCommonService.setCache_orderStatus(order.getId(), order, null);
            if(null == order.getOfficialPartnerId()){
            if (null == order.getOfficialPartnerId()) {
                //删除蓝牙秘钥
                String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId());
                if (StringUtils.isNotBlank(token)) {
                    redisService.deleteObject("rt:bluetooth:unlock:" + token);
                    redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId());
                    XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
                    BluetoothDeliverVo vo = new BluetoothDeliverVo();
                    vo.setCredential(token);
                    String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
                    vo.setVin(vin);
                    vo.setPassengerUid(order.getAppUserId());
                    BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
                    if (null == delete || delete.getCode() != 0) {
                        log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
                try {
                    String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId());
                    if (StringUtils.isNotBlank(token)) {
                        redisService.deleteObject("rt:bluetooth:unlock:" + token);
                        redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId());
                        XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
                        BluetoothDeliverVo vo = new BluetoothDeliverVo();
                        vo.setCredential(token);
                        String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
                        vo.setVin(vin);
                        vo.setPassengerUid(order.getAppUserId());
                        BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
                        if (null == delete || delete.getCode() != 0) {
                            log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            // 消息推送
@@ -806,7 +831,7 @@
        }
        log.info("运营人员取消订单成功,推送乘客消息完成");
        if(null == order.getOfficialPartnerId()){
        if (null == order.getOfficialPartnerId()) {
            //判断还原车辆状态
            if (null == order.getVehicleId()) {
                Object cacheObject1 = redisService.getCacheObject("CREATE_ORDER:" + order.getId().toString());
@@ -837,8 +862,7 @@
                cancelTaxiPassengerVo.setAppId(appid);
                BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
                if (baseVehicleUserDto == null) {
                    // TODO 本地无法调通
//            throw new RuntimeException("取消订单失败");
                    log.info("取消用户车辆绑定关系失败:{}", JSON.toJSONString(baseVehicleUserDto));
                }
                //还原车辆状态
@@ -851,12 +875,13 @@
                }
                // 下发命令
//            PushOrderDto pushOrderDto = new PushOrderDto();
//            pushOrderDto.setOrderId(order.getId().toString());
//            pushOrderDto.setVin(xpVehicle.getVehicleVin());
//            pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
//            orderMissionClient.cancelOrder(pushOrderDto);
//            log.info("运营人员取消订单成功,开始执行巡游订单 {}", order.getId());
                PushOrderDto pushOrderDto = new PushOrderDto();
                pushOrderDto.setEndTaskId(order.getStatus() < 6 ? order.getXpuStartTaskId() : order.getXpuEndTaskId());
                pushOrderDto.setOrderId(order.getId().toString());
                pushOrderDto.setVin(xpVehicle.getVehicleVin());
                pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
                orderMissionClient.cancelOrder(pushOrderDto);
                log.info("运营人员取消订单成功,开始执行巡游订单 {}", order.getId());
                //车辆继续巡游
                addCruiseMission(order, status);
@@ -864,7 +889,7 @@
                log.info("查询车辆信息失败,订单ID: {}, 下发取消订单命令失败", order.getId());
            }
            log.info("订单取消成功,订单ID: {}, 操作人: {}", order.getId(), SecurityUtils.getUsername());
        }else{
        } else {
            //流量接入-订单推送 推送取消订单
            officialPartnerUtil.pushCancelOrder(order.getOfficialPartnerId(), orderCancel, order.getStatus());
        }
@@ -899,7 +924,7 @@
        Long appUserId = order.getAppUserId();
        order.setAppUserId(null);
        this.updateById(order);
        order.setAppUserId(appUserId);
        bootCommonService.setCache_orderStatus(order.getId(), order, null);
        // 消息推送
@@ -1001,12 +1026,23 @@
            });
        }
        if(order.getOfficialPartnerId() == null){
        if (order.getOfficialPartnerId() == null) {
            //给车端发送取消靠边停车的报文
            PushOrderDto cancelDto = new PushOrderDto();
            cancelDto.setStartTaskId(order.getXpuStartTaskId());
            cancelDto.setEndTaskId(order.getXpuEndTaskId());
            cancelDto.setOrderId(order.getId().toString());
            cancelDto.setVin(vin);
            cancelDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
            cancelDto.setCancelScene(CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE.getCode());
            orderMissionClient.cancelOrder(cancelDto);
            //创建定时任务执行延迟驶离终点和下发巡游单
            XpPoint point = xpPointClient.queryById(order.getEndPointId()).getData();
            Integer parkingTimeLimit = point.getParkingTimeLimit();
            //如果点位位于场站内,则使用场站的限停时间
            if(null != point.getStationId()){
            if (null != point.getStationId()) {
                XpStation xpStation = xpStationClient.getXpStationById(point.getStationId()).getData();
                parkingTimeLimit = xpStation.getParkingTimeLimit();
            }
@@ -1022,7 +1058,7 @@
                    DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(parkingTimeLimit)),
                    jobMaps
            );
        }else{
        } else {
            //流量接入-订单推送 推送关闭订单
            officialPartnerUtil.pushEndOrder(order.getOfficialPartnerId(), order, "运维人员关闭订单");
        }
@@ -1221,7 +1257,7 @@
            pushOrderDto.setEndPoiName(order.getEndPointName());
            pushOrderDto.setOrderType(OrderType.USER_ORDER);
            pushOrderDto.setStage(1);
            if(null != cruiseOrder){
            if (null != cruiseOrder) {
                pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
            }
@@ -1343,7 +1379,11 @@
                returnOrder.setOrderReverse(lastCruise.getOrderReverse());
                log.info("巡游订单状态为{},默认返回原出发点", lastCruise.getStatus());
            }
            R<XpCruiseOrder> orderR = xpCruisePlanClient.findReturnCruisePoint(returnOrder);
            if(null != orderR && 200 != orderR.getCode()){
                log.error(orderR.getMsg());
                return;
            }
            xpCruiseOrderMapper.insert(returnOrder);
            // 下发巡游订单到原车辆
@@ -1359,7 +1399,7 @@
            pushOrderDto.setEndLongitude(returnOrder.getEndLon());
            pushOrderDto.setOrderType(OrderType.CRUISE_ORDER);
            pushOrderDto.setStage(2);
            if(null != lastCruise){
            if (null != lastCruise) {
                pushOrderDto.setLastOrderId("XU" + lastCruise.getId());
                pushOrderDto.setLastXpuTaskId(lastCruise.getXpuTaskId());
            }
@@ -1386,7 +1426,7 @@
            XpPoint startPoint = getPointById(startPointId);
            if (startPoint == null) {
                log.warn("获取用户快捷胶囊失败,起点不存在,uid:{}, startPointId:{}", uid, startPointId);
                log.info("获取用户快捷胶囊失败,起点不存在,uid:{}, startPointId:{}", uid, startPointId);
                return null;
            }
@@ -1448,13 +1488,18 @@
        }
        XpPoint start = getPointById(startPointId);
        GlobalCoordinates startCoordinates = new GlobalCoordinates(start.getPointLon(), start.getPointLat());
        List<Long> pointIdsByUserId = Optional.ofNullable(xpAppUserCollectAddrClient.getPointIdsByUserId(Long.valueOf(uid)).getData())
                .orElse(new ArrayList<>());
        List<Long> longList = xpAppUserCollectAddrClient.getPointIdsByUserId(Long.valueOf(uid)).getData();
        if (null == longList) {
            longList = new ArrayList<>();
        }
        for (Long pointId : endPointId) {
            XpPoint endPoint = getPointById(pointId);
            if(null == endPoint){
                continue;
            }
            Integer parkingTimeLimit = endPoint.getParkingTimeLimit();
            //如果点位位于场站内,则使用场站的限停时间
            if(null != endPoint.getStationId()){
            if (null != endPoint.getStationId()) {
                XpStation xpStation = xpStationClient.getXpStationById(endPoint.getStationId()).getData();
                parkingTimeLimit = xpStation.getParkingTimeLimit();
            }
@@ -1472,7 +1517,7 @@
                ret.setTime(parkingTimeLimit);
                ret.setElectronicAreaId(endPoint.getElectronicAreaId());
                // 判断是否收藏
                if (pointIdsByUserId.contains(endPoint.getId())) {
                if (longList.contains(endPoint.getId())) {
                    ret.setIsCollect(1);
                }
                return ret;
@@ -1555,7 +1600,7 @@
    private Integer getMinOrderDistanceSafely(String uid, Long startPointId) {
        R<Integer> result = xpSystemSettingClient.getMinOrderDistance();
        if (result == null || result.getCode() != R.SUCCESS || result.getData() == null) {
            log.error("获取用户快捷胶囊失败,最小下单距离配置异常,uid:{}, startPointId:{}, result:{}", uid, startPointId, JSON.toJSONString(result));
            log.info("获取用户快捷胶囊失败,最小下单距离配置异常,uid:{}, startPointId:{}, result:{}", uid, startPointId, JSON.toJSONString(result));
            return null;
        }
        return result.getData();
@@ -1711,7 +1756,7 @@
        }
        List<XpHistoryStartPointsVo> objects = new ArrayList<XpHistoryStartPointsVo>();
        if(!data.isEmpty()){
        if (!data.isEmpty()) {
            //收藏的数据
            List<XpHistoryStartPointsVo> collect = data.stream().filter(s -> s.getIsCollect() == 1)
                    .sorted(Comparator.comparing(XpHistoryStartPointsVo::getDistance)).collect(Collectors.toList());
@@ -1750,7 +1795,7 @@
            );
        }
        List<XpHistoryEndPointsVo> objects = new ArrayList<XpHistoryEndPointsVo>();
        if(!data.isEmpty()){
        if (!data.isEmpty()) {
            //收藏的数据
            List<XpHistoryEndPointsVo> collect = data.stream().filter(s -> s.getIsCollect() == 1)
                    .sorted(Comparator.comparing(XpHistoryEndPointsVo::getDistance)).collect(Collectors.toList());
@@ -1803,7 +1848,7 @@
                if (xpPoint != null) {
                    Integer parkingTimeLimit = xpPoint.getParkingTimeLimit();
                    //如果点位位于场站内,则使用场站的限停时间
                    if(null != xpPoint.getStationId()){
                    if (null != xpPoint.getStationId()) {
                        XpStation xpStation = xpStationClient.getXpStationById(xpPoint.getStationId()).getData();
                        parkingTimeLimit = xpStation.getParkingTimeLimit();
                    }
@@ -1818,7 +1863,7 @@
                if (xpPoint != null) {
                    Integer parkingTimeLimit = xpPoint.getParkingTimeLimit();
                    //如果点位位于场站内,则使用场站的限停时间
                    if(null != xpPoint.getStationId()){
                    if (null != xpPoint.getStationId()) {
                        XpStation xpStation = xpStationClient.getXpStationById(xpPoint.getStationId()).getData();
                        parkingTimeLimit = xpStation.getParkingTimeLimit();
                    }
@@ -1866,7 +1911,9 @@
            throw new ServiceException("订单状态错误", I18nKeyConstant.ORDER_STATUS_ERROR);
        }
        try {
            redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
            if(StringUtils.isNotEmpty(order.getQueueName())){
                redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
@@ -1888,7 +1935,7 @@
        // 移除mongo数据
        xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString());
        if(null == order.getOfficialPartnerId()){
        if (null == order.getOfficialPartnerId()) {
            //判断还原车辆状态
            if (null == order.getVehicleId()) {
                Object cacheObject1 = redisService.getCacheObject("CREATE_ORDER:" + order.getId().toString());
@@ -1912,9 +1959,11 @@
                }
                //是否能取消行程
                String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
                boolean cancelShow = this.isCancelShow(order, vin);
                if (cancelShow) {
                    throw new ServiceException("当前订单状态不允许取消,行程即将完成", I18nKeyConstant.ORDER_CANCEL_FAILED);
                if(status == 6){
                    boolean cancelShow = this.isCancelShow(order, vin);
                    if (cancelShow) {
                        throw new ServiceException("当前订单状态不允许取消,行程即将完成", I18nKeyConstant.ORDER_CANCEL_FAILED);
                    }
                }
                // 组装调用车机参数
@@ -1939,24 +1988,61 @@
                }
                //删除蓝牙秘钥
                String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId());
                if (StringUtils.isNotBlank(token)) {
                    redisService.deleteObject("rt:bluetooth:unlock:" + token);
                    redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId());
                    BluetoothDeliverVo vo = new BluetoothDeliverVo();
                    vo.setCredential(token);
                    vo.setVin(vin);
                    vo.setPassengerUid(order.getAppUserId());
                    BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
                    if (null == delete || delete.getCode() != 0) {
                        log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
                try {
                    String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId());
                    if (StringUtils.isNotBlank(token)) {
                        redisService.deleteObject("rt:bluetooth:unlock:" + token);
                        redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId());
                        BluetoothDeliverVo vo = new BluetoothDeliverVo();
                        vo.setCredential(token);
                        vo.setVin(vin);
                        vo.setPassengerUid(order.getAppUserId());
                        BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
                        if (null == delete || delete.getCode() != 0) {
                            log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //判断是否有连环单
                String json = redisService.getCacheObject(CacheConstants.nextOrder(order.getId().toString()));
                if (StringUtils.isNotEmpty(json)) {
                    JSONObject jsonObject = JSON.parseObject(json);
                    Long id = jsonObject.getLong("orderId");
                    //判断订单状态
                    XpOrder xpOrder1 = this.getById(id);
                    if (2 == xpOrder1.getStatus()) {
                        //开始推送订单给车端
                        // 下发命令
                        PushOrderDto pushOrderDto = new PushOrderDto();
                        pushOrderDto.setStartTaskId(xpOrder1.getXpuStartTaskId());
                        pushOrderDto.setEndTaskId(xpOrder1.getXpuEndTaskId());
                        pushOrderDto.setVin(vin);
                        pushOrderDto.setOrderId(xpOrder1.getId().toString());
                        pushOrderDto.setStartWaypointId(xpOrder1.getStartPointId());
                        pushOrderDto.setEndWaypointId(xpOrder1.getEndPointId());
                        pushOrderDto.setStartLatitude(xpOrder1.getStartLat());
                        pushOrderDto.setStartLongitude(xpOrder1.getStartLon());
                        pushOrderDto.setEndLatitude(xpOrder1.getEndLat());
                        pushOrderDto.setEndLongitude(xpOrder1.getEndLon());
                        pushOrderDto.setEndPoiName(xpOrder1.getEndPointName());
                        pushOrderDto.setOrderType(OrderType.USER_ORDER);
                        pushOrderDto.setStage(1);
                        pushOrderDto.setLastOrderId(order.getId().toString());
                        pushOrderDto.setLastXpuTaskId(status == 1 ? order.getXpuStartTaskId() : order.getXpuEndTaskId());
                        pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask);
                        // 调用推送服务  orderId + carVin
                        orderMissionClient.pushOrder(pushOrderDto);
                        log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder1.getOrderNumber(), xpOrder1.getOrderNumber());
                        return;
                    }
                }
                //车辆继续巡游
                addCruiseMission(order, status);
            }
        }else{
        } else {
            //流量接入-订单推送 推送取消订单
            officialPartnerUtil.pushCancelOrder(order.getOfficialPartnerId(), xpOrderCancel, order.getStatus());
        }
@@ -1976,22 +2062,26 @@
        baseMapper.updateById(order);
        order.setAppUserId(appUserId);
        bootCommonService.setCache_orderStatus(order.getId(), order, null);
        if(null == order.getOfficialPartnerId()){
        if (null == order.getOfficialPartnerId()) {
            //删除蓝牙秘钥
            String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId());
            if (StringUtils.isNotBlank(token)) {
                redisService.deleteObject("rt:bluetooth:unlock:" + token);
                redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId());
                XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
                String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
                BluetoothDeliverVo vo = new BluetoothDeliverVo();
                vo.setCredential(token);
                vo.setVin(vin);
                vo.setPassengerUid(order.getAppUserId());
                BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
                if (null == delete || delete.getCode() != 0) {
                    log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
            try {
                String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + order.getId());
                if (StringUtils.isNotBlank(token)) {
                    redisService.deleteObject("rt:bluetooth:unlock:" + token);
                    redisService.deleteObject("rt:bluetooth:unlock:order:" + order.getId());
                    XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
                    String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
                    BluetoothDeliverVo vo = new BluetoothDeliverVo();
                    vo.setCredential(token);
                    vo.setVin(vin);
                    vo.setPassengerUid(order.getAppUserId());
                    BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
                    if (null == delete || delete.getCode() != 0) {
                        log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
@@ -2003,7 +2093,9 @@
        xpOrderCancel.setCreateTime(LocalDateTime.now());
        xpOrderCancelService.save(xpOrderCancel);
        redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
        if(StringUtils.isNotEmpty(order.getQueueName())){
            redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
        }
        // 消息推送
        Map<String, Object> params = new HashMap<>();
@@ -2044,7 +2136,7 @@
        xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString());
        //流量接入-订单推送 推送取消订单
        if(Objects.nonNull(order.getOfficialPartnerId())){
        if (Objects.nonNull(order.getOfficialPartnerId())) {
            officialPartnerUtil.pushCancelOrder(order.getOfficialPartnerId(), xpOrderCancel, order.getStatus());
        }
        return order;
@@ -2070,9 +2162,11 @@
        if (xpOrder.getStatus() != 9) {
            throw new ServiceException("订单状态错误", I18nKeyConstant.ORDER_STATUS_ERROR);
        }
        Long appUserId = xpOrder.getAppUserId();
        xpOrder.setAppUserId(null);
        xpOrder.setStatus(10);
        baseMapper.updateById(xpOrder);
        xpOrder.setAppUserId(appUserId);
        bootCommonService.setCache_orderStatus(xpOrder.getId(), xpOrder, null);
        XpOrderEvaluate evaluate = new XpOrderEvaluate();
@@ -2121,7 +2215,7 @@
                XpPoint xpPoint = xpPointClient.queryById(startPointId).getData();
                Integer parkingTimeLimit = xpPoint.getParkingTimeLimit();
                //如果点位位于场站内,则使用场站的限停时间
                if(null != xpPoint.getStationId()){
                if (null != xpPoint.getStationId()) {
                    XpStation xpStation = xpStationClient.getXpStationById(xpPoint.getStationId()).getData();
                    parkingTimeLimit = xpStation.getParkingTimeLimit();
                }
@@ -2161,6 +2255,14 @@
                QuartzManager.removeJob((OrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.ORDER_CANCEL);
                //乘客已上车,重新倒计时不开始行程取消订单
                XpPoint xpPoint1 = xpPointClient.queryById(xpOrder.getStartPointId()).getData();
                if(StringUtils.isEmpty(xpPoint1.getCityCode())){
                    Map<String, String> geocode = gdMapGeocodingUtil.geocode(xpPoint1.getPointLon().toString(), xpPoint1.getPointLat().toString());
                    if(null != geocode){
                        xpPoint1.setCityCode(geocode.get("cityCode"));
                        xpPoint1.setCityName(geocode.get("address"));
                        xpPointClient.editXpPoint(xpPoint1);
                    }
                }
                XpTradingStrategy tradingStrategy = tradingStrategyClient.getTradingStrategyByCityCode(xpPoint1.getCityCode()).getData();
                if (null != tradingStrategy) {
                    Map<String, ? extends Object> cancelJobMaps1 =
@@ -2262,7 +2364,7 @@
                XpPoint point = xpPointClient.queryById(xpOrder.getEndPointId()).getData();
                Integer parkingTimeLimit2 = point.getParkingTimeLimit();
                //如果点位位于场站内,则使用场站的限停时间
                if(null != point.getStationId()){
                if (null != point.getStationId()) {
                    XpStation xpStation = xpStationClient.getXpStationById(point.getStationId()).getData();
                    parkingTimeLimit2 = xpStation.getParkingTimeLimit();
                }
@@ -2280,7 +2382,7 @@
                    Long id = jsonObject.getLong("orderId");
                    //判断订单状态
                    XpOrder xpOrder1 = this.getById(id);
                    if(2 == xpOrder1.getStatus()){
                    if (2 == xpOrder1.getStatus()) {
                        jobMaps = new ImmutableMap.Builder<String, String>()
                                .put("id", id.toString())
                                .put("oldOrderId", xpOrder.getId().toString())
@@ -2297,7 +2399,7 @@
                        );
                    }
                    //连环派订单取消的情况,继续走巡游
                    if(0 == xpOrder1.getStatus()){
                    if (0 == xpOrder1.getStatus()) {
                        QuartzManager.addJob(
                                AddCruiseMissionJob.class,
                                (AddCruiseMissionJob.name + xpOrder.getId()).toUpperCase(),
@@ -2322,6 +2424,7 @@
        xpOrder.setStatus(status);
        xpOrder.setAppUserId(null);
        this.updateById(xpOrder);
        xpOrder.setAppUserId(appUserId);
        bootCommonService.setCache_orderStatus(xpOrder.getId(), xpOrder, null);
        return R.ok();
    }
@@ -2381,7 +2484,7 @@
     * 豁免
     */
    public void setFree(Long id) {
        XpOrder order = baseMapper.selectById(id);
        //将支付金额修改成0 并将状态修改成 订单状态9
        XpOrder xpOrder1 = new XpOrder();
        xpOrder1.setId(id);
@@ -2390,6 +2493,7 @@
        xpOrder1.setStatus(OrderStatusEnum.PENDING_PAYMENT.getCode());
        xpOrder1.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(xpOrder1);
        xpOrder1.setAppUserId(order.getAppUserId());
        bootCommonService.setCache_orderStatus(xpOrder1.getId(), xpOrder1, null);
    }
@@ -2422,27 +2526,33 @@
        order.setAppUserId(appUserId);
        bootCommonService.setCache_orderStatus(order.getId(), order, null);
        //删除蓝牙秘钥
        String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId);
        if(StringUtils.isNotBlank(token)){
            redisService.deleteObject("rt:bluetooth:unlock:" + token);
            redisService.deleteObject("rt:bluetooth:unlock:order:" + orderId);
            XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
            String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
            BluetoothDeliverVo vo = new BluetoothDeliverVo();
            vo.setCredential(token);
            vo.setVin(vin);
            vo.setPassengerUid(order.getAppUserId());
            BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
            if(null == delete || delete.getCode() != 0){
                log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
        try {
            String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId);
            if (StringUtils.isNotBlank(token)) {
                redisService.deleteObject("rt:bluetooth:unlock:" + token);
                redisService.deleteObject("rt:bluetooth:unlock:order:" + orderId);
                XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
                String vin = SensitiveDataCryptoUtil.decryptIfPossible(xpVehicle.getVehicleVin());
                BluetoothDeliverVo vo = new BluetoothDeliverVo();
                vo.setCredential(token);
                vo.setVin(vin);
                vo.setPassengerUid(order.getAppUserId());
                BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
                if (null == delete || delete.getCode() != 200) {
                    log.info("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 根据订单所属开通城市id 查询定价
        XpPricing pricing = bootCommonService.getXpPricing(order.getCityId(), order.getVehicleId());
        if (pricing == null) {
            log.info("计算价格-获取定价规则失败 {} {}", orderId, order.getCityId());
            throw new ServiceException("当前城市未配置定价规则", I18nKeyConstant.ORDER_PRICING_NOT_EXISTS);
        }
        log.info("计算价格-获取定价规则成功 {} {}", orderId, JSON.toJSONString(pricing));
        // 费用
@@ -2457,6 +2567,7 @@
            TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(), trajectory.getLocatetime());
            gpsPoints.add(point);
        }
        log.info("计算价格-获取导航规则 {} {}", orderId, JSON.toJSONString(gpsPoints));
        TaxiPricingDemoService.PricingConfig config = new TaxiPricingDemoService.PricingConfig();
        JSONArray startingFareJsonArray = JSONArray.parseArray(pricing.getStartingFareJson());
@@ -2477,6 +2588,7 @@
            com.alibaba.fastjson2.JSONObject basicPricingJson = com.alibaba.fastjson2.JSONObject.parseObject(pricing.getBasicPricingJson());
            XpPricingCardVo xpPricingCardVo = xpPricingUtil.calculationFixedPrice(uid, basicPricingJson, null, mileageKilometers, duration1, 0, 0.0, pricing.getIsDynamicPrice(), order.getCityId(), pricing.getDynamicPricingJson());
            log.info("计算价格-计算一口价结果 {} {}", orderId, JSON.toJSONString(xpPricingCardVo));
            XpOrderDetail xpOrderDetail = new XpOrderDetail();
            xpOrderDetail.setDetailType(1);
            xpOrderDetail.setOrderId(orderId);
@@ -2508,9 +2620,10 @@
                totalPrice = totalPrice.add(xpOrderDetail1.getMoney());
                xpOrderDetailMapper.insert(xpOrderDetail1);
            }
            log.info("计算价格-保存费用明细 {} {}", orderId, JSON.toJSONString(xpOrderDetails));
            // 默认费率1
            double priceRate = 1;
            double priceRate = 100;
            if (pricing.getIsDynamicPrice() == 1) {
                // 先判断是否已经调价过了
                Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid);
@@ -2518,48 +2631,24 @@
                    // 是否调价过了
                    priceRate = Double.parseDouble(userDynamicPriceObj.toString());
                } else {
                    // 没有调过
                    //是否触发动态调价 redis获取
                    Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + order.getCityId());
                    if (dynamicPriceObj != null) {
                        JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson());
                        // 触发动态调价
                        // value=时间
                        String timeStr = dynamicPriceObj.toString();
                        // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                        Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId()));
                        // X单上升一次调价
                        Integer orderNum = getOrderNum(jsonObject, 4);
                        // 需要调价的次数
                        int count = num / orderNum;
                        if (count > 0) {
                            // 计算每次上升的费率
                            Integer upRate = getOrderNum(jsonObject, 5);
                            BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                            for (int i = count; i > 0; i--) {
                                // 当前费率+(费率*上升百分比)
                                priceRate = new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                            }
                            // 天气预报动态调价
                            JSONArray ws = jsonObject.getJSONArray("weather");
                            if (null != ws) {
                                WeatherDTO data = xpMapClient.wether(order.getCityCode()).getData();
                                List<WeatherDTO.Lives> lives = data.getLives();
                                if (lives != null && !lives.isEmpty()) {
                                    String w = lives.get(0).getWeather();
                                    for (Object o : ws) {
                                        JSONObject ele = JSONObject.parseObject(o.toString());
                                        if (w.contains(ele.getString("weatherType"))) {
                                            double floatRate = jsonObject.getDouble("ratio");
                                            priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                                            break;
                                        }
                                    }
                                }
                            }
                    JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson());
                    Integer num1 = jsonObject.getInteger("num1");
                    String timeStr = LocalDateTime.now().minusMinutes(num1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                    Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId()));
                    // X单上升一次调价
                    Integer orderNum = getOrderNum(jsonObject, 4);
                    // 需要调价的次数
                    int count = num / orderNum;
                    if (count > 0) {
                        // 计算每次上升的费率
                        Integer upRate = getOrderNum(jsonObject, 5);
                        BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                        for (int i = count; i > 0; i--) {
                            // 当前费率+(费率*上升百分比)
                            priceRate = new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                        }
                        if(priceRate > 1){
                            // 冷却时间
                            Integer time = getOrderNum(jsonObject, 6);
                            // 触发调价了
@@ -2567,14 +2656,38 @@
                        }
                    }
                }
            }
                log.info("供需后的费率 {}", priceRate);
                //是否触发动态调价 redis获取
                JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson());
                // 天气预报动态调价
                JSONArray ws = jsonObject.getJSONArray("weatherRules");
                if (null != ws) {
                    WeatherDTO data = xpMapClient.wether(order.getCityCode()).getData();
                    List<WeatherDTO.Lives> lives = data.getLives();
                    if (lives != null && !lives.isEmpty()) {
                        String w = lives.get(0).getWeather();
                        for (Object o : ws) {
                            JSONObject ele = JSONObject.parseObject(o.toString());
                            if (w.contains(ele.getString("weatherType")) || ele.getString("weatherType").contains(w)) {
                                double floatRate = ele.getDouble("ratio");
                                priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                                break;
                            }
                        }
                    }
                }
            }
            priceRate = new BigDecimal(priceRate).divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
            log.info("浮动费率 {}", priceRate);
            log.info("计算价格-计算费率 {} {}", orderId, priceRate);
            order.setOrderMoney(totalPrice.multiply(new BigDecimal(priceRate)));
            order.setAppUserId(null);
            baseMapper.updateById(order);
        } else {
            //动态计费
            if (pricing.getPricingType() == 1) {
                log.info("执行动态计费 {}", orderId);
                for (int i = 0; i < startingFareJsonArray.size(); i++) {
                    com.alibaba.fastjson2.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i);
                    String num1 = jsonObject.getString("num1");
@@ -2583,10 +2696,11 @@
                    String num4 = jsonObject.getString("num4");
                    String num5 = jsonObject.getString("num5");
                    String num6 = jsonObject.getString("num6");
                    String num7 = jsonObject.getString("num7");
                    String num7 = StringUtils.isNotBlank(jsonObject.getString("num7")) ? jsonObject.getString("num7") : "0";
                    config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7)));
                    // 判断当前是那个时段
                    log.info("执行动态计费-开始计算时间段 {}", orderId);
                    Calendar calendarStart = Calendar.getInstance();
                    calendarStart.setTime(date);
                    calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num1").split(":")[0]));
@@ -2598,6 +2712,7 @@
                    calendarEnd.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num2").split(":")[1]));
                    // 找到符合条件的直接跳出循环
                    if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) {
                        log.info("执行动态计费-开始计算时间段 {} {} {}", orderId, calendarStart.getTimeInMillis(), calendarEnd.getTimeInMillis());
                        paramNum4 = jsonObject.getDouble("num4");
                        paramNum5 = jsonObject.getDouble("num5");
                        break;
@@ -2622,6 +2737,7 @@
            TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService();
            Integer holidayToday = holidayUtil.isHolidayToday();
            log.info("执行动态计费 holidayToday:{}", holidayToday);
            Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getBoardingTime()), order.getMileageKilometers(), gpsPoints, config, holidayToday);
            log.info("======= 订单计费账单 =======");
            bill.forEach((detail, price) -> log.info(detail + ": " + price + " 元"));
@@ -2631,7 +2747,7 @@
            log.info("应付总额: " + totalAmount + " 元");
            BigDecimal startMoney = BigDecimal.ZERO;
            // 默认费率1
            double priceRate = 1;
            double priceRate = 100;
            if (pricing.getIsDynamicPrice() == 1) {
                // 先判断是否已经调价过了
                Object userDynamicPriceObj = redisService.getCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid);
@@ -2639,48 +2755,24 @@
                    // 是否调价过了
                    priceRate = Double.parseDouble(userDynamicPriceObj.toString());
                } else {
                    // 没有调过
                    //是否触发动态调价 redis获取
                    Object dynamicPriceObj = redisService.getCacheObject("DYNAMIC_PRICE_" + order.getCityId());
                    if (dynamicPriceObj != null) {
                        JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson());
                        // 触发动态调价
                        // value=时间
                        String timeStr = dynamicPriceObj.toString();
                        // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                        Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId()));
                        // X单上升一次调价
                        Integer orderNum = getOrderNum(jsonObject, 4);
                        // 需要调价的次数
                        int count = num / orderNum;
                        if (count > 0) {
                            // 计算每次上升的费率
                            Integer upRate = getOrderNum(jsonObject, 5);
                            BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                            for (int i = count; i > 0; i--) {
                                // 当前费率+(费率*上升百分比)
                                priceRate = new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                            }
                            // 天气预报动态调价
                            JSONArray ws = jsonObject.getJSONArray("weather");
                            if (null != ws) {
                                WeatherDTO data = xpMapClient.wether(order.getCityCode()).getData();
                                List<WeatherDTO.Lives> lives = data.getLives();
                                if (lives != null && !lives.isEmpty()) {
                                    String w = lives.get(0).getWeather();
                                    for (Object o : ws) {
                                        JSONObject ele = JSONObject.parseObject(o.toString());
                                        if (w.contains(ele.getString("weatherType"))) {
                                            double floatRate = jsonObject.getDouble("ratio");
                                            priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                                            break;
                                        }
                                    }
                                }
                            }
                    JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson());
                    Integer num1 = jsonObject.getInteger("num1");
                    String timeStr = LocalDateTime.now().minusMinutes(num1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                    // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率
                    Integer num = this.getOrderNum(new GetOrderNumDto(timeStr, order.getCityId()));
                    // X单上升一次调价
                    Integer orderNum = getOrderNum(jsonObject, 4);
                    // 需要调价的次数
                    int count = num / orderNum;
                    if (count > 0) {
                        // 计算每次上升的费率
                        Integer upRate = getOrderNum(jsonObject, 5);
                        BigDecimal divide = new BigDecimal(upRate).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
                        for (int i = count; i > 0; i--) {
                            // 当前费率+(费率*上升百分比)
                            priceRate = new BigDecimal(priceRate).multiply(divide).add(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue();
                        }
                        if(priceRate > 1){
                            // 冷却时间
                            Integer time = getOrderNum(jsonObject, 6);
                            // 触发调价了
@@ -2688,7 +2780,31 @@
                        }
                    }
                }
                log.info("供需后的费率 {}", priceRate);
                //是否触发动态调价 redis获取
                JSONObject jsonObject = JSONObject.parseObject(pricing.getDynamicPricingJson());
                // 天气预报动态调价
                JSONArray ws = jsonObject.getJSONArray("weatherRules");
                if (null != ws) {
                    WeatherDTO data = xpMapClient.wether(order.getCityCode()).getData();
                    List<WeatherDTO.Lives> lives = data.getLives();
                    if (lives != null && !lives.isEmpty()) {
                        String w = lives.get(0).getWeather();
                        for (Object o : ws) {
                            JSONObject ele = JSONObject.parseObject(o.toString());
                            if (w.contains(ele.getString("weatherType")) || ele.getString("weatherType").contains(w)) {
                                double floatRate = ele.getDouble("ratio");
                                priceRate = new BigDecimal(priceRate).add(new BigDecimal(floatRate)).doubleValue();
                                break;
                            }
                        }
                    }
                }
            }
            priceRate = new BigDecimal(priceRate).divide(new BigDecimal(100)).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
            log.info("浮动费率 {}", priceRate);
            log.info("计算价格-计算费率 {} {}", orderId, priceRate);
            // 封装费用明细数据
            for (Map.Entry<String, BigDecimal> stringBigDecimalEntry : bill.entrySet()) {
                // 封装起步价
@@ -2831,6 +2947,7 @@
            for (XpOrderDetail xpOrderDetail : xpOrderDetails) {
                xpOrderDetailMapper.insert(xpOrderDetail);
            }
            log.info("计算价格-计算费用明细 {} {}", orderId, JSON.toJSONString(xpOrderDetails));
            for (FareBreakdownDetailVo fareBreakdownDetailVo : duration) {
                if (order.getDurationMoney() == null) {
@@ -2906,8 +3023,23 @@
        // 判断是否有计划
        R<XpCruisePlanVehicle> xpCruisePlanR = xpCruisePlanClient.getCruisePlan(vehicle.getId());
        if (xpCruisePlanR == null || xpCruisePlanR.getData() == null) {
            log.info("添加巡游单失败,没有符合条件的巡游计划", vehicle.getPlateNumber());
            return;
            log.info("未找到匹配的巡游计划,无法执行巡游订单 {}", vehicle.getPlateNumber());
            //没有巡游计划,判断是否在定向服务里面
            List<XpTargetedServiceVehicle> data = targetedServiceClient.getAllTargetedServiceVehicleByCityCode(order.getCityCode()).getData();
            if(data.isEmpty()){
                log.info("给车端发送取消行程报文 {}", vehicle.getPlateNumber());
                PushOrderDto cancelDto = new PushOrderDto();
                cancelDto.setStartTaskId(order.getXpuStartTaskId());
                cancelDto.setEndTaskId(order.getXpuEndTaskId());
                cancelDto.setOrderId(order.getId().toString());
                String vin1 = SensitiveDataCryptoUtil.decryptIfPossible(vehicle.getVehicleVin());
                cancelDto.setVin(vin1);
                cancelDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
                cancelDto.setCancelScene(CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE.getCode());
                orderMissionClient.cancelOrder(cancelDto);
                return;
            }
        }
        // 获取配置 根据配置判断是否该收车 如果是则找到收车点位进行收车操作
        R<XpTaskRule> xpTaskRuleR = xpTaskRuleClient.queryDetail();
@@ -2954,11 +3086,14 @@
            xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId());
            xpCruiseOrder.setMissionId(xpCruiseOrders.getMissionId());
        }
        // 先找计划
        R<List<XpCruisePlanPoint>> pointList = xpCruisePlanClient.getCruisePlanPointList(vehicle.getId());
        if(200 != pointList.getCode()){
            return;
        }
        //所有没有赋值终点点位的情况,全部导航到巡游计划的第一个点位开始执行巡游任务
        if (null == xpCruiseOrder.getEndPointId()) {
            // 先找计划
            List<XpCruisePlanPoint> planPointList = xpCruisePlanClient.getCruisePlanPointList(vehicle.getId()).getData();
            XpCruisePlanPoint xpCruisePlanPoint = planPointList.get(0);
            XpCruisePlanPoint xpCruisePlanPoint = pointList.getData().get(0);
            Long endPointId = xpCruisePlanPoint.getPointId();
            XpPoint endPoint = xpPointClient.queryById(endPointId).getData();
            xpCruiseOrder.setEndPointId(endPointId);
@@ -2981,11 +3116,69 @@
                xpVehicleClient.updateVehicleById(vehicle1);
                //找到车辆的收车点位 更新终点点位
                R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder);
                if (200 != returnCruisePoint.getCode()) {
                if (200 == returnCruisePoint.getCode()) {
                    xpCruiseOrder = returnCruisePoint.getData();
                    xpCruiseOrder.setOrderType(2);
                    xpCruiseOrder.setOrderReverse(1);
                }
            }
        }else{
            //获取巡游导航数据,如果无法获取到有效的导航,则继续用下一个点位作为终点
            LonLatDto destination = new LonLatDto();
            LonLatDto origin = new LonLatDto();
            boolean ROUTE_FLAG = false;
            boolean start = false;
            if(xpCruiseOrder.getOrderReverse() == 1){
                for (XpCruisePlanPoint xpCruisePlanPoint1 : pointList.getData()) {
                    if (start || xpCruisePlanPoint1.getPointId().equals(xpCruiseOrder.getEndPointId())) {
                        start = true;
                        origin.setLongitude(xpCruiseOrder.getStartLon());
                        origin.setLatitude(xpCruiseOrder.getStartLat());
                        XpPoint xpPoint1 = xpPointClient.queryById(xpCruisePlanPoint1.getPointId()).getData();
                        destination.setLongitude(xpPoint1.getPointLon());
                        destination.setLatitude(xpPoint1.getPointLat());
                        OrderRouteAndFareDto dto1 = new OrderRouteAndFareDto();
                        dto1.setOrigin(origin);
                        dto1.setDestination(destination);
                        dto1.setRouteType(3);
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto1);
                        if (200 != routeVoR.getCode()) {
                            continue;
                        }
                        RouteVo routeVo = routeVoR.getData();
                        redisService.setCacheObject("CRUISE_ROUTE:" + xpCruiseOrder.getVehicleId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.DAYS);
                        ROUTE_FLAG = true;
                        break;
                    }
                }
            }else{
                for (int i = pointList.getData().size() - 1; i >= 0; i--) {
                    XpCruisePlanPoint xpCruisePlanPoint1 = pointList.getData().get(i);
                    if(start || xpCruisePlanPoint1.getPointId().equals(xpCruiseOrder.getEndPointId())){
                        start = true;
                        origin.setLongitude(xpCruiseOrder.getStartLon());
                        origin.setLatitude(xpCruiseOrder.getStartLat());
                        XpPoint xpPoint1 = xpPointClient.queryById(xpCruisePlanPoint1.getPointId()).getData();
                        destination.setLongitude(xpPoint1.getPointLon());
                        destination.setLatitude(xpPoint1.getPointLat());
                        OrderRouteAndFareDto dto1 = new OrderRouteAndFareDto();
                        dto1.setOrigin(origin);
                        dto1.setDestination(destination);
                        dto1.setRouteType(3);
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto1);
                        if (200 != routeVoR.getCode()) {
                            continue;
                        }
                        RouteVo routeVo = routeVoR.getData();
                        redisService.setCacheObject("CRUISE_ROUTE:" + xpCruiseOrder.getVehicleId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.DAYS);
                        ROUTE_FLAG = true;
                        break;
                    }
                }
            }
            if(!ROUTE_FLAG){
                log.info("巡游计划获取导航信息失败 {}", JSON.toJSONString(vehicle));
                return;
            }
        }
        xpCruiseOrderMapper.insert(xpCruiseOrder);
@@ -3003,7 +3196,7 @@
        pushOrderDto.setEndLongitude(xpCruiseOrder.getEndLon());
        pushOrderDto.setOrderType(OrderType.CRUISE_ORDER);
        pushOrderDto.setStage(2);
        if(null != order){
        if (null != order) {
            pushOrderDto.setLastOrderId(order.getId() + "");
            pushOrderDto.setLastXpuTaskId(order.getXpuEndTaskId());
        }
@@ -3025,18 +3218,22 @@
        R<XpCruisePlanVehicle> xpCruisePlanR = xpCruisePlanClient.getCruisePlan(vehicle.getId());
        if (xpCruisePlanR == null || xpCruisePlanR.getData() == null) {
            log.info("未找到匹配的巡游计划,无法执行巡游订单 {}", vehicle.getPlateNumber());
            log.info("给车端发送取消行程报文 {}", vehicle.getPlateNumber());
            //没有巡游计划,判断是否在定向服务里面
            List<XpTargetedServiceVehicle> data = targetedServiceClient.getAllTargetedServiceVehicleByCityCode(order.getCityCode()).getData();
            if(data.isEmpty()){
                log.info("给车端发送取消行程报文 {}", vehicle.getPlateNumber());
            PushOrderDto cancelDto = new PushOrderDto();
            cancelDto.setStartTaskId(order.getXpuStartTaskId());
            cancelDto.setEndTaskId(order.getXpuEndTaskId());
            cancelDto.setOrderId(order.getId().toString());
            String vin1 = SensitiveDataCryptoUtil.decryptIfPossible(vehicle.getVehicleVin());
            cancelDto.setVin(vin1);
            cancelDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
            cancelDto.setCancelScene(CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE.getCode());
            orderMissionClient.cancelOrder(cancelDto);
            return;
                PushOrderDto cancelDto = new PushOrderDto();
                cancelDto.setStartTaskId(order.getXpuStartTaskId());
                cancelDto.setEndTaskId(order.getXpuEndTaskId());
                cancelDto.setOrderId(order.getId().toString());
                String vin1 = SensitiveDataCryptoUtil.decryptIfPossible(vehicle.getVehicleVin());
                cancelDto.setVin(vin1);
                cancelDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
                cancelDto.setCancelScene(CancelOrderSceneEnum.REASSIGN_OLD_VEHICLE.getCode());
                orderMissionClient.cancelOrder(cancelDto);
                return;
            }
        }
        String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicle.getVehicleVin());
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
@@ -3085,10 +3282,14 @@
            xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId());
            xpCruiseOrder.setMissionId(xpCruiseOrders.getMissionId());
        }
        // 先找计划
        R<List<XpCruisePlanPoint>> pointList = xpCruisePlanClient.getCruisePlanPointList(vehicle.getId());
        if(200 != pointList.getCode()){
            return;
        }
        //所有没有赋值终点点位的情况,全部导航到巡游计划的第一个点位开始执行巡游任务
        if (null == xpCruiseOrder.getEndPointId()) {
            // 先找计划
            List<XpCruisePlanPoint> planPointList = xpCruisePlanClient.getCruisePlanPointList(vehicle.getId()).getData();
            List<XpCruisePlanPoint> planPointList = pointList.getData();
            XpCruisePlanPoint xpCruisePlanPoint = planPointList.get(0);
            Long endPointId = xpCruisePlanPoint.getPointId();
            XpPoint endPoint = xpPointClient.queryById(endPointId).getData();
@@ -3120,6 +3321,64 @@
                    xpCruiseOrder.setOrderReverse(1);
                }
            }
        }else{
            //获取巡游导航数据,如果无法获取到有效的导航,则继续用下一个点位作为终点
            LonLatDto destination = new LonLatDto();
            LonLatDto origin = new LonLatDto();
            boolean ROUTE_FLAG = false;
            boolean start = false;
            if(xpCruiseOrder.getOrderReverse() == 1){
                for (XpCruisePlanPoint xpCruisePlanPoint1 : pointList.getData()) {
                    if (start || xpCruisePlanPoint1.getPointId().equals(xpCruiseOrder.getEndPointId())) {
                        start = true;
                        origin.setLongitude(xpCruiseOrder.getStartLon());
                        origin.setLatitude(xpCruiseOrder.getStartLat());
                        XpPoint xpPoint1 = xpPointClient.queryById(xpCruisePlanPoint1.getPointId()).getData();
                        destination.setLongitude(xpPoint1.getPointLon());
                        destination.setLatitude(xpPoint1.getPointLat());
                        OrderRouteAndFareDto dto1 = new OrderRouteAndFareDto();
                        dto1.setOrigin(origin);
                        dto1.setDestination(destination);
                        dto1.setRouteType(3);
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto1);
                        if (200 != routeVoR.getCode()) {
                            continue;
                        }
                        RouteVo routeVo = routeVoR.getData();
                        redisService.setCacheObject("CRUISE_ROUTE:" + xpCruiseOrder.getVehicleId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.DAYS);
                        ROUTE_FLAG = true;
                        break;
                    }
                }
            }else{
                for (int i = pointList.getData().size() - 1; i >= 0; i--) {
                    XpCruisePlanPoint xpCruisePlanPoint1 = pointList.getData().get(i);
                    if(start || xpCruisePlanPoint1.getPointId().equals(xpCruiseOrder.getEndPointId())){
                        start = true;
                        origin.setLongitude(xpCruiseOrder.getStartLon());
                        origin.setLatitude(xpCruiseOrder.getStartLat());
                        XpPoint xpPoint1 = xpPointClient.queryById(xpCruisePlanPoint1.getPointId()).getData();
                        destination.setLongitude(xpPoint1.getPointLon());
                        destination.setLatitude(xpPoint1.getPointLat());
                        OrderRouteAndFareDto dto1 = new OrderRouteAndFareDto();
                        dto1.setOrigin(origin);
                        dto1.setDestination(destination);
                        dto1.setRouteType(3);
                        R<RouteVo> routeVoR = xpMapClient.getOrderDistanceAndDuration(dto1);
                        if (200 != routeVoR.getCode()) {
                            continue;
                        }
                        RouteVo routeVo = routeVoR.getData();
                        redisService.setCacheObject("CRUISE_ROUTE:" + xpCruiseOrder.getVehicleId(), com.alibaba.fastjson.JSON.toJSONString(routeVo), 24L, TimeUnit.DAYS);
                        ROUTE_FLAG = true;
                        break;
                    }
                }
            }
            if(!ROUTE_FLAG){
                log.info("巡游计划获取导航信息失败 {}", JSON.toJSONString(vehicle));
                return;
            }
        }
        xpCruiseOrderMapper.insert(xpCruiseOrder);
@@ -3138,7 +3397,7 @@
        pushOrderDto.setEndLongitude(xpCruiseOrder.getEndLon());
        pushOrderDto.setOrderType(OrderType.CRUISE_ORDER);
        pushOrderDto.setStage(2);
        if(null != order){
        if (null != order) {
            pushOrderDto.setLastOrderId(order.getId() + "");
            pushOrderDto.setLastXpuTaskId(status < 5 ? order.getXpuStartTaskId() : order.getXpuEndTaskId());
        }
@@ -3440,9 +3699,14 @@
//            creditOrderCreateDto.setUid(Long.valueOf(uid));
//            creditOrderCreateDto.setBusinessId("xp-robotaxi");
//            creditOrderCreateDto.setCategory("009001");
//            creditOrderCreateDto.setBusinessOrderId("");
//            creditOrderCreateDto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
//            creditOrderCreateDto.setSubject("小鹏集团|robotaxi");
//            creditOrderCreateDto.setPayType("13");
        // TODO 需要根据环境补充路径
//            creditOrderCreateDto.setPayCallbackUrl("");
//
//            creditOrderCreateDto.setBusinessExtendData("{\"mainOrderId\":\"" +order.getOrderNumber() + "\"}");
//
//
//
//            // 信用下单
@@ -3460,6 +3724,8 @@
//
//                order.setPayType(3);
//                order.setAuthOrderId(data.getAuthOrderId());
//                order.setBusinessOrderId(creditOrderCreateDto.getBusinessOrderId());
//                order.setMainOrderId(order.getOrderNumber());
//
//                return R.ok(resultMap);
//            }
@@ -3471,7 +3737,7 @@
//            CreditPrecreateDto creditPrecreateDto = new CreditPrecreateDto();
//            creditPrecreateDto.setUid(uid);
//            creditPrecreateDto.setBizId("xp-robotaxi");
//            creditPrecreateDto.setBizOrderId("");
//            creditPrecreateDto.setBizOrderId(OrderCodeUtil.getOrderCode("MMZF"));
//            creditPrecreateDto.setPayScene(99);
//            creditPrecreateDto.setAmount(order.getOrderMoney().multiply(new BigDecimal(100)).intValue());
//            creditPrecreateDto.setCategory("009001");
@@ -3483,20 +3749,27 @@
//            businessExtend.put("notifyUrl", "");
//            creditPrecreateDto.setBusinessExtend(businessExtend);
//
//            creditPrecreateDto.setExtBusinessData2("{\"mainOrderId\":\"" +order.getOrderNumber() + "\"}");
//
//            R<CreditPrecreateVo> creditPrecreateVoR = xpPayFrontClient.precreate(creditPrecreateDto);
//            if (creditPrecreateVoR.getCode()==200) {
//                CreditPrecreateVo data = creditPrecreateVoR.getData();
//                resultMap.put("status", 2);
//                resultMap.put("value", data);
//
//                order.setPayType(1);
//                order.setBusinessOrderId(creditPrecreateDto.getBizOrderId());
//                order.setMainOrderId(order.getOrderNumber());
//                this.updateById(order);
//
//                return R.ok(resultMap);
//            }
//        }
//        return R.fail();
        // mvp版本不做支付 使用优惠券抵扣为0元订单处理 处理订单状态即可
        XpOrder order = this.getById(dto.getOrderId());
        Long appUserId = order.getAppUserId();
        order.setStatus(9);
        order.setAppUserId(null);
        if (order.getCouponId() != null) {
@@ -3514,6 +3787,7 @@
            }
        }
        baseMapper.updateById(order);
        order.setAppUserId(appUserId);
        bootCommonService.setCache_orderStatus(order.getId(), order, null);
        return R.ok();
    }
@@ -3530,6 +3804,7 @@
        if (insert <= 0) {
            return false;
        }
//        pushOrderCreateToMinistry(xpOrder, "新增订单");
        return true;
    }
@@ -3802,7 +4077,9 @@
                // Redis弹出这个队列元素
                // value 订单Id_经纬度_状态_用户id_订单编号_距离_时间
                try {
                    redisService.popFirstElement(order.getQueueName());
                    if(StringUtils.isNotEmpty(order.getQueueName())){
                        redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
                    }
                } catch (Exception e) {
                    log.error("Redis弹出队列元素出错");
                }
@@ -3821,6 +4098,9 @@
                this.updateById(order);
                order.setAppUserId(appUserId);
                bootCommonService.setCache_orderStatus(order.getId(), order, null);
                if (vehicle != null) {
//                    pushOrderMatchToMinistry(order, vehicle, appUserId, order.getAcceptanceTime(), "推单成功");
                }
                //构建推送消息
                Map<String, Object> params = new HashMap<>();
@@ -3861,16 +4141,16 @@
                //生成前往上车点的导航数据
                //查询车辆位置
                 VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(dto.getXpVehicleVin())), VehiclePosition.class);
                 if (Objects.isNull(vehiclePosition)) {
                     throw new RuntimeException("车辆位置信息不存在");
                 }
                VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(dto.getXpVehicleVin())), VehiclePosition.class);
                if (Objects.isNull(vehiclePosition)) {
                    throw new RuntimeException("车辆位置信息不存在");
                }
                LonLatDto destination = new LonLatDto();
                LonLatDto origin = new LonLatDto();
                //查询司机当前位置到起点的线路
                 origin.setLongitude(vehiclePosition.getPoint().getX());
                 origin.setLatitude(vehiclePosition.getPoint().getY());
                origin.setLongitude(vehiclePosition.getPoint().getX());
                origin.setLatitude(vehiclePosition.getPoint().getY());
//                origin.setLongitude(104.055499);
//                origin.setLatitude(30.586747);
                destination.setLongitude(order.getStartLon());
@@ -3893,59 +4173,63 @@
                //推送乘客车辆到达预约点的导航数据
                sendRoute(addTaxiPassengerVo.getUid(), orderId, "ORDER_NAVIGATION_START_DATA", dto.getXpVehicleVin());
                //生成蓝牙token
                //生成过期时间 (接单时间+到达上车点预估时间+上车点等待时间+行程预估时间+下车点等待时间+30分钟)
                XpPoint startPoint = xpPointClient.queryById(order.getStartPointId()).getData();
                Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_END_DATA:" + appUserId);
                RouteVo routeVo1 = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                XpPoint endPoint = xpPointClient.queryById(order.getEndPointId()).getData();
                Integer parkingTimeLimit = startPoint.getParkingTimeLimit();
                //如果点位位于场站内,则使用场站的限停时间
                if(null != startPoint.getStationId()){
                    XpStation xpStation = xpStationClient.getXpStationById(startPoint.getStationId()).getData();
                    parkingTimeLimit = xpStation.getParkingTimeLimit();
                }
                try {
                    //生成蓝牙token
                    //生成过期时间 (接单时间+到达上车点预估时间+上车点等待时间+行程预估时间+下车点等待时间+30分钟)
                    XpPoint startPoint = xpPointClient.queryById(order.getStartPointId()).getData();
                    Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_END_DATA:" + appUserId);
                    RouteVo routeVo1 = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                    XpPoint endPoint = xpPointClient.queryById(order.getEndPointId()).getData();
                    Integer parkingTimeLimit = startPoint.getParkingTimeLimit();
                    //如果点位位于场站内,则使用场站的限停时间
                    if (null != startPoint.getStationId()) {
                        XpStation xpStation = xpStationClient.getXpStationById(startPoint.getStationId()).getData();
                        parkingTimeLimit = xpStation.getParkingTimeLimit();
                    }
                Integer parkingTimeLimit1 = endPoint.getParkingTimeLimit();
                //如果点位位于场站内,则使用场站的限停时间
                if(null != endPoint.getStationId()){
                    XpStation xpStation = xpStationClient.getXpStationById(endPoint.getStationId()).getData();
                    parkingTimeLimit1 = xpStation.getParkingTimeLimit();
                    Integer parkingTimeLimit1 = endPoint.getParkingTimeLimit();
                    //如果点位位于场站内,则使用场站的限停时间
                    if (null != endPoint.getStationId()) {
                        XpStation xpStation = xpStationClient.getXpStationById(endPoint.getStationId()).getData();
                        parkingTimeLimit1 = xpStation.getParkingTimeLimit();
                    }
                    LocalDateTime localDateTime = order.getAcceptanceTime().plusSeconds(routeVo.getDuration()).plusMinutes(parkingTimeLimit)
                            .plusSeconds(routeVo1.getDuration()).plusMinutes(parkingTimeLimit1).plusMinutes(30);
                    long expirationTime = localDateTime.toEpochSecond(ZoneOffset.of("+8")) * 1000;
                    //生成token
                    String token = bluetoothUnlockTokenUtil.generateBluetoothUnlockToken(order.getAppUserId(),
                            order.getId(), order.getVehicleId(), expirationTime);
                    log.info("生成蓝牙token:{} 有效期:{} 订单号: {}", token, expirationTime, order.getOrderNumber());
                    //存储缓存
                    String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicle.getVehicleVin());
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("userId", order.getAppUserId());
                    jsonObject.put("orderId", order.getId());
                    jsonObject.put("vehicleId", order.getVehicleId());
                    jsonObject.put("expirationTime", expirationTime);
                    jsonObject.put("orderNumber", order.getOrderNumber());
                    jsonObject.put("vehicleVin", vin);
                    jsonObject.put("createTime", System.currentTimeMillis());
                    redisService.setCacheObject("rt:bluetooth:unlock:" + token, jsonObject.toJSONString(), expirationTime, TimeUnit.SECONDS);
                    redisService.setCacheObject("rt:bluetooth:unlock:order:" + order.getId(), token, expirationTime, TimeUnit.SECONDS);
                    //开始下发蓝牙token
                    BluetoothDeliverVo vo = new BluetoothDeliverVo();
                    vo.setCredential(token);
                    vo.setVin(vin);
                    vo.setPassengerUid(order.getAppUserId());
                    BaseVehicleUserDto deliver = bluetoothUnlockClient.deliver(vo);
                    log.info("下发蓝牙token结果:{}", JSON.toJSONString(deliver));
                    if (null == deliver) {
                        log.info("下发蓝牙token失败");
                    }
                    if (200 != deliver.getCode()) {
                        log.info("下发蓝牙token失败:{} {}", deliver.getMsg(), order.getOrderNumber());
                    } else {
                        log.info("下发蓝牙token成功:{} {}", deliver.getData(), order.getOrderNumber());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                LocalDateTime localDateTime = order.getAcceptanceTime().plusSeconds(routeVo.getDuration()).plusMinutes(parkingTimeLimit)
                        .plusSeconds(routeVo1.getDuration()).plusMinutes(parkingTimeLimit1).plusMinutes(30);
                long expirationTime = localDateTime.toEpochSecond(ZoneOffset.of("+8")) * 1000;
                //生成token
                String token = bluetoothUnlockTokenUtil.generateBluetoothUnlockToken(order.getAppUserId(),
                        order.getId(), order.getVehicleId(), expirationTime);
                log.info("生成蓝牙token:{} 有效期:{} 订单号: {}", token, expirationTime, order.getOrderNumber());
                //存储缓存
                String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicle.getVehicleVin());
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("userId", order.getAppUserId());
                jsonObject.put("orderId", order.getId());
                jsonObject.put("vehicleId", order.getVehicleId());
                jsonObject.put("expirationTime", expirationTime);
                jsonObject.put("orderNumber", order.getOrderNumber());
                jsonObject.put("vehicleVin", vin);
                jsonObject.put("createTime", System.currentTimeMillis());
                redisService.setCacheObject("rt:bluetooth:unlock:" + token, jsonObject.toJSONString(), expirationTime, TimeUnit.SECONDS);
                redisService.setCacheObject("rt:bluetooth:unlock:order:" + order.getId(), token, expirationTime, TimeUnit.SECONDS);
                //开始下发蓝牙token
                BluetoothDeliverVo vo = new BluetoothDeliverVo();
                vo.setCredential(token);
                vo.setVin(vin);
                vo.setPassengerUid(order.getAppUserId());
                BaseVehicleUserDto deliver = bluetoothUnlockClient.deliver(vo);
                log.info("下发蓝牙token结果:{}", JSON.toJSONString(deliver));
                if(null == deliver){
                    throw new ServiceException("下发蓝牙token失败");
                }
                if(200 != deliver.getCode()){
                    log.error("下发蓝牙token失败:{} {}", deliver.getMsg(), order.getOrderNumber());
                    throw new ServiceException(deliver.getMsg());
                }
                log.info("下发蓝牙token成功:{} {}", deliver.getData(), order.getOrderNumber());
            }
            if (order.getStatus() == 2) {
@@ -4103,7 +4387,7 @@
            XpPoint startPoint = xpPointR.getData();
            Integer parkingTimeLimit = startPoint.getParkingTimeLimit();
            //如果点位位于场站内,则使用场站的限停时间
            if(null != startPoint.getStationId()){
            if (null != startPoint.getStationId()) {
                XpStation xpStation = xpStationClient.getXpStationById(startPoint.getStationId()).getData();
                parkingTimeLimit = xpStation.getParkingTimeLimit();
            }
@@ -4115,7 +4399,7 @@
            XpPoint endPoint = xpPointR1.getData();
            Integer parkingTimeLimit = endPoint.getParkingTimeLimit();
            //如果点位位于场站内,则使用场站的限停时间
            if(null != endPoint.getStationId()){
            if (null != endPoint.getStationId()) {
                XpStation xpStation = xpStationClient.getXpStationById(endPoint.getStationId()).getData();
                parkingTimeLimit = xpStation.getParkingTimeLimit();
            }
@@ -4384,6 +4668,7 @@
     */
    @Override
    public List<UserOrderListVo> getUserOrderList(UserOrderListDto dto) {
        dto.setPageNo((dto.getPageNo() - 1) * dto.getPageSize());
        List<XpOrder> list = this.list(new QueryWrapper<XpOrder>().eq("app_user_id", dto.getUid())
                .eq("is_deleted", 0)
                .eq(dto.getOrderStatus() != null, "status", dto.getOrderStatus())
@@ -4393,6 +4678,7 @@
        List<UserOrderListVo> collect = list.stream().map(order -> {
            UserOrderListVo vo = new UserOrderListVo();
            vo.setOrderId(order.getId());
            vo.setOrderNumber(order.getOrderNumber());
            vo.setOrderStatus(order.getStatus());
            vo.setOrderCreatedAt(order.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
@@ -4470,6 +4756,8 @@
        if (xpOrder.getStatus() >= 8) {
            return R.fail("订单已结束,无法修改");
        }
        XpVehicle matchedVehicle = null;
        LocalDateTime distributeTime = null;
        switch (vo.getOrderStatus()) {
            case 2:
@@ -4486,13 +4774,17 @@
                if (null == xpVehicle) {
                    return R.fail("车牌号不存在");
                }
                matchedVehicle = xpVehicle;
                xpOrder.setOfficialPartnerId(officialPartnerId);
                xpOrder.setVehicleId(xpVehicle.getId());
                xpOrder.setAcceptanceTime(vo.getAcceptanceTime());
                distributeTime = vo.getAcceptanceTime();
                redisService.setCacheObject("ORDER_STATUS:" + xpOrder.getId(), OrderStatusEnum.READY_DEPART.getCode(), 24L, TimeUnit.HOURS);
                //将订单弹出队列
                try {
                    redisService.popFirstElement(xpOrder.getQueueName());
                    if(StringUtils.isNotEmpty(xpOrder.getQueueName())){
                        redisService.removeByPattern(xpOrder.getQueueName(), xpOrder.getOrderNumber());
                    }
                } catch (Exception e) {
                    log.error("Redis弹出队列元素出错");
                }
@@ -4556,7 +4848,7 @@
                XpPoint xpPoint = xpPointClient.queryById(startPointId).getData();
                Integer parkingTimeLimit = xpPoint.getParkingTimeLimit();
                //如果点位位于场站内,则使用场站的限停时间
                if(null != xpPoint.getStationId()){
                if (null != xpPoint.getStationId()) {
                    XpStation xpStation = xpStationClient.getXpStationById(xpPoint.getStationId()).getData();
                    parkingTimeLimit = xpStation.getParkingTimeLimit();
                }
@@ -4607,6 +4899,14 @@
                QuartzManager.removeJob((OrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.ORDER_CANCEL);
                //乘客已上车,重新倒计时不开始行程取消订单
                XpPoint xpPoint1 = xpPointClient.queryById(xpOrder.getStartPointId()).getData();
                if(StringUtils.isEmpty(xpPoint1.getCityCode())){
                    Map<String, String> geocode = gdMapGeocodingUtil.geocode(xpPoint1.getPointLon().toString(), xpPoint1.getPointLat().toString());
                    if(null != geocode){
                        xpPoint1.setCityCode(geocode.get("cityCode"));
                        xpPoint1.setCityName(geocode.get("address"));
                        xpPointClient.editXpPoint(xpPoint1);
                    }
                }
                XpTradingStrategy tradingStrategy = tradingStrategyClient.getTradingStrategyByCityCode(xpPoint1.getCityCode()).getData();
                if (null != tradingStrategy) {
                    Map<String, ? extends Object> cancelJobMaps1 =
@@ -4722,7 +5022,7 @@
                XpPoint point = xpPointClient.queryById(xpOrder.getEndPointId()).getData();
                Integer parkingTimeLimit1 = point.getParkingTimeLimit();
                //如果点位位于场站内,则使用场站的限停时间
                if(null != point.getStationId()){
                if (null != point.getStationId()) {
                    XpStation xpStation = xpStationClient.getXpStationById(point.getStationId()).getData();
                    parkingTimeLimit1 = xpStation.getParkingTimeLimit();
                }
@@ -4768,6 +5068,9 @@
        }
        xpOrder.setStatus(vo.getOrderStatus());
        this.updateById(xpOrder);
        if (vo.getOrderStatus() == 2 && matchedVehicle != null) {
//            pushOrderMatchToMinistry(xpOrder, matchedVehicle, xpOrder.getAppUserId(), distributeTime, "合作商接单成功");
        }
        //推送订单状态给乘客端
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> content = new HashMap<>();
@@ -4805,6 +5108,185 @@
        return R.ok();
    }
    private void pushOrderCreateToMinistry(XpOrder order, String scene) {
        if (order == null) {
            return;
        }
        try {
            RegulationOrderCreateInfoDTO dto = buildOrderCreateInfoForMinistry(order);
            String response = ministryOfTransportOrderReporter.pushOrderCreateInfo(dto);
            log.info("{}后上报交通部DDFQ完成, orderId={}, orderNo={}, response={}",
                    scene, order.getId(), order.getOrderNumber(), response);
        } catch (Exception e) {
            log.error("{}后上报交通部DDFQ失败, orderId={}, orderNo={}",
                    scene, order.getId(), order.getOrderNumber(), e);
        }
    }
    private void pushOrderMatchToMinistry(XpOrder order, XpVehicle vehicle, Long appUserId, LocalDateTime distributeTime, String scene) {
        if (order == null || vehicle == null) {
            return;
        }
        try {
            RegulationOrderMatchInfoDTO dto = buildOrderMatchInfoForMinistry(order, vehicle, appUserId, distributeTime);
            String response = ministryOfTransportOrderReporter.pushOrderMatchInfo(dto);
            log.info("{}后上报交通部DDCG完成, orderId={}, orderNo={}, vehicleId={}, response={}",
                    scene, order.getId(), order.getOrderNumber(), vehicle.getId(), response);
        } catch (Exception e) {
            log.error("{}后上报交通部DDCG失败, orderId={}, orderNo={}, vehicleId={}",
                    scene, order.getId(), order.getOrderNumber(), vehicle.getId(), e);
        }
    }
    private RegulationOrderCreateInfoDTO buildOrderCreateInfoForMinistry(XpOrder order) {
        XpAppUser appUser = queryAppUser(order.getAppUserId());
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime orderTime = defaultIfNull(order.getCreateTime(), now);
        LocalDateTime departTime = order.getEstimatedTime() != null
                ? order.getEstimatedTime()
                : defaultIfNull(order.getRideTime(), orderTime);
        RegulationOrderCreateInfoDTO dto = new RegulationOrderCreateInfoDTO();
        dto.setCompanyId(ministryTransportProperties.getCompanyId());
        dto.setAddress(ministryTransportProperties.getAddressCode());
        dto.setOrderId(defaultIfBlank(order.getOrderNumber(), String.valueOf(order.getId())));
        dto.setDepartTime(formatTransportTime(departTime));
        dto.setOrderTime(formatTransportTime(orderTime));
        dto.setPassengerPhone(appUser == null ? "" : defaultIfBlank(appUser.getPhoneNumber(), ""));
        dto.setPassengerNote("");
        dto.setDeparture(defaultIfBlank(order.getStartAddress(), ""));
        dto.setDepLongitude(formatCoordinate(order.getStartLon()));
        dto.setDepLatitude(formatCoordinate(order.getStartLat()));
        dto.setDestination(defaultIfBlank(order.getEndAddress(), ""));
        dto.setDestLongitude(formatCoordinate(order.getEndLon()));
        dto.setDestLatitude(formatCoordinate(order.getEndLat()));
        dto.setEncrypt("1");
        dto.setFareType(ministryTransportProperties.getFareType());
        dto.setOrderSource("0");
        dto.setPsgName(appUser == null ? "乘客" : defaultIfBlank(appUser.getNickName(), "乘客"));
        dto.setPsgGender(mapPassengerGender(appUser == null ? null : appUser.getGender()));
        dto.setPsgTotal("1");
        dto.setIsReserve(order.getEstimatedTime() != null ? "1" : "0");
        dto.setPreMile(formatDecimal(order.getMileageKilometers(), 0));
        dto.setPreTime(formatDecimal(order.getDuration(), 0));
        dto.setPreFare(formatAmount(order.getOrderMoney()));
        dto.setDepartCity(defaultIfBlank(order.getCityCode(), ministryTransportProperties.getDepartCityDefault()));
        dto.setDestCity(defaultIfBlank(order.getCityCode(), ministryTransportProperties.getDestCityDefault()));
        dto.setIsFromThirdPlatform("0");
        dto.setProtocolVersion(ministryTransportProperties.getProtocolVersion());
        return dto;
    }
    private RegulationOrderMatchInfoDTO buildOrderMatchInfoForMinistry(XpOrder order, XpVehicle vehicle, Long appUserId, LocalDateTime distributeTime) {
        String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicle.getVehicleVin());
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
        GeoJsonPoint point = vehiclePosition == null ? null : vehiclePosition.getPoint();
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime orderTime = defaultIfNull(order.getCreateTime(), now);
        LocalDateTime actualDistributeTime = defaultIfNull(distributeTime, defaultIfNull(order.getAcceptanceTime(), now));
        RegulationOrderMatchInfoDTO dto = new RegulationOrderMatchInfoDTO();
        dto.setCompanyId(ministryTransportProperties.getCompanyId());
        dto.setAddress(ministryTransportProperties.getAddressCode());
        dto.setOrderId(defaultIfBlank(order.getOrderNumber(), String.valueOf(order.getId())));
        dto.setLongitude(formatCoordinate(point == null ? order.getStartLon() : point.getX()));
        dto.setLatitude(formatCoordinate(point == null ? order.getStartLat() : point.getY()));
        dto.setEncrypt("1");
        dto.setLicenseId(ministryTransportProperties.getDriverLicenseId());
        dto.setDriverPhone(ministryTransportProperties.getDriverPhone());
        dto.setVehicleNo(defaultIfBlank(vehicle.getPlateNumber(), ""));
        dto.setPlateColor(getPlateColor(vehicle.getPlateNumber()));
        dto.setDistributeTime(formatTransportTime(actualDistributeTime));
        dto.setOrderTime(formatTransportTime(orderTime));
        dto.setCarCertNo(ministryTransportProperties.getVehicleCertNo());
        dto.setDriverName(ministryTransportProperties.getDriverName());
        dto.setIdNo(ministryTransportProperties.getDriverIdNo());
        dto.setDriCertNo(ministryTransportProperties.getDriverCertNo());
        dto.setDepartCity(defaultIfBlank(order.getCityCode(), ministryTransportProperties.getDepartCityDefault()));
        dto.setDestCity(defaultIfBlank(order.getCityCode(), ministryTransportProperties.getDestCityDefault()));
        dto.setDepartLocale(defaultIfBlank(order.getStartAddress(), ""));
        dto.setDepartLocaleDetail(defaultIfBlank(order.getStartAddress(), ""));
        dto.setDepartLon(formatCoordinate(order.getStartLon()));
        dto.setDepartLat(formatCoordinate(order.getStartLat()));
        dto.setDesLocale(defaultIfBlank(order.getEndAddress(), ""));
        dto.setDesLocaleDetail(defaultIfBlank(order.getEndAddress(), ""));
        dto.setDesLon(formatCoordinate(order.getEndLon()));
        dto.setDesLat(formatCoordinate(order.getEndLat()));
        dto.setLatestDestTime(formatTransportTime(actualDistributeTime.minusMinutes(30)));
        dto.setIsFromThirdPlatform("0");
        dto.setProtocolVersion(ministryTransportProperties.getProtocolVersion());
        return dto;
    }
    private XpAppUser queryAppUser(Long appUserId) {
        if (appUserId == null) {
            return null;
        }
        try {
            R<XpAppUser> result = xpAppUserClient.queryOperationsUserById(appUserId);
            return result == null ? null : result.getData();
        } catch (Exception e) {
            log.warn("查询乘客信息失败, appUserId={}", appUserId, e);
            return null;
        }
    }
    private LocalDateTime defaultIfNull(LocalDateTime value, LocalDateTime defaultValue) {
        return value == null ? defaultValue : value;
    }
    private String defaultIfBlank(String value, String defaultValue) {
        return StringUtils.isBlank(value) ? defaultValue : value;
    }
    private String formatTransportTime(LocalDateTime time) {
        return time == null ? null : time.format(MinistryOfTransportOrderReporter.DATA_TIME_FORMATTER);
    }
    private String formatCoordinate(Double value) {
        if (value == null) {
            return "0";
        }
        return BigDecimal.valueOf(value)
                .multiply(BigDecimal.valueOf(1_000_000L))
                .setScale(0, RoundingMode.HALF_UP)
                .toPlainString();
    }
    private String formatDecimal(Number value, int scale) {
        if (value == null) {
            return "0";
        }
        return BigDecimal.valueOf(value.doubleValue())
                .setScale(scale, RoundingMode.HALF_UP)
                .toPlainString();
    }
    private String formatAmount(BigDecimal value) {
        if (value == null) {
            return "0";
        }
        return value.stripTrailingZeros().toPlainString();
    }
    private String mapPassengerGender(Integer gender) {
        if (Integer.valueOf(1).equals(gender)) {
            return "1";
        }
        if (Integer.valueOf(2).equals(gender)) {
            return "2";
        }
        return "0";
    }
    private String getPlateColor(String plateNumber) {
        if (StringUtils.isBlank(plateNumber)) {
            return "蓝色";
        }
        String plateWithoutProvince = plateNumber.substring(1);
        return plateWithoutProvince.length() == 7 ? "渐变绿" : "蓝色";
    }
    @Override
    public UserOrderInfoVo getOrderHistoryInfo(Long orderId) {
        XpOrder xpOrder = this.getById(orderId);
@@ -4827,11 +5309,11 @@
        vo.setTripEndedAt(null == xpOrder.getTripEnd() ? "" : xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        vo.setPaymentCompletedAt("");
        XpOrderEvaluate orderEvaluate = xpOrderEvaluateService.getOne(new QueryWrapper<XpOrderEvaluate>().eq("order_id", xpOrder.getId()));
        if(null != orderEvaluate){
        if (null != orderEvaluate) {
            vo.setUserRatedAt(orderEvaluate.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }
        XpOrderCancel xpOrderCancel = xpOrderCancelService.getOne(new QueryWrapper<XpOrderCancel>().eq("order_id", xpOrder.getId()));
        if(null != xpOrderCancel){
        if (null != xpOrderCancel) {
            vo.setOrderCancelledAt(xpOrderCancel.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            vo.setCancelReasonType(xpOrderCancel.getCancelSource() == 1 ? "用户取消" : xpOrderCancel.getCancelSource() == 4 ? "超时取消" : "系统取消");
        }
@@ -4842,6 +5324,7 @@
    /**
     * 查询订单状态
     *
     * @param orderId
     * @return
     */
@@ -4849,27 +5332,31 @@
    public OrderStatusFromOrderIdVo queryOrderStatusFromOrderId(Long orderId) {
        XpOrder order = this.getById(orderId);
        if(order==null){
        if (order == null) {
            return null;
        }
        if(order.getPayType()==3){
        if (order.getPayType() == 3) {
            // 免密查询 如果成功则调用结算
            CreditOrderQueryDto dto = new CreditOrderQueryDto();
            dto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
            dto.setBusinessOrderId(order.getBusinessOrderId());
            dto.setAuthOrderId(order.getAuthOrderId());
            dto.setPayType("13");
            R<CreditOrderQueryVo> creditOrderQueryVoR = xpPayFrontClient.queryCreditOrder(dto);
            if(creditOrderQueryVoR.getCode()==200){
            if (creditOrderQueryVoR.getCode() == 200) {
                CreditOrderQueryVo creditOrderQueryVo = creditOrderQueryVoR.getData();
                if(creditOrderQueryVo.getCreditOrderStatus().equals("DONE")){
                if (creditOrderQueryVo.getCreditOrderStatus().equals("DONE")) {
                    // 订单确认 需要吊起扣款
                    CreditOrderWxPayDto creditOrderWxPayDto = new CreditOrderWxPayDto();
                    creditOrderWxPayDto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
                    creditOrderWxPayDto.setBusinessOrderId(order.getBusinessOrderId());
                    creditOrderWxPayDto.setAuthOrderId(order.getAuthOrderId());
                    creditOrderWxPayDto.setPayCallbackUrl("13");
                    creditOrderWxPayDto.setTotalAmount( order.getOrderMoney().multiply(BigDecimal.valueOf(100)).longValue());
                    // TODO 需要根据环境补充路径
                    creditOrderWxPayDto.setPayCallbackUrl("");
                    creditOrderWxPayDto.setTotalAmount(order.getOrderMoney().multiply(BigDecimal.valueOf(100)).longValue());
                    creditOrderWxPayDto.setSubject("小鹏集团|robotaxi");
                    creditOrderWxPayDto.setPayType("13");
                    creditOrderWxPayDto.setBusinessId("xp-robotaxi");
                    creditOrderWxPayDto.setCategory("009001");
                    List<CreditOrderCreateDto.PostPayment> postPayments = new ArrayList<>();
                    CreditOrderCreateDto.PostPayment postPayment = new CreditOrderCreateDto.PostPayment();
@@ -4878,13 +5365,38 @@
                    postPayments.add(postPayment);
                    creditOrderWxPayDto.setPostPayments(postPayments);
                    R<CreditOrderWxPayVo> creditOrderWxPayVoR = xpPayFrontClient.creditOrderWxPay(creditOrderWxPayDto);
                }else if(creditOrderQueryVo.getCreditOrderStatus().equals("CREATED") || creditOrderQueryVo.getCreditOrderStatus().equals("DOING")){
                }
            }
        }else {
        } else {
            // 微信支付也需要查询下
            PayOrderQueryDto queryDto = new PayOrderQueryDto();
            queryDto.setBizId("xp-robotaxi");
            queryDto.setBizOrderId(order.getBusinessOrderId());
            R<PayOrderQueryVo> payOrderQueryVoR = xpPayFrontClient.queryPayOrder(queryDto);
            if (payOrderQueryVoR.getCode() == 200) {
                PayOrderQueryVo payOrderQueryVo = payOrderQueryVoR.getData();
                if (payOrderQueryVo.getPayStatus() == 1) {
                    // 支付成功
                    order.setStatus(9);
                    order.setAppUserId(null);
                    order.setAuthOrderId(payOrderQueryVo.getPayOrderId());
                    if (payOrderQueryVo.getPayType() == 13) {
                        order.setPayType(3);
                    }
                    this.updateById(order);
                    // 财务推送
                    xpFrdXfipEventPush(order, payOrderQueryVo.getAmount(), payOrderQueryVo.getPayOrderId());
                }
            }
        }
        OrderStatusFromOrderIdVo orderStatusFromOrderIdVo = new OrderStatusFromOrderIdVo();
@@ -4893,9 +5405,147 @@
        return orderStatusFromOrderIdVo;
    }
    @Override
    public void creditPayCall(XpOrder order) {
        CreditOrderWxPayDto dto = new CreditOrderWxPayDto();
        dto.setBusinessId("xp-robotaxi");
        dto.setBusinessOrderId(order.getBusinessOrderId());
        dto.setAuthOrderId(order.getAuthOrderId());
        dto.setCategory("009001");
        // TODO 需要根据环境补充路径
        dto.setPayCallbackUrl("");
        dto.setTotalAmount(order.getOrderMoney().multiply(BigDecimal.valueOf(100)).longValue());
        dto.setSubject("小鹏集团|robotaxi");
        dto.setPayType("13");
        List<CreditOrderCreateDto.PostPayment> postPayments = new ArrayList<>();
        CreditOrderCreateDto.PostPayment postPayment = new CreditOrderCreateDto.PostPayment();
        postPayment.setName("收费标准");
        postPayment.setDescription("行程价格动态浮动,具体详情可在费用详情或计价规则查看");
        dto.setPostPayments(postPayments);
        R<CreditOrderWxPayVo> creditOrderWxPayVoR = xpPayFrontClient.creditOrderWxPay(dto);
    }
    /**
     * 对接财务数据推送
     *
     * @param order
     */
    @Override
    public void xpFrdXfipEventPush(XpOrder order, Long payFee, String orderId) {
        if (order.getFrdXfipEvenetStatus() == 1) {
            return;
        }
        XpFrdXfipEventIngestReqDTO xpFrdXfipEventIngestReqDTO = new XpFrdXfipEventIngestReqDTO();
        xpFrdXfipEventIngestReqDTO.setEventId("RT_04");
        xpFrdXfipEventIngestReqDTO.setBusinessLine("RT");
        xpFrdXfipEventIngestReqDTO.setReqId(OrderCodeUtil.getOrderCode("FRDXFOPEVENT"));
        XpFrdXfipEventIngestContentDTO xpFrdXfipEventIngestContentDTO = new XpFrdXfipEventIngestContentDTO();
        xpFrdXfipEventIngestContentDTO.setCompanyCode("8000");
        xpFrdXfipEventIngestContentDTO.setOrderType("SELF_OPERATED");
        xpFrdXfipEventIngestContentDTO.setBusinessOrderNo(order.getMainOrderId());
        xpFrdXfipEventIngestContentDTO.setSubOrderNo(order.getBusinessOrderId());
        xpFrdXfipEventIngestContentDTO.setPaymentType("POST_PAY");
        xpFrdXfipEventIngestContentDTO.setOrderStatus("结算完成");
        xpFrdXfipEventIngestContentDTO.setSettlementDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        xpFrdXfipEventIngestContentDTO.setMaterialNo("XE2000398");
        xpFrdXfipEventIngestContentDTO.setBusinessPartnerCode("5004901");
        xpFrdXfipEventIngestContentDTO.setCurrency("CNY");
        xpFrdXfipEventIngestContentDTO.setConfirmedRevenueAmount(order.getOrderMoney());
        xpFrdXfipEventIngestContentDTO.setCashCollectedAmount(new BigDecimal(payFee).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
        xpFrdXfipEventIngestContentDTO.setCouponConsumedTotal(order.getCouponMoney() == null ? BigDecimal.ZERO : order.getCouponMoney());
        xpFrdXfipEventIngestContentDTO.setPaymentFlowNo(orderId);
        xpFrdXfipEventIngestContentDTO.setPaymentFlowAmount(new BigDecimal(payFee).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
        xpFrdXfipEventIngestContentDTO.setPaymentChannel("WECHAT");
        if (order.getCouponId() != null) {
            ArrayList<XpFrdXfipEventCouponLineDTO> list = new ArrayList<>(1);
            XpFrdXfipEventCouponLineDTO xpFrdXfipEventCouponLineDTO = new XpFrdXfipEventCouponLineDTO();
            xpFrdXfipEventCouponLineDTO.setCouponId(String.valueOf(order.getCouponId()));
            xpFrdXfipEventCouponLineDTO.setCouponType("ACTIVITY");
//            xpFrdXfipEventCouponLineDTO.setCouponIssuerCompanyCode("5004901");
//            xpFrdXfipEventCouponLineDTO.setSelfBorneAmount(order.getCouponMoney());
//            xpFrdXfipEventCouponLineDTO.setThirdPartyBorneAmount(BigDecimal.ZERO);
            xpFrdXfipEventCouponLineDTO.setCouponDeductionAmount(order.getCouponMoney());
            xpFrdXfipEventCouponLineDTO.setCouponIssuerCompanyCode("8000");
            list.add(xpFrdXfipEventCouponLineDTO);
            xpFrdXfipEventIngestContentDTO.setCouponLines(list);
        }
        xpFrdXfipEventIngestReqDTO.setContent(xpFrdXfipEventIngestContentDTO);
        R<XpFrdXfipEventIngestRespVO> ingest = xpFrdXfipEventClient.ingest(xpFrdXfipEventIngestReqDTO);
        if (ingest.getCode() == 200) {
            XpFrdXfipEventIngestRespVO data = ingest.getData();
            if (!data.getReceiveStatus().equals("REJECTED")) {
                // 推送成功
                order.setFrdXfipEvenetStatus(1);
                order.setFrdXfipEvenetId(data.getEventId());
            } else {
                // 推送失败
                order.setFrdXfipEvenetStatus(2);
                order.setFrdXfipEvenetId(data.getEventId());
            }
            log.info("xpFrdXfipEventPush:{}", data);
        } else {
            // 重试1次
            ingest = xpFrdXfipEventClient.ingest(xpFrdXfipEventIngestReqDTO);
            XpFrdXfipEventIngestRespVO data = ingest.getData();
            if (ingest.getCode() == 200) {
                if (!data.getReceiveStatus().equals("REJECTED")) {
                    // 推送成功
                    order.setFrdXfipEvenetStatus(1);
                    order.setFrdXfipEvenetId(data.getEventId());
                } else {
                    // 推送失败
                    order.setFrdXfipEvenetStatus(2);
                    order.setFrdXfipEvenetId(data.getEventId());
                }
                log.info("xpFrdXfipEventPush:{}", data);
            } else {
                // 推送失败
                order.setFrdXfipEvenetStatus(2);
                order.setFrdXfipEvenetId(data.getEventId());
            }
            log.info("xpFrdXfipEventPush:{}", ingest.getMsg());
        }
        order.setAppUserId(null);
        updateById(order);
    }
    @Override
    public CreditPayCallVo creditPaySuccessCall(CreditPaySuccessCallDto dto) {
        LambdaQueryWrapper<XpOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(XpOrder::getAuthOrderId, dto.getAuthOrderId());
        XpOrder order = this.getOne(wrapper.last("LIMIT 1"));
        if(dto.getPayStatus()==1){
            order.setStatus(9);
            order.setAppUserId(null);
            this.updateById(order);
            CreditPayCallVo vo = new CreditPayCallVo();
            vo.setRetCode("0");
            vo.setRetMsg("成功");
            // 对接财务
            this.xpFrdXfipEventPush(order,dto.getPayFee(),dto.getOrderId());
            return vo;
        }
        return null;
    }
    /**
     * 发票列表
     *
     * @param query
     * @return
     */
@@ -4910,51 +5560,89 @@
                .atEndOfMonth()
                .atTime(23, 59, 59);
        List<XpOrder> list =null;
        List<XpOrder> list = null;
        // 通过uid 和时间查出来数据  先判断是否传入了分页
        if (query.getPageNo()!=null && query.getPageSize()!=null) {
        if (query.getPageNo() != null && query.getPageSize() != null) {
            Page<XpOrder> page = new Page<>(query.getPageNo(), query.getPageSize());
            Page<XpOrder> orderPage = this.baseMapper.selectPage(page, new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).between(BaseModel::getCreateTime, startTime, endTime));
            Page<XpOrder> orderPage = this.baseMapper.selectPage(page, new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).between(BaseModel::getCreateTime, startTime, endTime).orderByDesc(BaseModel::getCreateTime));
            list = orderPage.getRecords();
        }else {
            list = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).between(BaseModel::getCreateTime, startTime, endTime));
        } else {
            list = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).between(BaseModel::getCreateTime, startTime, endTime).orderByDesc(BaseModel::getCreateTime));
        }
        if(list.isEmpty()){
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        ArrayList<XpInvoiceVo> xpInvoiceVoList = new ArrayList<>(list.size());
        R<List<XpVehicle>> r = xpVehicleClient.listByIds(list.stream().map(XpOrder::getVehicleId).collect(Collectors.toList()));
        List<XpVehicle> vehicleList = r.getData();
        // 数据组装
        for (XpOrder xpOrder : list) {
            XpInvoiceVo xpInvoiceVo = new XpInvoiceVo();
            xpInvoiceVo.setUid(xpOrder.getAppUserId().toString());
            xpInvoiceVo.setOrderNo(xpOrder.getOrderNumber());
            xpInvoiceVo.setOrderTotalAmount(xpOrder.getOrderMoney());
            xpInvoiceVo.setOrderDiscountAmount(xpOrder.getCouponMoney());
            xpInvoiceVo.setOrderFinishTime(String.valueOf(xpOrder.getTripEnd()));
            BigDecimal orderMoney = xpOrder.getOrderMoney() == null ? BigDecimal.ZERO : xpOrder.getOrderMoney();
            XpInvoiceVo.GoodsDetail goodsDetail = new XpInvoiceVo.GoodsDetail();
            goodsDetail.setProductName("Robotaxi出行服务");
            goodsDetail.setProductCode(null);
            goodsDetail.setProductSpecCode("XE2000398");
            goodsDetail.setProductSpec(null);
            goodsDetail.setProductUnit("次");
            goodsDetail.setQuantity(1);
            goodsDetail.setUnitPrice(orderMoney);
            goodsDetail.setInTaxAmount(orderMoney);
            goodsDetail.setTaxRate(null);
            goodsDetail.setTaxAmount(null);
            goodsDetail.setExTaxAmount(null);
            goodsDetail.setItemId(xpOrder.getOrderNumber());
            goodsDetail.setCouponAmount(xpOrder.getCouponMoney());
            goodsDetail.setCompanyCode("8000");
            JSONArray goodsDetailArray = new JSONArray();
            goodsDetailArray.add(goodsDetail);
            xpInvoiceVo.setGoodsDetail(JSON.toJSONString(goodsDetailArray));
            xpInvoiceVo.setOrderTotalAmount(xpOrder.getOrderMoney()!=null?xpOrder.getOrderMoney():BigDecimal.ZERO);
            xpInvoiceVo.setOrderBusAmount(xpOrder.getOrderMoney()!=null?xpOrder.getOrderMoney():BigDecimal.ZERO);
            xpInvoiceVo.setOrderDiscountAmount(xpOrder.getCouponMoney()!=null?xpOrder.getCouponMoney():BigDecimal.ZERO);
            xpInvoiceVo.setOrderFinishTime(xpOrder.getTripEnd()!=null?xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")):"");
            JSONObject extData = new JSONObject();
            extData.put("companyCode", "8000");
            extData.put("realCompanyCode", null);
            extData.put("siteName",null);
            extData.put("pile", null);
            extData.put("payFag", null);
            extData.put("supplierCode", null);
            xpInvoiceVo.setExtData(JSON.toJSONString(extData));
            xpInvoiceVo.setXpInvoiceFlag(true);
            xpInvoiceVo.setInvoiceStatus(xpOrder.getInvoiceStatus());
            XpInvoiceVo.Itinerary itinerary = new XpInvoiceVo.Itinerary();
            // yyyy-MM-dd格式
            itinerary.setTripStartDate(xpOrder.getAcceptanceTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripEndDate(xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripStartDate(xpOrder.getAcceptanceTime()!=null?xpOrder.getAcceptanceTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")):"");
            itinerary.setTripEndDate(xpOrder.getTripEnd()!=null?xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")):"");
            XpVehicle xpVehicle = vehicleList.stream().filter(vehicle -> vehicle.getId().equals(xpOrder.getVehicleId())).findFirst().get();
            itinerary.setCarType(xpVehicle.getVehicleModel());
            itinerary.setTripStartDate(xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripStartDate(xpOrder.getBoardingTime()!=null?xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")):"");
            itinerary.setCity(xpOrder.getCityName());
            itinerary.setStartPoint(xpOrder.getStartAddress());
            itinerary.setEndPoint(xpOrder.getEndAddress());
            itinerary.setMileage(xpOrder.getMileageKilometers().toString());
            itinerary.setAmount(xpOrder.getOrderMoney());
            itinerary.setMileage(xpOrder.getMileageKilometers()!=null ? xpOrder.getMileageKilometers().toString() :"0");
            UcUserInfo user = userResourcesClient.getBaseUserByUid(xpOrder.getAppUserId().toString());
            itinerary.setUserName(user.getNickName());
            itinerary.setUserAccount(user.getUid().toString());
            itinerary.setPhone(user.getMobile());
            itinerary.setPickupTime(xpOrder.getBoardingTime()!=null?xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")):"");
            itinerary.setDropOffTime(xpOrder.getTripEnd()!=null?xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")):"");
            itinerary.setOldPrice(xpOrder.getOrderMoney()!=null?xpOrder.getOrderMoney().toString():"0");
            itinerary.setCurrency("CNY");
            xpInvoiceVo.setItinerary(itinerary);
            xpInvoiceVoList.add(xpInvoiceVo);
@@ -4965,50 +5653,91 @@
    /**
     * 查询发票订单
     *
     * @param query
     * @return
     */
    @Override
    public List<XpInvoiceVo> queryInvoiceOrders(InvoiceOrdersQuery query) {
        if(query.getOrderNoList().isEmpty()){
        if (query.getOrderNoList().isEmpty()) {
            return Collections.emptyList();
        }
        List<XpOrder> list = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).in(XpOrder::getOrderNumber, query.getOrderNoList()));
        if(list.isEmpty()){
        if (list.isEmpty()) {
            return Collections.emptyList();
        }
        ArrayList<XpInvoiceVo> xpInvoiceVoList = new ArrayList<>(list.size());
        R<List<XpVehicle>> r = xpVehicleClient.listByIds(list.stream().map(XpOrder::getVehicleId).collect(Collectors.toList()));
        List<XpVehicle> vehicleList = r.getData();
        // 数据组装
        for (XpOrder xpOrder : list) {
            XpInvoiceVo xpInvoiceVo = new XpInvoiceVo();
            xpInvoiceVo.setUid(xpOrder.getAppUserId().toString());
            xpInvoiceVo.setOrderNo(xpOrder.getOrderNumber());
            xpInvoiceVo.setOrderTotalAmount(xpOrder.getOrderMoney());
            xpInvoiceVo.setOrderDiscountAmount(xpOrder.getCouponMoney());
            xpInvoiceVo.setOrderFinishTime(String.valueOf(xpOrder.getTripEnd()));
            BigDecimal orderMoney = xpOrder.getOrderMoney() == null ? BigDecimal.ZERO : xpOrder.getOrderMoney();
            XpInvoiceVo.GoodsDetail goodsDetail = new XpInvoiceVo.GoodsDetail();
            goodsDetail.setProductName("Robotaxi出行服务");
            goodsDetail.setProductCode(null);
            goodsDetail.setProductSpecCode("XE2000398");
            goodsDetail.setProductSpec(null);
            goodsDetail.setProductUnit("次");
            goodsDetail.setQuantity(1);
            goodsDetail.setUnitPrice(orderMoney);
            goodsDetail.setInTaxAmount(orderMoney);
            goodsDetail.setTaxRate(null);
            goodsDetail.setTaxAmount(null);
            goodsDetail.setExTaxAmount(null);
            goodsDetail.setItemId(xpOrder.getOrderNumber());
            goodsDetail.setCouponAmount(xpOrder.getCouponMoney());
            goodsDetail.setCompanyCode("8000");
            JSONArray goodsDetailArray = new JSONArray();
            goodsDetailArray.add(goodsDetail);
            xpInvoiceVo.setGoodsDetail(JSON.toJSONString(goodsDetailArray));
            xpInvoiceVo.setOrderTotalAmount(xpOrder.getOrderMoney()!=null?xpOrder.getOrderMoney():BigDecimal.ZERO);
            xpInvoiceVo.setOrderBusAmount(xpOrder.getOrderMoney()!=null?xpOrder.getOrderMoney():BigDecimal.ZERO);
            xpInvoiceVo.setOrderDiscountAmount(xpOrder.getCouponMoney()!=null?xpOrder.getCouponMoney():BigDecimal.ZERO);
            xpInvoiceVo.setOrderFinishTime(xpOrder.getTripEnd()!=null?xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")):"");
            JSONObject extData = new JSONObject();
            extData.put("companyCode", "8000");
            extData.put("realCompanyCode", null);
            extData.put("siteName",null);
            extData.put("pile", null);
            extData.put("payFag", null);
            extData.put("supplierCode", null);
            xpInvoiceVo.setExtData(JSON.toJSONString(extData));
            xpInvoiceVo.setXpInvoiceFlag(true);
            xpInvoiceVo.setInvoiceStatus(xpOrder.getInvoiceStatus());
            XpInvoiceVo.Itinerary itinerary = new XpInvoiceVo.Itinerary();
            // yyyy-MM-dd格式
            itinerary.setTripStartDate(xpOrder.getAcceptanceTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripEndDate(xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripStartDate(xpOrder.getAcceptanceTime()!=null?xpOrder.getAcceptanceTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")):"");
            itinerary.setTripEndDate(xpOrder.getTripEnd()!=null?xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")):"");
            XpVehicle xpVehicle = vehicleList.stream().filter(vehicle -> vehicle.getId().equals(xpOrder.getVehicleId())).findFirst().get();
            itinerary.setCarType(xpVehicle.getVehicleModel());
            itinerary.setTripStartDate(xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            itinerary.setTripStartDate(xpOrder.getBoardingTime()!=null?xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")):"");
            itinerary.setCity(xpOrder.getCityName());
            itinerary.setStartPoint(xpOrder.getStartAddress());
            itinerary.setEndPoint(xpOrder.getEndAddress());
            itinerary.setMileage(xpOrder.getMileageKilometers().toString());
            itinerary.setAmount(xpOrder.getOrderMoney());
            itinerary.setMileage(xpOrder.getMileageKilometers()!=null ? xpOrder.getMileageKilometers().toString() :"0");
            UcUserInfo user = userResourcesClient.getBaseUserByUid(xpOrder.getAppUserId().toString());
            itinerary.setUserName(user.getNickName());
            itinerary.setUserAccount(user.getUid().toString());
            itinerary.setPhone(user.getMobile());
            itinerary.setPickupTime(xpOrder.getBoardingTime()!=null?xpOrder.getBoardingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")):"");
            itinerary.setDropOffTime(xpOrder.getTripEnd()!=null?xpOrder.getTripEnd().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")):"");
            itinerary.setOldPrice(xpOrder.getOrderMoney()!=null?xpOrder.getOrderMoney().toString():"0");
            itinerary.setCurrency("CNY");
            xpInvoiceVo.setItinerary(itinerary);
            xpInvoiceVoList.add(xpInvoiceVo);
@@ -5024,12 +5753,12 @@
    @Override
    public void updateInvoiceStatus(UpdateInvoiceStatusDto dto) {
        List<UpdateInvoiceStatusDto.Order> orderList = dto.getOrderList();
        if(!orderList.isEmpty()){
        if (!orderList.isEmpty()) {
            List<String> orderNos = orderList.stream().map(UpdateInvoiceStatusDto.Order::getOrderNo).collect(Collectors.toList());
            List<XpOrder> xpOrders = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().in(XpOrder::getOrderNumber, orderNos));
            for (XpOrder xpOrder : xpOrders) {
                UpdateInvoiceStatusDto.Order order = orderList.stream().filter(e -> e.getOrderNo().equals(xpOrder.getOrderNumber())).findFirst().orElse(null);
                if(order!=null){
                if (order != null) {
                    xpOrder.setInvoiceStatus(order.getInvoiceStatus());
                    xpOrder.setInvoiceId(dto.getRequestId());
                    xpOrder.setAppUserId(null);