diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractHandler.java index 7222aaab9..98d2ba71d 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/AbstractHandler.java @@ -46,19 +46,25 @@ public abstract class AbstractHandler implements InitializingBean { protected byte[] getResult(YKCDataProtocol ykcDataProtocol, byte[] messageBody) { // 起始标志 byte[] head = ykcDataProtocol.getHead(); + // 序列号域 byte[] serialNumber = ykcDataProtocol.getSerialNumber(); + // 加密标志 byte[] encryptFlag = ykcDataProtocol.getEncryptFlag(); + // 请求帧类型 byte[] requestFrameType = ykcDataProtocol.getFrameType(); + // 应答帧类型 byte[] responseFrameType = YKCFrameTypeCode.PlatformAnswersRelation.getResponseFrameTypeBytes(requestFrameType); // 数据域 值为“序列号域+加密标志+帧类型标志+消息体”字节数之和 byte[] dataFields = Bytes.concat(serialNumber, encryptFlag, responseFrameType, messageBody); + // 计算crc: 从序列号域到数据域的 CRC 校验 int crc16 = CRC16Util.calcCrc16(dataFields); + return Bytes.concat(head, BytesUtil.intToBytes(dataFields.length, 1), dataFields, BytesUtil.intToBytes(crc16)); } diff --git a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ReservationChargingStartupResultHandler.java b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ReservationChargingStartupResultHandler.java index ba3cd3944..041b1b9c4 100644 --- a/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ReservationChargingStartupResultHandler.java +++ b/jsowell-netty/src/main/java/com/jsowell/netty/handler/yunkuaichong/ReservationChargingStartupResultHandler.java @@ -16,7 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** - * 预约充电启动结果上送 + * 0x65预约充电启动结果上送 */ @Slf4j @Component @@ -66,7 +66,7 @@ public class ReservationChargingStartupResultHandler extends AbstractHandler{ byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); String vinCode = BytesUtil.bcd2Str(vinCodeByteArr); - // 启动结果 + // 启动结果 0x00失败 0x01成功 startIndex += length; length = 1; byte[] startupResultByteArr = BytesUtil.copyBytes(msgBody, startIndex, length); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java b/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java index bf940bcaf..6e50736b0 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/domain/OrderBasicInfo.java @@ -76,7 +76,7 @@ public class OrderBasicInfo { private String vinCode; /** - * 启动方式(0-后管启动;1-用户app启动;2-卡启动;3-离线卡启动; 4-联联平台启动; 5-车辆vin码启动) + * 启动方式(0-后管启动;1-用户app启动;2-卡启动;3-离线卡启动; 4-联联平台启动; 5-车辆vin码启动; 6-个人桩预约启动) */ private String startMode; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java index e41c0f646..263c84c22 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/GenerateOrderDTO.java @@ -17,6 +17,14 @@ import java.math.BigDecimal; @Data public class GenerateOrderDTO extends BasicPileDTO{ private static final long serialVersionUID = -1374766807594759104L; + + /** + * 交易流水号 + * 无transactionCode, 表示由平台端启动充电, 平台自行生成交易流水号 + * 有transactionCode, 表示桩端主动启动充电, 平台使用桩端生成的交易流水号 + */ + private String transactionCode; + /** * 会员id */ diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/ReservationChargingStartupResult.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/ReservationChargingStartupResult.java index 089788305..e40695c09 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/ReservationChargingStartupResult.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/ReservationChargingStartupResult.java @@ -5,6 +5,9 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +/** + * 0x65预约充电启动结果封装对象 + */ @Data @NoArgsConstructor @AllArgsConstructor @@ -31,7 +34,7 @@ public class ReservationChargingStartupResult { private String vinCode; /** - * 启动结果 + * 启动结果 0x00失败 0x01成功 */ private String startupResult; diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java index 4b3c75194..739d67982 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/OrderBasicInfoService.java @@ -469,4 +469,10 @@ public interface OrderBasicInfoService{ * @param endTime */ List getOrderDetailByStationIds(List stationIds, String startTime, String endTime); + + /** + * 创建预约启动充电订单 + * @param chargingStartupResult + */ + void createReservationOrder(ReservationChargingStartupResult chargingStartupResult); } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index e272679d0..c8d72fe86 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -3530,7 +3530,10 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { @Override public OrderBasicInfo saveOrder2Database(GenerateOrderDTO dto) throws ParseException { String orderCode = generateNewOrderCode(); - String transactionCode = IdUtils.generateTransactionCode(dto.getPileSn(), dto.getConnectorCode()); + String transactionCode = dto.getTransactionCode(); + if (StringUtils.isBlank(transactionCode)) { + transactionCode = IdUtils.generateTransactionCode(dto.getPileSn(), dto.getConnectorCode()); + } if (StringUtils.isBlank(dto.getStartType())) { dto.setStartType(StartTypeEnum.NOW.getValue()); @@ -3593,31 +3596,35 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { // 订单详情 BillingTemplateVO billingTemplate = dto.getBillingTemplate(); logger.info("订单使用的计费模板-orderCode:{}, billingTemplate:{}", orderCode, JSON.toJSONString(billingTemplate)); - BigDecimal sharpElectricityPrice = billingTemplate.getSharpElectricityPrice() != null ? billingTemplate.getSharpElectricityPrice() : BigDecimal.ZERO; - BigDecimal sharpServicePrice = billingTemplate.getSharpServicePrice() != null ? billingTemplate.getSharpServicePrice() : BigDecimal.ZERO; - BigDecimal peakElectricityPrice = billingTemplate.getPeakElectricityPrice() != null ? billingTemplate.getPeakElectricityPrice() : BigDecimal.ZERO; - BigDecimal peakServicePrice = billingTemplate.getPeakServicePrice() != null ? billingTemplate.getPeakServicePrice() : BigDecimal.ZERO; - BigDecimal flatElectricityPrice = billingTemplate.getFlatElectricityPrice() != null ? billingTemplate.getFlatElectricityPrice() : BigDecimal.ZERO; - BigDecimal flatServicePrice = billingTemplate.getFlatServicePrice() != null ? billingTemplate.getFlatServicePrice() : BigDecimal.ZERO; - BigDecimal valleyElectricityPrice = billingTemplate.getValleyElectricityPrice() != null ? billingTemplate.getValleyElectricityPrice() : BigDecimal.ZERO; - BigDecimal valleyServicePrice = billingTemplate.getValleyServicePrice() != null ? billingTemplate.getValleyServicePrice() : BigDecimal.ZERO; + OrderDetail orderDetail = null; + if (billingTemplate != null) { + BigDecimal sharpElectricityPrice = billingTemplate.getSharpElectricityPrice() != null ? billingTemplate.getSharpElectricityPrice() : BigDecimal.ZERO; + BigDecimal sharpServicePrice = billingTemplate.getSharpServicePrice() != null ? billingTemplate.getSharpServicePrice() : BigDecimal.ZERO; + BigDecimal peakElectricityPrice = billingTemplate.getPeakElectricityPrice() != null ? billingTemplate.getPeakElectricityPrice() : BigDecimal.ZERO; + BigDecimal peakServicePrice = billingTemplate.getPeakServicePrice() != null ? billingTemplate.getPeakServicePrice() : BigDecimal.ZERO; + BigDecimal flatElectricityPrice = billingTemplate.getFlatElectricityPrice() != null ? billingTemplate.getFlatElectricityPrice() : BigDecimal.ZERO; + BigDecimal flatServicePrice = billingTemplate.getFlatServicePrice() != null ? billingTemplate.getFlatServicePrice() : BigDecimal.ZERO; + BigDecimal valleyElectricityPrice = billingTemplate.getValleyElectricityPrice() != null ? billingTemplate.getValleyElectricityPrice() : BigDecimal.ZERO; + BigDecimal valleyServicePrice = billingTemplate.getValleyServicePrice() != null ? billingTemplate.getValleyServicePrice() : BigDecimal.ZERO; - OrderDetail orderDetail = OrderDetail.builder() - .orderCode(orderCode) - .sharpPrice(sharpElectricityPrice.add(sharpServicePrice)) - .sharpElectricityPrice(sharpElectricityPrice) - .sharpServicePrice(sharpServicePrice) - .peakPrice(peakElectricityPrice.add(peakServicePrice)) - .peakElectricityPrice(peakElectricityPrice) - .peakServicePrice(peakServicePrice) - .flatPrice(flatElectricityPrice.add(flatServicePrice)) - .flatElectricityPrice(flatElectricityPrice) - .flatServicePrice(flatServicePrice) - .valleyPrice(valleyElectricityPrice.add(valleyServicePrice)) - .valleyElectricityPrice(valleyElectricityPrice) - .valleyServicePrice(valleyServicePrice) - .build(); + orderDetail = OrderDetail.builder() + .orderCode(orderCode) + .sharpPrice(sharpElectricityPrice.add(sharpServicePrice)) + .sharpElectricityPrice(sharpElectricityPrice) + .sharpServicePrice(sharpServicePrice) + .peakPrice(peakElectricityPrice.add(peakServicePrice)) + .peakElectricityPrice(peakElectricityPrice) + .peakServicePrice(peakServicePrice) + .flatPrice(flatElectricityPrice.add(flatServicePrice)) + .flatElectricityPrice(flatElectricityPrice) + .flatServicePrice(flatServicePrice) + .valleyPrice(valleyElectricityPrice.add(valleyServicePrice)) + .valleyElectricityPrice(valleyElectricityPrice) + .valleyServicePrice(valleyServicePrice) + .build(); + } + // 保存到数据库 OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() .orderBasicInfo(orderBasicInfo) .orderDetail(orderDetail) @@ -3745,5 +3752,40 @@ public class OrderBasicInfoServiceImpl implements OrderBasicInfoService { return orderBasicInfoMapper.getOrderDetailByStationIds(stationIds, startTime, endTime); } + @Override + public void createReservationOrder(ReservationChargingStartupResult chargingStartupResult) { + String orderCode = generateNewOrderCode(); + String transactionCode = chargingStartupResult.getTransactionCode(); + + String status = StringUtils.equals(chargingStartupResult.getStartupResult(), "00") + ? OrderStatusEnum.IN_THE_CHARGING.getValue() + : OrderStatusEnum.ABNORMAL.getValue(); + + // 订单基本信息 + OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() + .orderCode(orderCode) + .transactionCode(transactionCode) + .orderStatus(status) + .pileSn(chargingStartupResult.getPileSn()) + .connectorCode(chargingStartupResult.getConnectorCode()) + .pileConnectorCode(chargingStartupResult.getPileSn() + chargingStartupResult.getConnectorCode()) + .startMode("6") + .payStatus(Constants.TWO) + .payMode(Constants.THREE) + .orderAmount(BigDecimal.ZERO) + .virtualAmount(BigDecimal.ZERO) + .settleAmount(BigDecimal.ZERO) + .startType(StartTypeEnum.RESERVED.getValue()) + .reason(chargingStartupResult.getFailReason()) + .build(); + + // 保存到数据库 + OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() + .orderBasicInfo(orderBasicInfo) + .orderDetail(null) + .build(); + pileTransactionService.doCreateOrder(createOrderTransactionDTO); + } + } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java index 10a7f37fb..06013e9ce 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/PileBasicInfoServiceImpl.java @@ -90,6 +90,9 @@ public class PileBasicInfoServiceImpl implements PileBasicInfoService { @Autowired private WxAppletRemoteService wxAppletRemoteService; + @Autowired + private OrderBasicInfoService orderBasicInfoService; + /** * 查询设备管理 * @@ -1218,7 +1221,10 @@ public class PileBasicInfoServiceImpl implements PileBasicInfoService { */ @Override public void startupResult(ReservationChargingStartupResult chargingStartupResult) { + // 创建订单 + orderBasicInfoService.createReservationOrder(chargingStartupResult); + // 小程序通知 - wxAppletRemoteService.reservationStartupResultSendMsg(); + wxAppletRemoteService.reservationStartupResultSendMsg(chargingStartupResult); } } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java index de933a2b3..70c85b445 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/DelayMerchantProgramLogic.java @@ -71,7 +71,10 @@ public class DelayMerchantProgramLogic extends AbstractProgramLogic { orderBasicInfoService.analysisPileParameter(dto); // 校验充电桩相关的信息 - orderBasicInfoService.checkPileInfo(dto); + if (StringUtils.isBlank(dto.getTransactionCode())) { + // 无transactionCode, 表示由平台端启动充电, 需要验证充电桩状态 + orderBasicInfoService.checkPileInfo(dto); + } // 保存订单到数据库 saveOrder2Database return orderBasicInfoService.saveOrder2Database(dto); diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java index 147db42fd..926858719 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/programlogic/NotDelayMerchantProgramLogic.java @@ -72,7 +72,10 @@ public class NotDelayMerchantProgramLogic extends AbstractProgramLogic { orderBasicInfoService.analysisPileParameter(dto); // 校验充电桩相关的信息 - orderBasicInfoService.checkPileInfo(dto); + if (StringUtils.isBlank(dto.getTransactionCode())) { + // 无transactionCode, 表示由平台端启动充电, 需要验证充电桩状态 + orderBasicInfoService.checkPileInfo(dto); + } // 保存订单到数据库 saveOrder2Database return orderBasicInfoService.saveOrder2Database(dto); diff --git a/jsowell-pile/src/main/java/com/jsowell/wxpay/service/WxAppletRemoteService.java b/jsowell-pile/src/main/java/com/jsowell/wxpay/service/WxAppletRemoteService.java index ee2f9f9e6..c96ab08cb 100644 --- a/jsowell-pile/src/main/java/com/jsowell/wxpay/service/WxAppletRemoteService.java +++ b/jsowell-pile/src/main/java/com/jsowell/wxpay/service/WxAppletRemoteService.java @@ -14,6 +14,7 @@ import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.http.HttpUtils; import com.jsowell.pile.domain.MemberBasicInfo; +import com.jsowell.pile.dto.ReservationChargingStartupResult; import com.jsowell.pile.service.MemberBasicInfoService; import com.jsowell.pile.service.PileBillingTemplateService; import com.jsowell.pile.service.OrderBasicInfoService; @@ -277,7 +278,7 @@ public class WxAppletRemoteService { /** * 预约充电结果小程序服务通知 */ - public Map reservationStartupResultSendMsg() { + public Map reservationStartupResultSendMsg(ReservationChargingStartupResult chargingStartupResult) { AppletTemplateMessageSendDTO msgInfo = new AppletTemplateMessageSendDTO(); return uniAppSendMsg(msgInfo); }