Pu Zhibing
2025-01-23 792cbb986fb8c32f6bbc1638c4ae264372e7a28f
新增引流接口及业务逻辑
1个文件已删除
26个文件已添加
21个文件已修改
3352 ■■■■ 已修改文件
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ChargingGunFallbackFactory.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/SiteFallbackFactory.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingGunClient.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderAccountingStrategyFallbackFactory.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderAccountingStrategyClient.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/OrderClient.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/StartChargeResult.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TChargingOrder.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/Operator.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OperatorClient.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/dto/ChargingPercentProvinceDto.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyDetailController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingGunController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/controller/TCECController.java 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/AESUtil.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/NotificationStopCharge.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/QueryStopCharge.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/SignUtil.java 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java 1155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java 198 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TokenUtil.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseModel.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseRequest.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseResult.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartCharge.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartChargeResult.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStopChargeResult.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuth.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuthResult.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationStats.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStopChargeResult.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryToken.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryTokenResult.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderAccountingStrategyController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/OperatorMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/OperatorService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/OperatorServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ChargingGunFallbackFactory.java
@@ -61,6 +61,11 @@
            }
    
            @Override
            public R<List<TChargingGun>> getChargingGunByChargingPileIds(List<Integer> chargingPileIds) {
                return R.fail("根据充电桩ids获取枪失败:" + throwable.getMessage());
            }
            @Override
            public R pushChargingGunStatus(Integer id, Integer status) {
                return R.fail("接口状态变化后推送给第三方失败:" + throwable.getMessage());
            }
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/SiteFallbackFactory.java
@@ -6,6 +6,7 @@
import com.ruoyi.chargingPile.api.model.Site;
import com.ruoyi.chargingPile.api.model.TChargingPile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.page.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
@@ -53,6 +54,11 @@
                return R.fail("根据合作商id获取合作商详情失败:" + throwable.getMessage());
            }
            @Override
            public PageInfo<Site> getSiteListPaging(Integer PageNo, Integer PageSize) {
                return null;
            }
        };
    }
}
ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingGunClient.java
@@ -69,6 +69,16 @@
    
    
    /**
     * 根据充电桩ids获取枪
     * @param chargingPileIds
     * @return
     */
    @PostMapping("/t-charging-gun/getChargingGunByChargingPileIds")
    R<List<TChargingGun>> getChargingGunByChargingPileIds(@RequestParam("chargingPileIds") List<Integer> chargingPileIds);
    /**
     * 接口状态变化后推送给第三方
     * @param id
     * @param status
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderAccountingStrategyFallbackFactory.java
@@ -4,6 +4,7 @@
import com.ruoyi.order.api.feignClient.ChargingOrderAccountingStrategyClient;
import com.ruoyi.order.api.feignClient.ChargingOrderClient;
import com.ruoyi.order.api.model.TChargingOrder;
import com.ruoyi.order.api.model.TChargingOrderAccountingStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
@@ -38,6 +39,11 @@
            public R<List<Double>> getDailyChargingDegree(Integer days, Set<Integer> siteIds) {
                return R.fail("获取给定天数每天的充电度数失败:" + throwable.getMessage());
            }
            @Override
            public R<List<TChargingOrderAccountingStrategy>> getChargingOrderAccountingStrategyByOrderId(Long chargingOrderId) {
                return R.fail("根据订单id查询充电明细失败:" + throwable.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java
@@ -4,6 +4,7 @@
import com.ruoyi.common.core.dto.ChargingOrderGroup;
import com.ruoyi.common.core.dto.ChargingPercentProvinceDto;
import com.ruoyi.order.api.feignClient.ChargingOrderClient;
import com.ruoyi.order.api.model.AddTripartitePlatformOrder;
import com.ruoyi.order.api.model.ChargingListQuery;
import com.ruoyi.order.api.model.TChargingOrder;
import com.ruoyi.order.api.model.TSettlementConfirm;
@@ -63,7 +64,12 @@
            public R<List<ChargingOrderGroup>> getBySiteIdAndTime(ChargingPercentProvinceDto chargingPercentProvinceDto) {
                return null;
            }
            @Override
            public R<List<TChargingOrder>> getOrderBySiteIdAndTime(ChargingPercentProvinceDto chargingPercentProvinceDto) {
                return R.fail("根据站点id和时间区间查询订单数据失败:" + throwable.getMessage());
            }
            @Override
            public R<Integer> getChargingCount(TChargingCountQuery req) {
                return R.fail("根据会员id和有效期查询有效期内享受充电折扣次数:" + throwable.getMessage());
@@ -174,6 +180,22 @@
            public R<List<TChargingOrder>> getCarChargingOrder(Long carId, String startTime, String endTime) {
                return R.fail("根据车辆id获取指定时间范围内的数据失败:" + throwable.getMessage());
            }
            @Override
            public R addTripartitePlatformOrder(AddTripartitePlatformOrder query) {
                return R.fail("添加三方平台充电订单数据失败:" + throwable.getMessage());
            }
            @Override
            public R<TChargingOrder> getChargingOrderByStartChargeSeq(String startChargeSeq) {
                return R.fail("根据三方平台订单id获取充电数据失败:" + throwable.getMessage());
            }
            @Override
            public R tripartitePlatformStopCharge(String startChargeSeq) {
                return R.fail("三方平台请求停止充电失败:" + throwable.getMessage());
            }
        };
    }
}
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderAccountingStrategyClient.java
@@ -4,6 +4,7 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.order.api.factory.ChargingOrderAccountingStrategyFallbackFactory;
import com.ruoyi.order.api.factory.ChargingOrderFallbackFactory;
import com.ruoyi.order.api.model.TChargingOrderAccountingStrategy;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -38,4 +39,13 @@
     */
    @PostMapping("/t-charging-order-accounting-strategy/getDailyChargingDegree/{days}")
    R<List<Double>> getDailyChargingDegree(@PathVariable("days") Integer days, @RequestParam("siteIds") Set<Integer> siteIds);
    /**
     * 根据订单id查询充电明细
     * @param chargingOrderId
     * @return
     */
    @PostMapping("/t-charging-order-accounting-strategy/getChargingOrderAccountingStrategyByOrderId")
    R<List<TChargingOrderAccountingStrategy>> getChargingOrderAccountingStrategyByOrderId(@RequestParam("chargingOrderId") Long chargingOrderId);
}
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java
@@ -6,6 +6,7 @@
import com.ruoyi.common.core.dto.ChargingPercentProvinceDto;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.order.api.factory.ChargingOrderFallbackFactory;
import com.ruoyi.order.api.model.AddTripartitePlatformOrder;
import com.ruoyi.order.api.model.ChargingListQuery;
import com.ruoyi.order.api.model.TChargingOrder;
import com.ruoyi.order.api.model.TSettlementConfirm;
@@ -42,6 +43,15 @@
    @PostMapping(value = "/t-charging-order/getBySiteIdAndTime")
    R<List<ChargingOrderGroup>> getBySiteIdAndTime(@RequestBody ChargingPercentProvinceDto chargingPercentProvinceDto);
    /**
     * 根据站点id和时间区间查询订单数据
     * @param chargingPercentProvinceDto
     * @return
     */
    @PostMapping(value = "/t-charging-order/getOrderBySiteIdAndTime")
    R<List<TChargingOrder>> getOrderBySiteIdAndTime(@RequestBody ChargingPercentProvinceDto chargingPercentProvinceDto);
@@ -235,5 +245,33 @@
     * @return
     */
    @PostMapping("/t-charging-order/getCarChargingOrder")
    R<List<TChargingOrder>> getCarChargingOrder(@RequestParam("carId") Long carId, @RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime);
    R<List<TChargingOrder>> getCarChargingOrder(@RequestParam("carId") Long carId, @RequestParam("startTime") String startTime,
                                                @RequestParam("endTime") String endTime);
    /**
     * 添加三方平台充电订单数据
     * @return
     */
    @PostMapping("/t-charging-order/addTripartitePlatformOrder")
    R addTripartitePlatformOrder(@RequestBody AddTripartitePlatformOrder query);
    /**
     * 根据三方平台订单id获取充电数据
     * @param startChargeSeq
     * @return
     */
    @PostMapping("/t-charging-order/getChargingOrderByStartChargeSeq")
    R<TChargingOrder> getChargingOrderByStartChargeSeq(@RequestParam("startChargeSeq") String startChargeSeq);
    /**
     * 三方平台请求停止充电
     * @param startChargeSeq
     * @return
     */
    @PostMapping("/t-charging-order/tripartitePlatformStopCharge")
    R tripartitePlatformStopCharge(@RequestParam("startChargeSeq") String startChargeSeq);
}
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/OrderClient.java
@@ -24,10 +24,16 @@
 */
@FeignClient(contextId = "OrderClient", value = ServiceNameConstants.ORDER_SERVICE, fallbackFactory = OrderFallbackFactory.class)
public interface OrderClient {
    @PostMapping(value = "/t-charging-order/management/give/vip")
    public R managementGiveVip(@RequestBody TGrantVip grantVip);
    R managementGiveVip(@RequestBody TGrantVip grantVip);
    @GetMapping("/t-exchange-order/getSalesCountByGoodsIds/{goodsIds}")
    R<List<Integer>> getSalesCountByGoodsId(@PathVariable("goodsIds") String goodsIds);
    @GetMapping("/t-exchange-order/getCount")
    R<Integer> getSalesCountByGoodsIdgetCount(@RequestParam("goodId") Integer goodId,@RequestParam("goodeType")Integer goodeType,@RequestParam("buyType")Integer buyType);
@@ -37,21 +43,31 @@
     * @return
     */
    @GetMapping("/t-exchange-order/getCodeByOrderId/{goodsIds}")
    public R<List<String>> getCodeByOrderId(@PathVariable("goodsIds")String goodsIds);
    R<List<String>> getCodeByOrderId(@PathVariable("goodsIds")String goodsIds);
    //查询已兑换的订单数
    @PostMapping("/t-exchange-order/getById")
    public R<Long> getExchangeById(@RequestParam("goodId") Integer goodId,@RequestParam("userId")  Long userId,@RequestParam("goodType") Integer goodType);
    R<Long> getExchangeById(@RequestParam("goodId") Integer goodId,@RequestParam("userId")  Long userId,@RequestParam("goodType") Integer goodType);
    @PostMapping("/t-exchange-order/create")
    public R<ExchangeBackDto> exchangeCreate(@RequestBody ExchangeDto exchangeDto);
    R<ExchangeBackDto> exchangeCreate(@RequestBody ExchangeDto exchangeDto);
    @PostMapping("/t-vip-order/addVipOrder1")
    public R<Long> addVipOrder(@RequestBody TVipOrder vipOrder);
    R<Long> addVipOrder(@RequestBody TVipOrder vipOrder);
    @PostMapping("/t-shopping-order/create")
    public R<TShoppingOrder> shopCreate(@RequestBody ExchangeDto exchangeDto);
    R<TShoppingOrder> shopCreate(@RequestBody ExchangeDto exchangeDto);
    @PostMapping("/t-shopping-order/callBack")
    public R callBack(@RequestParam("code")String code,@RequestParam("outTradeNo")String outTradeNo);
    R callBack(@RequestParam("code")String code,@RequestParam("outTradeNo")String outTradeNo);
    @PostMapping("/t-vip-order/callBack")
    public R vipCallBack(@RequestParam("code")String code,@RequestParam("outTradeNo")String outTradeNo);
    R vipCallBack(@RequestParam("code")String code,@RequestParam("outTradeNo")String outTradeNo);
    /**
@@ -61,6 +77,8 @@
     */
    @PostMapping(value = "/t-exchange-order/activityStatistics")
    R<TActivityVO> activityStatistics(@RequestBody TActivityStatisticsQuery dto);
    @PostMapping(value = "/chargingBill/accountBillList")
    @ApiOperation(value = "列表查询", tags = {"管理后台-账户结算账单"})
    R<AccountListVO> accountBillList(@RequestBody ChargingListQuery dto);
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.order.api.model;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author zhibing.pu
 * @Date 2025/1/22 18:20
 */
@Data
public class AddTripartitePlatformOrder {
    /**
     * 三方充电订单号
     */
    private String startChargeSeq;
    /**
     * 充电枪id
     */
    private Integer chargingGunId;
    /**
     * 运营商id
     */
    private String operatorId;
    /**
     * 支付方式(1=微信,2=支付宝)
     */
    private Integer rechargePaymentType;
    /**
     * 充电余额
     */
    private BigDecimal paymentAmount;
}
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/StartChargeResult.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.order.api.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送启动充电结果
 * @author zhibing.pu
 * @Date 2025/1/22 18:40
 */
@Data
public class StartChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    private Integer StartChargeSeqStat;
    /**
     * 充电设别接口编码
     */
    @NotNull
    private String ConnectorID;
    /**
     * 充电启动时间
     */
    @NotNull
    private String StartTime;
}
ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TChargingOrder.java
@@ -48,9 +48,18 @@
    @ApiModelProperty(value = "订单类型(1=充电订单(小程序),2=充电订单(刷卡))")
    @TableField("order_type")
    private Integer orderType;
    @ApiModelProperty(value = "0平台1其他")
    @ApiModelProperty(value = "订单来源(1=自己平台,2=三方平台)")
    @TableField("order_source")
    private Integer orderSource;
    @ApiModelProperty(value = "运营商id")
    @TableField("operator_id")
    private Integer operatorId;
    @ApiModelProperty(value = "三方平台名称")
    @TableField("tripartite_platform_name")
    private String tripartitePlatformName;
    @ApiModelProperty(value = "三方平台充电订单号")
    @TableField("start_charge_seq")
    private String startChargeSeq;
    @ApiModelProperty(value = "平台或其他第三分名字")
    @TableField("source_name")
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/Operator.java
New file
@@ -0,0 +1,67 @@
package com.ruoyi.other.api.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
 * 运营商信息
 * @author zhibing.pu
 * @Date 2025/1/22 15:05
 */
@Data
@TableName("t_operator")
public class Operator {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 运营商唯一码
     */
    @TableField("operatorId")
    private String operatorId;
    /**
     * 运营商名称
     */
    @TableField("name")
    private String name;
    /**
     * 运营商秘钥
     */
    @TableField("operatorSecret")
    private String operatorSecret;
    /**
     * 数据加密秘钥
     */
    @TableField("dataSecret")
    private String dataSecret;
    /**
     * 初始化向量
     */
    @TableField("dataSecretIv")
    private String dataSecretIv;
    /**
     * 签名秘钥
     */
    @TableField("sigSecret")
    private String sigSecret;
    /**
     * token
     */
    @TableField(exist = false)
    private String token;
    /**
     * 登录时间
     */
    @TableField(exist = false)
    private Long loginTime;
    /**
     * 过期时间
     */
    @TableField(exist = false)
    private Long expireTime;
}
ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java
New file
@@ -0,0 +1,25 @@
package com.ruoyi.other.api.factory;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.other.api.domain.Operator;
import com.ruoyi.other.api.feignClient.OperatorClient;
import org.springframework.cloud.openfeign.FallbackFactory;
/**
 * @author zhibing.pu
 * @Date 2025/1/22 15:16
 */
public class OperatorFallbackFactory implements FallbackFactory<OperatorClient> {
    @Override
    public OperatorClient create(Throwable cause) {
        return new OperatorClient() {
            @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
New file
@@ -0,0 +1,29 @@
package com.ruoyi.other.api.feignClient;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.other.api.domain.Operator;
import com.ruoyi.other.api.factory.OperatorFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
 * @author zhibing.pu
 * @Date 2025/1/22 15:15
 */
@FeignClient(contextId = "OperatorClient", value = ServiceNameConstants.OTHER_SERVICE, fallbackFactory = OperatorFallbackFactory.class)
public interface OperatorClient {
    /**
     * 获取运营商数据
     * @param operatorId
     * @return
     */
    @PostMapping("/operator/getOperator")
    R<Operator> getOperator(@RequestParam("operatorId") String operatorId);
}
ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -8,4 +8,5 @@
com.ruoyi.other.api.factory.CouponFallbackFactory
com.ruoyi.other.api.factory.InvoiceTypeFallbackFactory
com.ruoyi.other.api.factory.WebSocketFallbackFactory
com.ruoyi.other.api.factory.UserTagFallbackFactory
com.ruoyi.other.api.factory.UserTagFallbackFactory
com.ruoyi.other.api.factory.OperatorFallbackFactory
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/dto/ChargingPercentProvinceDto.java
@@ -9,8 +9,9 @@
@Data
public class ChargingPercentProvinceDto {
    String provinceCode;
    LocalDate date1;
    LocalDate date2;
    Set<Integer> siteIds;
    private String provinceCode;
    private LocalDate date1;
    private LocalDate date2;
    private Set<Integer> siteIds;
    private String tripartitePlatformName;
}
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyDetailController.java
@@ -187,7 +187,8 @@
     */
    @GetMapping("/getListByAccountingStrategyId")
    public R<List<TAccountingStrategyDetail>> getListByAccountingStrategyId(@RequestParam("id") Integer id){
        List<TAccountingStrategyDetail> list = accountingStrategyDetailService.list(new LambdaQueryWrapper<TAccountingStrategyDetail>().eq(TAccountingStrategyDetail::getAccountingStrategyId, id));
        List<TAccountingStrategyDetail> list = accountingStrategyDetailService.list(new LambdaQueryWrapper<TAccountingStrategyDetail>()
                .eq(TAccountingStrategyDetail::getAccountingStrategyId, id).orderByAsc(TAccountingStrategyDetail::getStartTime));
        return R.ok(list);
    }
ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingGunController.java
@@ -304,7 +304,21 @@
     */
    @PostMapping("/getChargingGunByChargingPileId")
    public R<List<TChargingGun>> getChargingGunByChargingPileId(@RequestParam("chargingPileId") Integer chargingPileId){
        List<TChargingGun> list = chargingGunService.list(new LambdaQueryWrapper<TChargingGun>().eq(TChargingGun::getChargingPileId, chargingPileId).eq(TChargingGun::getDelFlag, 0));
        List<TChargingGun> list = chargingGunService.list(new LambdaQueryWrapper<TChargingGun>().eq(TChargingGun::getChargingPileId, chargingPileId)
                .eq(TChargingGun::getDelFlag, 0));
        return R.ok(list);
    }
    /**
     * 根据充电桩ids获取枪
     * @param chargingPileIds
     * @return
     */
    @PostMapping("/getChargingGunByChargingPileIds")
    public R<List<TChargingGun>> getChargingGunByChargingPileIds(@RequestParam("chargingPileIds") List<Integer> chargingPileIds){
        List<TChargingGun> list = chargingGunService.list(new LambdaQueryWrapper<TChargingGun>().in(TChargingGun::getChargingPileId, chargingPileIds)
                .eq(TChargingGun::getDelFlag, 0));
        return R.ok(list);
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/controller/TCECController.java
File was deleted
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/AESUtil.java
New file
@@ -0,0 +1,107 @@
package com.ruoyi.integration.drainage;
import com.ruoyi.common.core.utils.StringUtils;
import org.springframework.util.Base64Utils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 * 定义AES加密解密工具类
 */
public class AESUtil {
    private static final String KEY_ALGORITHM = "AES";//加密方式
    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";//默认的加密算法
    private static final String KEY = "1234567890abcdef";//密码
    private static final String IV_PARAMETER = "1234567890abcdef";//偏移量
    private static final String CHARSET = "UTF-8";//编码
    /**
     * 加密操作
     * @param content  待加密内容
     * @return
     * @throws Exception
     */
    public static String encrypt(String content) {
        return encrypt(content, KEY, IV_PARAMETER);
    }
    /**
     * 加密操作
     * @param content  待加密内容
     * @return
     * @throws Exception
     */
    public static String encrypt(String content, String key, String iv_parameter) {
        try {
            if(StringUtils.isEmpty(content)){
                return content;
            }
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            byte[] raw = key.getBytes(CHARSET);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(iv_parameter.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(content.getBytes(CHARSET));
            return Base64Utils.encodeToString(encrypted);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    public static String decrypt(String content) {
        return decrypt(content, KEY, IV_PARAMETER);
    }
    /**
     *解密操作
     * @param content 待解密内容
     * @return
     * @throws Exception
     */
    public static String decrypt(String content, String key, String iv_parameter) {
        try {
            if(StringUtils.isEmpty(content)){
                return content;
            }
            byte[] raw = key.getBytes(CHARSET);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(iv_parameter.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = Base64Utils.decodeFromString(content);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, CHARSET);
            return originalString;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }
    public static void main(String[] ages){
        String encrypt = AESUtil.encrypt("{\"total\":1,\"stationStatusInfo\":{\"operationID\":\"123456789\",\"stationID\":\"111111111111111\",\"connectorStatusInfos\":{\"connectorID\":1,\"equipmentID\":\"10000000000000000000001\",\"status\":4,\"currentA\":0,\"currentB\":0,\"currentC\":0,\"voltageA\":0,\"voltageB\":0,\"voltageC\":0,\"soc\":10,}}}");
        System.err.println(encrypt);
//        String travel = AESUtil.decrypt("IGc1VSVN8ruGbmmXUQQKZQ==");
//        System.err.println(travel);
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/NotificationStopCharge.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.integration.drainage;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送停止充电结果应答
 * @author zhibing.pu
 * @Date 2025/1/23 9:17
 */
@Data
public class NotificationStopCharge {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 失败原因
     * 0:无
     * 1:接收失败
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/QueryStopCharge.java
New file
@@ -0,0 +1,24 @@
package com.ruoyi.integration.drainage;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求停止充电
 * @author zhibing.pu
 * @Date 2025/1/22 19:56
 */
@Data
public class QueryStopCharge {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    private String ConnectorID;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/SignUtil.java
New file
@@ -0,0 +1,208 @@
package com.ruoyi.integration.drainage;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
 * 签名工具
 * @author zhibing.pu
 * @Date 2025/1/23 11:30
 */
public class SignUtil {
    /*************************************快电******************************************/
    /**
     * 签名算法
     *
     * @param aValue 加密的原文,即源数据
     * @param aKey   密钥 这是针对一条字符串进行加密的方法
     */
    public static String hmacSign (String aValue, String aKey) {
        byte k_ipad[] = new byte[64];
        byte k_opad[] = new byte[64];
        byte keyb[];
        byte value[];
        try {
            keyb = aKey.getBytes("UTF-8");
            value = aValue.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            keyb = aKey.getBytes();
            value = aValue.getBytes();
        }
        Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
        Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
        for (int i = 0; i < keyb.length; i++) {
            k_ipad[i] = (byte) (keyb[i] ^ 0x36);
            k_opad[i] = (byte) (keyb[i] ^ 0x5c);
        }
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
        md.update(k_ipad);
        md.update(value);
        byte dg[] = md.digest();
        md.reset();
        md.update(k_opad);
        md.update(dg, 0, 16);
        dg = md.digest();
        return toHex(dg);
    }
    public static String toHex (byte input[]) {
        if (input == null) {
            return null;
        }
        StringBuffer output = new StringBuffer(input.length * 2);
        for (int i = 0; i < input.length; i++) {
            int current = input[i] & 0xff;
            if (current < 16) {
                output.append("0");
            }
            output.append(Integer.toString(current, 16));
        }
        return output.toString().toUpperCase();
    }
    /*************************************新电途******************************************/
    /**
     * HmacMd5的计算公式为:HMAC(K,M) = H(K⊕opad∣H(K⊕ipad∣M))
     * 其中:K是密钥(byte[] key),长度可为64字节(后面涉及描述都是以字节byte进行),若小于该长度,在密钥后面用0(即0x00)补齐。
     * M是消息内容(byte[] m);
     * H是散列函数(此处采用MD5);
     * opad和ipad分别是由若干个0x5c和0x36组成的字符串;
     * ⊕表示异或运算;
     * ∣表示连接操作。
     **/
    public static byte[] getHMacMD5Bytes(byte[] key, byte[] m) {
        try {
            //定义长度
            int length = 64;
            //定义opad和ipad
            byte[] opad = new byte[length];
            byte[] ipad = new byte[length];
            for (int i = 0; i < length; i++) {
                opad[i] = 0x5C;
                ipad[i] = 0x36;
            }
            byte[] actualKey = key;
            byte[] keyArr = new byte[length];
            //如果密钥长度,大于64字节,就使用MD5算法计算其散列值,作为密钥
            if (key.length > length) {
                actualKey = md5(key);
            }
            for (int i = 0; i < actualKey.length; i++) {
                keyArr[i] = actualKey[i];
            }
            //如果密钥长度不足64字节,就使用0x00补齐到64字节
            if (actualKey.length < length) {
                for (int i = key.length; i < length; i++) {
                    keyArr[i] = 0x00;
                }
            }
            //使用密钥和ipad进行异或运算【K⊕ipad】
            byte[] kIpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kIpadXorResult[i] = (byte) (keyArr[i] ^ ipad[i]);
            }
            //将待加密数据M追加到kIpadXorResult后面【K⊕ipad∣M】
            byte[] firstAppendResult = new byte[kIpadXorResult.length + m.length];
            for (int i = 0; i < kIpadXorResult.length; i++) {
                firstAppendResult[i] = kIpadXorResult[i];
            }
            for (int i = 0; i < m.length; i++) {
                firstAppendResult[i + keyArr.length] = m[i];
            }
            //做MD5运算【H(K⊕ipad∣M)】
            byte[] firstHashResult = md5(firstAppendResult);
            //使用密钥和opad进行异或运算【K⊕opad】
            byte[] kOpadXorResult = new byte[length];
            for (int i = 0; i < length; i++) {
                kOpadXorResult[i] = (byte) (keyArr[i] ^ opad[i]);
            }
            //将firstHashResult追加到kOpadXorResult后面【K⊕opad∣H(K⊕ipad∣M)】
            byte[] secondAppendResult = new byte[kOpadXorResult.length + firstHashResult.length];
            for (int i = 0; i < kOpadXorResult.length; i++) {
                secondAppendResult[i] = kOpadXorResult[i];
            }
            for (int i = 0; i < firstHashResult.length; i++) {
                secondAppendResult[kOpadXorResult.length + i] = firstHashResult[i];
            }
            //做MD5运算【H(K⊕opad∣H(K⊕ipad∣M))】
            return md5(secondAppendResult);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * MD5(产生出一个128位(16字节)的散列值)
     **/
    private static byte[] md5(byte[] str) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str);
        return md.digest();
    }
    /**
     * HEX转化为字符串
     **/
    public static String bytesToHexString(byte[] m) {
        StringBuilder stringBuilder = new StringBuilder();
        if (m == null || m.length <= 0) {
            return null;
        }
        for (int i = 0; i < m.length; i++) {
            int v = m[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        //最后得到的签名,统一转化为大写
        return stringBuilder.toString().toUpperCase();
    }
    public static void main(String[] args) {
//        String encrypt = AESUtil.encrypt("{\"total\":1,\"stationStatusInfo\":{\"operationID\":\"123456789\",\"stationID\":\"111111111111111\",\"connectorStatusInfos\":{\"connectorID\":1,\"equipmentID\":\"10000000000000000000001\",\"status\":4,\"currentA\":0,\"currentB\":0,\"currentC\":0,\"voltageA\":0,\"voltageB\":0,\"voltageC\":0,\"soc\":10,}}}");
//        String s = hmacSign(encrypt, "123456789abcdef");
//        System.err.println(s);
        //签名秘钥SigSecret
        String key = "1234567890abcdef";
        //运营商标识OperatorId
        String operatorId = "123456789";
        //参数信息Data
        String data = "il7B0BSEjFdzpyKzfOFpvg/Se1CP802RItKYFPfSLRxJ3jf0bVl9hvYOEktPAYW2nd7S8MBcyHYyacHKbISq5iTmDzG+ivnR+SZJv3USNTYVMz9rCQVSxd0cLlqsJauko79NnwQJbzDTyLooYoIwz75qBOH2/xOMirpeEqRJrF/EQjWekJmGk9RtboXePu2rka+Xm51syBPhiXJAq0GfbfaFu9tNqs/e2Vjja/ltE1M0lqvxfXQ6da6HrThsm5id4ClZFIi0acRfrsPLRixS/IQYtksxghvJwbqOsbIsITail9Ayy4tKcogeEZiOO+4Ed264NSKmk7l3wKwJLAFjCFogBx8GE3OBz4pqcAn/ydA=";
        //时间戳TimeStamp(格式:年月日时分秒)
        String timeStamp = "20160729142400";
        //自增序列Seq
        String seq = "0001";
        //进行字符串拼接、计算
        String m = new StringBuilder(operatorId).append(data).append(timeStamp).append(seq).toString();
        byte[] hmacMd5 = getHMacMD5Bytes(key.getBytes(), m.getBytes());
        // 打印计算得到的签名Sig
        System.out.println(bytesToHexString(hmacMd5));
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java
New file
@@ -0,0 +1,1155 @@
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.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.common.security.service.TokenService;
import com.ruoyi.integration.drainage.model.*;
import com.ruoyi.integration.drainage.model.enu.*;
import com.ruoyi.order.api.feignClient.ChargingOrderAccountingStrategyClient;
import com.ruoyi.order.api.feignClient.ChargingOrderClient;
import com.ruoyi.order.api.model.AddTripartitePlatformOrder;
import com.ruoyi.order.api.model.StartChargeResult;
import com.ruoyi.order.api.model.TChargingOrder;
import com.ruoyi.order.api.model.TChargingOrderAccountingStrategy;
import com.ruoyi.other.api.domain.Operator;
import com.ruoyi.other.api.feignClient.OperatorClient;
import com.ruoyi.system.api.model.LoginUser;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author zhibing.pu
 * @Date 2025/1/21 17:52
 */
@RestController
@RequestMapping("/evcs/v1.0")
public class TCECController {
    @Resource
    private SiteClient siteClient;
    @Resource
    private ChargingPileClient chargingPileClient;
    @Resource
    private ChargingGunClient chargingGunClient;
    @Resource
    private ChargingOrderClient chargingOrderClient;
    @Resource
    private OperatorClient operatorClient;
    @Resource
    private AccountingStrategyDetailClient accountingStrategyDetailClient;
    @Resource
    private ChargingOrderAccountingStrategyClient chargingOrderAccountingStrategyClient;
    @Resource
    private TokenUtil tokenUtil;
    private static Map<Long, Integer> map = new HashMap<>();
    /**
     * 请求校验
     * @param baseRequest
     * @param request
     * @return
     */
    public BaseResult requestCheck(Boolean tokenCheck, BaseRequest baseRequest, HttpServletRequest request){
        BaseResult baseResult = new BaseResult();
        baseResult.setRet(0);
        baseResult.setMsg("成功");
        baseResult.setOperatorID(baseRequest.getOperatorID());
        Long mapKey = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        Integer integer = map.get(mapKey);
        if(null == integer){
            integer = 1;
        }else{
            integer++;
        }
        map.put(mapKey, integer);
        baseResult.setTimeStamp(mapKey);
        baseResult.setSeq(String.format("%04d", integer));
        //清空小于当前时间的map中的无效数据
        for (Long k : map.keySet()) {
            if(k <= (mapKey - 10)){
                map.remove(k);
            }
        }
        //校验token和签名
        String operatorID = baseRequest.getOperatorID();
        String sig = baseRequest.getSig();
        Long timeStamp = baseRequest.getTimeStamp();
        String data = baseRequest.getData();
        String seq = baseRequest.getSeq();
        if(StringUtils.isEmpty(operatorID) || StringUtils.isEmpty(sig) || StringUtils.isEmpty(data) || StringUtils.isEmpty(seq) || null == timeStamp){
            baseResult.setRet(4003);
            baseResult.setMsg("参数异常");
            return baseResult;
        }
        R<Operator> r = operatorClient.getOperator(operatorID);
        if(200 != r.getCode()){
            baseResult.setRet(500);
            baseResult.setMsg("系统异常");
            return baseResult;
        }
        //校验token
        if(tokenCheck){
            LoginUser loginUser = tokenUtil.getLoginUser(request);
            if(null == loginUser){
                baseResult.setRet(4002);
                baseResult.setMsg("身份校验失败,无效的token");
                return baseResult;
            }
        }
        Operator operator = r.getData();
        baseRequest.setOperator(operator);
        //校验签名
        String sign = buildSign(baseRequest);
        if(!sign.equals(sig)){
            baseResult.setRet(4001);
            baseResult.setMsg("签名校验失败");
            return baseResult;
        }
        baseResult.setOperator(operator);
        return baseResult;
    }
    /**
     * 构建签名字符串
     * @param model
     * @return
     */
    public String buildSign(BaseModel model){
        Operator operator = model.getOperator();
        //签名秘钥SigSecret
        String key = operator.getSigSecret();
        String sign = "";
        switch (operator.getName()){
            case "XinDianTu":
                //进行字符串拼接、计算
                String m = new StringBuilder(model.getOperatorID()).append(model.getData()).append(model.getTimeStamp()).append(model.getSeq()).toString();
                byte[] hmacMd5 = SignUtil.getHMacMD5Bytes(key.getBytes(), m.getBytes());
                // 打印计算得到的签名Sig
                sign = SignUtil.bytesToHexString(hmacMd5);
                break;
            case "KuaiDian":
                sign = SignUtil.hmacSign(model.getData(), key);
                break;
        }
        return sign;
    }
    /**
     * 获取token
     * @return
     */
    @PostMapping("/query_token")
    public BaseResult queryToken(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        BaseResult baseResult = requestCheck(false, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        QueryTokenResult queryTokenResult = new QueryTokenResult();
        Operator operator = baseResult.getOperator();
        if(null == operator){
            queryTokenResult.setSuccStat(1);
            queryTokenResult.setFailReason(1);
            return baseResult;
        }
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryToken queryToken = JSON.parseObject(decrypt, QueryToken.class);
        if(!queryToken.getOperatorSecret().equals(operator.getOperatorSecret())){
            queryTokenResult.setSuccStat(1);
            queryTokenResult.setFailReason(2);
            //参数加密
            String jsonString = JSON.toJSONString(queryTokenResult);
            String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
            baseResult.setData(encrypt);
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        //生成token
        Map<String, Object> token = tokenUtil.createToken(operator);
        String access_token = token.get("access_token").toString();
        Long expires_in = Long.valueOf(token.get("expires_in").toString());
        queryTokenResult.setSuccStat(0);
        queryTokenResult.setFailReason(0);
        queryTokenResult.setAccessToken(access_token);
        queryTokenResult.setTokenAvailableTime(expires_in * 60);
        //参数加密
        String jsonString = JSON.toJSONString(queryTokenResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 查询充电站信息
     * @return
     */
    @PostMapping("/query_stations_info")
    public BaseResult queryStationsInfo(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryStationsInfo queryStationsInfo = JSON.parseObject(decrypt, QueryStationsInfo.class);
        Integer pageNo = queryStationsInfo.getPageNo();
        Integer pageSize = queryStationsInfo.getPageSize();
        if(null == pageNo){
            pageNo = 1;
        }
        if(null == pageSize){
            pageSize = 10;
        }
        PageInfo<Site> siteListPaging = siteClient.getSiteListPaging(pageNo, pageSize);
        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()));
        //参数加密
        String jsonString = JSON.toJSONString(queryStationsInfoResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 构建站点数据
     * @param sites
     * @return
     */
    public List<StationInfo> buildSite(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());
        List<TChargingGun> chargingGunList = chargingGunClient.getChargingGunByChargingPileIds(collect1).getData();
        List<StationInfo> StationInfos = new ArrayList<>();
        for (Site datum : sites) {
            StationInfo stationInfo = new StationInfo();
            stationInfo.setStationID(datum.getId().toString());
            stationInfo.setOperatorID("");
            stationInfo.setEquipmentOwnerID("91510903906171535D");
            stationInfo.setStationName(datum.getName());
            stationInfo.setCountryCode(datum.getCountryCode());
            stationInfo.setAreaCode(datum.getDistrictsCode());
            stationInfo.setAddress(datum.getAddress());
            stationInfo.setStationTel(datum.getPhone());
            stationInfo.setServiceTel(datum.getServicePhone());
            switch (datum.getSiteType()){
                case 0:
                    stationInfo.setStationType(StationTypeEnum.OTHER.getType());
                    break;
                case 1:
                    stationInfo.setStationType(StationTypeEnum.PUBLIC.getType());
                    break;
                case 2:
                    stationInfo.setStationType(StationTypeEnum.PERSONAGE.getType());
                    break;
                case 3:
                    stationInfo.setStationType(StationTypeEnum.BUS_SPECIFIC.getType());
                    break;
                case 4:
                    stationInfo.setStationType(StationTypeEnum.SANITATION_SPECIFIC.getType());
                    break;
                case 5:
                    stationInfo.setStationType(StationTypeEnum.LOGISTICS_SPECIFIC.getType());
                    break;
                case 6:
                    stationInfo.setStationType(StationTypeEnum.TEXT_SPECIFIC.getType());
                    break;
            }
            if(datum.getStatus() == 1){
                stationInfo.setStationStatus(StationStatusEnum.NORMAL_USE.getStatus());
            }
            if(datum.getStatus() == 2){
                stationInfo.setStationStatus(StationStatusEnum.MAINTAIN.getStatus());
            }
            if(datum.getStatus() == 3){
                stationInfo.setStationStatus(StationStatusEnum.OFF_LINE.getStatus());
            }
            stationInfo.setParkNums(datum.getParkingSpace());
            stationInfo.setStationLat(new BigDecimal(datum.getLat()).setScale(6, RoundingMode.DOWN));
            stationInfo.setStationLng(new BigDecimal(datum.getLon()).setScale(6, RoundingMode.DOWN));
            stationInfo.setConstruction(datum.getConstructionSite() == 0 ? ConstructionEnum.OTHER.getType() : datum.getConstructionSite());
            stationInfo.setPictures(Arrays.asList(datum.getImgUrl().split(",")));
            stationInfo.setSiteGuide(datum.getGuide());
            stationInfo.setMatchCars(datum.getVehicleDescription());
            stationInfo.setBusineHours(datum.getStartServiceTime() + "-" + datum.getEndServiceTime());
            stationInfo.setElectricityFee(datum.getRateDescription());
            //构建充电设备信息数据
            stationInfo.setEquipmentInfos(buildEquipmentInfo(datum.getId(), tChargingPiles, chargingGunList));
            StationInfos.add(stationInfo);
        }
        return StationInfos;
    }
    /**
     * 构建桩数据
     * @param tChargingPiles
     * @return
     */
    public List<EquipmentInfo> buildEquipmentInfo(Integer siteId, List<TChargingPile> tChargingPiles, List<TChargingGun> chargingGunList){
        List<EquipmentInfo> equipmentInfos = new ArrayList<>();
        List<TChargingPile> collect = tChargingPiles.stream().filter(s -> s.getSiteId().equals(siteId)).collect(Collectors.toList());
        for (TChargingPile tChargingPile : collect) {
            EquipmentInfo equipmentInfo = new EquipmentInfo();
            equipmentInfo.setEquipmentID(tChargingPile.getId().toString());
            equipmentInfo.setManufacturerID(tChargingPile.getManufacturerCode());
            equipmentInfo.setManufacturerName(tChargingPile.getManufacturer());
            equipmentInfo.setEquipmentModel(tChargingPile.getEquipmentType());
            if(null != tChargingPile.getProductionDate()){
                equipmentInfo.setProductionDate(tChargingPile.getProductionDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            }
            switch (tChargingPile.getType()){
                case 0:
                    equipmentInfo.setEquipmentType(EquipmentTypeEnum.OTHER.getType());
                    break;
                case 1:
                    equipmentInfo.setEquipmentType(EquipmentTypeEnum.DIRECT_CURRENT.getType());
                    break;
                case 2:
                    equipmentInfo.setEquipmentType(EquipmentTypeEnum.ALTERNATING_CURRENT.getType());
                    break;
                case 3:
                    equipmentInfo.setEquipmentType(EquipmentTypeEnum.ALTERNATING_DIRECT.getType());
                    break;
                case 4:
                    equipmentInfo.setEquipmentType(EquipmentTypeEnum.WIRELESS_DEVICE.getType());
                    break;
            }
            //构建设备接口信息
            equipmentInfo.setConnectorInfos(buildConnectorInfos(tChargingPile.getId(), chargingGunList));
            equipmentInfos.add(equipmentInfo);
        }
        return equipmentInfos;
    }
    /**
     * 构建接口数据
     * @param chargingGunList
     * @return
     */
    public List<ConnectorInfo> buildConnectorInfos(Integer chargingPileId, 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) {
            ConnectorInfo connectorInfo = new ConnectorInfo();
            connectorInfo.setConnectorID(chargingGun.getId().toString());
            connectorInfo.setConnectorName(chargingGun.getName());
            switch (chargingGun.getType()){
                case 0:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.OTHER.getType());
                    break;
                case 1:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.HOUSEHOLD_SOCKET.getType());
                    break;
                case 2:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.AC_SOCKET.getType());
                    break;
                case 3:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.AC_INTERFACE_PLUG.getType());
                    break;
                case 4:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.DC_INTERFACE_GUN_HEAD.getType());
                    break;
                case 5:
                    connectorInfo.setConnectorType(ConnectorTypeEnum.WIRELESS_CHARGING_STAND.getType());
                    break;
            }
            connectorInfo.setVoltageUpperLimits(chargingGun.getUpperRatedVoltage().intValue());
            connectorInfo.setVoltageLowerLimits(chargingGun.getLowerLimitOfRatedVoltage().intValue());
            connectorInfo.setCurrent(chargingGun.getRatedCurrent().intValue());
            connectorInfo.setPower(chargingGun.getRatedPower());
            connectorInfo.setParkNo(chargingGun.getParkingNumber());
            connectorInfo.setNationalStandard(Integer.valueOf(chargingGun.getNationalStandard()));
            connectorInfos.add(connectorInfo);
        }
        return connectorInfos;
    }
    /**
     * 接口状态变化后推送给第三方
     * @return
     */
    @PostMapping("/pushChargingGunStatus")
    public R pushChargingGunStatus(@RequestParam("id") Integer id, @RequestParam("status") Integer status){
        ConnectorStatusInfo connectorStatusInfo = new ConnectorStatusInfo();
        connectorStatusInfo.setConnectorID(id.toString());
        switch (status){
            case 1:
                connectorStatusInfo.setStatus(0);
                break;
            case 2:
                connectorStatusInfo.setStatus(1);
                break;
            case 3:
                connectorStatusInfo.setStatus(2);
                break;
            case 4:
                connectorStatusInfo.setStatus(3);
                break;
            case 5:
                connectorStatusInfo.setStatus(3);
                break;
            case 6:
                connectorStatusInfo.setStatus(4);
                break;
            case 7:
                connectorStatusInfo.setStatus(255);
                break;
        }
        NotificationStationStatusResult result = TCECUtil.notificationStationStatus(connectorStatusInfo);
        return R.ok();
    }
    /**
     * 设备接口状态查询
     * @return
     */
    @PostMapping("/query_station_status")
    public BaseResult queryStationStatus(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryStationStatus queryStationsInfo = JSON.parseObject(decrypt, QueryStationStatus.class);
        List<Integer> collect = queryStationsInfo.getStationIDs().stream().map(Integer::valueOf).collect(Collectors.toList());
        List<Site> data = siteClient.getSiteByIds(collect).getData();
        List<Integer> siteIds = data.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());
        List<TChargingGun> chargingGunList = chargingGunClient.getChargingGunByChargingPileIds(collect1).getData();
        QueryStationStatusResult result = new QueryStationStatusResult();
        result.setTotal(data.size());
        List<StationStatusInfo> StationStatusInfos = new ArrayList<>();
        for (Site datum : data) {
            StationStatusInfo stationStatusInfo = new StationStatusInfo();
            stationStatusInfo.setStationID(datum.getId().toString());
            //构建接口状态
            List<ConnectorStatusInfo> ConnectorStatusInfos = new ArrayList<>();
            List<TChargingGun> collect2 = chargingGunList.stream().filter(s -> s.getSiteId().equals(datum.getId())).collect(Collectors.toList());
            for (TChargingGun chargingGun : collect2) {
                ConnectorStatusInfo info = new ConnectorStatusInfo();
                info.setConnectorID(chargingGun.getId().toString());
                switch (chargingGun.getStatus()){
                    case 1:
                        info.setStatus(0);
                        break;
                    case 2:
                        info.setStatus(1);
                        break;
                    case 3:
                        info.setStatus(2);
                        break;
                    case 4:
                        info.setStatus(3);
                        break;
                    case 5:
                        info.setStatus(3);
                        break;
                    case 6:
                        info.setStatus(4);
                        break;
                    case 7:
                        info.setStatus(255);
                        break;
                }
                ConnectorStatusInfos.add(info);
            }
            stationStatusInfo.setConnectorStatusInfos(ConnectorStatusInfos);
            StationStatusInfos.add(stationStatusInfo);
        }
        result.setStationStatusInfos(StationStatusInfos);
        //参数加密
        String jsonString = JSON.toJSONString(result);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 查询统计信息
     * @return
     */
    @PostMapping("/query_station_stats")
    public BaseResult queryStationStats(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryStationStats queryStationStats = JSON.parseObject(decrypt, QueryStationStats.class);
        QueryStationStatsResult result = new QueryStationStatsResult();
        ChargingPercentProvinceDto dto = new ChargingPercentProvinceDto();
        dto.setDate1(LocalDate.parse(queryStationStats.getStartTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        dto.setDate2(LocalDate.parse(queryStationStats.getEndTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        dto.setSiteIds(new HashSet<>(Integer.valueOf(queryStationStats.getStationID())));
        dto.setTripartitePlatformName(operator.getName());
        List<TChargingOrder> chargingOrders = chargingOrderClient.getOrderBySiteIdAndTime(dto).getData();
        BigDecimal reduce = chargingOrders.stream().map(TChargingOrder::getChargingCapacity).reduce(BigDecimal.ZERO, BigDecimal::add);
        StationStatsInfo stationStats = new StationStatsInfo();
        stationStats.setStationID(chargingOrders.get(0).getSiteId().toString());
        stationStats.setStartTime(queryStationStats.getStartTime());
        stationStats.setEndTime(queryStationStats.getEndTime());
        stationStats.setStationElectricity(reduce);
        //构建设备统计数据
        List<EquipmentStatsInfo> EquipmentStatsInfos = new ArrayList<>();
        Map<Integer, List<TChargingOrder>> collect = chargingOrders.stream().collect(Collectors.groupingBy(TChargingOrder::getChargingPileId));
        for (Integer integer : collect.keySet()) {
            List<TChargingOrder> tChargingOrders = collect.get(integer);
            BigDecimal reduce1 = tChargingOrders.stream().map(TChargingOrder::getChargingCapacity).reduce(BigDecimal.ZERO, BigDecimal::add);
            EquipmentStatsInfo equipmentStatsInfo = new EquipmentStatsInfo();
            equipmentStatsInfo.setEquipmentID(integer.toString());
            equipmentStatsInfo.setEquipmentElectricity(reduce1);
            //构建设备接口统计数据
            Map<Integer, List<TChargingOrder>> collect2 = tChargingOrders.stream().collect(Collectors.groupingBy(TChargingOrder::getChargingGunId));
            List<ConnectorStatsInfo> ConnectorStatsInfos = new ArrayList<>();
            for (Integer integer1 : collect2.keySet()) {
                List<TChargingOrder> tChargingOrders1 = collect2.get(integer1);
                BigDecimal reduce2 = tChargingOrders1.stream().map(TChargingOrder::getChargingCapacity).reduce(BigDecimal.ZERO, BigDecimal::add);
                ConnectorStatsInfo connectorStatsInfo = new ConnectorStatsInfo();
                connectorStatsInfo.setConnectorID(integer1.toString());
                connectorStatsInfo.setConnectorElectricity(reduce2);
                ConnectorStatsInfos.add(connectorStatsInfo);
            }
            equipmentStatsInfo.setConnectorStatsInfos(ConnectorStatsInfos);
            EquipmentStatsInfos.add(equipmentStatsInfo);
        }
        stationStats.setEquipmentStatsInfos(EquipmentStatsInfos);
        result.setStationStats(stationStats);
        //参数加密
        String jsonString = JSON.toJSONString(result);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 请求设备认证
     * @return
     */
    @PostMapping("/query_equip_auth")
    public BaseResult queryEquipAuth(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryEquipAuth queryEquipAuth = JSON.parseObject(decrypt, QueryEquipAuth.class);
        String connectorID = queryEquipAuth.getConnectorID();
        TChargingGun tChargingGun = chargingGunClient.getChargingGunById(Integer.valueOf(connectorID)).getData();
        if(null == tChargingGun){
            baseResult.setRet(4004);
            baseResult.setMsg("connectorID 参数无效");
            return baseResult;
        }
        QueryEquipAuthResult queryEquipAuthResult = new QueryEquipAuthResult();
        queryEquipAuthResult.setEquipAuthSeq(queryEquipAuth.getEquipAuthSeq());
        queryEquipAuthResult.setConnectorID(connectorID);
        //1=离线,2=空闲,3=占用(未充电),4=占用(充电中),5=占用(已充满),6=占用(预约锁定),7=故障
        switch (tChargingGun.getStatus()){
            case 1:
                queryEquipAuthResult.setSuccStat(1);
                queryEquipAuthResult.setFailReason(2);
                break;
            case 2:
                queryEquipAuthResult.setSuccStat(0);
                queryEquipAuthResult.setFailReason(0);
                break;
            case 3:
                queryEquipAuthResult.setSuccStat(0);
                queryEquipAuthResult.setFailReason(1);
                break;
            case 4:
                queryEquipAuthResult.setSuccStat(1);
                queryEquipAuthResult.setFailReason(4);
                break;
            case 5:
                queryEquipAuthResult.setSuccStat(1);
                queryEquipAuthResult.setFailReason(5);
                break;
            case 6:
                queryEquipAuthResult.setSuccStat(1);
                queryEquipAuthResult.setFailReason(6);
                break;
            case 7:
                queryEquipAuthResult.setSuccStat(1);
                queryEquipAuthResult.setFailReason(2);
                break;
        }
        //参数加密
        String jsonString = JSON.toJSONString(queryEquipAuthResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 查询业务策略信息
     * @return
     */
    @PostMapping("/query_equip_business_policy")
    public BaseResult queryEquipBusinessPolicy(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryEquipBusinessPolicy queryEquipBusinessPolicy = JSON.parseObject(decrypt, QueryEquipBusinessPolicy.class);
        //构建返回结果
        QueryEquipBusinessPolicyResult queryEquipBusinessPolicyResult = new QueryEquipBusinessPolicyResult();
        queryEquipBusinessPolicyResult.setEquipBizSeq(queryEquipBusinessPolicy.getEquipBizSeq());
        queryEquipBusinessPolicyResult.setConnectorID(queryEquipBusinessPolicy.getConnectorID());
        queryEquipBusinessPolicyResult.setSuccStat(0);
        queryEquipBusinessPolicyResult.setFailReason(0);
        String connectorID = queryEquipBusinessPolicy.getConnectorID();
        TChargingGun tChargingGun = chargingGunClient.getChargingGunById(Integer.valueOf(connectorID)).getData();
        if(null == tChargingGun){
            baseResult.setRet(4004);
            baseResult.setMsg("connectorID 参数无效");
            //参数加密
            String jsonString = JSON.toJSONString(queryEquipBusinessPolicyResult);
            String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
            baseResult.setData(encrypt);
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Integer accountingStrategyId = tChargingGun.getAccountingStrategyId();
        if(null == accountingStrategyId){
            List<Site> data = siteClient.getSiteByIds(Arrays.asList(tChargingGun.getSiteId())).getData();
            accountingStrategyId = data.get(0).getAccountingStrategyId();
        }
        List<TAccountingStrategyDetail> accountingStrategyDetails = accountingStrategyDetailClient.getListByAccountingStrategyId(accountingStrategyId).getData();
        if(accountingStrategyDetails.size() == 0){
            queryEquipBusinessPolicyResult.setSuccStat(1);
            queryEquipBusinessPolicyResult.setFailReason(1);
            queryEquipBusinessPolicyResult.setSumPeriod(0);
            //参数加密
            String jsonString = JSON.toJSONString(queryEquipBusinessPolicyResult);
            String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
            baseResult.setData(encrypt);
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        List<PolicyInfo> PolicyInfos = new ArrayList<>();
        for (TAccountingStrategyDetail accountingStrategyDetail : accountingStrategyDetails) {
            PolicyInfo policyInfo = new PolicyInfo();
            policyInfo.setStartTime(accountingStrategyDetail.getStartTime().replaceAll(":", "") + "00");
            policyInfo.setElecPrice(accountingStrategyDetail.getElectrovalence());
            policyInfo.setSevicePrice(accountingStrategyDetail.getServiceCharge());
            PolicyInfos.add(policyInfo);
        }
        queryEquipBusinessPolicyResult.setSumPeriod(PolicyInfos.size());
        queryEquipBusinessPolicyResult.setPolicyInfos(PolicyInfos);
        //参数加密
        String jsonString = JSON.toJSONString(queryEquipBusinessPolicyResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 请求定充电
     * @return
     */
    @PostMapping("/query_start_charge")
    public BaseResult queryStartCharge(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryStartCharge queryStartCharge = JSON.parseObject(decrypt, QueryStartCharge.class);
        //构建返回结果
        QueryStartChargeResult result = new QueryStartChargeResult();
        result.setStartChargeSeq(queryStartCharge.getStartChargeSeq());
        result.setConnectorID(queryStartCharge.getConnectorID());
        String connectorID = queryStartCharge.getConnectorID();
        TChargingGun tChargingGun = chargingGunClient.getChargingGunById(Integer.valueOf(connectorID)).getData();
        //设备不存在
        if(null == tChargingGun){
            baseResult.setRet(4004);
            baseResult.setMsg("connectorID 参数无效");
            result.setSuccStat(1);
            result.setFailReason(1);
            result.setStartChargeSeqStat(5);
            //参数加密
            String jsonString = JSON.toJSONString(result);
            String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
            baseResult.setData(encrypt);
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        //设备离线
        if(tChargingGun.getStatus() == 1){
            result.setSuccStat(1);
            result.setFailReason(2);
            result.setStartChargeSeqStat(5);
            //参数加密
            String jsonString = JSON.toJSONString(result);
            String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
            baseResult.setData(encrypt);
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        //调用充电接口
        AddTripartitePlatformOrder addTripartitePlatformOrder = new AddTripartitePlatformOrder();
        addTripartitePlatformOrder.setStartChargeSeq(queryStartCharge.getStartChargeSeq());
        addTripartitePlatformOrder.setChargingGunId(tChargingGun.getId());
//        addTripartitePlatformOrder.setOperatorId(query.get);
        addTripartitePlatformOrder.setPaymentAmount(queryStartCharge.getPaymentAmount());
        addTripartitePlatformOrder.setRechargePaymentType(queryStartCharge.getPaymentType());
        R order = chargingOrderClient.addTripartitePlatformOrder(addTripartitePlatformOrder);
        //启动失败
        if(200 != order.getCode()){
            result.setSuccStat(1);
            result.setFailReason(1);
            result.setStartChargeSeqStat(2);
            //参数加密
            String jsonString = JSON.toJSONString(result);
            String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
            baseResult.setData(encrypt);
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        result.setStartChargeSeqStat(1);
        result.setSuccStat(0);
        result.setFailReason(0);
        //参数加密
        String jsonString = JSON.toJSONString(result);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 启动充电结果推送
     * @param result
     * @return
     */
    @PostMapping("/notificationStartChargeResult")
    public R notificationStartChargeResult(@RequestBody StartChargeResult result){
        NotificationStartCharge notificationStartCharge = new NotificationStartCharge();
        BeanUtils.copyProperties(result, notificationStartCharge);
        com.ruoyi.integration.drainage.model.NotificationStartChargeResult notificationStartChargeResult = TCECUtil.notificationStartChargeResult(notificationStartCharge);
        //启动重试推送机制
        if(null == notificationStartChargeResult || 1 == notificationStartChargeResult.getSuccStat()){
        }
        return R.ok();
    }
    /**
     * 查询充电状态
     * @return
     */
    @PostMapping("/query_equip_charge_status")
    public BaseResult queryEquipChargeStatus(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryEquipChargeStatus queryEquipChargeStatus = JSON.parseObject(decrypt, QueryEquipChargeStatus.class);
        //校验token和签名
        QueryEquipChargeStatusResult queryEquipChargeStatusResult = buildQueryEquipChargeStatusResult(queryEquipChargeStatus.getStartChargeSeq());
        //参数加密
        String jsonString = JSON.toJSONString(queryEquipChargeStatusResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 构建充电状态结果
     * @param startChargeSeq
     * @return
     */
    public QueryEquipChargeStatusResult buildQueryEquipChargeStatusResult(String startChargeSeq){
        //构建返回结果
        QueryEquipChargeStatusResult queryEquipChargeStatusResult = new QueryEquipChargeStatusResult();
        queryEquipChargeStatusResult.setStartChargeSeq(startChargeSeq);
        TChargingOrder chargingOrder = chargingOrderClient.getChargingOrderByStartChargeSeq(startChargeSeq).getData();
        if(null == chargingOrder){
            return null;
        }
        //0=未知,1=等待中/已插枪,2=启动中,3=充电中,4=停止中,5=已结束
        switch (chargingOrder.getStatus()){
            case 0:
                queryEquipChargeStatusResult.setStartChargeSeqStat(5);
                break;
            case 1:
                queryEquipChargeStatusResult.setStartChargeSeqStat(0);
                break;
            case 2:
                queryEquipChargeStatusResult.setStartChargeSeqStat(1);
                break;
            case 3:
                queryEquipChargeStatusResult.setStartChargeSeqStat(2);
                break;
            case 4:
                queryEquipChargeStatusResult.setStartChargeSeqStat(3);
                break;
            case 5:
                queryEquipChargeStatusResult.setStartChargeSeqStat(4);
                break;
        }
        queryEquipChargeStatusResult.setConnectorID(chargingOrder.getChargingGunId().toString());
        TChargingGun chargingGun = chargingGunClient.getChargingGunById(chargingOrder.getChargingGunId()).getData();
        //1=离线,2=空闲,3=占用(未充电),4=占用(充电中),5=占用(已充满),6=占用(预约锁定),7=故障
        switch (chargingGun.getStatus()){
            case 1:
                queryEquipChargeStatusResult.setConnectorStatus(0);
                break;
            case 2:
                queryEquipChargeStatusResult.setConnectorStatus(1);
                break;
            case 3:
                queryEquipChargeStatusResult.setConnectorStatus(2);
                break;
            case 4:
                queryEquipChargeStatusResult.setConnectorStatus(3);
                break;
            case 5:
                queryEquipChargeStatusResult.setConnectorStatus(1);
                break;
            case 6:
                queryEquipChargeStatusResult.setConnectorStatus(4);
                break;
            case 7:
                queryEquipChargeStatusResult.setConnectorStatus(255);
                break;
        }
        queryEquipChargeStatusResult.setCurrentA(chargingOrder.getCurrent());
        queryEquipChargeStatusResult.setVoltageA(chargingOrder.getVoltage());
        queryEquipChargeStatusResult.setSoc(chargingOrder.getTotalElectricity());
        queryEquipChargeStatusResult.setStartTime((null == chargingOrder.getStartTime() ? chargingOrder.getCreateTime() : chargingOrder.getStartTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        queryEquipChargeStatusResult.setEndTime((null == chargingOrder.getStartTime() ? LocalDateTime.now() : chargingOrder.getEndTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        queryEquipChargeStatusResult.setTotalPower(chargingOrder.getElectricity());
        queryEquipChargeStatusResult.setElecMoney(chargingOrder.getTotalElectricity());
        queryEquipChargeStatusResult.setSeviceMoney(chargingOrder.getServiceCharge());
        queryEquipChargeStatusResult.setTotalMoney(chargingOrder.getTotalElectricity().add(chargingOrder.getServiceCharge()));
        //构建充电明细
        List<ChargeDetail> chargeDetails = new ArrayList<>();
        List<TChargingOrderAccountingStrategy> data = chargingOrderAccountingStrategyClient.getChargingOrderAccountingStrategyByOrderId(chargingOrder.getId()).getData();
        LocalDateTime startTime = chargingOrder.getStartTime();
        LocalDateTime endTime = chargingOrder.getEndTime();
        String s_format = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String e_format = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        for (TChargingOrderAccountingStrategy datum : data) {
            ChargeDetail chargeDetail = new ChargeDetail();
            if(s_format.equals(e_format)){
                chargeDetail.setDetailStartTime(s_format + " " + datum.getStartTime() + ":00");
                chargeDetail.setDetailEndTime(s_format + " " + datum.getEndTime() + ":59");
            }else{
                String substring = datum.getEndTime().substring(0, datum.getEndTime().indexOf(":"));
                if(Integer.valueOf(substring) > 12){
                    chargeDetail.setDetailStartTime(s_format + " " + datum.getStartTime() + ":00");
                    chargeDetail.setDetailEndTime(s_format + " " + datum.getEndTime() + ":59");
                }else{
                    chargeDetail.setDetailStartTime(e_format + " " + datum.getStartTime() + ":00");
                    chargeDetail.setDetailEndTime(e_format + " " + datum.getEndTime() + ":59");
                }
            }
            chargeDetail.setElecPrice(datum.getElectrovalence());
            chargeDetail.setSevicePrice(datum.getServiceCharge());
            chargeDetail.setDetailPower(datum.getChargingCapacity());
            chargeDetail.setDetailElecMoney(datum.getPeriodElectricPrice());
            chargeDetail.setDetailSeviceMoney(datum.getPeriodServicePrice());
            chargeDetails.add(chargeDetail);
        }
        queryEquipChargeStatusResult.setChargeDetails(chargeDetails);
        return queryEquipChargeStatusResult;
    }
    /**
     * 推送充电状态
     * @param startChargeSeq
     * @return
     */
    @PostMapping("/notificationEquipChargeStatus")
    public R notificationEquipChargeStatus(@RequestParam("startChargeSeq") String startChargeSeq){
        QueryEquipChargeStatusResult queryEquipChargeStatusResult = buildQueryEquipChargeStatusResult(startChargeSeq);
        NotificationEquipChargeStatusResult notificationEquipChargeStatusResult = TCECUtil.notificationEquipChargeStatus(queryEquipChargeStatusResult);
        //启动重试推送机制
        if(null == notificationEquipChargeStatusResult || 1 == notificationEquipChargeStatusResult.getSuccStat()){
        }
        return R.ok();
    }
    /**
     * 请求停止充电
     * @return
     */
    @PostMapping("/query_stop_charge")
    public BaseResult queryStopCharge(@RequestBody BaseRequest baseRequest, HttpServletRequest request){
        //校验token和签名
        BaseResult baseResult = requestCheck(true, baseRequest, request);
        if(0 != baseResult.getRet()){
            baseResult.setData("");
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        Operator operator = baseResult.getOperator();
        //解密参数
        String decrypt = AESUtil.decrypt(baseRequest.getData(), operator.getDataSecret(), operator.getDataSecretIv());
        QueryStopCharge queryStopCharge = JSON.parseObject(decrypt, QueryStopCharge.class);
        QueryStopChargeResult queryStopChargeResult = new QueryStopChargeResult();
        queryStopChargeResult.setStartChargeSeq(queryStopCharge.getStartChargeSeq());
        queryStopChargeResult.setStartChargeSeqStat(3);
        queryStopChargeResult.setSuccStat(0);
        queryStopChargeResult.setFailReason(0);
        //执行停机操作
        R r = chargingOrderClient.tripartitePlatformStopCharge(queryStopCharge.getStartChargeSeq());
        if(200 != r.getCode()){
            queryStopChargeResult.setStartChargeSeqStat(5);
            queryStopChargeResult.setSuccStat(1);
            queryStopChargeResult.setFailReason(3);
            //参数加密
            String jsonString = JSON.toJSONString(queryStopChargeResult);
            String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
            baseResult.setData(encrypt);
            baseResult.setSig(buildSign(baseResult));
            return baseResult;
        }
        //参数加密
        String jsonString = JSON.toJSONString(queryStopChargeResult);
        String encrypt = AESUtil.encrypt(jsonString, operator.getDataSecret(), operator.getDataSecretIv());
        baseResult.setData(encrypt);
        baseResult.setSig(buildSign(baseResult));
        return baseResult;
    }
    /**
     * 推送停止充电结果
     * @param startChargeSeq    充电订单号
     * @param connectorID       充电设备接口编码
     * @return
     */
    @PostMapping("/notificationStopChargeResult")
    public R notificationStopChargeResult(@RequestParam("startChargeSeq") String startChargeSeq, @RequestParam("connectorID") String connectorID){
        NotificationStopChargeResult info = new NotificationStopChargeResult();
        info.setStartChargeSeq(startChargeSeq);
        info.setStartChargeSeqStat(4);
        info.setConnectorID(connectorID);
        info.setSuccStat(0);
        info.setFailReason(0);
        NotificationStopCharge notificationStopCharge = TCECUtil.notificationStopChargeResult(info);
        //启动重试推送机制
        if(null == notificationStopCharge || 1 == notificationStopCharge.getSuccStat()){
        }
        return R.ok();
    }
    /**
     * 推送订单信息
     * @param startChargeSeq
     * @return
     */
    @PostMapping("/notificationChargeOrderInfo")
    public R notificationChargeOrderInfo(@RequestParam("startChargeSeq") String startChargeSeq){
        NotificationChargeOrderInfo info = buildNotificationChargeOrderInfo(startChargeSeq);
        NotificationChargeOrderInfoResult notificationChargeOrderInfoResult = TCECUtil.notificationChargeOrderInfo(info);
        //启动重试推送机制
        if(null == notificationChargeOrderInfoResult || 1 == notificationChargeOrderInfoResult.getConfirmResult()){
        }
        return R.ok();
    }
    /**
     * 构建推送订单信息
     * @param startChargeSeq
     * @return
     */
    public NotificationChargeOrderInfo buildNotificationChargeOrderInfo(String startChargeSeq){
        //构建返回结果
        NotificationChargeOrderInfo notificationChargeOrderInfo = new NotificationChargeOrderInfo();
        notificationChargeOrderInfo.setStartChargeSeq(startChargeSeq);
        TChargingOrder chargingOrder = chargingOrderClient.getChargingOrderByStartChargeSeq(startChargeSeq).getData();
        if(null == chargingOrder){
            return null;
        }
        notificationChargeOrderInfo.setConnectorID(chargingOrder.getChargingGunId().toString());
        notificationChargeOrderInfo.setStartTime((null == chargingOrder.getStartTime() ? chargingOrder.getCreateTime() : chargingOrder.getStartTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        notificationChargeOrderInfo.setEndTime((null == chargingOrder.getStartTime() ? LocalDateTime.now() : chargingOrder.getEndTime()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        notificationChargeOrderInfo.setTotalPower(chargingOrder.getElectricity());
        notificationChargeOrderInfo.setTotalElecMoney(chargingOrder.getTotalElectricity());
        notificationChargeOrderInfo.setTotalSeviceMoney(chargingOrder.getServiceCharge());
        notificationChargeOrderInfo.setTotalMoney(chargingOrder.getTotalElectricity().add(chargingOrder.getServiceCharge()));
        //结束方式(0=异常终止,1=主动终止,2=满电终止,3=费用不足终止)
        switch (chargingOrder.getEndMode()){
            case 0:
                notificationChargeOrderInfo.setStopReason(3);
                break;
            case 1:
                notificationChargeOrderInfo.setStopReason(0);
                break;
            case 2:
                notificationChargeOrderInfo.setStopReason(2);
                break;
            case 3:
                notificationChargeOrderInfo.setStopReason(5);
                break;
        }
        //构建充电明细
        List<ChargeDetail> chargeDetails = new ArrayList<>();
        List<TChargingOrderAccountingStrategy> data = chargingOrderAccountingStrategyClient.getChargingOrderAccountingStrategyByOrderId(chargingOrder.getId()).getData();
        LocalDateTime startTime = chargingOrder.getStartTime();
        LocalDateTime endTime = chargingOrder.getEndTime();
        String s_format = startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String e_format = endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        for (TChargingOrderAccountingStrategy datum : data) {
            ChargeDetail chargeDetail = new ChargeDetail();
            if(s_format.equals(e_format)){
                chargeDetail.setDetailStartTime(s_format + " " + datum.getStartTime() + ":00");
                chargeDetail.setDetailEndTime(s_format + " " + datum.getEndTime() + ":59");
            }else{
                String substring = datum.getEndTime().substring(0, datum.getEndTime().indexOf(":"));
                if(Integer.valueOf(substring) > 12){
                    chargeDetail.setDetailStartTime(s_format + " " + datum.getStartTime() + ":00");
                    chargeDetail.setDetailEndTime(s_format + " " + datum.getEndTime() + ":59");
                }else{
                    chargeDetail.setDetailStartTime(e_format + " " + datum.getStartTime() + ":00");
                    chargeDetail.setDetailEndTime(e_format + " " + datum.getEndTime() + ":59");
                }
            }
            chargeDetail.setElecPrice(datum.getElectrovalence());
            chargeDetail.setSevicePrice(datum.getServiceCharge());
            chargeDetail.setDetailPower(datum.getChargingCapacity());
            chargeDetail.setDetailElecMoney(datum.getPeriodElectricPrice());
            chargeDetail.setDetailSeviceMoney(datum.getPeriodServicePrice());
            chargeDetails.add(chargeDetail);
        }
        notificationChargeOrderInfo.setChargeDetails(chargeDetails);
        return notificationChargeOrderInfo;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java
@@ -2,8 +2,15 @@
import cn.hutool.http.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.integration.drainage.model.*;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
/**
 * 中电联TCEC标准
@@ -12,6 +19,63 @@
 */
@Slf4j
public class TCECUtil {
    /**
     * 运营商标识
     */
    private static final String OperatorID = "";
    /**
     * 运营商秘钥
     */
    private static final String OperatorSecret = "";
    /**
     * tokne
     */
    private static String token = "";
    /**
     * token过期时间,秒
     */
    private static Long TokenAvailableTime = 0L;
    private static Map<Long, Integer> map = new HashMap<>();
    /**
     * 获取token
     */
    public static void queryToken(){
        HttpRequest post = HttpUtil.createPost("");
        post.contentType("application/json;charset=utf-8");
        JSONObject body = new JSONObject();
        body.put("OperatorID", OperatorID);
        body.put("OperatorSecret", OperatorSecret);
        post.body(body.toJSONString());
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("获取token失败:" + execute.body());
            return;
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer succStat = jsonObject.getInteger("SuccStat");
        if(0 != succStat){
            log.error("获取token失败:" + jsonObject.getString("FailReason"));
            return;
        }
        token = jsonObject.getString("AccessToken");
        TokenAvailableTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) + jsonObject.getLong("TokenAvailableTime");
    }
    /**
     * 获取token
     * @return
     */
    public static String getToken(){
        long second = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
        if(second >= TokenAvailableTime){
            queryToken();
        }
        return token;
    }
    
    
    
@@ -21,8 +85,7 @@
     */
    public static NotificationStationStatusResult notificationStationStatus(ConnectorStatusInfo info) {
        HttpRequest post = HttpUtil.createPost("");
        post.contentType(ContentType.JSON.toString());
        post.body(JSON.toJSONString(info));
        buildBody(post, info);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("设备状态变化推送失败:" + execute.body());
@@ -32,32 +95,32 @@
    }
    
    
    /**
     * 查询统计信息
     * @param query
     * 推送启动充电结果
     * @param info
     * @return
     */
    public QueryStationStatsResult queryStationStats(QueryStationStats query){
    }
    /**
     * 查询业务策略信息
     * @param query
     * @return
     */
    public BaseResult<QueryEquipBusinessPolicyResult> queryEquipBusinessPolicy(QueryEquipBusinessPolicy query){
    public static NotificationStartChargeResult notificationStartChargeResult(NotificationStartCharge info){
        HttpRequest post = HttpUtil.createPost("");
        buildBody(post, info);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("启动充电结果推送失败:" + execute.body());
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer ret = jsonObject.getInteger("Ret");
        if(0 != ret){
            log.error("启动充电结果推送失败:" + execute.body());
            return null;
        }
        return jsonObject.getObject("Data", NotificationStartChargeResult.class);
    }
    
    
    /**
     * 查询充电状态
     * @param query
     * @return
     */
    public BaseResult<QueryEquipChargeStatusResult> queryEquipChargeStatus(QueryEquipChargeStatus query){
    }
    
    
    /**
@@ -65,18 +128,101 @@
     * @param info
     * @return
     */
    public BaseResult<NotificationEquipChargeStatusResult> notificationEquipChargeStatus(QueryEquipChargeStatusResult info){
    public static NotificationEquipChargeStatusResult notificationEquipChargeStatus(QueryEquipChargeStatusResult info){
        HttpRequest post = HttpUtil.createPost("");
        buildBody(post, info);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送充电状态失败:" + execute.body());
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer ret = jsonObject.getInteger("Ret");
        if(0 != ret){
            log.error("推送充电状态失败:" + execute.body());
            return null;
        }
        return jsonObject.getObject("Data", NotificationEquipChargeStatusResult.class);
    }
    
    
    /**
     * 推送充电订单信息
     * @param indo
     * 推送停止充电结果
     * @param info
     * @return
     */
    public BaseResult<NotificationChargeOrderInfoResult> notificationChargeOrderInfo(NotificationChargeOrderInfo indo){
    public static NotificationStopCharge notificationStopChargeResult(NotificationStopChargeResult info){
        HttpRequest post = HttpUtil.createPost("");
        buildBody(post, info);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送停止充电结果失败:" + execute.body());
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer ret = jsonObject.getInteger("Ret");
        if(0 != ret){
            log.error("推送停止充电结果失败:" + execute.body());
            return null;
        }
        return jsonObject.getObject("Data", NotificationStopCharge.class);
    }
    
    
    
    /**
     * 推送充电订单信息
     * @param info
     * @return
     */
    public static NotificationChargeOrderInfoResult notificationChargeOrderInfo(NotificationChargeOrderInfo info){
        HttpRequest post = HttpUtil.createPost("");
        buildBody(post, info);
        HttpResponse execute = post.execute();
        if(200 != execute.getStatus()){
            log.error("推送充电订单信息失败:" + execute.body());
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(execute.body());
        Integer ret = jsonObject.getInteger("Ret");
        if(0 != ret){
            log.error("推送充电订单信息失败:" + execute.body());
            return null;
        }
        return jsonObject.getObject("Data", NotificationChargeOrderInfoResult.class);
    }
    /**
     * 构建请求参数和消息头
     * @param post
     * @param o
     */
    public static void buildBody(HttpRequest post, Object o){
        Long key = Long.valueOf(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
        Integer integer = map.get(key);
        if(null == integer){
            integer = 1;
        }else{
            integer++;
        }
        map.put(key, integer);
        post.contentType("application/json;charset=utf-8");
        post.header("Authorization", "Bearer " + getToken());
        JSONObject body = new JSONObject();
        body.put("OperatorID", OperatorID);
        body.put("Data", AESUtil.encrypt(JSON.toJSONString(o)));
        body.put("TimeStamp", key);
        body.put("Seq", String.format("%04d", integer));
        body.put("Sig", "");
        post.body(body.toJSONString());
        //清空小于当前时间的map中的无效数据
        for (Long k : map.keySet()) {
            if(k <= (key - 10)){
                map.remove(k);
            }
        }
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TokenUtil.java
New file
@@ -0,0 +1,165 @@
package com.ruoyi.integration.drainage;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.exception.auth.NotLoginException;
import com.ruoyi.common.core.utils.JwtUtils;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils;
import com.ruoyi.common.core.utils.uuid.IdUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.other.api.domain.Operator;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.api.model.LoginUserApplet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * token验证处理
 *
 * @author ruoyi
 */
@Component
public class TokenUtil {
    @Autowired
    private RedisService redisService;
    protected static final long MILLIS_SECOND = 1000;
    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
    private final static long expireTime = CacheConstants.EXPIRATION;
    private final static long expireAppletTime = CacheConstants.EXPIRATION_APPLET;
    private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
    private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
    /**
     * 创建令牌
     */
    public Map<String, Object> createToken(Operator operator) {
        String token = IdUtils.fastUUID();
        operator.setToken(token);
        refreshToken(operator);
        // Jwt存储信息
        Map<String, Object> claimsMap = new HashMap<String, Object>();
        claimsMap.put(SecurityConstants.USER_KEY, token);
        claimsMap.put(SecurityConstants.DETAILS_USER_ID, operator.getOperatorId());
        claimsMap.put(SecurityConstants.USER_TYPE, "system");
        claimsMap.put(SecurityConstants.DETAILS_USERNAME, operator.getName());
        // 接口返回信息
        Map<String, Object> rspMap = new HashMap<String, Object>();
        rspMap.put("access_token", JwtUtils.createToken(claimsMap));
        rspMap.put("expires_in", expireTime);
        return rspMap;
    }
    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    public LoginUser getLoginUser() {
        LoginUser loginUser = getLoginUser(ServletUtils.getRequest());
        if (loginUser == null) {
            throw new NotLoginException("令牌已过期,请重新登录!");
        }
        return loginUser;
    }
    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    public LoginUser getLoginUser(HttpServletRequest request) {
        // 获取请求携带的令牌
        String token = SecurityUtils.getToken(request);
        return getLoginUser(token);
    }
    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    public LoginUser getLoginUser(String token) {
        LoginUser user = null;
        try {
            if (StringUtils.isNotEmpty(token)) {
                String userkey = JwtUtils.getUserKey(token);
                user = redisService.getCacheObject(getTokenKey(userkey));
                return user;
            }
        } catch (Exception e) {
        }
        return user;
    }
    /**
     * 设置用户身份信息
     */
    public void setLoginUser(Operator operator) {
        if (StringUtils.isNotNull(operator) && StringUtils.isNotEmpty(operator.getToken())) {
            refreshToken(operator);
        }
    }
    /**
     * 删除用户缓存信息
     */
    public void delLoginUser(String token) {
        if (StringUtils.isNotEmpty(token)) {
            String userkey = JwtUtils.getUserKey(token);
            redisService.deleteObject(getTokenKey(userkey));
        }
    }
    /**
     * 验证令牌有效期,相差不足120分钟,自动刷新缓存
     *
     * @param operator
     */
    public void verifyToken(Operator operator) {
        long expireTime = operator.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
            refreshToken(operator);
        }
    }
    /**
     * 刷新令牌有效期
     *
     * @param operator 登录信息
     */
    public void refreshToken(Operator operator) {
        operator.setLoginTime(System.currentTimeMillis());
        operator.setExpireTime(operator.getLoginTime() + expireTime * MILLIS_MINUTE);
        // 根据uuid将loginUser缓存
        String userKey = getTokenKey(operator.getToken());
        redisService.setCacheObject(userKey, operator, expireTime, TimeUnit.MINUTES);
    }
    public void refreshToken1(LoginUserApplet dto) {
        dto.setLoginTime(System.currentTimeMillis());
        dto.setExpireTime(dto.getLoginTime() + expireAppletTime * MILLIS_MINUTE);
        // 根据uuid将loginUser缓存
        String userKey = getTokenKey(dto.getToken());
        redisService.setCacheObject(userKey, dto, expireAppletTime, TimeUnit.MINUTES);
    }
    private String getTokenKey(String token) {
        return ACCESS_TOKEN + token;
    }
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseModel.java
New file
@@ -0,0 +1,40 @@
package com.ruoyi.integration.drainage.model;
import com.ruoyi.other.api.domain.Operator;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * @author zhibing.pu
 * @Date 2025/1/23 18:33
 */
@Data
public class BaseModel {
    /**
     * 运营商标识
     */
    @NotNull
    private String OperatorID;
    /**
     * 参数内容
     */
    @NotNull
    private String Data;
    /**
     * 时间戳
     * yyyyMMddHHmmss
     */
    @NotNull
    private Long TimeStamp;
    /**
     * 自增序列
     * 4位自增序列取自时间戳,同一秒内按序列自增长,新秒重计。如 0001
     */
    @NotNull
    private String Seq;
    /**
     * 运营商对象
     */
    private Operator operator;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseRequest.java
@@ -10,29 +10,7 @@
 * @Date 2025/1/21 17:08
 */
@Data
public class BaseRequest<T> {
    /**
     * 运营商标识
     */
    @NotNull
    private String OperatorID;
    /**
     * 参数内容
     */
    @NotNull
    private T Data;
    /**
     * 时间戳
     * yyyyMMddHHmmss
     */
    @NotNull
    private Long TimeStamp;
    /**
     * 自增序列
     * 4位自增序列取自时间戳,同一秒内按序列自增长,新秒重计。如 0001
     */
    @NotNull
    private String Seq;
public class BaseRequest extends BaseModel {
    /**
     * 数字签名
     */
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseResult.java
@@ -1,5 +1,6 @@
package com.ruoyi.integration.drainage.model;
import com.ruoyi.other.api.domain.Operator;
import lombok.Data;
import javax.validation.constraints.NotNull;
@@ -10,7 +11,7 @@
 * @Date 2025/1/21 15:54
 */
@Data
public class BaseResult<T> {
public class BaseResult extends BaseModel {
    /**
     * 参数编码
     * -1:系统繁忙,此时请求方稍后重试
@@ -29,13 +30,13 @@
    @NotNull
    private String Msg;
    /**
     * 参数实体
     */
    @NotNull
    private T Data;
    /**
     * 签名
     */
    @NotNull
    private String Sig;
    /**
     * 运营商对象
     */
    private Operator operator;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartCharge.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送启动充电结果
 * @author zhibing.pu
 * @Date 2025/1/22 18:40
 */
@Data
public class NotificationStartCharge {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    private Integer StartChargeSeqStat;
    /**
     * 充电设别接口编码
     */
    @NotNull
    private String ConnectorID;
    /**
     * 充电启动时间
     */
    @NotNull
    private String StartTime;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartChargeResult.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送启动充电结果返回值
 * @author zhibing.pu
 * @Date 2025/1/22 18:47
 */
@Data
public class NotificationStartChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 失败原因
     * 0:无
     * 1:接收失败
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStopChargeResult.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 推送停止充电结果
 * @author zhibing.pu
 * @Date 2025/1/23 9:13
 */
@Data
public class NotificationStopChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    private Integer StartChargeSeqStat;
    /**
     * 充电设备接口编码
     */
    @NotNull
    private String ConnectorID;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备不存在
     * 2:此设备离线
     * 3:此设备已停止充电
     * 4`9:自定义
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuth.java
New file
@@ -0,0 +1,24 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求设备认证
 * @author zhibing.pu
 * @Date 2025/1/22 16:15
 */
@Data
public class QueryEquipAuth {
    /**
     * 设备认证流水
     */
    @NotNull
    private String EquipAuthSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    private String ConnectorID;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuthResult.java
New file
@@ -0,0 +1,40 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求设备认证返回结果
 * @author zhibing.pu
 * @Date 2025/1/22 16:16
 */
@Data
public class QueryEquipAuthResult {
    /**
     * 设备认证流水号
     */
    @NotNull
    private String EquipAuthSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    private String ConnectorID;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备尚未插枪
     * 2:设备检测失败
     * 3·99:自定义
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java
New file
@@ -0,0 +1,40 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * 请求启动充电
 * @author zhibing.pu
 * @Date 2025/1/22 16:59
 */
@Data
public class QueryStartCharge {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 充电设备接口编码
     */
    @NotNull
    private String ConnectorID;
    /**
     * 二维码其他信息
     */
    @NotNull
    private String QRCode;
    /**
     * 支付方式(1=微信,2=支付宝)
     */
    @NotNull
    private Integer paymentType;
    /**
     * 充电余额
     */
    @NotNull
    private BigDecimal paymentAmount;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java
New file
@@ -0,0 +1,50 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求启动充电返回结果
 * @author zhibing.pu
 * @Date 2025/1/22 17:02
 */
@Data
public class QueryStartChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    private Integer StartChargeSeqStat;
    /**
     * 充电设别接口编码
     */
    @NotNull
    private String ConnectorID;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备不存在
     * 2:此设备离线
     * 3`9:自定义
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationStats.java
@@ -12,6 +12,11 @@
@Data
public class QueryStationStats {
    /**
     * 运营商ID
     */
    @NotNull
    private String OperatorID;
    /**
     * 充电站ID
     */
    @NotNull
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStopChargeResult.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 请求停止充电返回结果
 * @author zhibing.pu
 * @Date 2025/1/22 19:58
 */
@Data
public class QueryStopChargeResult {
    /**
     * 充电订单号
     */
    @NotNull
    private String StartChargeSeq;
    /**
     * 充电订单状态
     * 1:启动中
     * 2:充电中
     * 3:停止中
     * 4:已结束
     * 5:未知
     */
    @NotNull
    private Integer StartChargeSeqStat;
    /**
     * 操作结果
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 失败原因
     * 0:无
     * 1:此设备不存在
     * 2:此设备离线
     * 3:此设备已停止充电
     * 4`9:自定义
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryToken.java
New file
@@ -0,0 +1,24 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 获取token
 * @author zhibing.pu
 * @Date 2025/1/23 17:13
 */
@Data
public class QueryToken {
    /**
     * 运营商标识
     */
    @NotNull
    private String OperatorID;
    /**
     * 运营商秘钥
     */
    @NotNull
    private String OperatorSecret;
}
ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryTokenResult.java
New file
@@ -0,0 +1,45 @@
package com.ruoyi.integration.drainage.model;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
 * 获取token返回结果
 * @author zhibing.pu
 * @Date 2025/1/23 17:15
 */
@Data
public class QueryTokenResult {
    /**
     * 运营商标识
     */
    @NotNull
    private String OperatorID;
    /**
     * 成功状态
     * 0:成功
     * 1:失败
     */
    @NotNull
    private Integer SuccStat;
    /**
     * 获取的凭证
     */
    @NotNull
    private String AccessToken;
    /**
     * 凭证有效期,秒
     */
    @NotNull
    private Long TokenAvailableTime;
    /**
     * 失败原因
     * 0:无
     * 1:无此运营商
     * 2:秘钥错误
     * 3`9自定义
     */
    @NotNull
    private Integer FailReason;
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderAccountingStrategyController.java
@@ -1,7 +1,9 @@
package com.ruoyi.order.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.order.api.model.TChargingOrderAccountingStrategy;
import com.ruoyi.order.service.TChargingOrderAccountingStrategyService;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.*;
@@ -52,5 +54,18 @@
        List<Double> list = chargingOrderAccountingStrategyService.getDailyChargingDegree(days, siteIds);
        return R.ok(list);
    }
    /**
     * 根据订单id查询充电明细
     * @param chargingOrderId
     * @return
     */
    @PostMapping("/getChargingOrderAccountingStrategyByOrderId")
    public R<List<TChargingOrderAccountingStrategy>> getChargingOrderAccountingStrategyByOrderId(@RequestParam("chargingOrderId") Long chargingOrderId){
        List<TChargingOrderAccountingStrategy> list = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>().eq(TChargingOrderAccountingStrategy::getChargingOrderId, chargingOrderId));
        return R.ok(list);
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java
@@ -20,6 +20,7 @@
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.dto.ChargingOrderGroup;
import com.ruoyi.common.core.dto.ChargingPercentProvinceDto;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.BasePojo;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.annotation.Logical;
@@ -605,6 +606,27 @@
        List<ChargingOrderGroup> groups = chargingOrderService.chargingOrderGroup(chargingPercentProvinceDto);
        return R.ok(groups);
    }
    /**
     * 根据站点id和时间区间查询订单数据
     * @param chargingPercentProvinceDto
     * @return
     */
    @PostMapping(value = "/getOrderBySiteIdAndTime")
    public R<List<TChargingOrder>> getOrderBySiteIdAndTime(@RequestBody ChargingPercentProvinceDto chargingPercentProvinceDto){
        LocalDate date1 = chargingPercentProvinceDto.getDate1();
        LocalDate date2 = chargingPercentProvinceDto.getDate2();
        String tripartitePlatformName = chargingPercentProvinceDto.getTripartitePlatformName();
        List<TChargingOrder> list = chargingOrderService.list(new LambdaQueryWrapper<TChargingOrder>().in(TChargingOrder::getSiteId, chargingPercentProvinceDto.getSiteIds())
                .between(null != date1 && null != date2, TChargingOrder::getPayTime, date1.atTime(0, 0, 0), date2.atTime(23, 59, 59))
                .eq(TChargingOrder::getDelFlag, 0).eq(TChargingOrder::getStatus, 5)
                .eq(StringUtils.isNotEmpty(tripartitePlatformName), TChargingOrder::getOrderSource, 2)
                .eq(StringUtils.isNotEmpty(tripartitePlatformName), TChargingOrder::getTripartitePlatformName, tripartitePlatformName));
        return R.ok(list);
    }
    /**
     * 根据充电枪id获取正在进行中的订单
@@ -1988,51 +2010,7 @@
        List<Integer> gunIds = list.stream().map(TChargingOrder::getChargingGunId).collect(Collectors.toList());
        return R.ok(gunIds);
    }
    private static List<TChargingOrder> getSampleData() {
        // 这里可以替换为实际查询逻辑
        List<TChargingOrder> list = new ArrayList<>();
        // 示例数据
        for (int i = 0; i < 24; i++) {
            TChargingOrder order = new TChargingOrder();
            order.setStartTime(LocalDateTime.now().minusHours(23 - i));
            order.setOrderAmount(BigDecimal.valueOf(i + 1));
            list.add(order);
        }
        return list;
    }
    private static List<Map<String, BigDecimal>> processData(List<TChargingOrder> list) {
        Map<LocalDateTime, BigDecimal> hourlySum = new HashMap<>();
        // 按每个小时分组并求和
        for (TChargingOrder order : list) {
            LocalDateTime hour = order.getStartTime().truncatedTo(ChronoUnit.HOURS);
            BigDecimal amount = order.getOrderAmount();
            hourlySum.merge(hour, amount, BigDecimal::add);
        }
        // 创建结果列表
        List<Map<String, BigDecimal>> resultList = new ArrayList<>();
        for (int i = 1; i <= 23; i++) {
            LocalDateTime keyHour = LocalDateTime.now().withHour(i);
            BigDecimal sum = BigDecimal.ZERO;
            // 计算键之后的一小时的数据之和
            for (int j = i + 1; j <= 23; j++) {
                LocalDateTime nextHour = LocalDateTime.now().withHour(j);
                sum = sum.add(hourlySum.getOrDefault(nextHour, BigDecimal.ZERO));
            }
            Map<String, BigDecimal> entry = new HashMap<>();
            entry.put(String.valueOf(i), sum);
            resultList.add(entry);
        }
        return resultList;
    }
    /**
@@ -2116,4 +2094,42 @@
        return R.ok(list);
    }
    
    /**
     * 添加三方平台充电订单数据
     * @return
     */
    @PostMapping("/addTripartitePlatformOrder")
    public R addTripartitePlatformOrder(@RequestBody AddTripartitePlatformOrder query){
        return chargingOrderService.addTripartitePlatformOrder(query.getChargingGunId(), query.getOperatorId(),
                query.getRechargePaymentType(),
                query.getPaymentAmount(),
                query.getStartChargeSeq());
    }
    /**
     * 根据三方平台订单id获取充电数据
     * @param startChargeSeq
     * @return
     */
    @PostMapping("/getChargingOrderByStartChargeSeq")
    public R<TChargingOrder> getChargingOrderByStartChargeSeq(@RequestParam("startChargeSeq") String startChargeSeq){
        TChargingOrder chargingOrder = chargingOrderService.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getStartChargeSeq, startChargeSeq));
        return R.ok(chargingOrder);
    }
    /**
     * 三方平台请求停止充电
     * @param startChargeSeq
     * @return
     */
    @PostMapping("/tripartitePlatformStopCharge")
    public R tripartitePlatformStopCharge(@RequestParam("startChargeSeq") String startChargeSeq){
        return chargingOrderService.tripartitePlatformStopCharge(startChargeSeq);
    }
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java
@@ -19,7 +19,9 @@
import com.ruoyi.order.vo.ChargingOrderListInfoVO;
import com.ruoyi.order.vo.EndOfChargePageInfo;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
@@ -286,4 +288,19 @@
    List<TChargingOrder> getChargingOrder(TChargingOrderVo order);
    Long countCar(List<String> brands);
    /**
     * 添加三方平台充电订单数据
     * @param chargingGunId
     */
    R addTripartitePlatformOrder(Integer chargingGunId, String operatorId, Integer rechargePaymentType, BigDecimal paymentAmount, String startChargeSeq);
    /**
     * 三方平台停止充电操作
     * @param startChargeSeq
     * @return
     */
    R tripartitePlatformStopCharge(@RequestParam("startChargeSeq") String startChargeSeq);
}
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -202,6 +202,9 @@
    
    //计数器
    private Map<String, Integer> boot_failed_map = new HashMap<>();
    @Resource
    private OperatorClient operatorClient;
@@ -465,7 +468,7 @@
        chargingOrder.setRechargeAmount(addChargingOrder.getPaymentAmount());
        chargingOrder.setAppCouponId(addChargingOrder.getAppUserCouponId());
        chargingOrder.setVipDiscountAmount(BigDecimal.ZERO);
        chargingOrder.setOrderSource(0);
        chargingOrder.setOrderSource(1);
        chargingOrder.setTitle("【充电桩充电】" + chargingPile.getNumber() + "号桩/" + tChargingGun.getCode() + "号枪");
        
        Site site = siteClient.getSiteByIds(Arrays.asList(tChargingGun.getSiteId())).getData().get(0);
@@ -845,7 +848,7 @@
    public void refund(String code){
        log.info(code + ":-------------------充电启动失败,执行退款-------------------");
        TChargingOrder chargingOrder = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getCode, code));
        if(chargingOrder.getStatus() == 2){
        if(chargingOrder.getOrderSource() == 1 && chargingOrder.getStatus() == 2){
            Integer rechargePaymentType = chargingOrder.getRechargePaymentType();
            BigDecimal rechargeAmount = chargingOrder.getRechargeAmount();
            //构建退款明细
@@ -3974,4 +3977,144 @@
    public Long countCar(List<String> brands) {
        return this.baseMapper.countCar(brands);
    }
    /**
     * 添加三方平台充电订单数据
     * @param chargingGunId
     */
    @Override
    public R addTripartitePlatformOrder(Integer chargingGunId, String operatorId, Integer rechargePaymentType, BigDecimal paymentAmount, String startChargeSeq) {
        //检查当前枪是否是正在使用中
        TChargingOrder one = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getChargingGunId, chargingGunId)
                .in(TChargingOrder::getStatus, Arrays.asList(1, 2, 3)).eq(TChargingOrder::getDelFlag, 0));
        if(null != one){
            return R.fail("充电枪正在充电中,启动失败");
        }
        //构建新的待支付订单
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        TChargingOrder chargingOrder = new TChargingOrder();
        String code = "CD" + Double.valueOf(Math.random() * 1000).intValue() + sdf.format(new Date());
        chargingOrder.setCode(code);
        chargingOrder.setOrderType(1);
        chargingOrder.setOrderClassification(1);
        TChargingGun tChargingGun = chargingGunClient.getChargingGunById(chargingGunId).getData();
        TChargingPile chargingPile = chargingPileClient.getChargingPileById(tChargingGun.getChargingPileId()).getData();
        chargingOrder.setSiteId(tChargingGun.getSiteId());
        chargingOrder.setChargingPileId(tChargingGun.getChargingPileId());
        chargingOrder.setChargingGunId(chargingGunId);
        chargingOrder.setRechargePaymentType(rechargePaymentType);
        chargingOrder.setRechargePaymentStatus(2);
        chargingOrder.setRechargeAmount(paymentAmount);
        chargingOrder.setVipDiscountAmount(BigDecimal.ZERO);
        chargingOrder.setOrderSource(2);
        Operator operator = operatorClient.getOperator(operatorId).getData();
        chargingOrder.setOperatorId(operator.getId());
        chargingOrder.setAppUserId(operator.getId().longValue());
        chargingOrder.setTripartitePlatformName(operator.getName());
        chargingOrder.setStartChargeSeq(startChargeSeq);
        chargingOrder.setTitle("【充电桩充电】" + chargingPile.getNumber() + "号桩/" + tChargingGun.getCode() + "号枪");
        chargingOrder.setStatus(2);
        chargingOrder.setPayTime(LocalDateTime.now());
        chargingOrder.setChargeAmount(chargingOrder.getRechargeAmount());
        chargingOrder.setVipDiscountAmount(BigDecimal.ZERO);
        this.save(chargingOrder);
        Integer accountingStrategyId = tChargingGun.getAccountingStrategyId();
        if(null == accountingStrategyId){
            Site site = siteClient.getSiteByIds(Arrays.asList(tChargingGun.getSiteId())).getData().get(0);
            //查询站点上面的计费策略
            accountingStrategyId = site.getAccountingStrategyId();
        }
        TAccountingStrategy accountingStrategy = accountingStrategyClient.getAccountingStrategyById(accountingStrategyId).getData();
        //添加订单的计费策略
        List<TAccountingStrategyDetail> strategyDetailList = accountingStrategyDetailClient.getListByAccountingStrategyId(accountingStrategyId).getData();
        AccountingStrategyOrder accountingStrategyOrder = new AccountingStrategyOrder();
        BeanUtils.copyProperties(accountingStrategy, accountingStrategyOrder);
        accountingStrategyOrder.setChargingOrderId(chargingOrder.getId());
        accountingStrategyOrderService.save(accountingStrategyOrder);
        List<AccountingStrategyDetailOrder> list1 = new ArrayList<>();
        for (TAccountingStrategyDetail tAccountingStrategyDetail : strategyDetailList) {
            AccountingStrategyDetailOrder accountingStrategyDetailOrder = new AccountingStrategyDetailOrder();
            BeanUtils.copyProperties(tAccountingStrategyDetail, accountingStrategyDetailOrder);
            accountingStrategyDetailOrder.setChargingOrderId(chargingOrder.getId());
            list1.add(accountingStrategyDetailOrder);
        }
        accountingStrategyDetailOrderService.saveBatch(list1);
        //添加安全检测数据到缓存中,每步安全检测完成后需要更新缓存数据
        PreChargeCheck preChargeCheck = new PreChargeCheck();
        preChargeCheck.setElectronicLockLock(false);
        preChargeCheck.setInsulationTesting(false);
        preChargeCheck.setSecureConnectionDetection(false);
        preChargeCheck.setStartupSuccess(1);
        String key = "AQJC_" + chargingOrder.getChargingGunId();
        redisService.setCacheObject(key, preChargeCheck, 24L, TimeUnit.HOURS);
        BigDecimal rechargeAmount = chargingOrder.getRechargeAmount();
        //调用远程启动充电消息
        PlatformStartCharging platformStartCharging = new PlatformStartCharging();
        platformStartCharging.setTransaction_serial_number(chargingOrder.getCode());
        platformStartCharging.setCharging_pile_code(chargingPile.getCode());
        platformStartCharging.setCharging_gun_code(tChargingGun.getCode());
        //使用订单id作为逻辑卡号
        platformStartCharging.setCard_number(chargingOrder.getId().toString());
        platformStartCharging.setAccount_balance(rechargeAmount);
        log.info(chargingOrder.getCode() + ":-------------------远程调起开始充电请求-------------------" + platformStartCharging.toString());
        sendMessageClient.platformStartCharging(platformStartCharging);
        //异步线程检测远程启动的应答结果。如果失败,则需要全额退款
        Long id = chargingOrder.getId();
        //执行5分钟的定时任务检测
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(()->{
            if(timingDetection(id)){
                scheduler.shutdown();
            }
        }, 5, 1, TimeUnit.SECONDS);
        return R.ok();
    }
    /**
     * 三方平台停止充电操作
     * @param startChargeSeq
     * @return
     */
    @Override
    public R tripartitePlatformStopCharge(String startChargeSeq) {
        TChargingOrder order = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getStartChargeSeq, startChargeSeq));
        Integer status = order.getStatus();
        if(status != 3){
            return R.fail("还未开始充电");
        }
        if(status == 4 || status == 5){
            return R.fail("不能重复操作");
        }
        TChargingOrder chargingOrder = new TChargingOrder();
        chargingOrder.setId(order.getId());
        chargingOrder.setAppUserId(order.getOperatorId().longValue());
        chargingOrder.setEndTime(LocalDateTime.now());
        chargingOrder.setStatus(4);
        chargingOrder.setEndMode(1);
        this.updateById(chargingOrder);
        String code1 = order.getCode();
        TChargingGun chargingGun = chargingGunClient.getChargingGunById(order.getChargingGunId()).getData();
        //异步线程处理停机
        ExecutorService cachedThreadPool = Executors.newFixedThreadPool(1);
        cachedThreadPool.execute(()->{
            //调用硬件停止充电,停止成功后开始计算费用退款
            TChargingPile chargingPile = chargingPileClient.getChargingPileById(order.getChargingPileId()).getData();
            PlatformStopCharging platformStopCharging = new PlatformStopCharging();
            platformStopCharging.setCharging_pile_code(chargingPile.getCode());
            platformStopCharging.setCharging_gun_code(chargingGun.getCode());
            sendMessageClient.platformStopCharging(platformStopCharging);
            log.info(code1 + ":-------------------远程停止充电请求-------------------");
            log.info(platformStopCharging.toString());
        });
        return R.ok();
    }
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java
New file
@@ -0,0 +1,36 @@
package com.ruoyi.other.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.other.api.domain.Operator;
import com.ruoyi.other.service.OperatorService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * @author zhibing.pu
 * @Date 2025/1/22 15:12
 */
@RestController
@RequestMapping("/operator")
public class OperatorController {
    @Resource
    private OperatorService operatorService;
    /**
     * 获取运营商数据
     * @param operatorId
     * @return
     */
    @PostMapping("/getOperator")
    public R<Operator> getOperator(@RequestParam("operatorId") String operatorId){
        Operator operator = operatorService.getOne(new LambdaQueryWrapper<Operator>().eq(Operator::getOperatorId, operatorId));
        return R.ok(operator);
    }
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/OperatorMapper.java
New file
@@ -0,0 +1,11 @@
package com.ruoyi.other.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.other.api.domain.Operator;
/**
 * @author zhibing.pu
 * @Date 2025/1/22 15:08
 */
public interface OperatorMapper extends BaseMapper<Operator> {
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/OperatorService.java
New file
@@ -0,0 +1,11 @@
package com.ruoyi.other.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.other.api.domain.Operator;
/**
 * @author zhibing.pu
 * @Date 2025/1/22 15:09
 */
public interface OperatorService extends IService<Operator> {
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/OperatorServiceImpl.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.other.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.other.api.domain.Operator;
import com.ruoyi.other.mapper.OperatorMapper;
import com.ruoyi.other.service.OperatorService;
import org.springframework.stereotype.Service;
/**
 * @author zhibing.pu
 * @Date 2025/1/22 15:09
 */
@Service
public class OperatorServiceImpl extends ServiceImpl<OperatorMapper, Operator> implements OperatorService {
}