|
|
@@ -1,7 +1,26 @@
|
|
|
package com.kym.service.miniapp.impl;
|
|
|
|
|
|
+import cn.dev33.satoken.stp.StpUtil;
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
+import com.kym.common.constant.ResponseEnum;
|
|
|
+import com.kym.common.enums.EnPlusApi;
|
|
|
+import com.kym.common.exception.BusinessException;
|
|
|
+import com.kym.common.utils.AESUtil;
|
|
|
+import com.kym.common.utils.IDGenerator;
|
|
|
+import com.kym.entity.miniapp.ChargeOrder;
|
|
|
+import com.kym.service.admin.EquipmentInfoService;
|
|
|
+import com.kym.service.admin.EquipmentRelationService;
|
|
|
+import com.kym.service.enplus.EnPlusService;
|
|
|
+import com.kym.service.miniapp.AccountService;
|
|
|
+import com.kym.service.miniapp.ChargeOrderService;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+
|
|
|
/**
|
|
|
* @author skyline
|
|
|
* @description 充电
|
|
|
@@ -9,7 +28,128 @@ import org.springframework.stereotype.Service;
|
|
|
*/
|
|
|
@Service
|
|
|
public class ChargeServiceImpl {
|
|
|
+ private static final Logger LOGGER = LoggerFactory.getLogger(ChargeServiceImpl.class);
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IDGenerator idGenerator;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EquipmentRelationService equipmentRelationService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ChargeOrderService chargeOrderService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private AccountService accountService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EquipmentInfoService equipmentInfoService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private EnPlusService enPlusService;
|
|
|
+
|
|
|
+ @Value("${en-plus.operator-id}")
|
|
|
+ private String operatorId;
|
|
|
+
|
|
|
+ String startCharge(String connectorId) {
|
|
|
+ var userId = StpUtil.getSession().getLong("userId");
|
|
|
+ if (connectorId.length() == 6) {
|
|
|
+ // 查询EN+设备SN
|
|
|
+ var equipmentRelation = equipmentRelationService.getByShortId(connectorId);
|
|
|
+ var equipmentId = equipmentRelation.getEquipmentId();
|
|
|
+ if (equipmentId.length() == 16) {
|
|
|
+ // 如果是16位,末尾补1作为单枪枪号
|
|
|
+ equipmentId = equipmentId.concat("1");
|
|
|
+ }
|
|
|
+ // 二维码文本
|
|
|
+ var qrCode = "";
|
|
|
+ // 当前设备是是否有正在进行中的订单
|
|
|
+ var chargeOrder = chargeOrderService.getChargingOrderByUserId(userId);
|
|
|
+ if (chargeOrder == null) {
|
|
|
+ LOGGER.error("用户:{}存在进行中的订单:{}", userId, chargeOrder.getId());
|
|
|
+ throw new BusinessException(ResponseEnum.ORDER_IN_PROGRESS);
|
|
|
+ }
|
|
|
+ // 查询用户余额
|
|
|
+ var account = accountService.getAccountByUserId(userId);
|
|
|
+ if (account.getBalance().compareTo(BigDecimal.valueOf(2L)) != 1) {
|
|
|
+ LOGGER.error("用户:{}余额不足2元,余额:{}", userId, account.getBalance());
|
|
|
+ throw new BusinessException(ResponseEnum.INSUFFICIENT_USER_BALANCE);
|
|
|
+ }
|
|
|
+ // 传递给EN+的余额要小于实际余额,防止订单超扣的情况,这里少传0.5元
|
|
|
+ var amount = account.getBalance().subtract(BigDecimal.valueOf(0.5));
|
|
|
+
|
|
|
+ // 充电订单号/设备认证号
|
|
|
+ String startChargeSeq = operatorId.substring(0, 8).concat(String.valueOf(idGenerator.nextId()));
|
|
|
+
|
|
|
+ // 请求设备认证
|
|
|
+ var equipAuth = equipmentInfoService.queryEquipAuth(connectorId, startChargeSeq);
|
|
|
+
|
|
|
+ if (equipAuth.containsKey("SuccStat") && equipAuth.getIntValue("SuccStat") == 0) {
|
|
|
+ // TODO 查询业务策略信息(计费信息),目前计费在EN+完成,后续自主计费需要开发
|
|
|
+ // 启动充电
|
|
|
+ var startCharge = queryStartCharge(startChargeSeq, connectorId, qrCode, amount);
|
|
|
+ if (startCharge.containsKey("SuccStat") && startCharge.getIntValue("SuccStat") == 0) {
|
|
|
+ // 启动成功,生成充电订单
|
|
|
+ var order = new ChargeOrder();
|
|
|
+ order.setUserId(userId);
|
|
|
+ order.setStationId(equipmentRelation.getStationId());
|
|
|
+ order.setStartChargeSeq(startChargeSeq);
|
|
|
+ order.setConnectorId(connectorId);
|
|
|
+ order.setChargeStatus(startCharge.getIntValue("StartChargeSeqStat"));
|
|
|
+ chargeOrderService.save(order);
|
|
|
+ // TODO: 2023-08-07 包装成自己的数据
|
|
|
+ return startChargeSeq;
|
|
|
+ } else {
|
|
|
+ // 启动充电失败
|
|
|
+ LOGGER.error("设备启动充电失败:{}", startCharge);
|
|
|
+ switch (equipAuth.getIntValue("FailReason")) {
|
|
|
+ case 1 -> // 设备不存在
|
|
|
+ throw new BusinessException(ResponseEnum.EN_PLUS_EQUIP_NOT_EXIST);
|
|
|
+ case 2 -> // 设备离线
|
|
|
+ throw new BusinessException(ResponseEnum.EN_PLUS_EQUIP_OFFLINE);
|
|
|
+ }
|
|
|
+ throw new BusinessException(ResponseEnum.EN_PLUS_EQUIP_START_FAIL);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 设备认证失败
|
|
|
+ LOGGER.error("设备认证失败:{}", equipAuth);
|
|
|
+ switch (equipAuth.getIntValue("FailReason")) {
|
|
|
+ case 1 -> // 设备未插枪
|
|
|
+ throw new BusinessException(ResponseEnum.EN_PLUS_EQUIP_NOT_CONNECTED);
|
|
|
+ case 2 -> // 设备检测失败
|
|
|
+ throw new BusinessException(ResponseEnum.EN_PLUS_EQUIP_AUTH_FAIL);
|
|
|
+ }
|
|
|
+ throw new BusinessException(ResponseEnum.EN_PLUS_EQUIP_AUTH_FAIL);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 充电桩编号错误
|
|
|
+ LOGGER.error("用户:{}请求充电,设备编码错误:{}", userId, connectorId);
|
|
|
+ throw new BusinessException(ResponseEnum.EQUIP_CONNECTOR_ID_ERROR);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
+ * 请求EN+启动充电
|
|
|
+ *
|
|
|
+ * @param startChargeSeq
|
|
|
+ * @param connectorId
|
|
|
+ * @param qrCode
|
|
|
+ * @param amount
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public JSONObject queryStartCharge(String startChargeSeq, String connectorId, String qrCode, BigDecimal amount) {
|
|
|
+ var param = """
|
|
|
+ {
|
|
|
+ "StartChargeSeq":%s,
|
|
|
+ "ConnectorID":%s,
|
|
|
+ "QRCode":%s,
|
|
|
+ "amount",%d
|
|
|
+ }
|
|
|
+ """.formatted(startChargeSeq, connectorId, qrCode, amount);
|
|
|
+ var response = enPlusService.enPlusPost(EnPlusApi.EN_PLUS_QUERY_START_CHARGE.getApi(), enPlusService.buildParams(param));
|
|
|
+ return JSONObject.parseObject(AESUtil.decrypt(response.getData()));
|
|
|
+ }
|
|
|
|
|
|
}
|