package com.jsowell.service; import com.alibaba.fastjson2.JSONObject; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.core.page.PageResponse; import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.enums.MemberWalletEnum; import com.jsowell.common.enums.ykc.ActionTypeEnum; import com.jsowell.common.enums.ykc.OrderPayModeEnum; import com.jsowell.common.enums.ykc.OrderPayRecordEnum; import com.jsowell.common.enums.ykc.OrderPayStatusEnum; import com.jsowell.common.enums.ykc.OrderStatusEnum; import com.jsowell.common.enums.ykc.PayModeEnum; import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.enums.ykc.ScenarioEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.bean.BeanUtils; import com.jsowell.common.util.id.IdUtils; import com.jsowell.netty.command.ykc.PublishPileBillingTemplateCommand; import com.jsowell.netty.command.ykc.StartChargingCommand; import com.jsowell.netty.service.yunkuaichong.YKCPushCommandService; import com.jsowell.pile.domain.MemberTransactionRecord; import com.jsowell.pile.domain.OrderBasicInfo; import com.jsowell.pile.domain.OrderDetail; import com.jsowell.pile.domain.OrderPayRecord; import com.jsowell.pile.domain.WxpayCallbackRecord; import com.jsowell.pile.dto.BasicPileDTO; import com.jsowell.pile.dto.GenerateOrderDTO; import com.jsowell.pile.dto.PayOrderDTO; import com.jsowell.pile.dto.PayOrderSuccessCallbackDTO; import com.jsowell.pile.dto.PaymentScenarioDTO; import com.jsowell.pile.dto.QueryConnectorListDTO; import com.jsowell.pile.dto.QueryOrderDTO; import com.jsowell.pile.dto.SettleOrderDTO; import com.jsowell.pile.dto.StopChargingDTO; import com.jsowell.pile.dto.UniAppQueryOrderDTO; import com.jsowell.pile.dto.WeixinPayDTO; import com.jsowell.pile.service.IMemberBasicInfoService; import com.jsowell.pile.service.IMemberTransactionRecordService; import com.jsowell.pile.service.IOrderBasicInfoService; import com.jsowell.pile.service.IOrderPayRecordService; import com.jsowell.pile.service.IPileBillingTemplateService; import com.jsowell.pile.service.IPileConnectorInfoService; import com.jsowell.pile.service.IPileStationInfoService; import com.jsowell.pile.service.WechatPayService; import com.jsowell.pile.service.WxpayCallbackRecordService; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; import com.jsowell.pile.transaction.service.TransactionService; import com.jsowell.pile.vo.base.PileInfoVO; import com.jsowell.pile.vo.uniapp.MemberVO; import com.jsowell.pile.vo.uniapp.OrderVO; import com.jsowell.pile.vo.uniapp.PileConnectorDetailVO; import com.jsowell.pile.vo.uniapp.UniAppOrderVO; import com.jsowell.pile.vo.web.BillingTemplateVO; import com.jsowell.pile.vo.web.OrderDetailInfoVO; import com.jsowell.pile.vo.web.PileStationVO; import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO; import com.jsowell.wxpay.dto.WeChatRefundDTO; import com.jsowell.wxpay.response.WechatPayNotifyParameter; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @Service public class OrderService { private final Logger log = LoggerFactory.getLogger(this.getClass()); private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Autowired private TransactionService pileTransactionService; @Autowired private IPileBillingTemplateService pileBillingTemplateService; @Autowired private IOrderBasicInfoService orderBasicInfoService; @Autowired private PileRemoteService pileRemoteService; @Autowired private YKCPushCommandService ykcPushCommandService; @Autowired private PileService pileService; @Autowired private MemberService memberService; @Autowired private IMemberBasicInfoService memberBasicInfoService; @Autowired private IOrderPayRecordService orderPayRecordService; @Autowired private WechatPayService wechatPayService; @Autowired private WxpayCallbackRecordService wxpayCallbackRecordService; @Autowired private IPileConnectorInfoService pileConnectorInfoService; @Autowired private IMemberTransactionRecordService memberTransactionRecordService; @Autowired private RedisCache redisCache; @Autowired private IPileStationInfoService pileStationInfoService; /** * 生成订单 * * @param dto * @return */ public String generateOrder(GenerateOrderDTO dto) { log.info("generateOrder param:{}", JSONObject.toJSONString(dto)); // 处理前端传的参数 analysisPileParameter(dto); // 校验充电桩相关的信息 checkPileInfo(dto); // 保存订单到数据库 saveOrder2Database String orderCode = saveOrder2Database(dto); return orderCode; } /** * 订单支付 * * @param dto */ public Map payOrder(PayOrderDTO dto) throws Exception { Map resultMap = Maps.newHashMap(); OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR); } if (!StringUtils.equals(orderInfo.getPayStatus(), "0")) { // 订单已支付 throw new BusinessException(ReturnCodeEnum.CODE_ORDER_IS_NOT_TO_BE_PAID_ERROR); } String orderCode = orderInfo.getOrderCode(); // 该订单充电金额 BigDecimal chargeAmount = dto.getPayAmount(); // 记录支付流水 List payRecordList = Lists.newArrayList(); if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { // 余额支付 // 查询该会员的余额 MemberVO memberVO = memberService.getMemberInfoByMemberId(dto.getMemberId()); BigDecimal totalAccountAmount = memberVO.getTotalAccountAmount(); if (totalAccountAmount.compareTo(chargeAmount) < 0) { // 总余额小于充电金额 throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT); } BigDecimal principalAmount = memberVO.getPrincipalBalance(); // 会员剩余本金金额 BigDecimal giftAmount = memberVO.getGiftBalance(); // 会员剩余赠送余额 BigDecimal principalPay = null; // 30 BigDecimal giftPay = null; // 10 // 先扣除本金金额,再扣除赠送金额 BigDecimal subtract = principalAmount.subtract(chargeAmount); if (subtract.compareTo(BigDecimal.ZERO) >= 0) { principalPay = chargeAmount; } else { if (principalAmount.compareTo(BigDecimal.ZERO) > 0) { principalPay = principalAmount; } giftPay = subtract.negate(); } // 更新会员钱包 UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() .memberId(dto.getMemberId()) .type(MemberWalletEnum.TYPE_OUT.getValue()) .subType(MemberWalletEnum.SUBTYPE_PAYMENT_FOR_ORDER.getValue()) .updatePrincipalBalance(principalPay) .updateGiftBalance(giftPay) .relatedOrderCode(orderCode) .build(); memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO); // 记录流水 if (principalPay != null) { payRecordList.add(OrderPayRecord.builder() .orderCode(dto.getOrderCode()) .payMode(OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue()) .payAmount(principalPay) .createBy(dto.getMemberId()) .build()); } if (giftPay != null) { payRecordList.add(OrderPayRecord.builder() .orderCode(dto.getOrderCode()) .payMode(OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue()) .payAmount(giftPay) .createBy(dto.getMemberId()) .build()); } // 余额支付可以直接调支付回调方法 PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(chargeAmount) .payMode(dto.getPayMode()) .build(); payOrderSuccessCallback(callbackDTO); // 余额支付订单 记录会员交易流水 MemberTransactionRecord record = MemberTransactionRecord.builder() .orderCode(orderCode) .scenarioType(ScenarioEnum.ORDER.getValue()) .memberId(memberVO.getMemberId()) .actionType(ActionTypeEnum.FORWARD.getValue()) .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue()) .amount(dto.getPayAmount()) // 单位元 .build(); memberTransactionRecordService.insertSelective(record); } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { // 微信支付 String openId = memberService.getOpenIdByCode(dto.getCode()); if (StringUtils.isBlank(openId)) { throw new BusinessException(ReturnCodeEnum.CODE_GET_OPEN_ID_BY_CODE_ERROR); } WeixinPayDTO weixinPayDTO = new WeixinPayDTO(); weixinPayDTO.setOpenId(openId); weixinPayDTO.setAmount(dto.getPayAmount().toString()); // 支付订单 附加参数 PaymentScenarioDTO paymentScenarioDTO = PaymentScenarioDTO.builder() .type(ScenarioEnum.ORDER.getValue()) .orderCode(dto.getOrderCode()) .memberId(orderInfo.getMemberId()) .build(); weixinPayDTO.setAttach(JSONObject.toJSONString(paymentScenarioDTO)); weixinPayDTO.setDescription("充电费用"); Map weixinMap = this.weixinPayV3(weixinPayDTO); // 返回微信支付参数 resultMap.put("weixinMap", weixinMap); } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())) { // 支付宝支付 // TODO 返回支付宝支付参数 } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue())) { // 白名单支付 // 白名单支付可以直接调支付回调方法 PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(dto.getPayAmount()) .payMode(dto.getPayMode()) .build(); payOrderSuccessCallback(callbackDTO); } // 订单支付流水入库 if (CollectionUtils.isNotEmpty(payRecordList)) { orderPayRecordService.batchInsert(payRecordList); } return resultMap; } /** * 订单支付成功 支付回调 * 支付成功后掉用这个方法 * 1. 修改订单支付状态 * 2. 发送启动充电指令 */ public void payOrderSuccessCallback(PayOrderSuccessCallbackDTO dto) { OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); BigDecimal payAmount = dto.getPayAmount(); // 修改订单 orderInfo.setPayMode(dto.getPayMode()); orderInfo.setPayStatus("1"); orderInfo.setPayAmount(payAmount); orderInfo.setPayTime(new Date()); orderBasicInfoService.updateOrderBasicInfo(orderInfo); String pileSn = orderInfo.getPileSn(); // 发送启动充电指令前,再次下发计费模板 BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); if (billingTemplateVO != null) { PublishPileBillingTemplateCommand templateCommand = new PublishPileBillingTemplateCommand(); templateCommand.setBillingTemplateVO(billingTemplateVO); templateCommand.setPileSn(pileSn); ykcPushCommandService.pushPublishPileBillingTemplate(templateCommand); } // 发送启动指令 StartChargingCommand startChargingCommand = StartChargingCommand.builder() .pileSn(pileSn) .connectorCode(orderInfo.getConnectorCode()) .orderCode(dto.getOrderCode()) .chargeAmount(payAmount) .build(); ykcPushCommandService.pushStartChargingCommand(startChargingCommand); } /** * 保存订单信息到数据库 * * @param dto * @return */ private String saveOrder2Database(GenerateOrderDTO dto) { String orderCode = IdUtils.getOrderCode(); String transactionCode = IdUtils.generateTransactionCode(dto.getPileSn(), dto.getConnectorCode()); // 订单基本信息 OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() .orderCode(orderCode) .transactionCode(transactionCode) .orderStatus(OrderStatusEnum.NOT_START.getValue()) .memberId(dto.getMemberId()) .stationId(dto.getPileConnector().getStationId()) .pileSn(dto.getPileSn()) .connectorCode(dto.getConnectorCode()) .pileConnectorCode(dto.getPileSn() + dto.getConnectorCode()) .startMode(dto.getStartMode()) .payStatus(Constants.ZERO) .payAmount(dto.getChargeAmount()) .payMode(dto.getPayMode()) .orderAmount(BigDecimal.ZERO) .build(); // 订单详情 OrderDetail orderDetail = OrderDetail.builder() .orderCode(orderCode) .sharpElectricityPrice(dto.getBillingTemplate().getSharpElectricityPrice()) .sharpServicePrice(dto.getBillingTemplate().getSharpServicePrice()) .peakElectricityPrice(dto.getBillingTemplate().getPeakElectricityPrice()) .peakServicePrice(dto.getBillingTemplate().getPeakServicePrice()) .flatElectricityPrice(dto.getBillingTemplate().getFlatElectricityPrice()) .flatServicePrice(dto.getBillingTemplate().getFlatServicePrice()) .valleyElectricityPrice(dto.getBillingTemplate().getValleyElectricityPrice()) .valleyServicePrice(dto.getBillingTemplate().getValleyServicePrice()) .build(); OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() .orderBasicInfo(orderBasicInfo) .orderDetail(orderDetail) .build(); pileTransactionService.doCreateOrder(createOrderTransactionDTO); return orderCode; } /** * 校验充电桩相关的信息 * * @param dto */ private void checkPileInfo(GenerateOrderDTO dto) { // 查询充电桩状态 是否空闲 枪口是否占用 PileConnectorDetailVO pileConnector = pileService.queryPileConnectorDetail(dto.getPileSn() + dto.getConnectorCode()); if (pileConnector == null) { log.error("checkPileInfo充电枪口为空 pileSn:{}, connectorCode:{}", dto.getPileSn(), dto.getConnectorCode()); throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR); } // 判断枪口状态 if (!(StringUtils.equals(pileConnector.getConnectorStatus(), PileConnectorDataBaseStatusEnum.FREE.getValue()) || StringUtils.equals(pileConnector.getConnectorStatus(), PileConnectorDataBaseStatusEnum.OCCUPIED_NOT_CHARGED.getValue()))) { log.error("checkPileInfo充电枪口状态不正确,当前状态为:{}", pileConnector.getConnectorStatus()); throw new BusinessException(ReturnCodeEnum.CODE_PILE_CONNECTOR_STATUS_ERROR); } // 查询充电桩的计费模板 BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(dto.getPileSn()); if (billingTemplateVO == null) { throw new BusinessException(ReturnCodeEnum.CODE_BILLING_TEMPLATE_NULL_ERROR); } dto.setPileConnector(pileConnector); dto.setBillingTemplate(billingTemplateVO); } /** * 处理前端传的参数 * pileConnectorCode = pileSn + connectorCode * * @param dto */ public void analysisPileParameter(BasicPileDTO dto) { if (StringUtils.isBlank(dto.getPileSn()) || StringUtils.isBlank(dto.getConnectorCode())) { // 从pileConnectorCode解析 String pileConnectorCode = dto.getPileConnectorCode(); if (StringUtils.isNotEmpty(pileConnectorCode) && pileConnectorCode.length() == Constants.PILE_CONNECTOR_CODE_LENGTH) { dto.setPileSn(StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2)); dto.setConnectorCode(StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length())); } else { throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR); } } else { // 说明pileSn 和 connectorCode前端传了,那就校验一下长度 if (dto.getPileSn().length() != Constants.PILE_SN_LENGTH || dto.getConnectorCode().length() != Constants.CONNECTOR_CODE_LENGTH) { throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR); } } } /** * 结算订单 * endCharging * * @param dto 结算订单参数 */ public void settleOrderForWeb(SettleOrderDTO dto) { analysisPileParameter(dto); // 查询订单详情,验证订单中的桩编号是否正确 OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderBasicInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR); } if (!(StringUtils.equals(orderBasicInfo.getPileSn(), dto.getPileSn()) && StringUtils.equals(orderBasicInfo.getConnectorCode(), dto.getConnectorCode()))) { throw new BusinessException(ReturnCodeEnum.CODE_ORDER_PILE_MAPPING_ERROR); } // push远程停机指令 pileRemoteService.remoteStopCharging(dto.getPileSn(), dto.getConnectorCode()); // 桩计算的消费金额 // 对比一下,是否需要退款 } /** * 通过会员Id查询订单列表 * * @param memberId 会员Id * @return 订单信息集合 */ public PageResponse getListByMemberIdAndOrderStatus(String memberId, UniAppQueryOrderDTO dto) throws ParseException { String orderStatus = dto.getOrderStatus(); if (StringUtils.isBlank(orderStatus)) { throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR); } ArrayList orderStatusList = Lists.newArrayList(); if (StringUtils.equals("2", orderStatus)) { // 查未完成订单 CollectionUtils.addAll(orderStatusList, "0", "1", "2", "3", "4", "5"); } else if (StringUtils.equals("3", orderStatus)) { // 查已完成订单 orderStatusList.add("6"); } // 分页 PageHelper.startPage(dto.getPageNum(), dto.getPageSize()); List list = orderBasicInfoService.getListByMemberIdAndOrderStatus(memberId, orderStatusList); PageInfo pageInfo = new PageInfo<>(list); for (OrderVO orderVO : pageInfo.getList()) { orderVO.setPileConnectorCode(orderVO.getPileSn() + orderVO.getConnectorCode()); Date endTimeDate; Date startTimeDate = sdf.parse(orderVO.getStartTime()); if (StringUtils.isNotBlank(orderVO.getEndTime())) { endTimeDate = sdf.parse(orderVO.getEndTime()); } else { endTimeDate = new Date(); } // 计算出两个时间差 orderVO.setChargingTime(DateUtils.getDatePoor(endTimeDate, startTimeDate)); } // 返回结果集 PageResponse pageResponse = PageResponse.builder() .pageNum(dto.getPageNum()) .pageSize(dto.getPageSize()) .list(pageInfo.getList()) .pages(pageInfo.getPages()) .total(pageInfo.getTotal()) .build(); return pageResponse; } /** * 微信支付v3 * * @param dto * @return * @throws Exception */ public Map weixinPayV3(WeixinPayDTO dto) throws Exception { return wechatPayService.weixinPayV3(dto); } /** * 用户停止充电 * * @param dto */ public void stopCharging(StopChargingDTO dto) { // 查订单 OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR); } // 校验订单中的会员与操作会员是否一致 if (!StringUtils.equals(orderInfo.getMemberId(), dto.getMemberId())) { throw new BusinessException(ReturnCodeEnum.CODE_ORDER_MEMBER_NOT_MATCH_ERROR); } // 发送停止指令 pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode()); log.info("订单号:{}发送停机指令成功", dto.getOrderCode()); } /** * 微信支付回调 * * @param request * @param body * @throws Exception */ public void wechatPayCallback(HttpServletRequest request, WechatPayNotifyParameter body) throws Exception { // 获取微信支付成功返回的信息 Map map = wechatPayService.wechatPayCallbackInfo(request, body); String type = (String) map.get("type"); BigDecimal amount = (BigDecimal) map.get("amount"); // 微信给的amount单位是分 amount = amount.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); // 转换为元 String orderCode = (String) map.get("orderCode"); String memberId = (String) map.get("memberId"); if (StringUtils.equals(type, ScenarioEnum.ORDER.getValue())) { // 1-订单支付 // 支付订单成功 // orderCode = (String) map.get("orderCode"); PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(amount) .payMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .build(); // 订单支付成功 支付回调 payOrderSuccessCallback(callbackDTO); // 记录订单支付流水 OrderPayRecord orderPayRecord = OrderPayRecord.builder() .orderCode(orderCode) .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue()) .payAmount(amount) .createBy(null) .build(); orderPayRecordService.batchInsert(Lists.newArrayList(orderPayRecord)); } else if (StringUtils.equals(type, ScenarioEnum.BALANCE.getValue())) { // 2-充值余额 // 充值余额成功 // memberId = (String) map.get("memberId"); UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO(); dto.setMemberId(memberId); dto.setType(MemberWalletEnum.TYPE_IN.getValue()); dto.setSubType(MemberWalletEnum.SUBTYPE_TOP_UP.getValue()); dto.setUpdatePrincipalBalance(amount); memberBasicInfoService.updateMemberBalance(dto); } // 微信支付订单 记录会员交易流水 MemberTransactionRecord record = MemberTransactionRecord.builder() .orderCode(orderCode) .scenarioType(type) .memberId(memberId) .actionType(ActionTypeEnum.FORWARD.getValue()) .payMode(PayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .amount(amount) // 单位元 .outTradeNo(String.valueOf(map.get("out_trade_no"))) .transactionId(String.valueOf(map.get("transaction_id"))) .build(); memberTransactionRecordService.insertSelective(record); } public void weChatRefund(WeChatRefundDTO dto) { log.info("微信退款接口 param:{}", JSONObject.toJSONString(dto)); orderBasicInfoService.weChatRefund(dto); } /** * 查询订单详情信息 * @param orderCode 订单编号 * @return */ public OrderDetailInfoVO queryOrderDetailInfo(String orderCode) { OrderDetailInfoVO vo = new OrderDetailInfoVO(); // 订单信息 OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); if (orderBasicInfo == null) { return vo; } OrderDetailInfoVO.OrderInfo order = new OrderDetailInfoVO.OrderInfo(); order.setOrderCode(orderBasicInfo.getOrderCode()); order.setOrderStatus(orderBasicInfo.getOrderStatus()); order.setStartTime(DateUtils.formatDateTime(orderBasicInfo.getChargeStartTime())); order.setEndTime(DateUtils.formatDateTime(orderBasicInfo.getChargeEndTime())); order.setCreateTime(DateUtils.formatDateTime(orderBasicInfo.getCreateTime())); order.setStopReasonMsg(orderBasicInfo.getReason()); order.setStartSOC(orderBasicInfo.getStartSOC()); order.setEndSOC(orderBasicInfo.getEndSOC()); vo.setOrderInfo(order); // 设备信息 PileInfoVO pileInfoVO = pileService.selectPileInfoBySn(orderBasicInfo.getPileSn()); vo.setPileInfo(pileInfoVO); // 枪口实时数据信息 String pileConnectorCode = orderBasicInfo.getPileSn() + orderBasicInfo.getConnectorCode(); QueryConnectorListDTO dto = new QueryConnectorListDTO(); dto.setConnectorCodeList(Lists.newArrayList(pileConnectorCode)); List chargingRealTimeDataList = orderBasicInfoService.getChargingRealTimeData(orderCode); if (CollectionUtils.isNotEmpty(chargingRealTimeDataList)) { List infoList = Lists.newArrayList(); for (RealTimeMonitorData realTimeMonitorData : chargingRealTimeDataList) { OrderDetailInfoVO.RealTimeMonitorData info = new OrderDetailInfoVO.RealTimeMonitorData(); info.setInstantCurrent(realTimeMonitorData.getOutputCurrent()); // 电流 info.setInstantVoltage(realTimeMonitorData.getOutputVoltage()); // 电压 info.setInstantPower(realTimeMonitorData.getOutputPower()); // 功率 info.setSOC(realTimeMonitorData.getSOC()); info.setTime(realTimeMonitorData.getDateTime()); // 时间 infoList.add(info); } // 监控信息 OrderDetailInfoVO.OrderRealTimeInfo realTimeInfo = new OrderDetailInfoVO.OrderRealTimeInfo(); RealTimeMonitorData realTimeMonitorData = chargingRealTimeDataList.get(0); realTimeInfo.setOrderAmount(realTimeMonitorData.getChargingAmount()); // realTimeInfo.setTotalElectricityAmount(); // realTimeInfo.setTotalServiceAmount(); realTimeInfo.setChargedDegree(realTimeMonitorData.getChargingDegree()); // realTimeInfo.setSOC(realTimeMonitorData.getSOC()); realTimeInfo.setChargingTime(realTimeMonitorData.getSumChargingTime()); vo.setOrderRealTimeInfo(realTimeInfo); // 根据时间进行正序排序 infoList = infoList.stream() .sorted(Comparator.comparing(OrderDetailInfoVO.RealTimeMonitorData::getTime)) .collect(Collectors.toList()); vo.setRealTimeMonitorDataList(infoList); } // 支付流水 List orderPayRecordList = orderPayRecordService.getOrderPayRecordList(orderCode); if (CollectionUtils.isNotEmpty(orderPayRecordList)) { OrderPayRecord orderPayRecord = orderPayRecordList.get(0); List payRecordList = Lists.newArrayList(); OrderDetailInfoVO.PayRecord payInfo = new OrderDetailInfoVO.PayRecord(); // 余额支付如果是由本金和赠送一起支付的,合并为一个 BigDecimal bigDecimal = orderPayRecordList.stream() .map(OrderPayRecord::getPayAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); payInfo.setPayAmount(bigDecimal.toString()); payInfo.setPayStatus(orderBasicInfo.getPayStatus()); payInfo.setPayTime(DateUtils.formatDateTime(orderBasicInfo.getPayTime())); String payMode = orderPayRecord.getPayMode(); if (StringUtils.equals(payMode, OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue()) || StringUtils.equals(payMode, OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue())) { // 使用余额支付 payInfo.setPayMode(OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue()); payInfo.setPayModeDesc(OrderPayModeEnum.PAYMENT_OF_BALANCE.getLabel()); } else if (StringUtils.equals(payMode, OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue())){ // 使用微信支付 payInfo.setPayMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()); payInfo.setPayModeDesc(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getLabel()); // 查微信支付回调记录 WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService.selectByOrderCode(orderCode); if (wxpayCallbackRecord != null) { payInfo.setOutTradeNo(wxpayCallbackRecord.getOutTradeNo()); payInfo.setTransactionId(wxpayCallbackRecord.getTransactionId()); } } else if (StringUtils.equals(payMode, OrderPayRecordEnum.WHITELIST_PAYMENT.getValue())){ // 使用白名单支付 payInfo.setPayMode(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue()); payInfo.setPayModeDesc(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getLabel()); } payRecordList.add(payInfo); vo.setPayRecordList(payRecordList); } // 查订单明细 OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode); if (orderDetail != null) { OrderDetailInfoVO.BillingDetails billingDetails = new OrderDetailInfoVO.BillingDetails(); BeanUtils.copyBeanProp(billingDetails, orderDetail); vo.setBillingDetails(billingDetails); } // 用户信息 MemberVO memberVO = memberService.getMemberInfoByMemberId(orderBasicInfo.getMemberId()); vo.setMemberInfo(memberVO); return vo; } public void wechatPayRefundCallback(HttpServletRequest request, WechatPayNotifyParameter body) throws Exception { // 获取微信退款成功返回的信息 Map map = wechatPayService.wechatPayRefundCallbackInfo(request, body); } /** * 获取小程序订单详情 * @param orderCode * @return */ public UniAppOrderVO getUniAppOrderDetail(String orderCode) { OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); if (orderBasicInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR); } UniAppOrderVO vo = new UniAppOrderVO(); vo.setOrderCode(orderBasicInfo.getOrderCode()); vo.setPileSn(orderBasicInfo.getPileSn()); vo.setConnectorCode(orderBasicInfo.getConnectorCode()); vo.setPileConnectorCode(orderBasicInfo.getPileSn() + orderBasicInfo.getConnectorCode()); String orderStatus = orderBasicInfo.getOrderStatus(); vo.setOrderStatus(orderStatus); vo.setStartChargingTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderBasicInfo.getChargeStartTime())); Date chargeEndTime = orderBasicInfo.getChargeEndTime(); if (Objects.nonNull(chargeEndTime)) { vo.setEndChargingTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, chargeEndTime)); } PileStationVO stationInfo = pileStationInfoService.getStationInfo(orderBasicInfo.getStationId()); vo.setStationName(stationInfo.getStationName()); vo.setReason(orderBasicInfo.getReason()); vo.setOrderAmount(String.valueOf(orderBasicInfo.getOrderAmount())); vo.setPayAmount(String.valueOf(orderBasicInfo.getPayAmount())); // 订单状态描述 String orderStatusDescribe; if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) { // 未启动还有两种情况 待支付 / 支付成功 String payStatus = orderBasicInfo.getPayStatus(); if (StringUtils.equals(payStatus, OrderPayStatusEnum.paid.getValue())) { // 支付成功,未启动 orderStatusDescribe = OrderPayStatusEnum.paid.getLabel() + ", " + OrderStatusEnum.getOrderStatus(orderStatus); } else { // 待支付 orderStatusDescribe = OrderPayStatusEnum.unpaid.getLabel(); } } else { orderStatusDescribe = OrderStatusEnum.getOrderStatus(orderStatus); } vo.setOrderStatusDescribe(orderStatusDescribe); // 获取充电桩枪口信息 PileConnectorDetailVO pileConnectorDetailVO = pileService.queryPileConnectorDetail(vo.getPileConnectorCode()); if (pileConnectorDetailVO != null) { vo.setPileConnectorStatus(pileConnectorDetailVO.getConnectorStatus()); } // 获取订单充电数据 List monitorDataList = orderBasicInfoService.getChargingRealTimeData(orderCode); if (CollectionUtils.isNotEmpty(monitorDataList)) { List chargingDataList = Lists.newArrayList(); UniAppOrderVO.ChargingData data = null; for (int i = 0; i < monitorDataList.size(); i++) { RealTimeMonitorData monitorData = monitorDataList.get(i); data = new UniAppOrderVO.ChargingData(); data.setDateTime(monitorData.getDateTime()); String outputVoltage = monitorData.getOutputVoltage(); data.setOutputVoltage(outputVoltage); String outputCurrent = monitorData.getOutputCurrent(); data.setOutputCurrent(outputCurrent); BigDecimal power = new BigDecimal(outputCurrent).multiply(new BigDecimal(outputVoltage)) .divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP); data.setPower(power.toString()); data.setSOC(monitorData.getSOC()); data.setBatteryMaxTemperature(monitorData.getBatteryMaxTemperature()); chargingDataList.add(data); // vo中的实时数据,最新一条就取monitorDataList第一个 if (i == 0) { vo.setBatteryMaxTemperature(data.getBatteryMaxTemperature()); vo.setOutputPower(data.getPower()); vo.setOutputCurrent(data.getOutputCurrent()); vo.setOutputVoltage(data.getOutputVoltage()); vo.setSOC(data.getSOC()); BigDecimal chargingAmount = new BigDecimal(monitorData.getChargingAmount()).setScale(2, BigDecimal.ROUND_HALF_UP); // 充电金额 vo.setChargingAmount(chargingAmount.toString()); BigDecimal chargingDegree = new BigDecimal(monitorData.getChargingDegree()).setScale(2, BigDecimal.ROUND_HALF_UP); // 充电度数 vo.setChargingDegree(chargingDegree.toString()); vo.setSumChargingTime(monitorData.getSumChargingTime()); vo.setTimeRemaining(monitorData.getTimeRemaining()); } } // monitorDataList是按照时间倒序的,chargingDataList需要按照时间正序 Collections.reverse(chargingDataList); vo.setChargingDataList(chargingDataList); } OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode); if (orderDetail != null) { UniAppOrderVO.BillingDetails billingDetails = new UniAppOrderVO.BillingDetails(); BeanUtils.copyBeanProp(billingDetails, orderDetail); vo.setBillingDetails(billingDetails); } return vo; } /** * 根据订单号查询充电桩启动状态 * @param orderCode * @return */ public String selectPileStarterStatus(String orderCode) { List chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderCode); // 只有充电桩上传的实时数据中的状态为充电,才能查到实时数据列表 return CollectionUtils.isNotEmpty(chargingRealTimeData) ? Constants.ONE : Constants.ZERO; } public void closeStartFailedOrder(QueryOrderDTO dto) { orderBasicInfoService.closeStartFailedOrder(dto.getStartTime(), dto.getEndTime()); } }