From 792cbb986fb8c32f6bbc1638c4ae264372e7a28f Mon Sep 17 00:00:00 2001 From: Pu Zhibing <393733352@qq.com> Date: 星期四, 23 一月 2025 19:31:36 +0800 Subject: [PATCH] 新增引流接口及业务逻辑 --- ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 147 ++ ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/SiteFallbackFactory.java | 6 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStopChargeResult.java | 47 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/QueryStopCharge.java | 24 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/SignUtil.java | 208 +++ ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java | 1155 ++++++++++++++++++++ ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseModel.java | 40 ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingGunController.java | 16 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartCharge.java | 39 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuth.java | 24 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/OperatorService.java | 11 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/OperatorServiceImpl.java | 15 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryToken.java | 24 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartChargeResult.java | 33 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderAccountingStrategyFallbackFactory.java | 6 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseResult.java | 13 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationStats.java | 5 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java | 17 ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ChargingGunFallbackFactory.java | 5 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java | 40 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/OperatorMapper.java | 11 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java | 50 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TChargingOrder.java | 11 ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyDetailController.java | 3 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/OrderClient.java | 34 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java | 25 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/dto/ChargingPercentProvinceDto.java | 9 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java | 106 + ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/NotificationStopCharge.java | 33 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseRequest.java | 24 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryTokenResult.java | 45 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderAccountingStrategyController.java | 15 ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports | 3 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/StartChargeResult.java | 39 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/Operator.java | 67 + ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java | 198 +++ ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java | 36 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TokenUtil.java | 165 ++ ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java | 24 /dev/null | 259 ---- ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingGunClient.java | 10 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderAccountingStrategyClient.java | 10 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java | 33 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OperatorClient.java | 29 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java | 40 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/AESUtil.java | 107 + ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuthResult.java | 40 ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStopChargeResult.java | 51 48 files changed, 2,973 insertions(+), 379 deletions(-) diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ChargingGunFallbackFactory.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ChargingGunFallbackFactory.java index 4da7d9e..384df0f 100644 --- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/ChargingGunFallbackFactory.java +++ b/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()); } diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/SiteFallbackFactory.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/SiteFallbackFactory.java index d33b267..241b97c 100644 --- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/factory/SiteFallbackFactory.java +++ b/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; + } }; } } diff --git a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingGunClient.java b/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingGunClient.java index 6370e8b..bb7bc35 100644 --- a/ruoyi-api/ruoyi-api-chargingPile/src/main/java/com/ruoyi/chargingPile/api/feignClient/ChargingGunClient.java +++ b/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 diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderAccountingStrategyFallbackFactory.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderAccountingStrategyFallbackFactory.java index 7af99c0..a5a173c 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderAccountingStrategyFallbackFactory.java +++ b/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()); + } }; } } diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java index 0062651..23c64cf 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/factory/ChargingOrderFallbackFactory.java +++ b/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()); + } }; } } diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderAccountingStrategyClient.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderAccountingStrategyClient.java index 2f98b2c..43607fb 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderAccountingStrategyClient.java +++ b/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); } diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java index e54666c..ffd6ad3 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/ChargingOrderClient.java +++ b/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); } diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/OrderClient.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/OrderClient.java index 50ce67e..80bb36e 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/feignClient/OrderClient.java +++ b/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); diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java new file mode 100644 index 0000000..fc54026 --- /dev/null +++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/AddTripartitePlatformOrder.java @@ -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; +} diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/StartChargeResult.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/StartChargeResult.java new file mode 100644 index 0000000..6e09c38 --- /dev/null +++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/StartChargeResult.java @@ -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; +} diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TChargingOrder.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TChargingOrder.java index 2562032..ef2e441 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TChargingOrder.java +++ b/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") diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/Operator.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/Operator.java new file mode 100644 index 0000000..895cc2b --- /dev/null +++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/Operator.java @@ -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; +} diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java new file mode 100644 index 0000000..d223fba --- /dev/null +++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/OperatorFallbackFactory.java @@ -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()); + } + }; + } +} diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OperatorClient.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OperatorClient.java new file mode 100644 index 0000000..8dcbee4 --- /dev/null +++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/OperatorClient.java @@ -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); + + +} diff --git a/ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 1d2b67a..9d2a866 100644 --- a/ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/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 \ No newline at end of file +com.ruoyi.other.api.factory.UserTagFallbackFactory +com.ruoyi.other.api.factory.OperatorFallbackFactory \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/dto/ChargingPercentProvinceDto.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/dto/ChargingPercentProvinceDto.java index 1f8e948..40cd4a7 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/dto/ChargingPercentProvinceDto.java +++ b/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; } diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyDetailController.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyDetailController.java index 9d81853..cb640f7 100644 --- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TAccountingStrategyDetailController.java +++ b/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); } diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingGunController.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingGunController.java index db5974b..961ab8a 100644 --- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/TChargingGunController.java +++ b/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); } } diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/controller/TCECController.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/controller/TCECController.java deleted file mode 100644 index 2f8cfaa..0000000 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/controller/TCECController.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.ruoyi.integration.controller; - -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.TChargingGun; -import com.ruoyi.chargingPile.api.model.TChargingPile; -import com.ruoyi.common.core.domain.R; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.core.web.page.PageInfo; -import com.ruoyi.integration.drainage.TCECUtil; -import com.ruoyi.integration.drainage.model.*; -import com.ruoyi.integration.drainage.model.enu.*; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * @author zhibing.pu - * @Date 2025/1/21 17:52 - */ -@RestController -@RequestMapping("") -public class TCECController { - - @Resource - private SiteClient siteClient; - - @Resource - private ChargingPileClient chargingPileClient; - - @Resource - private ChargingGunClient chargingGunClient; - - - /** - * 查询充电站信息 - * @param query - * @return - */ - @PostMapping("/query_stations_info") - public QueryStationsInfoResult queryStationsInfo(@RequestBody QueryStationsInfo query){ - Integer pageNo = query.getPageNo(); - Integer pageSize = query.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()); - - List<StationInfo> StationInfos = new ArrayList<>(); - for (Site datum : siteListPaging.getRecords()) { - StationInfo stationInfo = new StationInfo(); - stationInfo.setStationID(datum.getId().toString()); - stationInfo.setOperatorID(); - stationInfo.setEquipmentOwnerID(); - 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()); - //构建充电设备信息数据 - List<TChargingPile> tChargingPiles = chargingPileClient.getChargingPileBySiteId(datum.getId()).getData(); - stationInfo.setEquipmentInfos(buildEquipmentInfo(tChargingPiles)); - StationInfos.add(stationInfo); - } - queryStationsInfoResult.setStationInfos(StationInfos); - return queryStationsInfoResult; - } - - - /** - * 构建桩数据 - * @param tChargingPiles - * @return - */ - public List<EquipmentInfo> buildEquipmentInfo(List<TChargingPile> tChargingPiles){ - List<EquipmentInfo> equipmentInfos = new ArrayList<>(); - for (TChargingPile tChargingPile : tChargingPiles) { - 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; - } - - //构建设备接口信息 - List<TChargingGun> chargingGunList = chargingGunClient.getChargingGunByChargingPileId(tChargingPile.getId()).getData(); - equipmentInfo.setConnectorInfos(buildConnectorInfos(chargingGunList)); - equipmentInfos.add(equipmentInfo); - } - return equipmentInfos; - } - - - /** - * 构建接口数据 - * @param chargingGunList - * @return - */ - public List<ConnectorInfo> buildConnectorInfos(List<TChargingGun> chargingGunList){ - List<ConnectorInfo> connectorInfos = new ArrayList<>(); - for (TChargingGun chargingGun : chargingGunList) { - 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(); - } - - - - /** - * 设备接口状态查询 - * @param query - * @return - */ - @PostMapping("/query_station_status") - public QueryStationStatusResult queryStationStatus(@RequestBody QueryStationStatus query){ - - } -} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/AESUtil.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/AESUtil.java new file mode 100644 index 0000000..b8e4433 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/AESUtil.java @@ -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); + } +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/NotificationStopCharge.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/NotificationStopCharge.java new file mode 100644 index 0000000..a1e4a99 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/NotificationStopCharge.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/QueryStopCharge.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/QueryStopCharge.java new file mode 100644 index 0000000..49bea78 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/QueryStopCharge.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/SignUtil.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/SignUtil.java new file mode 100644 index 0000000..d3d43e9 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/SignUtil.java @@ -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)); + } +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java new file mode 100644 index 0000000..3aa324b --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECController.java @@ -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; + } +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java index 428a49e..0cadb76 100644 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TCECUtil.java +++ b/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); + } + } + } } diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TokenUtil.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TokenUtil.java new file mode 100644 index 0000000..5bc9ab1 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/TokenUtil.java @@ -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; + } +} \ No newline at end of file diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseModel.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseModel.java new file mode 100644 index 0000000..e8b5882 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseModel.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseRequest.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseRequest.java index d2a11da..e5cec9e 100644 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseRequest.java +++ b/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 { /** * 数字签名 */ diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseResult.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseResult.java index 0a94794..be66fd5 100644 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/BaseResult.java +++ b/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; } diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartCharge.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartCharge.java new file mode 100644 index 0000000..226069a --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartCharge.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartChargeResult.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartChargeResult.java new file mode 100644 index 0000000..3bde406 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStartChargeResult.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStopChargeResult.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStopChargeResult.java new file mode 100644 index 0000000..1a6802c --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/NotificationStopChargeResult.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuth.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuth.java new file mode 100644 index 0000000..46f0aa5 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuth.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuthResult.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuthResult.java new file mode 100644 index 0000000..98d57f6 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryEquipAuthResult.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java new file mode 100644 index 0000000..358f366 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartCharge.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java new file mode 100644 index 0000000..2cf489c --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStartChargeResult.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationStats.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationStats.java index fd22d00..8d1928e 100644 --- a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStationStats.java +++ b/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 diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStopChargeResult.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStopChargeResult.java new file mode 100644 index 0000000..041bb6e --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryStopChargeResult.java @@ -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; + +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryToken.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryToken.java new file mode 100644 index 0000000..f901d65 --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryToken.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryTokenResult.java b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryTokenResult.java new file mode 100644 index 0000000..4a9c4ae --- /dev/null +++ b/ruoyi-service/ruoyi-integration/src/main/java/com/ruoyi/integration/drainage/model/QueryTokenResult.java @@ -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; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderAccountingStrategyController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderAccountingStrategyController.java index b24aa02..11d0ca0 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderAccountingStrategyController.java +++ b/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); + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java index 131e1fe..2b730f5 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java +++ b/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); + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java index 097546f..175381f 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java +++ b/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); } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java index 1b60d48..d30ab60 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java +++ b/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(); + } } diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java new file mode 100644 index 0000000..a23961c --- /dev/null +++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/OperatorController.java @@ -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); + } +} diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/OperatorMapper.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/OperatorMapper.java new file mode 100644 index 0000000..70b8a21 --- /dev/null +++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/OperatorMapper.java @@ -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> { +} diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/OperatorService.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/OperatorService.java new file mode 100644 index 0000000..62cc953 --- /dev/null +++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/OperatorService.java @@ -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> { +} diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/OperatorServiceImpl.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/OperatorServiceImpl.java new file mode 100644 index 0000000..daae44b --- /dev/null +++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/OperatorServiceImpl.java @@ -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 { +} -- Gitblit v1.7.1