Pu Zhibing
2025-01-26 1266ed302b259f09a9370bc4315316b8a212b5d0
修改bug
7个文件已添加
23个文件已修改
694 ■■■■■ 已修改文件
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ParkingLotFallbackFactory.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ParkingLotClient.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-integration/src/main/java/com/ruoyi/integration/api/factory/TCECClientFallbackFactory.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-integration/src/main/java/com/ruoyi/integration/api/feignClient/TCECClient.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OperatorClient.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/SiteController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyController.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TParkingLotController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/TCECKDUtil.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/NotificationStationChangeResult.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/QueryTerminalCode.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/QueryTerminalCodeResult.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/StationChange.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/ConnectorInfo.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/PlaceHolder.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/PlaceHolderPrice.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationsInfoResult.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/StationInfo.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/enu/InterfaceUrlEnum.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ParkingLotFallbackFactory.java
@@ -35,6 +35,12 @@
                return R.fail("通过站点id查询停车场信息调用失败:" + throwable.getMessage());
            }
            @Override
            public R<List<TParkingLot>> getAllParkingLot() {
                return R.fail("获取所有停车场数据失败:" + throwable.getMessage());
            }
            @Override
            public R<TParkingRecord> getRecordById(Long siteId) {
                return R.fail("通过id查询停车场记录:" + throwable.getMessage());
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ParkingLotClient.java
@@ -27,13 +27,21 @@
     * 通过站点id查询停车场信息
     */
    @PostMapping(value = "/t-parking-lot/getLotBySiteId")
    public R<TParkingLot> getLotBySiteId(@RequestParam("siteId") Integer siteId);
    R<TParkingLot> getLotBySiteId(@RequestParam("siteId") Integer siteId);
    /**
     * 获取所有停车场数据
     */
    @PostMapping(value = "/t-parking-lot/getAllParkingLot")
    R<List<TParkingLot>> getAllParkingLot();
    @GetMapping(value = "/t-parking-lot/getRecordById")
    public R<TParkingRecord> getRecordById(@RequestParam("id") Long siteId);
    R<TParkingRecord> getRecordById(@RequestParam("id") Long siteId);
    @PostMapping(value = "/t-parking-lot/getRecordAmount")
    public R<BigDecimal> getRecordAmount(@RequestParam("sixBefore") LocalDate sixBefore);
    R<BigDecimal> getRecordAmount(@RequestParam("sixBefore") LocalDate sixBefore);
    
    
    /**
ruoyi-api/ruoyi-api-integration/src/main/java/com/ruoyi/integration/api/factory/TCECClientFallbackFactory.java
@@ -5,6 +5,8 @@
import com.ruoyi.integration.api.vo.StartChargeResult;
import org.springframework.cloud.openfeign.FallbackFactory;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2025/1/24 10:33
@@ -40,6 +42,11 @@
            public R notificationChargeOrderInfo(String startChargeSeq, Integer operatorId) {
                return R.fail("推送订单信息失败:" + cause.getMessage());
            }
            @Override
            public R notificationStationChange(List<Integer> siteIds) {
                return R.fail("站点变更推送通知失败:" + cause.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-integration/src/main/java/com/ruoyi/integration/api/feignClient/TCECClient.java
@@ -9,6 +9,8 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
 * @author zhibing.pu
 * @Date 2025/1/24 10:32
@@ -64,6 +66,17 @@
     * @param startChargeSeq
     * @return
     */
    @PostMapping("/notificationChargeOrderInfo")
    @PostMapping("/evcs/v1.0/notificationChargeOrderInfo")
    R notificationChargeOrderInfo(@RequestParam("startChargeSeq") String startChargeSeq, @RequestParam("operatorId") Integer operatorId);
    /**
     * 站点变更推送通知
     * @param siteIds
     * @return
     */
    @PostMapping("/evcs/v1.0/notificationStationChange")
    R notificationStationChange(@RequestParam("siteIds") List<Integer> siteIds);
}
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java
@@ -2,6 +2,7 @@
import lombok.Data;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
/**
@@ -30,4 +31,9 @@
     * 充电余额
     */
    private BigDecimal paymentAmount;
    /**
     * 充电车牌号
     */
    @Null
    private String PlateNum;
}
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java
@@ -24,6 +24,11 @@
            }
            
            @Override
            public R<Operator> getOperatorByName(String name) {
                return R.fail("获取运营商数据失败:" + cause.getMessage());
            }
            @Override
            public R<Operator> getOperator(String operatorId) {
                return R.fail("获取运营商数据失败:" + cause.getMessage());
            }
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OperatorClient.java
@@ -30,6 +30,16 @@
    
    /**
     * 获取运营商数据
     * @param name
     * @return
     */
    @PostMapping("/operator/getOperatorByName")
    R<Operator> getOperatorByName(@RequestParam("name") String name);
    /**
     * 获取运营商数据
     * @param operatorId
     * @return
     */
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/SiteController.java
@@ -332,8 +332,7 @@
        return R.ok(divide);
    }
    @Resource
    private SiteClient siteClient;
    
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyController.java
@@ -28,6 +28,7 @@
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.integration.api.feignClient.IntegrationClient;
import com.ruoyi.integration.api.feignClient.TCECClient;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.feignClient.SysUserClient;
import io.swagger.annotations.ApiOperation;
@@ -44,6 +45,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import static com.ruoyi.common.core.context.SecurityContextHolder.getUserId;
@@ -66,11 +68,14 @@
    private TChargingPileService chargingPileService;
    @Autowired
    private ISiteService siteService;
    @Autowired
    @Resource
    private SysUserClient sysUserClient;
    
    @Resource
    private IntegrationClient integrationClient;
    @Resource
    private TCECClient tcecClient;
    @Autowired
@@ -386,12 +391,12 @@
                        site.setAccountingStrategyId(byId.getId());
                    }
                    siteService.updateBatchById(list);
                    //
                    //
                    accountingStrategyService.removeById(one.getId());
                    //推送三方平台
                    List<Integer> siteIds = list.stream().map(Site::getId).collect(Collectors.toList());
                    tcecClient.notificationStationChange(siteIds);
                }
                //硬件
    
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TParkingLotController.java
@@ -158,6 +158,18 @@
    }
    
    
    /**
     * 获取所有停车场数据
     */
    @PostMapping(value = "/getAllParkingLot")
    public R<List<TParkingLot>> getAllParkingLot(){
        List<TParkingLot> list = parkingLotService.list(new LambdaQueryWrapper<TParkingLot>().eq(TParkingLot::getDelFlag, 0));
        return R.fail(list);
    }
    @RequiresPermissions(value = {"/paymentOrder/order"}, logical = Logical.OR)
    @GetMapping(value = "/getRecordById")
    public R<TParkingRecord> getRecordById(@RequestParam("id") Long id){
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
@@ -25,6 +25,7 @@
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.integration.api.feignClient.IntegrationClient;
import com.ruoyi.integration.api.feignClient.TCECClient;
import com.ruoyi.other.api.domain.TVip;
import com.ruoyi.other.api.feignClient.RoleSiteClient;
import com.ruoyi.other.api.feignClient.UserSiteClient;
@@ -72,8 +73,6 @@
    @Resource
    private AppUserClient appUserClient;
    @Resource
    private VipClient vipClient;
    @Resource
    private SysUserRoleClient sysUserRoleClient;
    @Resource
    private TParkingLotService parkingLotService;
@@ -88,6 +87,9 @@
    
    @Resource
    private TPartnerSiteService partnerSiteService;
    @Resource
    private TCECClient tcecClient;
    
    
    /**
@@ -462,5 +464,8 @@
        for (TChargingPile tChargingPile : list1) {
            integrationClient.setupBillingModel1(tChargingPile.getCode(), JSON.toJSONString(accountingStrategyDetails));
        }
        //推送三方平台
        tcecClient.notificationStationChange(Arrays.asList(id));
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java
@@ -1,18 +1,16 @@
package com.ruoyi.integration.drainage;
import com.alibaba.fastjson.JSON;
import com.ruoyi.chargingPile.api.feignClient.AccountingStrategyDetailClient;
import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient;
import com.ruoyi.chargingPile.api.feignClient.ChargingPileClient;
import com.ruoyi.chargingPile.api.feignClient.SiteClient;
import com.ruoyi.chargingPile.api.model.Site;
import com.ruoyi.chargingPile.api.model.TAccountingStrategyDetail;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.chargingPile.api.model.TChargingPile;
import com.ruoyi.chargingPile.api.feignClient.*;
import com.ruoyi.chargingPile.api.model.*;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.dto.ChargingPercentProvinceDto;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.integration.drainage.kuaidian.TCECKDUtil;
import com.ruoyi.integration.drainage.kuaidian.model.NotificationStationChangeResult;
import com.ruoyi.integration.drainage.kuaidian.model.QueryTerminalCode;
import com.ruoyi.integration.drainage.kuaidian.model.QueryTerminalCodeResult;
import com.ruoyi.integration.drainage.model.*;
import com.ruoyi.integration.drainage.model.enu.*;
import com.ruoyi.order.api.feignClient.ChargingOrderAccountingStrategyClient;
@@ -73,6 +71,10 @@
    private TokenUtil tokenUtil;
    
    private static Map<Long, Integer> map = new HashMap<>();
    @Resource
    private ParkingLotClient parkingLotClient;
    
    
    /**
@@ -234,11 +236,12 @@
            pageSize = 10;
        }
        PageInfo<Site> siteListPaging = siteClient.getSiteListPaging(pageNo, pageSize);
        List<TParkingLot> parkingLots = parkingLotClient.getAllParkingLot().getData();
        QueryStationsInfoResult queryStationsInfoResult = new QueryStationsInfoResult();
        queryStationsInfoResult.setPageNo(pageNo);
        queryStationsInfoResult.setPageCount((0 == (siteListPaging.getTotal() % pageSize) ? 0 : 1) + Double.valueOf(siteListPaging.getTotal() / pageSize).intValue());
        queryStationsInfoResult.setItemSize(Long.valueOf(siteListPaging.getTotal()).intValue());
        queryStationsInfoResult.setStationInfos(buildSite(siteListPaging.getRecords()));
        queryStationsInfoResult.setStationInfos(buildSite(parkingLots, siteListPaging.getRecords()));
        //参数加密
        String jsonString = JSON.toJSONString(queryStationsInfoResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
@@ -253,7 +256,7 @@
     * @param sites
     * @return
     */
    public List<StationInfo> buildSite(List<Site> sites){
    public List<StationInfo> buildSite(List<TParkingLot> parkingLots, List<Site> sites){
        List<Integer> siteIds = sites.stream().map(Site::getId).collect(Collectors.toList());
        List<TChargingPile> tChargingPiles = chargingPileClient.getChargingPileBySiteIds(siteIds).getData();
        List<Integer> collect1 = tChargingPiles.stream().map(TChargingPile::getId).collect(Collectors.toList());
@@ -312,12 +315,42 @@
            stationInfo.setMatchCars(datum.getVehicleDescription());
            stationInfo.setBusineHours(datum.getStartServiceTime() + "-" + datum.getEndServiceTime());
            stationInfo.setElectricityFee(datum.getRateDescription());
            //添加停车费信息
            Optional<TParkingLot> first = parkingLots.stream().filter(s -> s.getSiteId().equals(datum.getId())).findFirst();
            if(first.isPresent()){
                TParkingLot tParkingLot = first.get();
                buildPlaceHolder(tParkingLot, stationInfo);
            }
            //构建充电设备信息数据
            stationInfo.setEquipmentInfos(buildEquipmentInfo(datum.getId(), tChargingPiles, chargingGunList));
            StationInfos.add(stationInfo);
        }
        return StationInfos;
    }
    /**
     * 构建停车费信息
     * @param tParkingLot
     * @param stationInfo
     */
    public void buildPlaceHolder(TParkingLot tParkingLot, StationInfo stationInfo){
        stationInfo.setOvertimeFee(tParkingLot.getName() + "停车费");
        PlaceHolder placeHolder = new PlaceHolder();
        placeHolder.setFreeTime(tParkingLot.getChargeFreeDuration());
        placeHolder.setMaxFee(tParkingLot.getChargeCapping());
        List<PlaceHolderPrice> PlaceHolderPrices = new ArrayList<>();
        PlaceHolderPrice placeHolderPrice = new PlaceHolderPrice();
        placeHolderPrice.setStartTime("00:00");
        placeHolderPrice.setEndTime("23:59");
        placeHolderPrice.setPrice(tParkingLot.getChargeRate());
        PlaceHolderPrices.add(placeHolderPrice);
        placeHolder.setPlaceHolderPrices(PlaceHolderPrices);
        stationInfo.setPlaceHolder(placeHolder);
    }
    
    
    
@@ -357,7 +390,7 @@
            }
            
            //构建设备接口信息
            equipmentInfo.setConnectorInfos(buildConnectorInfos(tChargingPile.getId(), chargingGunList));
            equipmentInfo.setConnectorInfos(buildConnectorInfos(tChargingPile.getId(), tChargingPile.getCode(), chargingGunList));
            equipmentInfos.add(equipmentInfo);
        }
        return equipmentInfos;
@@ -369,7 +402,7 @@
     * @param chargingGunList
     * @return
     */
    public List<ConnectorInfo> buildConnectorInfos(Integer chargingPileId, List<TChargingGun> chargingGunList){
    public List<ConnectorInfo> buildConnectorInfos(Integer chargingPileId, String code, List<TChargingGun> chargingGunList){
        List<ConnectorInfo> connectorInfos = new ArrayList<>();
        List<TChargingGun> collect = chargingGunList.stream().filter(s -> s.getChargingPileId().equals(chargingPileId)).collect(Collectors.toList());
        for (TChargingGun chargingGun : collect) {
@@ -402,6 +435,7 @@
            connectorInfo.setPower(chargingGun.getRatedPower());
            connectorInfo.setParkNo(chargingGun.getParkingNumber());
            connectorInfo.setNationalStandard(Integer.valueOf(chargingGun.getNationalStandard()));
            connectorInfo.setQRCode("https://mxcd.zhinenganguan.com?No=" + code + chargingGun.getCode());
            connectorInfos.add(connectorInfo);
        }
        return connectorInfos;
@@ -732,6 +766,49 @@
    
    
    /**
     * 站点变更推送通知(快电)
     * @param siteIds
     * @return
     */
    @PostMapping("/notificationStationChange")
    public R notificationStationChange(@RequestParam("siteIds") List<Integer> siteIds){
        Operator operator = operatorClient.getOperatorByName("KuaiDian").getData();
        NotificationStationChangeResult notificationStationChange = TCECKDUtil.notificationStationChange(operator, 3, siteIds);
        //启动重试推送机制
        if(null == notificationStationChange || 1 == notificationStationChange.getSuccStat()){
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
            threadPoolExecutor.execute(new Runnable() {
                //计数器
                Integer size = 0;
                @Override
                public void run() {
                    NotificationStationChangeResult notificationStationChange1 = TCECKDUtil.notificationStationChange(operator, 3, siteIds);
                    //启动重试推送机制
                    if(null != notificationStationChange1 && 0 == notificationStationChange1.getSuccStat()){
                        threadPoolExecutor.shutdown();
                        return;
                    }
                    size++;
                    if(size >= 5){
                        threadPoolExecutor.shutdown();
                        return;
                    }
                    //间隔一分钟重试一次
                    try {
                        Thread.sleep(60000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
        return R.ok();
    }
    /**
     * 请求定充电
     * @return
     */
@@ -788,6 +865,7 @@
        addTripartitePlatformOrder.setOperatorId(operator.getOperatorId());
        addTripartitePlatformOrder.setPaymentAmount(queryStartCharge.getPaymentAmount());
        addTripartitePlatformOrder.setRechargePaymentType(queryStartCharge.getPaymentType());
        addTripartitePlatformOrder.setPlateNum(queryStartCharge.getPlateNum());
        R order = chargingOrderClient.addTripartitePlatformOrder(addTripartitePlatformOrder);
        //启动失败
        if(200 != order.getCode()){
@@ -1238,4 +1316,37 @@
        notificationChargeOrderInfo.setChargeDetails(chargeDetails);
        return notificationChargeOrderInfo;
    }
    /**
     * 二维码查询抢号(快电)
     * @param baseRequest
     * @param request
     * @return
     */
    @PostMapping("/query_terminal_code")
    public BaseResult queryTerminalCode(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(TCECUtil.buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryTerminalCode queryTerminalCode = JSON.parseObject(decrypt, QueryTerminalCode.class);
        String qrCode = queryTerminalCode.getQRCode();
        String substring = qrCode.substring(qrCode.indexOf("=") + 1);
        QueryTerminalCodeResult queryTerminalCodeResult = new QueryTerminalCodeResult();
        queryTerminalCodeResult.setTerminalCode(substring);
        //参数加密
        String jsonString = JSON.toJSONString(queryTerminalCodeResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(TCECUtil.buildSign(baseResult));
        return baseResult;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java
@@ -4,6 +4,8 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.integration.drainage.kuaidian.model.NotificationStationChangeResult;
import com.ruoyi.integration.drainage.kuaidian.model.StationChange;
import com.ruoyi.integration.drainage.model.*;
import com.ruoyi.integration.drainage.model.enu.InterfaceUrlEnum;
import com.ruoyi.other.api.domain.Operator;
@@ -15,7 +17,9 @@
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * 中电联TCEC标准
@@ -96,6 +100,32 @@
    
    
    /**
     * 站点变更通知
     * @param operator
     * @param type
     * @param siteIds
     * @return
     */
    public static NotificationStationChangeResult notificationStationChange(Operator operator, Integer type, List<Integer> siteIds) {
        StationChange stationChange = new StationChange();
        stationChange.setOperatorId(OperatorID);
        stationChange.setType(type);
        List<String> collect = siteIds.stream().map(String::valueOf).collect(Collectors.toList());
        stationChange.setStationIds(collect);
        HttpRequest post = HttpUtil.createPost(operator.getTestUrl() + InterfaceUrlEnum.NOTIFICATION_STATION_CHANGE.getUrl());
        buildBody(post, stationChange, operator);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送站点变更通知失败:" + execute.body());
            return null;
        }
        return JSON.parseObject(execute.body(), NotificationStationChangeResult.class);
    }
    /**
     * 推送启动充电结果
     * @param info
     * @return
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/TCECKDUtil.java
New file
@@ -0,0 +1,159 @@
package com.ruoyi.integration.drainage.kuaidian;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.integration.drainage.AESUtil;
import com.ruoyi.integration.drainage.SignUtil;
import com.ruoyi.integration.drainage.kuaidian.model.NotificationStationChangeResult;
import com.ruoyi.integration.drainage.kuaidian.model.StationChange;
import com.ruoyi.integration.drainage.model.*;
import com.ruoyi.integration.drainage.model.enu.InterfaceUrlEnum;
import com.ruoyi.other.api.domain.Operator;
import com.ruoyi.other.api.feignClient.OperatorClient;
import lombok.extern.slf4j.Slf4j;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * 中电联TCEC标准(快电)
 * @author zhibing.pu
 * @Date 2025/1/21 11:48
 */
@Slf4j
public class TCECKDUtil {
    /**
     * 运营商标识
     */
    private static final String OperatorID = "";
    private static OperatorClient operatorClient = SpringUtils.getBean(OperatorClient.class);
    private static Map<Long, Integer> map = new HashMap<>();
    /**
     * 获取token
     */
    public static String queryToken(Operator operator){
        HttpRequest post = HttpUtil.createPost("");
        post.contentType("application/json;charset=utf-8");
        JSONObject body = new JSONObject();
        body.put("OperatorID", OperatorID);
        body.put("OperatorSecret", operator.getOurOperatorSecret());
        post.body(body.toJSONString());
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("获取三方token失败:" + execute.body());
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer succStat = jsonObject.getInteger("SuccStat");
        if(0 != succStat){
            log.error("获取三方token失败:" + jsonObject.getString("FailReason"));
            return null;
        }
        String token = jsonObject.getString("AccessToken");
        Long tokenAvailableTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) + jsonObject.getLong("TokenAvailableTime");
        LocalDateTime localDateTime = Instant.ofEpochSecond(tokenAvailableTime).atOffset(ZoneOffset.UTC).toLocalDateTime();
        operator.setAccessToken(token);
        operator.setTokenAvailableTime(localDateTime);
        operatorClient.editOperator(operator);
        return token;
    }
    /**
     * 获取token
     * @return
     */
    public static String getToken(Operator operator){
        if(null != operator.getTokenAvailableTime() && operator.getTokenAvailableTime().isBefore(LocalDateTime.now())){
            return operator.getAccessToken();
        }else{
            return queryToken(operator);
        }
    }
    /**
     * 站点变更通知
     * @param operator
     * @param type
     * @param siteIds
     * @return
     */
    public static NotificationStationChangeResult notificationStationChange(Operator operator, Integer type, List<Integer> siteIds) {
        StationChange stationChange = new StationChange();
        stationChange.setOperatorId(OperatorID);
        stationChange.setType(type);
        List<String> collect = siteIds.stream().map(String::valueOf).collect(Collectors.toList());
        stationChange.setStationIds(collect);
        HttpRequest post = HttpUtil.createPost(operator.getTestUrl() + InterfaceUrlEnum.NOTIFICATION_STATION_CHANGE.getUrl());
        buildBody(post, stationChange, operator);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送站点变更通知失败:" + execute.body());
            return null;
        }
        return JSON.parseObject(execute.body(), NotificationStationChangeResult.class);
    }
    /**
     * 构建请求参数和消息头
     * @param post
     * @param o
     */
    public static void buildBody(HttpRequest post, Object o, Operator operator){
        Long timeStamp = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        Integer integer = map.get(timeStamp);
        if(null == integer){
            integer = 1;
        }else{
            integer++;
        }
        map.put(timeStamp, integer);
        post.contentType("application/json;charset=utf-8");
        post.header("Authorization", "Bearer " + getToken(operator));
        BaseRequest baseRequest = new BaseRequest();
        baseRequest.setOperatorID(OperatorID);
        baseRequest.setTimeStamp(timeStamp);
        baseRequest.setSeq(String.format("%04d", integer));
        String jsonString = JSON.toJSONString(o);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseRequest.setData(encrypt);
        baseRequest.setOperator(operator);
        baseRequest.setSig(buildSign(baseRequest));
        post.body(JSON.toJSONString(baseRequest));
        //清空小于当前时间的map中的无效数据
        for (Long k : map.keySet()) {
            if(k <= (timeStamp - 10)){
                map.remove(k);
            }
        }
    }
    public static String buildSign(BaseModel model){
        Operator operator = model.getOperator();
        //签名秘钥SigSecret
        String key = operator.getSigSecret();
        String sign = SignUtil.hmacSign(model.getData(), key);
        return sign;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/NotificationStationChangeResult.java
New file
@@ -0,0 +1,40 @@
package com.ruoyi.integration.drainage.kuaidian.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * 站点变更通知返回结果
 * @author zhibing.pu
 * @Date 2025/1/26 10:45
 */
@Data
public class NotificationStationChangeResult {
    /**
     * 运营商ID
     */
    @NotNull
    private String OperatorId;
    /**
     * 站点ID
     */
    @NotNull
    private List<String> StationIds;
    /**
     * 成功状态
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 失败原因
     * 0:无
     * 1:无效站点
     * 2`9:自定义
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/QueryTerminalCode.java
New file
@@ -0,0 +1,19 @@
package com.ruoyi.integration.drainage.kuaidian.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 二维码查询抢号
 * @author zhibing.pu
 * @Date 2025/1/26 11:12
 */
@Data
public class QueryTerminalCode {
    /**
     * 二维码信息
     */
    @NotNull
    private String QRCode;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/QueryTerminalCodeResult.java
New file
@@ -0,0 +1,19 @@
package com.ruoyi.integration.drainage.kuaidian.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 二维码查询抢号结果
 * @author zhibing.pu
 * @Date 2025/1/26 11:18
 */
@Data
public class QueryTerminalCodeResult {
    /**
     * 枪号
     */
    @NotNull
    private String TerminalCode;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/kuaidian/model/StationChange.java
New file
@@ -0,0 +1,31 @@
package com.ruoyi.integration.drainage.kuaidian.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
 * 站点变更通知
 * @author zhibing.pu
 * @Date 2025/1/26 10:34
 */
@Data
public class StationChange {
    /**
     * 运营商ID
     */
    @NotNull
    private String operatorId;
    /**
     * 变更类型
     * 3:站点计费策略变更
     */
    @NotNull
    private Integer type;
    /**
     * 站点ID
     */
    @NotNull
    private List<String> stationIds;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/ConnectorInfo.java
@@ -60,4 +60,9 @@
     */
    @NotNull
    private Integer NationalStandard;
    /**
     * 枪二维码
     */
    @Null
    private String QRCode;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/PlaceHolder.java
New file
@@ -0,0 +1,42 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
 * 占位费信息
 * @author zhibing.pu
 * @Date 2025/1/26 9:29
 */
@Data
public class PlaceHolder {
    /**
     * 免费时长
     */
    @NotNull
    private Integer FreeTime;
    /**
     * 嘴阀占位费
     */
    @NotNull
    private BigDecimal MaxFee;
    /**
     * 生效开始时间
     * yyyy-MM-dd HH:mm:ss
     */
    @NotNull
    private String EffectStartTime;
    /**
     * 生效结束时间
     */
    @NotNull
    private String EffectEndTime;
    /**
     * 占位费价格
     */
    @NotNull
    private List<PlaceHolderPrice> PlaceHolderPrices;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/PlaceHolderPrice.java
New file
@@ -0,0 +1,32 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 占位费价格
 * @author zhibing.pu
 * @Date 2025/1/26 9:33
 */
@Data
public class PlaceHolderPrice {
    /**
     * 开始时段
     * HH:mm
     */
    @NotNull
    private String StartTime;
    /**
     * 结束时段
     * HH:mm
     */
    @NotNull
    private String EndTime;
    /**
     * 单价
     */
    @NotNull
    private BigDecimal Price;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java
@@ -3,6 +3,7 @@
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.math.BigDecimal;
/**
@@ -37,4 +38,9 @@
     */
    @NotNull
    private BigDecimal paymentAmount;
    /**
     * 充电车牌号
     */
    @Null
    private String PlateNum;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java
@@ -3,6 +3,7 @@
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
/**
 * 请求启动充电返回结果
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationsInfoResult.java
@@ -2,6 +2,8 @@
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import java.util.List;
/**
@@ -14,17 +16,21 @@
    /**
     * 当前页数
     */
    @NotNull
    private Integer PageNo;
    /**
     * 页码总数
     */
    @NotNull
    private Integer PageCount;
    /**
     * 总记录条数
     */
    @NotNull
    private Integer ItemSize;
    /**
     * 充电站信息列表
     */
    @NotNull
    private List<StationInfo> StationInfos;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/StationInfo.java
@@ -151,4 +151,14 @@
     */
    @NotNull
    private List<EquipmentInfo> EquipmentInfos;
    /**
     * 占位费描述
     */
    @Null
    private String OvertimeFee;
    /**
     * 占位费信息
     */
    @Null
    private PlaceHolder PlaceHolder;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/enu/InterfaceUrlEnum.java
@@ -7,6 +7,7 @@
 */
public enum InterfaceUrlEnum {
    NOTIFICATION_STATION_STATUS("/notification_station_status", "设备状态变化推送"),
    NOTIFICATION_STATION_CHANGE("/notification_station_change", "站点计费策略变更推送"),
    NOTIFICATION_START_CHARGE_RESULT("/notification_start_charge_result", "推送启动充电结果"),
    NOTIFICATION_EQUIP_CHARGE_STATUS("/notification_equip_charge_status", "推送充电状态"),
    NOTIFICATION_STOP_CHARGE_RESULT("/notification_stop_charge_result", "推送停止充电结果"),
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
@@ -2101,10 +2101,7 @@
     */
    @PostMapping("/addTripartitePlatformOrder")
    public R addTripartitePlatformOrder(@RequestBody AddTripartitePlatformOrder query){
        return chargingOrderService.addTripartitePlatformOrder(query.getChargingGunId(), query.getOperatorId(),
                query.getRechargePaymentType(),
                query.getPaymentAmount(),
                query.getStartChargeSeq());
        return chargingOrderService.addTripartitePlatformOrder(query);
    }
    
    
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java
@@ -7,10 +7,7 @@
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.order.api.dto.SettlementConfirmAdd;
import com.ruoyi.order.api.model.ChargingListQuery;
import com.ruoyi.order.api.model.TChargingOrder;
import com.ruoyi.order.api.model.TChargingOrderRefund;
import com.ruoyi.order.api.model.TSettlementConfirm;
import com.ruoyi.order.api.model.*;
import com.ruoyi.order.api.query.ChargingOrderQuery;
import com.ruoyi.order.api.query.SettlementListQuery;
import com.ruoyi.order.api.query.UploadRealTimeMonitoringDataQuery;
@@ -292,9 +289,9 @@
    
    /**
     * 添加三方平台充电订单数据
     * @param chargingGunId
     * @param query
     */
    R addTripartitePlatformOrder(Integer chargingGunId, String operatorId, Integer rechargePaymentType, BigDecimal paymentAmount, String startChargeSeq);
    R addTripartitePlatformOrder(AddTripartitePlatformOrder query);
    
    
    /**
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -4019,12 +4019,12 @@
    
    /**
     * 添加三方平台充电订单数据
     * @param chargingGunId
     * @param query
     */
    @Override
    public R addTripartitePlatformOrder(Integer chargingGunId, String operatorId, Integer rechargePaymentType, BigDecimal paymentAmount, String startChargeSeq) {
    public R addTripartitePlatformOrder(AddTripartitePlatformOrder query) {
        //检查当前枪是否是正在使用中
        TChargingOrder one = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getChargingGunId, chargingGunId)
        TChargingOrder one = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getChargingGunId, query.getChargingGunId())
                .in(TChargingOrder::getStatus, Arrays.asList(1, 2, 3)).eq(TChargingOrder::getDelFlag, 0));
        if(null != one){
            return R.fail("充电枪正在充电中,启动失败");
@@ -4037,21 +4037,30 @@
        chargingOrder.setCode(code);
        chargingOrder.setOrderType(1);
        chargingOrder.setOrderClassification(1);
        TChargingGun tChargingGun = chargingGunClient.getChargingGunById(chargingGunId).getData();
        TChargingGun tChargingGun = chargingGunClient.getChargingGunById(query.getChargingGunId()).getData();
        TChargingPile chargingPile = chargingPileClient.getChargingPileById(tChargingGun.getChargingPileId()).getData();
        chargingOrder.setSiteId(tChargingGun.getSiteId());
        chargingOrder.setChargingPileId(tChargingGun.getChargingPileId());
        chargingOrder.setChargingGunId(chargingGunId);
        chargingOrder.setRechargePaymentType(rechargePaymentType);
        chargingOrder.setChargingGunId(query.getChargingGunId());
        chargingOrder.setRechargePaymentType(query.getRechargePaymentType());
        chargingOrder.setRechargePaymentStatus(2);
        chargingOrder.setRechargeAmount(paymentAmount);
        chargingOrder.setRechargeAmount(query.getPaymentAmount());
        chargingOrder.setVipDiscountAmount(BigDecimal.ZERO);
        chargingOrder.setOrderSource(2);
        Operator operator = operatorClient.getOperator(operatorId).getData();
        Operator operator = operatorClient.getOperator(query.getOperatorId()).getData();
        chargingOrder.setOperatorId(operator.getId());
        chargingOrder.setAppUserId(operator.getId().longValue());
        chargingOrder.setTripartitePlatformName(operator.getName());
        chargingOrder.setStartChargeSeq(startChargeSeq);
        chargingOrder.setStartChargeSeq(query.getStartChargeSeq());
        //车辆信息
        if(StringUtils.hasLength(query.getPlateNum())){
            TAppUserCar appUserCar = appUserCarClient.getAppUserCarByLicensePlate(query.getPlateNum()).getData();
            if(null != appUserCar){
                chargingOrder.setAppUserCarId(appUserCar.getId());
            }
        }
        chargingOrder.setTitle("【充电桩充电】" + chargingPile.getNumber() + "号桩/" + tChargingGun.getCode() + "号枪");
        chargingOrder.setStatus(2);
        chargingOrder.setPayTime(LocalDateTime.now());
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java
@@ -35,6 +35,19 @@
    
    
    
    /**
     * 获取运营商数据
     * @param name
     * @return
     */
    @PostMapping("/getOperatorByName")
    public R<Operator> getOperatorByName(@RequestParam("name") String name){
        Operator operator = operatorService.getOne(new LambdaQueryWrapper<Operator>().eq(Operator::getName, name));
        return R.ok(operator);
    }
    
    /**
     * 获取运营商数据