“mitao”
2026-05-15 5c863676b014e5ae2fa601d89a83160b6e7a6c07
Merge remote-tracking branch 'origin/1.1' into 1.1
7个文件已添加
15个文件已修改
606 ■■■■■ 已修改文件
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/TokenController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpAppUserController.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/XpPayFrontMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpPayFrontService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpPayFrontServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpPayFrontMapper.xml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/payFront/CreditOrderQueryDto.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/payFront/XpPayFrontClientFallbackFactory.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/payFront/XpPayFrontClient.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/XpPayFront.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/OrderStatusFromOrderIdVo.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/controller/XpPricingController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpInvoiceController.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/vo/XpOrderHistoryListVO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaskOrderSendSmsUtil.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/resources/mapper/order/XpOrderMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/TokenController.java
@@ -154,7 +154,7 @@
    @PostMapping("/maintenance-app/base/v1/getVerificationCode")
    public R<?> verificationCodeLogin(@RequestBody AppLoginGetCodeDTO appLoginPasswordDTO) {
        if (StringUtils.isBlank(appLoginPasswordDTO.getPhoneNumber())) {
            return R.fail("璐﹀彿涓嶅瓨鍦?");
            return R.fail("手机号不能为空!");
        }
        XpOperationsUser xpOperationsUser = xpOperationsUserService.lambdaQuery()
                .in(XpOperationsUser::getPhoneNumber, SensitiveDataCryptoUtil.queryValues(appLoginPasswordDTO.getPhoneNumber()))
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpAppUserController.java
@@ -1,11 +1,23 @@
package com.xiaopeng.account.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaopeng.account.mapper.XpPayFrontMapper;
import com.xiaopeng.account.model.dto.CollectAddrDTO;
import com.xiaopeng.account.service.IXpAppUserService;
import com.xiaopeng.api.dto.payFront.CreditPaySignDto;
import com.xiaopeng.api.dto.payFront.CreditPaySignQueryDto;
import com.xiaopeng.api.dto.payFront.UnsignCreditPayDto;
import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO;
import com.xiaopeng.api.dto.statistics.UserStatisticsDTO;
import com.xiaopeng.api.feignClient.payFront.XpPayFrontClient;
import com.xiaopeng.api.model.account.XpAppUser;
import com.xiaopeng.api.model.account.XpPayFront;
import com.xiaopeng.api.vo.payFront.CreditPaySignQueryVo;
import com.xiaopeng.api.vo.payFront.CreditPaySignVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.OrderCodeUtil;
import com.xiaopeng.common.core.web.domain.BaseModel;
import com.xiaopeng.unifiedverification.interceptor.XpClientCheck;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -34,6 +46,13 @@
    @Resource
    private IXpAppUserService xpAppUserService;
    @Resource
    private XpPayFrontClient xpPayFrontClient;
    @Resource
    private XpPayFrontMapper xpPayFrontMapper;
    /**
     * 获取用户统计数据(内部接口)
@@ -84,9 +103,25 @@
    public R<Boolean> appUserGetPayPwd(HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        //调用其他接口获取 免密结果 todo yyy
        Boolean is = true;
        return R.ok(is);
        //调用其他接口获取 免密结果
        Boolean signed = false;
        CreditPaySignQueryDto creditPaySignQueryDto = new CreditPaySignQueryDto();
        creditPaySignQueryDto.setUid(Long.valueOf(uid));
        creditPaySignQueryDto.setBusinessId("xp-robotaxi");
        creditPaySignQueryDto.setCategory("009001");
        creditPaySignQueryDto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
        R<CreditPaySignQueryVo> creditPaySignQueryVoR = xpPayFrontClient.queryCreditPaySign(creditPaySignQueryDto);
        if (creditPaySignQueryVoR.getCode()==200) {
            CreditPaySignQueryVo data = creditPaySignQueryVoR.getData();
            // 查看是否有签约的
            long count = data.getSignList().stream().filter(e -> e.getStatus().equals("VALID")).count();
            if (count > 0){
                signed = true;
            }
        }
        return R.ok(signed);
    }
    /**
@@ -95,12 +130,61 @@
    @PostMapping("/api/v1/mini-program/appUser/setPayPwd")
    @ApiOperation(value = "个人中心-设置免密结果", tags = {"小程序-设置免密结果"})
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<?> appUserSetPayPwd(HttpServletRequest request) {
    public R<?> appUserSetPayPwd(@RequestParam Integer status,HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        //调用其他接口设置免密结果 todo yyy
        //调用其他接口设置免密结果
        if(status==1){
            CreditPaySignDto creditPaySignDto = new CreditPaySignDto();
            creditPaySignDto.setUid(Long.valueOf(uid));
            creditPaySignDto.setBusinessId("xp-robotaxi");
            creditPaySignDto.setCategory("009001");
            creditPaySignDto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
            creditPaySignDto.setPayType("13");
            R<CreditPaySignVo> creditPaySignVoR = xpPayFrontClient.creditPaySign(creditPaySignDto);
            if(creditPaySignVoR.getCode()==200){
                CreditPaySignVo data = creditPaySignVoR.getData();
                XpPayFront xpPayFront = new XpPayFront();
                xpPayFront.setUserId(Long.valueOf(uid));
                xpPayFront.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
                xpPayFrontMapper.insert(xpPayFront);
                return R.ok(data);
            }
        }else {
            UnsignCreditPayDto unsignCreditPayDto = new UnsignCreditPayDto();
            unsignCreditPayDto.setUid(Long.valueOf(uid));
            unsignCreditPayDto.setBusinessId("xp-robotaxi");
            unsignCreditPayDto.setCategory("009001");
            String businessOrderId= null;
            // 查询用户开通的id
            List<XpPayFront> xpPayFronts = xpPayFrontMapper.selectList(new LambdaQueryWrapper<XpPayFront>().eq(XpPayFront::getUserId, Long.valueOf(uid)).orderByDesc(BaseModel::getCreateTime));
            if(xpPayFronts.size()>0){
                businessOrderId = xpPayFronts.get(0).getBusinessOrderId();
            }
            if(businessOrderId==null){
                return R.ok();
            }
            unsignCreditPayDto.setBusinessOrderId(businessOrderId);
            unsignCreditPayDto.setPayType("13");
            R<?> unsignCreditPayVoR = xpPayFrontClient.unsign(unsignCreditPayDto);
            if(unsignCreditPayVoR.getCode()==200){
                // 移除信息
                xpPayFrontMapper.delete(new LambdaQueryWrapper<XpPayFront>().eq(XpPayFront::getUserId, Long.valueOf(uid)));
                return R.ok();
            }
        }
        return R.ok();
    }
//-----------------------------------------------app接口------------------------------------------
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/XpPayFrontMapper.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.account.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.account.XpPayFront;
/**
 * <p>
 * 用户免密支付记录 Mapper 接口
 * </p>
 *
 * @author xiaopeng
 * @since 2026-05-14
 */
public interface XpPayFrontMapper extends BaseMapper<XpPayFront> {
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpPayFrontService.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.account.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.account.XpPayFront;
/**
 * <p>
 * 用户免密支付记录 服务类
 * </p>
 *
 * @author xiaopeng
 * @since 2026-05-14
 */
public interface IXpPayFrontService extends IService<XpPayFront> {
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpPayFrontServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.account.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.account.mapper.XpPayFrontMapper;
import com.xiaopeng.account.service.IXpPayFrontService;
import com.xiaopeng.api.model.account.XpPayFront;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 用户免密支付记录 服务实现类
 * </p>
 *
 * @author xiaopeng
 * @since 2026-05-14
 */
@Service
public class XpPayFrontServiceImpl extends ServiceImpl<XpPayFrontMapper, XpPayFront> implements IXpPayFrontService {
}
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpPayFrontMapper.xml
New file
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.account.mapper.XpPayFrontMapper">
    <sql id="Base_Column_List">
        id, user_id, business_order_id, is_deleted, create_time, update_time, create_by, update_by
    </sql>
</mapper>
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/payFront/CreditOrderQueryDto.java
@@ -12,7 +12,7 @@
    @ApiModelProperty(value = "业务方id")
    @NotBlank(message = "业务方id不能为空")
    private String businessId;
    private String businessId="xp-robotaxi";
    @ApiModelProperty(value = "业务方订单id")
    @NotBlank(message = "业务方订单id不能为空")
@@ -27,7 +27,7 @@
    @ApiModelProperty(value = "业务方类目,由支付中心分配")
    @NotBlank(message = "业务方类目不能为空")
    private String category;
    private String category="009001";
    @ApiModelProperty(value = "支付类型(芝麻后付or微信支付分),13: 微信支付分")
    @NotBlank(message = "支付类型不能为空")
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java
@@ -50,6 +50,12 @@
            }
            @Override
            public R<Long> hasUnPayOrder(String uid) {
                log.error("查询未支付订单失败,原因: {}", cause.getMessage());
                return R.ok(0L);
            }
            @Override
            public R<XpOrder> queryOrderById(Long orderId) {
                log.error("根据订单id查询订单信息查询失败,原因: {}", cause.getMessage());
                return R.fail("根据订单id查询订单信息查询失败" + cause.getMessage());
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/payFront/XpPayFrontClientFallbackFactory.java
@@ -18,7 +18,6 @@
import com.xiaopeng.api.vo.payFront.CreditPaySignVo;
import com.xiaopeng.api.vo.payFront.CreditPrecreateVo;
import com.xiaopeng.api.vo.payFront.RefundVo;
import com.xiaopeng.api.vo.payFront.UnsignCreditPayVo;
import com.xiaopeng.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
@@ -78,7 +77,7 @@
            }
            @Override
            public R<UnsignCreditPayVo> unsign(UnsignCreditPayDto dto) {
            public R<?> unsign(UnsignCreditPayDto dto) {
                return fail("credit pay unsign failed");
            }
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java
@@ -43,6 +43,12 @@
    @PostMapping("/logan/inner/order/has-unpaid-order")
    R<Long> hasUnPaodOrder(@RequestParam String uid);
    /**
     * 查询是否有未支付订单
     */
    @PostMapping("/logan/inner/order/has-unpay-order")
    R<Long> hasUnPayOrder(@RequestParam String uid);
    /**
     * 通过订单id查询订单信息
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/payFront/XpPayFrontClient.java
@@ -18,7 +18,6 @@
import com.xiaopeng.api.vo.payFront.CreditPaySignVo;
import com.xiaopeng.api.vo.payFront.CreditPrecreateVo;
import com.xiaopeng.api.vo.payFront.RefundVo;
import com.xiaopeng.api.vo.payFront.UnsignCreditPayVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
@@ -35,9 +34,12 @@
        fallbackFactory = XpPayFrontClientFallbackFactory.class)
public interface XpPayFrontClient {
    // 微信支付分开通接口
    @PostMapping("/logan/pay/creditPay/sign")
    R<CreditPaySignVo> creditPaySign(@RequestBody CreditPaySignDto dto);
    // 主动查询开通结果接口
    @PostMapping("/logan/pay/creditPay/sign/query")
    R<CreditPaySignQueryVo> queryCreditPaySign(@RequestBody CreditPaySignQueryDto dto);
@@ -60,5 +62,5 @@
    R<CreditPrecreateVo> precreate(@RequestBody CreditPrecreateDto dto);
    @PostMapping("/logan/pay/creditPay/unsign")
    R<UnsignCreditPayVo> unsign(@RequestBody UnsignCreditPayDto dto);
    R<?> unsign(@RequestBody UnsignCreditPayDto dto);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/XpPayFront.java
New file
@@ -0,0 +1,38 @@
package com.xiaopeng.api.model.account;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xiaopeng.common.core.web.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
 * <p>
 * 用户免密支付记录
 * </p>
 *
 * @author xiaopeng
 * @since 2026-05-14
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("xp_pay_front")
@ApiModel(value = "XpPayFront对象", description = "用户免密支付记录")
public class XpPayFront extends BaseModel {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;
    @ApiModelProperty(value = "用户ID")
    private Long userId;
    @ApiModelProperty(value = "开通免密的businessOrderId")
    private String businessOrderId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java
@@ -238,6 +238,10 @@
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime tripEnd;
    @ApiModelProperty(value = "短信发送状态 0=未发送 1=已发送")
    @TableField("sms_status")
    private Integer smsStatus;
    @ApiModelProperty(value = "队列名称")
    @TableField("queue_name")
@@ -273,4 +277,9 @@
    @ApiModelProperty(value = "发票id")
    @TableField("invoice_id")
    private String invoiceId;
    @ApiModelProperty(value = "信用下单接口获取的支付中心授权单号(商户订单号)")
    @TableField("auth_order_id")
    private String authOrderId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/OrderStatusFromOrderIdVo.java
New file
@@ -0,0 +1,12 @@
package com.xiaopeng.api.vo.order;
import io.swagger.annotations.ApiModel;
import lombok.Data;
@Data
@ApiModel("订单支付状态VO")
public class OrderStatusFromOrderIdVo {
    private Long orderId;
    private Integer status;
}
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/controller/XpPricingController.java
@@ -7,6 +7,7 @@
import com.xiaopeng.api.dto.map.RouteStaleCheckDto;
import com.xiaopeng.api.dto.map.SelectNavigationRouteDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.model.operation.XpPricing;
import com.xiaopeng.api.vo.HotFixInfoVo;
import com.xiaopeng.api.vo.operation.MultiRouteAndFareVo;
@@ -52,13 +53,15 @@
    private final IXpGeoQueryEntityService xpGeoQueryEntityService;
    private final RedisService redisService;
    private final ImageTagProcessor imageTagProcessor;
    private final XpOrderClient xpOrderClient;
    public XpPricingController(XpPricingService xpPricingService, IXpGeoQueryEntityService xpGeoQueryEntityService, RedisService redisService, ImageTagProcessor imageTagProcessor) {
    public XpPricingController(XpPricingService xpPricingService, IXpGeoQueryEntityService xpGeoQueryEntityService, RedisService redisService, ImageTagProcessor imageTagProcessor, XpOrderClient xpOrderClient) {
        this.xpPricingService = xpPricingService;
        this.xpGeoQueryEntityService = xpGeoQueryEntityService;
        this.redisService = redisService;
        this.imageTagProcessor = imageTagProcessor;
        this.xpOrderClient = xpOrderClient;
    }
@@ -115,6 +118,14 @@
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<?> saveOrder(@RequestBody @Validated XpOrderDto dto, HttpServletRequest request) {
        String uid = request.getHeader("XP-Uid");
        R<Long> hasOrderResult = xpOrderClient.hasUnPayOrder(uid);
        if (hasOrderResult == null || R.isError(hasOrderResult)) {
            return R.fail("订单状态查询失败");
        }
        Long existingOrderId = hasOrderResult.getData();
        if (existingOrderId != null && existingOrderId > 0) {
            return R.fail("有未支付订单");
        }
        String orderId = xpPricingService.saveOrder(dto, uid);
        if(orderId==null){
            String language = request.getHeader("language");
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpInvoiceController.java
@@ -1,88 +1,23 @@
package com.xiaopeng.order.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaopeng.api.dto.QueryOrderRouteDTO;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.dto.order.GetOrderNumDto;
import com.xiaopeng.api.dto.order.PopOrderDto;
import com.xiaopeng.api.dto.order.UpdateInvoiceStatusDto;
import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO;
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.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.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.query.order.InvoiceOrdersQuery;
import com.xiaopeng.api.query.order.XpOrderInvoiceQuery;
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.*;
import com.xiaopeng.api.vo.vehicleConvoy.GetBleInfoVo;
import com.xiaopeng.api.vo.order.XpInvoiceVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.utils.StringUtils;
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.common.security.service.TokenService;
import com.xiaopeng.order.dto.OrderNavigationDto;
import com.xiaopeng.order.mangodb.model.OrderTrajectory;
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.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.XpOrderDetailVO;
import com.xiaopeng.order.model.vo.XpOrderHistoryVO;
import com.xiaopeng.order.model.vo.XpOrderPageVO;
import com.xiaopeng.order.service.IXpOrderService;
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 io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;
import java.util.List;
/**
 * <p>
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -151,6 +151,23 @@
    }
    /**
     * 查询是否有未支付订单
     * 返回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);
    }
    /**
     * 通过订单id查询订单信息
     *
     * @param orderId 订单id
@@ -281,12 +298,6 @@
     */
    @ApiOperation(value = "删除订单", tags = {"管理后台-交易管理-订单管理"})
    @DeleteMapping("/api/v1/order/deleteById")
    @AdminOperationLog(
            businessType = AdminBusinessType.ORDER_MANAGEMENT,
            operationType = AdminOperationType.DELETE,
            contentExpression = "'删除订单,id=' + #p0",
            appendRequestData = false
    )
    public R<?> deleteById(@ApiParam(value = "订单id", required = true) @RequestParam Long id) {
        xpOrderService.deleteOrder(id);
        return R.ok();
@@ -299,12 +310,6 @@
     */
    @ApiOperation(value = "订单导出", tags = {"管理后台-交易管理-订单管理"})
    @PostMapping("/api/v1/order/exportExcel")
    @AdminOperationLog(
            businessType = AdminBusinessType.ORDER_MANAGEMENT,
            operationType = AdminOperationType.EXPORT,
            content = "订单导出",
            appendRequestData = true
    )
    public void exportExcel(@RequestBody XpOrderExcelQuery query) {
        // 1. 查询导出数据
        List<XpOrderPageVO> dataList = xpOrderService.exportList(query);
@@ -346,12 +351,6 @@
     */
    @ApiOperation(value = "取消/关闭订单", tags = {"管理后台-交易管理-订单管理"})
    @PostMapping("/api/v1/order/cancelAndCloseById")
    @AdminOperationLog(
            businessType = AdminBusinessType.ORDER_MANAGEMENT,
            operationType = AdminOperationType.EDIT,
            content = "取消/关闭订单",
            appendRequestData = true
    )
    public R<?> cancelAndCloseById(@Validated @RequestBody XpOrderOperateDTO dto) {
        xpOrderService.cancelOrCloseOrder(dto.getOrderId(), dto.getType(),dto.getIsFree());
        return R.ok();
@@ -365,12 +364,6 @@
     */
    @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"}, notes = "车辆列表在 vehicleConvoy.availableList 服务")
    @PostMapping("/api/v1/order/reassignById")
    @AdminOperationLog(
            businessType = AdminBusinessType.ORDER_MANAGEMENT,
            operationType = AdminOperationType.EDIT,
            content = "改派订单",
            appendRequestData = true
    )
    public R<?> reassignById(@Validated @RequestBody XpOrderReassignDTO dto) {
        xpOrderService.reassignOrder(
                dto.getOrderId(),
@@ -387,12 +380,6 @@
            @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "amount", value = "新的订单金额", required = true, dataType = "BigDecimal")
    })
    @AdminOperationLog(
            businessType = AdminBusinessType.ORDER_MANAGEMENT,
            operationType = AdminOperationType.EDIT,
            contentExpression = "'订单改价,id=' + #p0 + ',amount=' + #p1",
            appendRequestData = false
    )
    public R<?> changeAmount(@RequestParam("id") Long id, @RequestParam("amount") BigDecimal amount) {
        xpOrderService.changeAmount(id, amount);
        return R.ok();
@@ -926,4 +913,21 @@
        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));
    }
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/vo/XpOrderHistoryListVO.java
@@ -67,5 +67,7 @@
    private Integer invoiceStatus;
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java
@@ -301,4 +301,13 @@
     * @return
     */
    UserOrderInfoVo getOrderHistoryInfo(Long orderId);
    /**
     * 获取订单状态
     * @param orderId
     * @return
     */
    OrderStatusFromOrderIdVo queryOrderStatusFromOrderId(Long orderId);
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -22,9 +22,7 @@
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
import com.xiaopeng.api.dto.order.*;
import com.xiaopeng.api.dto.payFront.CreditOrderCreateDto;
import com.xiaopeng.api.dto.payFront.CreditPaySignQueryDto;
import com.xiaopeng.api.dto.payFront.CreditPrecreateDto;
import com.xiaopeng.api.dto.payFront.*;
import com.xiaopeng.api.dto.pushMessage.SendMessageDTO;
import com.xiaopeng.api.dto.statistics.DailyCountDTO;
import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO;
@@ -61,10 +59,8 @@
import com.xiaopeng.api.vo.operation.NearestNextVo;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.*;
import com.xiaopeng.api.vo.payFront.CreditOrderCreateVo;
import com.xiaopeng.api.vo.payFront.CreditPaySignQueryVo;
import com.xiaopeng.api.vo.payFront.*;
import com.xiaopeng.api.vo.order.FareBreakdownVo;
import com.xiaopeng.api.vo.payFront.CreditPrecreateVo;
import com.xiaopeng.api.vo.vehicleConvoy.AddTaxiPassengerVo;
import com.xiaopeng.api.vo.vehicleConvoy.BluetoothDeliverVo;
import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo;
@@ -78,6 +74,7 @@
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.utils.DateUtils;
import com.xiaopeng.common.core.utils.GeodesyUtil;
import com.xiaopeng.common.core.utils.OrderCodeUtil;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.web.domain.BaseModel;
import com.xiaopeng.common.core.web.page.PageInfo;
@@ -3327,6 +3324,8 @@
    public R payment(XpOrderPayDto dto, String uid) {
        XpOrder order = this.getById(dto.getOrderId());
        HashMap<String, Object> resultMap = new HashMap<>();
        // 1.0 免密  //查询是否开通免密
@@ -3336,7 +3335,7 @@
        creditPaySignQueryDto.setUid(Long.valueOf(uid));
        creditPaySignQueryDto.setBusinessId("xp-robotaxi");
        creditPaySignQueryDto.setCategory("009001");
        creditPaySignQueryDto.setBusinessOrderId("");
        creditPaySignQueryDto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
        R<CreditPaySignQueryVo> creditPaySignQueryVoR = xpPayFrontClient.queryCreditPaySign(creditPaySignQueryDto);
        if (creditPaySignQueryVoR.getCode()==200) {
            CreditPaySignQueryVo data = creditPaySignQueryVoR.getData();
@@ -3353,9 +3352,9 @@
            CreditOrderCreateDto creditOrderCreateDto = new CreditOrderCreateDto();
            creditOrderCreateDto.setUid(Long.valueOf(uid));
            creditOrderCreateDto.setBusinessId("xp-robotaxi");
            creditOrderCreateDto.setCategory("xp_robotaxi_api");
            creditOrderCreateDto.setCategory("009001");
            creditOrderCreateDto.setBusinessOrderId("");
            creditOrderCreateDto.setSubject("009001");
            creditOrderCreateDto.setSubject("小鹏集团|robotaxi");
            creditOrderCreateDto.setPayType("13");
@@ -3371,6 +3370,10 @@
                CreditOrderCreateVo data = creditOrderCreateVoR.getData();
                resultMap.put("status", 1);
                resultMap.put("value", data);
                order.setPayType(3);
                order.setAuthOrderId(data.getAuthOrderId());
                return R.ok(resultMap);
            }
@@ -3378,7 +3381,6 @@
            // 未签约
            // 调用预下单接口
            XpOrder order = this.getById(dto.getOrderId());
            CreditPrecreateDto creditPrecreateDto = new CreditPrecreateDto();
            creditPrecreateDto.setUid(uid);
            creditPrecreateDto.setBizId("xp-robotaxi");
@@ -4705,6 +4707,59 @@
        return vo;
    }
    /**
     * 查询订单状态
     * @param orderId
     * @return
     */
    @Override
    public OrderStatusFromOrderIdVo queryOrderStatusFromOrderId(Long orderId) {
        XpOrder order = this.getById(orderId);
        if(order==null){
            return null;
        }
        if(order.getPayType()==3){
            // 免密查询 如果成功则调用结算
            CreditOrderQueryDto dto = new CreditOrderQueryDto();
            dto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
            dto.setAuthOrderId(order.getAuthOrderId());
            dto.setPayType("13");
            R<CreditOrderQueryVo> creditOrderQueryVoR = xpPayFrontClient.queryCreditOrder(dto);
            if(creditOrderQueryVoR.getCode()==200){
                CreditOrderQueryVo creditOrderQueryVo = creditOrderQueryVoR.getData();
                if(creditOrderQueryVo.getCreditOrderStatus().equals("DONE")){
                    // 订单确认 需要吊起扣款
                    CreditOrderWxPayDto creditOrderWxPayDto = new CreditOrderWxPayDto();
                    creditOrderWxPayDto.setBusinessOrderId(OrderCodeUtil.getOrderCode("MMZF"));
                    creditOrderWxPayDto.setAuthOrderId(order.getAuthOrderId());
                    creditOrderWxPayDto.setPayCallbackUrl("13");
                    creditOrderWxPayDto.setTotalAmount( order.getOrderMoney().multiply(BigDecimal.valueOf(100)).longValue());
                    creditOrderWxPayDto.setSubject("小鹏集团|robotaxi");
                    creditOrderWxPayDto.setPayType("13");
                    List<CreditOrderCreateDto.PostPayment> postPayments = new ArrayList<>();
                    CreditOrderCreateDto.PostPayment postPayment = new CreditOrderCreateDto.PostPayment();
                    postPayment.setName("收费标准");
                    postPayment.setDescription("行程价格动态浮动,具体详情可在费用详情或计价规则查看");
                    postPayments.add(postPayment);
                    creditOrderWxPayDto.setPostPayments(postPayments);
                    R<CreditOrderWxPayVo> creditOrderWxPayVoR = xpPayFrontClient.creditOrderWxPay(creditOrderWxPayDto);
                }else if(creditOrderQueryVo.getCreditOrderStatus().equals("CREATED") || creditOrderQueryVo.getCreditOrderStatus().equals("DOING")){
                }
            }
        }else {
            // 微信支付也需要查询下
        }
        OrderStatusFromOrderIdVo orderStatusFromOrderIdVo = new OrderStatusFromOrderIdVo();
        orderStatusFromOrderIdVo.setOrderId(order.getId());
        orderStatusFromOrderIdVo.setStatus(order.getStatus());
        return orderStatusFromOrderIdVo;
    }
    /**
     * 发票列表
@@ -4714,18 +4769,22 @@
    @Override
    public List<XpInvoiceVo> invoiceList(XpOrderInvoiceQuery query) {
        // 格式:yyyyMM 转yyyy-MM
        query.setStartTime(query.getStartTime().substring(0, 4) + "-" + query.getStartTime().substring(4, 6));
        query.setEndTime(query.getEndTime().substring(0, 4) + "-" + query.getEndTime().substring(4, 6));
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyyMM");
        LocalDateTime startTime = YearMonth.parse(query.getStartTime(), monthFormatter)
                .atDay(1)
                .atStartOfDay();
        LocalDateTime endTime = YearMonth.parse(query.getEndTime(), monthFormatter)
                .atEndOfMonth()
                .atTime(23, 59, 59);
        List<XpOrder> list =null;
        // 通过uid 和时间查出来数据  先判断是否传入了分页
        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, query.getStartTime(), query.getEndTime()));
            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));
            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, query.getStartTime(), query.getEndTime()));
            list = this.baseMapper.selectList(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.valueOf(query.getUid())).ge(XpOrder::getStatus, 9).between(BaseModel::getCreateTime, startTime, endTime));
        }
        if(list.isEmpty()){
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaskOrderSendSmsUtil.java
New file
@@ -0,0 +1,107 @@
package com.xiaopeng.order.utils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.xiaopeng.api.dto.account.UcUserInfo;
import com.xiaopeng.api.dto.operation.SmsDto;
import com.xiaopeng.api.feignClient.account.UserResourcesClient;
import com.xiaopeng.api.feignClient.operation.SmsClient;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.vo.operation.SmsVo;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.order.service.IXpOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
@Slf4j
@Component
public class TaskOrderSendSmsUtil {
    private static final int SMS_SENT = 1;
    private static final int BATCH_SIZE = 200;
    @Resource
    private IXpOrderService xpOrderService;
    @Resource
    private UserResourcesClient userResourcesClient;
    @Resource
    private SmsClient smsClient;
//    @Value("${sms.appid:}")
//    private String smsAppId;
//
//    @Value("${sms.order-pay.template-code:RobotaxiOrderPaySmsTpl}")
//    private String orderPayTemplateCode;
//
//    @Value("${sms.order-pay.app-push-config-code:RobotaxiOrderPaySms}")
//    private String orderPayAppPushConfigCode;
    /**
     * 每分钟查询一次待支付超过24小时且未发送短信的订单。
     */
    @Scheduled(cron = "0 */1 * * * ?")
    public void sendPendingPaymentSms() {
        LocalDateTime deadline = LocalDateTime.now().minusHours(24);
        List<XpOrder> orders = xpOrderService.list(new LambdaQueryWrapper<XpOrder>()
                .eq(XpOrder::getStatus, OrderStatusEnum.APPROVAL_REJECTION.getCode())
                .le(XpOrder::getTripEnd, deadline)
                .and(wrapper -> wrapper.isNull(XpOrder::getSmsStatus).or().ne(XpOrder::getSmsStatus, SMS_SENT))
                .orderByAsc(XpOrder::getTripEnd)
                .last("LIMIT " + BATCH_SIZE));
        if (orders == null || orders.isEmpty()) {
            return;
        }
        for (XpOrder order : orders) {
            try {
                sendSms(order);
            } catch (Exception e) {
                log.error("待支付订单短信发送失败,订单ID: {}, 订单号: {}", order.getId(), order.getOrderNumber(), e);
            }
        }
    }
    private void sendSms(XpOrder order) {
        if (order.getAppUserId() == null) {
            log.warn("待支付订单短信发送跳过,用户ID为空,订单ID: {}", order.getId());
            return;
        }
        UcUserInfo userInfo = userResourcesClient.getBaseUserByUid(String.valueOf(order.getAppUserId()));
        if (userInfo == null || StringUtils.isBlank(userInfo.getMobile())) {
            log.warn("待支付订单短信发送跳过,手机号为空,订单ID: {}, 用户ID: {}", order.getId(), order.getAppUserId());
            return;
        }
        SmsVo smsVo = new SmsVo();
        smsVo.setAppId("");
        smsVo.setPushType(1);
        smsVo.setReceivers(userInfo.getMobile());
        smsVo.setTemplateCode("orderPayTemplateCode");
        smsVo.setAppPushConfigCode("orderPayAppPushConfigCode");
        smsVo.setParams(new HashMap<>());
        smsVo.getParams().put("orderNo", order.getOrderNumber());
        SmsDto result = smsClient.pushSms(smsVo);
        if (result == null || result.getCode() == null || result.getCode() != 200) {
            log.warn("待支付订单短信发送未成功,订单ID: {}, 返回: {}", order.getId(), result);
            return;
        }
        order.setAppUserId(null);
        order.setSmsStatus(SMS_SENT);
        boolean updated = xpOrderService.updateById(order);
        if (!updated) {
            log.warn("待支付订单短信状态更新失败,订单ID: {}", order.getId());
        }
    }
}
xp-robotaxi-order-boot/src/main/resources/mapper/order/XpOrderMapper.xml
@@ -47,7 +47,7 @@
    <select id="getHistoryOrderList" resultType="com.xiaopeng.order.model.vo.XpOrderHistoryListVO">
        select start_point_name as originAddress, end_point_name as destinationAddress,start_point_id as startPointId,end_point_id as endPointId,
        DATE_FORMAT(create_time, '%H:%i') AS orderTime, pay_money as amount,create_time as time,DATE_FORMAT(create_time,'%Y-%m-%d') AS timeStr,
        id as orderId,status from xp_order where app_user_id = #{uid} and is_deleted = 0
        id as orderId,status,invoice_status invoiceStatus from xp_order where app_user_id = #{uid} and is_deleted = 0
        <if test="query.status != null">
            and status = #{query.status}
        </if>