liujie
2026-05-18 df7ea92f6e128abf309d389bd99ffc4602ee2049
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -3,6 +3,7 @@
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -15,13 +16,17 @@
import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto;
import com.xiaopeng.api.feignClient.account.SysGroupMenuClient;
import com.xiaopeng.api.feignClient.frdXfipEvent.XpFrdXfipEventClient;
import com.xiaopeng.api.feignClient.operation.XpWhiteListClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.VehicleMacClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.operation.XpOfficialPartner;
import com.xiaopeng.api.model.operation.XpWhitelist;
import com.xiaopeng.api.model.order.OrderTrajectory;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.account.LoginUser;
import com.xiaopeng.api.vo.operation.NavigationVo;
import com.xiaopeng.api.vo.operation.NearestNextVo;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.*;
@@ -32,16 +37,15 @@
import com.xiaopeng.common.core.utils.WebUtils;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.order.mangodb.model.OrderTrajectory;
import com.xiaopeng.order.mangodb.service.OrderTrajectoryService;
import com.xiaopeng.order.model.dto.XpOrderCommentDto;
import com.xiaopeng.order.model.dto.XpOrderOperateDTO;
import com.xiaopeng.order.model.dto.XpOrderPayDto;
import com.xiaopeng.order.model.dto.XpOrderReassignDTO;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.order.config.BluetoothDebugConfig;
import com.xiaopeng.order.dto.OrderNavigationDto;
import com.xiaopeng.order.model.dto.*;
import com.xiaopeng.order.model.exportExcel.XpOrderExportExcel;
import com.xiaopeng.order.model.query.XpHistoryOrderListQuery;
import com.xiaopeng.order.model.query.XpOrderExcelQuery;
import com.xiaopeng.order.model.query.XpOrderPageQuery;
import com.xiaopeng.order.model.vo.CreditPayCallVo;
import com.xiaopeng.order.model.vo.XpOrderDetailVO;
import com.xiaopeng.order.model.vo.XpOrderHistoryVO;
import com.xiaopeng.order.model.vo.XpOrderPageVO;
@@ -49,6 +53,7 @@
import com.xiaopeng.order.vo.BluetoothTokenVo;
import com.xiaopeng.order.vo.OrderDetailVo;
import com.xiaopeng.order.vo.UpdateOrderStatusVo;
import com.xiaopeng.order.vo.XpOrderInfoVo;
import com.xiaopeng.unifiedverification.interceptor.XpClientCheck;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
@@ -99,11 +104,16 @@
    @Resource
    private  VehicleMacClient vehicleMacClient;
    @Resource
    private SysGroupMenuClient groupMenuClient;
    @Resource
    private XpWhiteListClient xpWhiteListClient;
    @Resource
    private TokenService tokenService;
    @Autowired
    private BluetoothDebugConfig bluetoothDebugConfig;
    /**
@@ -132,6 +142,23 @@
        }
        return R.ok(0L);
    }
    /**
     * 查询是否有未支付订单
     * 返回0 可以下单,非0为未支付订单ID
     */
    @PostMapping("/logan/inner/order/has-unpay-order")
    @ApiOperation(value = "查询是否有未支付订单", tags = {"内部接口"})
    public R<Long> hasUnPayOrder(String uid) {
        XpOrder order = xpOrderService.getOne(new LambdaQueryWrapper<XpOrder>()
                .eq(XpOrder::getAppUserId, Long.parseLong(uid))
                .eq(XpOrder::getStatus, 8)
                .last("LIMIT 1"));
        if (order != null) {
            return R.ok(order.getId());
        }
        return R.ok(0L);
    }
    /**
@@ -230,8 +257,12 @@
    @ApiOperation(value = "订单分页列表", tags = {"管理后台-交易管理-订单管理", "管理后台-活动管理"})
    @PostMapping("/api/v1/order/pageList")
    public R<PageInfo<XpOrderPageVO>> pageList( @RequestBody XpOrderPageQuery query) {
        LoginUser loginUser = tokenService.getLoginUser();
        PageInfo<XpOrderPageVO> pageInfo = xpOrderService.pageList(query);
        pageInfo.getRecords().forEach(s->s.setPhoneNumber(groupMenuClient.getPhoneDesensitization(s.getPhoneNumber()).getData()));
        if(!loginUser.getPhoneDesensitizationExempt()){
            pageInfo.getRecords().forEach(s->s.setPhoneNumber(DesensitizedUtil.mobilePhone(s.getPhoneNumber())));
        }
        return R.ok(pageInfo);
    }
@@ -244,8 +275,12 @@
    @ApiOperation(value = "订单详情", tags = {"管理后台-交易管理-订单管理"})
    @GetMapping("/api/v1/order/queryById")
    public R<XpOrderDetailVO> queryById(@ApiParam(value = "订单id", required = true) @RequestParam Long id) {
        LoginUser loginUser = tokenService.getLoginUser();
        XpOrderDetailVO detail = xpOrderService.getOrderDetail(id);
        detail.setPhoneNumber(groupMenuClient.getPhoneDesensitization(detail.getPhoneNumber()).getData());
        if(!loginUser.getPhoneDesensitizationExempt()){
            detail.setPhoneNumber(DesensitizedUtil.mobilePhone(detail.getPhoneNumber()));
        }
        return R.ok(detail);
    }
@@ -691,6 +726,18 @@
    @GetMapping("/api/v1/mini-program/bluetooth/getUnlocktToken/{orderId}")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<BluetoothTokenVo> getBluetoothToken(@PathVariable("orderId") Long orderId, HttpServletRequest request) {
        // ========== 联调临时逻辑:通过 Nacos 配置返回固定蓝牙信息(bluetooth-debug.enabled=true 时生效) ==========
        if (bluetoothDebugConfig.isEnabled()) {
            BluetoothTokenVo vo = new BluetoothTokenVo();
            vo.setToken(bluetoothDebugConfig.getToken());
            vo.setMacAddress(bluetoothDebugConfig.getMacAddress());
            vo.setSlaveMacList(bluetoothDebugConfig.getSlaveMacList());
            return R.ok(vo);
        }
        // ========== 联调临时逻辑结束 ==========
        // 原逻辑
        String uid = request.getHeader("XP-Uid");
        XpOrder xpOrder = xpOrderService.getById(orderId);
        if (!Objects.equals(xpOrder.getAppUserId(), Long.valueOf(uid))) {
@@ -808,12 +855,130 @@
    @PostMapping("/drainage/v1/order/updateOrderStatus")
    @ApiOperation(value = "更新订单状态", notes = "流量接入-基础信息")
    @ApiOperation(value = "更新订单状态", notes = "流量接入-订单信息")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
    })
    public R<?> officialPartnerUpdateOrderStatus(@RequestBody UpdateOrderStatusVo vo){
        xpOrderService.officialPartnerUpdateOrderStatus(vo);
        return R.ok();
    public R<?> officialPartnerUpdateOrderStatus(@RequestBody UpdateOrderStatusVo vo, HttpServletRequest request){
        XpOfficialPartner officialPartner = tokenService.getOfficialPartner();
        return xpOrderService.officialPartnerUpdateOrderStatus(vo, officialPartner.getId());
    }
}
    @PostMapping("/drainage/v1/order/getOrderNavigation")
    @ApiOperation(value = "获取订单导航数据", notes = "流量接入-订单信息")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
    })
    public R<NavigationVo> getOrderNavigation(@RequestBody OrderNavigationDto dto, HttpServletRequest request){
        XpOfficialPartner officialPartner = tokenService.getOfficialPartner();
        XpOrder xpOrder = xpOrderService.getById(dto.getOrderId());
        if(!xpOrder.getOfficialPartnerId().equals(officialPartner.getId())){
            return R.fail("无权限");
        }
        NavigationVo navigationVo = null;
        if(1 == dto.getNavigationType()){
            Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId());
            if(null != cacheObject){
                navigationVo = JSON.parseObject(cacheObject.toString(), NavigationVo.class);
            }
        }
        if(2 == dto.getNavigationType()){
            Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId());
            if(null != cacheObject){
                navigationVo = JSON.parseObject(cacheObject.toString(), NavigationVo.class);
            }
        }
        return R.ok(navigationVo);
    }
    @PostMapping("/drainage/v1/order/getOrderInfo")
    @ApiOperation(value = "获取订单详情", notes = "流量接入-订单信息")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
    })
    public R<XpOrderInfoVo> getOfficialPartnerOrderInfo(@PathVariable Long orderId){
        XpOfficialPartner officialPartner = tokenService.getOfficialPartner();
        XpOrder xpOrder = xpOrderService.getById(orderId);
        if(!xpOrder.getOfficialPartnerId().equals(officialPartner.getId())){
            return R.fail("无权限");
        }
        XpOrderInfoVo xpOrderInfoVo = BeanUtil.copyProperties(xpOrder, XpOrderInfoVo.class);
        return R.ok(xpOrderInfoVo);
    }
    @ApiOperation(value = "获取订单支付状态", tags = {"小程序-业务流程"})
    @GetMapping("/api/v1/mini-program/order/queryOrderStatusFromOrderId")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<OrderStatusFromOrderIdVo> queryOrderStatusFromOrderId(Long orderId) {
        XpOrder order = xpOrderService.getById(orderId);
        OrderStatusFromOrderIdVo orderStatusFromOrderIdVo = new OrderStatusFromOrderIdVo();
        orderStatusFromOrderIdVo.setOrderId(order.getId());
        orderStatusFromOrderIdVo.setStatus(order.getStatus());
        return R.ok( xpOrderService.queryOrderStatusFromOrderId(orderId));
    }
    /**
     * 信用支付下单回调
     */
    @PostMapping("/base/v1/mini-program/order/creditPayCall")
    @ApiOperation(value = "信用支付下单回调", tags = {"小程序-发起支付"}, response = CreditPayCallVo.class)
    public CreditPayCallVo creditPayCall(@RequestBody CreditPayCallDto dto) {
        CreditPayCallVo vo = new CreditPayCallVo();
        vo.setRetCode("0");
        vo.setRetMsg("成功");
        if (dto == null || (StringUtils.isBlank(dto.getAuthOrderId()) || StringUtils.isBlank(dto.getBusinessOrderId()))) {
            return vo;
        }
        LambdaQueryWrapper<XpOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(XpOrder::getAuthOrderId, dto.getAuthOrderId());
        XpOrder order = xpOrderService.getOne(wrapper.last("LIMIT 1"));
        if (order == null) {
            return vo;
        }
        if ("SUCCESS".equals(dto.getCreditOrderStatus())) {
            // 发起扣款
            xpOrderService.creditPayCall(order);
        }
        return vo;
    }
    /**
     * 信用扣款回调
     */
    @PostMapping("/base/v1/mini-program/order/creditPaySuccessCall")
    @ApiOperation(value = "信用扣款回调", tags = {"小程序-发起支付"}, response = CreditPayCallVo.class)
    public CreditPayCallVo creditPaySuccessCall(@RequestBody CreditPaySuccessCallDto dto) {
        LambdaQueryWrapper<XpOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(XpOrder::getAuthOrderId, dto.getAuthOrderId());
        XpOrder order = xpOrderService.getOne(wrapper.last("LIMIT 1"));
        if(dto.getPayStatus()==1){
            order.setStatus(9);
            order.setAppUserId(null);
            xpOrderService.updateById(order);
            CreditPayCallVo vo = new CreditPayCallVo();
            vo.setRetCode("0");
            vo.setRetMsg("成功");
            // 对接财务
            xpOrderService.xpFrdXfipEventPush(order,dto.getPayFee(),dto.getOrderId());
            return vo;
        }
        return null;
    }
}