package com.jsowell.service; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.huifu.adapay.core.AdapayCore; import com.huifu.adapay.core.util.AdapaySign; import com.jsowell.adapay.vo.PaymentInfo; import com.jsowell.common.YouDianUtils; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.vo.AuthorizedDeptVO; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.core.domain.ykc.TransactionRecordsData; import com.jsowell.common.core.page.PageResponse; import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.enums.AcquirerEnum; import com.jsowell.common.enums.DelFlagEnum; import com.jsowell.common.enums.InvoiceRecordEnum; import com.jsowell.common.enums.MemberWalletEnum; import com.jsowell.common.enums.adapay.AdapayEventEnum; import com.jsowell.common.enums.adapay.AdapayPayChannelEnum; import com.jsowell.common.enums.ebike.EBikeStopReasonEnum; import com.jsowell.common.enums.uniapp.OccupyOrderPayStatusEnum; import com.jsowell.common.enums.uniapp.OccupyOrderStatusEnum; import com.jsowell.common.enums.ykc.*; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.DateUtils; import com.jsowell.common.util.SecurityUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.bean.BeanUtils; import com.jsowell.common.util.spring.SpringUtils; import com.jsowell.pile.domain.*; import com.jsowell.pile.domain.ebike.deviceupload.EBikeMessageCmd03; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.service.programlogic.AbstractProgramLogic; import com.jsowell.pile.service.programlogic.ProgramLogicFactory; import com.jsowell.pile.util.UserUtils; import com.jsowell.pile.vo.OrderPayRecordVO; import com.jsowell.pile.vo.base.OrderAmountDetailVO; import com.jsowell.pile.vo.base.OrderPeriodAmountVO; import com.jsowell.pile.vo.base.PileInfoVO; import com.jsowell.pile.vo.base.StationInfoVO; import com.jsowell.pile.vo.uniapp.customer.*; import com.jsowell.pile.vo.uniapp.customer.InvoiceRecordVO; import com.jsowell.pile.vo.web.*; import com.jsowell.thirdparty.common.CommonService; import com.jsowell.wxpay.response.WechatPayNotifyParameter; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.ParseException; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @Service public class OrderService { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private OrderBasicInfoService orderBasicInfoService; @Autowired private PileRemoteService pileRemoteService; @Autowired private PileService pileService; @Autowired private MemberService memberService; @Autowired private MemberBasicInfoService memberBasicInfoService; @Autowired private OrderPayRecordService orderPayRecordService; @Autowired private MemberTransactionRecordService memberTransactionRecordService; @Autowired private PileStationInfoService pileStationInfoService; @Autowired private OrderInvoiceRecordService orderInvoiceRecordService; @Autowired private PileStationWhitelistService pileStationWhitelistService; @Autowired private AdapayCallbackRecordService adapayCallbackRecordService; @Autowired private MemberInvoiceTitleService memberInvoiceTitleService; @Autowired private AdapayRefundRecordService adapayRefundRecordService; @Autowired private AdapayMemberAccountService adapayMemberAccountService; @Autowired private ClearingWithdrawInfoService clearingWithdrawInfoService; @Autowired private MemberAdapayRecordService memberAdapayRecordService; @Resource private OrderPileOccupyService orderPileOccupyService; @Resource private PileMerchantInfoService pileMerchantInfoService; @Resource private ClearingBillInfoService clearingBillInfoService; @Autowired private IThirdpartySnRelationService snRelationService; @Autowired private CommonService commonService; @Resource private RedisCache redisCache; @Autowired private PersonalChargingRecordService personalChargingRecordService; @Autowired private PileMsgRecordService pileMsgRecordService; @Autowired private RabbitTemplate rabbitTemplate; @Autowired private IOrderInsuranceInfoService orderInsuranceInfoService; // 引入线程池 private ThreadPoolTaskExecutor executor = SpringUtils.getBean("threadPoolTaskExecutor"); // 引入第三方平台任务线程池 private ThreadPoolTaskExecutor thirdpartyTaskExecutor = SpringUtils.getBean("thirdpartyTaskExecutor"); /** * 生成订单 * * @param dto * @return */ // @Deprecated // public String generateOrder(GenerateOrderDTO dto) throws ParseException { // OrderBasicInfo basicInfo = orderBasicInfoService.generateOrder(dto); // if (basicInfo != null) { // return basicInfo.getOrderCode(); // } // return null; // } /** * 生成订单 * * @param dto * @return */ public String generateOrderV2(GenerateOrderDTO dto) throws Exception { String delayMode = null; if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.WX_LITE.getValue())) { delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getAppId()); } else if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) { delayMode = pileMerchantInfoService.getDelayModeByAlipayAppId(dto.getAppId()); } // 新逻辑 AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(delayMode); OrderBasicInfo orderBasicInfo = orderLogic.generateOrder(dto); if (orderBasicInfo != null) { return orderBasicInfo.getOrderCode(); } return null; } /** * 订单支付 * * @param dto */ // @Deprecated // public Map payOrder(PayOrderDTO dto) throws Exception { // return orderBasicInfoService.payOrder(dto); // } /** * 订单支付 * * @param dto */ public Map payOrderV2(PayOrderDTO dto) { // String mode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId()); String delayMode = null; if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.WX_LITE.getValue())) { delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId()); } else if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) { delayMode = pileMerchantInfoService.getDelayModeByAlipayAppId(dto.getAlipayAppId()); } dto.setDelayMode(delayMode); // 获取处理逻辑 AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(delayMode); Map map = orderLogic.payOrder(dto); return map; } /** * 结算订单 * endCharging * * @param dto 结算订单参数 */ public void settleOrderForWeb(SettleOrderDTO dto) { orderBasicInfoService.analysisPileParameter(dto); // 查询订单详情,验证订单中的桩编号是否正确 OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderBasicInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL); } 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(), orderBasicInfo.getTransactionCode()); } /** * 通过会员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); } List 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"); } else if (StringUtils.equals("4", orderStatus)) { // 查询正在进行中的订单 orderStatusList.add("1"); } // 分页 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()); // 从缓存中获取充电时长 List chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderVO.getTransactionCode()); // 默认时间倒序排列,因此只取第一条就可以 if (CollectionUtils.isEmpty(chargingRealTimeData)) { orderVO.setChargingTime("-"); continue; } RealTimeMonitorData realTimeMonitorData = chargingRealTimeData.get(0); String sumChargingTime = realTimeMonitorData.getSumChargingTime(); // xx分钟 if (StringUtils.equals(orderVO.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) { if (StringUtils.isNotBlank(orderVO.getStartTime())) { // 订单如果是充电中,且开始时间不为空, 根据开始充电时间计算充电时长 sumChargingTime = String.valueOf(DateUtils.minutesSince(orderVO.getStartTime())); } } String chargingTime = "-"; try { // 分钟转成 x时x分 chargingTime = DateUtils.convertMinutesToTime(Integer.parseInt(sumChargingTime)); } catch (Exception e) { log.error("转换充电时间error, sumChargingTime:{}", sumChargingTime); } orderVO.setChargingTime(chargingTime); } // 返回结果集 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_INFO_IS_NULL); } // 判断订单状态是不是已经结算了 if (StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { throw new BusinessException(ReturnCodeEnum.CODE_ORDER_COMPLETE_ERROR); } /* 校验是否有权限操作该订单, 否则抛出异常 只有会员本人, 该桩的管理员可以操作 */ boolean permissionFlag = StringUtils.equals(orderInfo.getMemberId(), dto.getMemberId()) || UserUtils.checkStationAuth(orderInfo.getStationId()); // false无权限, true有权限 if (!permissionFlag) { throw new BusinessException(ReturnCodeEnum.CODE_NO_PERMISSION_TO_OPERATE_THE_ORDER_ERROR); } // 判断该桩是否推送了第三方站点(需要我方平台发送启动指令的,如:华为平台) List list = snRelationService.selectSnRelationListByParams(orderInfo.getStationId(), orderInfo.getPileSn(), null); if (CollectionUtils.isNotEmpty(list)) { for (ThirdPartySnRelationVO vo : list) { ThirdPartyCommonStopChargeDTO commonStopChargeDTO = new ThirdPartyCommonStopChargeDTO(); commonStopChargeDTO.setThirdPartyType(vo.getThirdPartyType()); commonStopChargeDTO.setOrderBasicInfo(orderInfo); // 调用统一停止充电接口 String result = commonService.commonStopCharge(commonStopChargeDTO); log.info("订单:{} 调用统一停止充电接口, result:{}", orderInfo, result); } }else { // 发送停止指令 pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode(), orderInfo.getTransactionCode()); } log.info("主动停止充电, orderCode:{}, transactionCode:{}, 发送停机指令成功", dto.getOrderCode(), orderInfo.getTransactionCode()); } /** * 微信退款 * * @param dto */ // public void weChatRefund(ApplyRefundDTO dto) { // log.info("微信退款接口 param:{}", JSON.toJSONString(dto)); // orderBasicInfoService.weChatRefund(dto); // } /** * 汇付退款 * * @param dto */ public void adapayRefund(ApplyRefundDTO dto) { log.info("汇付退款 param:{}", JSON.toJSONString(dto)); // 退款有两种情况 1-订单结算退款 2-用户余额退款 String refundType = dto.getRefundType(); if (StringUtils.equals(refundType, "1")) { orderBasicInfoService.refundOrderWithAdapay(dto); } else if (StringUtils.equals(refundType, "2")) { orderBasicInfoService.refundBalanceWithAdapay(dto); } else { log.warn("没有找到退款处理逻辑"); } } /** * 查询订单详情信息 * * @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.setTransactionCode(orderBasicInfo.getTransactionCode()); order.setOrderStatus(orderBasicInfo.getOrderStatus()); order.setLogicCard(orderBasicInfo.getLogicCard()); if (orderBasicInfo.getVinCode() != null) { order.setVinCode(orderBasicInfo.getVinCode()); } if (orderBasicInfo.getPlateNumber() != null) { order.setPlateNumber(orderBasicInfo.getPlateNumber()); } String describe = orderBasicInfoService.transformOrderStatusDescribe(orderBasicInfo.getOrderStatus(), orderBasicInfo.getPayStatus()); order.setOrderStatusDescribe(describe); order.setStartTime(DateUtils.formatDateTime(orderBasicInfo.getChargeStartTime())); order.setEndTime(DateUtils.formatDateTime(orderBasicInfo.getChargeEndTime())); order.setCreateTime(DateUtils.formatDateTime(orderBasicInfo.getCreateTime())); order.setStopReasonCode(orderBasicInfo.getStopReasonCode()); order.setStopReasonMsg(orderBasicInfo.getReason()); order.setStartSOC(orderBasicInfo.getStartSoc()); order.setEndSOC(orderBasicInfo.getEndSoc()); order.setOrderAmount(String.valueOf(orderBasicInfo.getOrderAmount())); order.setDiscountAmount(String.valueOf(orderBasicInfo.getDiscountAmount())); order.setSettleAmount(String.valueOf(orderBasicInfo.getSettleAmount())); order.setSettlementTime(DateUtils.formatDateTime(orderBasicInfo.getSettlementTime())); order.setMerchantId(orderBasicInfo.getMerchantId()); order.setInsuranceAmount(String.valueOf(orderBasicInfo.getInsuranceAmount())); 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(orderBasicInfo.getTransactionCode()); if (CollectionUtils.isNotEmpty(chargingRealTimeDataList)) { List infoList = Lists.newArrayList(); for (RealTimeMonitorData realTimeMonitorData : chargingRealTimeDataList) { OrderDetailInfoVO.PileMonitorData info = new OrderDetailInfoVO.PileMonitorData(); 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.setChargedDegree(realTimeMonitorData.getChargingDegree()); realTimeInfo.setChargingTime(realTimeMonitorData.getSumChargingTime()); realTimeInfo.setTime(realTimeMonitorData.getDateTime()); vo.setOrderRealTimeInfo(realTimeInfo); // 根据时间进行正序排序 infoList = infoList.stream() .sorted(Comparator.comparing(OrderDetailInfoVO.PileMonitorData::getTime)) .collect(Collectors.toList()); vo.setRealTimeMonitorDataList(infoList); // 最后一次实时数据 vo.setLastMonitorData(realTimeMonitorData); } // 支付流水对应页面支付信息 // List payRecords = orderPayRecordService.selectOrderPayInfoList(orderCode); List payRecordList = orderPayRecordService.selectOrderPayRecordList(orderCode); vo.setPayRecordList(payRecordList); // 查询退款明细 List orderRefundInfoList = orderBasicInfoService.getOrderRefundInfoList(orderBasicInfo); vo.setOrderRefundInfoList(orderRefundInfoList); // 查订单明细 OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode); if (orderDetail != null) { OrderAmountDetailVO billingDetails = new OrderAmountDetailVO(); BeanUtils.copyBeanProp(billingDetails, orderDetail); vo.setBillingDetails(billingDetails); List orderPeriodAmountVOS = orderBasicInfoService.transformPeriodAmountByOrderDetail(orderDetail); vo.setChargeDetails(orderPeriodAmountVOS); } // 用户信息 MemberVO memberVO = memberService.getMemberInfoByMemberId(orderBasicInfo.getMemberId()); vo.setMemberInfo(memberVO); try { // 因为原来的数据在redis中是永久保存,所以这里做下查询详情的时候,发现已经是完成的订单,redis数据存到表中 if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { // 如果是已完成的订单,把redis中的实时数据存到表中 orderBasicInfoService.realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode()); } } catch (Exception e) { log.error("后管查询订单详情时把redis中的实时数据存到表发生异常", e); } try { if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) { RealTimeMonitorData lastMonitorData = vo.getLastMonitorData(); if (lastMonitorData == null || DateUtils.intervalTime(lastMonitorData.getDateTime(), DateUtils.getDateTime()) > 2L) { // 没有实时数据 或者 间隔时间超过2分钟, 订单状态修改为异常 orderBasicInfo.setOrderStatus(OrderStatusEnum.ABNORMAL.getValue()); orderBasicInfo.setReason("充电桩长时间没有上传实时数据"); orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo); } } } catch (Exception e) { log.error("后管查询订单详情时校验订单状态", e); } return vo; } /** * 微信支付退款回调 * * @param request * @param body * @throws Exception */ 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); OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode); UniAppOrderVO vo = new UniAppOrderVO(); if (orderBasicInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL); } String pileSn = orderBasicInfo.getPileSn(); String connectorCode = orderBasicInfo.getConnectorCode(); // 异步发送获取实时数据指令 if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) { CompletableFuture.runAsync(() -> { try { pileRemoteService.getRealTimeMonitorData(pileSn, connectorCode); } catch (Exception e) { log.error("异步发送获取实时数据指令error", e); } }, executor); } vo.setOrderCode(orderBasicInfo.getOrderCode()); vo.setPileSn(pileSn); vo.setConnectorCode(connectorCode); vo.setPileConnectorCode(pileSn + connectorCode); String orderStatus = orderBasicInfo.getOrderStatus(); vo.setOrderStatus(orderStatus); // 订单状态描述 String orderStatusDescribe = orderBasicInfoService.transformOrderStatusDescribe(orderStatus, orderBasicInfo.getPayStatus()); vo.setOrderStatusDescribe(orderStatusDescribe); if (Objects.nonNull(orderBasicInfo.getChargeStartTime())) { 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.setStopReasonCode(orderBasicInfo.getStopReasonCode()); vo.setReason(orderBasicInfo.getReason()); vo.setOrderAmount(String.valueOf(orderBasicInfo.getOrderAmount())); vo.setPayAmount(String.valueOf(orderBasicInfo.getPayAmount())); vo.setPayMode(orderBasicInfo.getPayMode()); vo.setRemedialAmount(String.valueOf(orderBasicInfo.getRemedialAmount())); if (StringUtils.isNotBlank(String.valueOf(stationInfo.getFreeTime()))) { vo.setFreeTime(stationInfo.getFreeTime()); } if (StringUtils.isNotBlank(String.valueOf(stationInfo.getOccupyFee()))) { vo.setOccupyFee(stationInfo.getOccupyFee()); } // 获取充电桩枪口信息 PileConnectorDetailVO pileConnectorDetailVO = pileService.queryPileConnectorDetail(vo.getPileConnectorCode()); if (pileConnectorDetailVO != null) { vo.setPileConnectorStatus(pileConnectorDetailVO.getConnectorStatus()); } // 优惠金额 vo.setDiscountAmount(String.valueOf(orderBasicInfo.getDiscountAmount())); // 实付金额 vo.setActualAmount(String.valueOf(orderBasicInfo.getOrderAmount().subtract(orderBasicInfo.getDiscountAmount()))); // 获取订单充电数据 List monitorDataList = orderBasicInfoService.getChargingRealTimeData(orderBasicInfo.getTransactionCode()); 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, RoundingMode.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 = BigDecimal.ZERO; if (monitorData.getChargingAmount() != null) { chargingAmount = new BigDecimal(monitorData.getChargingAmount()).setScale(4, RoundingMode.HALF_UP); // 充电金额 } vo.setChargingAmount(chargingAmount.toString()); BigDecimal chargingDegree = BigDecimal.ZERO; if (monitorData.getChargingDegree() != null) { chargingDegree = new BigDecimal(monitorData.getChargingDegree()).setScale(4, RoundingMode.HALF_UP); // 充电度数 } vo.setChargingDegree(chargingDegree.toString()); vo.setSumChargingTime(monitorData.getSumChargingTime()); vo.setTimeRemaining(monitorData.getTimeRemaining()); } } // monitorDataList是按照时间倒序的,chargingDataList需要按照时间正序 Collections.reverse(chargingDataList); vo.setChargingDataList(chargingDataList); } if (orderDetail != null) { OrderAmountDetailVO billingDetails = new OrderAmountDetailVO(); BeanUtils.copyBeanProp(billingDetails, orderDetail); vo.setBillingDetails(billingDetails); if (StringUtils.equals(OrderStatusEnum.ORDER_COMPLETE.getValue(), orderStatus)) { BigDecimal totalUsedElectricity = orderDetail.getTotalUsedElectricity(); if (totalUsedElectricity != null && StringUtils.isNotBlank(vo.getChargingAmount()) && totalUsedElectricity.compareTo(new BigDecimal(vo.getChargingAmount())) > 0) { vo.setChargingDegree(String.valueOf(totalUsedElectricity)); } } } // 因为原来的数据在redis中是永久保存,所以这里做下查询详情的时候,发现已经是完成的订单,redis数据存到表中 CompletableFuture.runAsync(() -> { try { if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { // 如果是已完成的订单,把redis中的实时数据存到表中 orderBasicInfoService.realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode()); } } catch (Exception e) { log.error("后管查询订单详情时把redis中的实时数据存到表发生异常", e); } }, executor); return vo; } /** * 根据订单号查询充电桩启动状态 * * @param orderCode 订单编号 * @return 0: 未启动,1: 启动成功,2: 启动失败 */ public Map selectPileStarterStatus(String orderCode) { OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); if (orderInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL); } String status = Constants.ZERO; String reason = null; // 如果是订单完成状态 if (StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { status = Constants.TWO; reason = orderInfo.getReason(); } else { // 查询订单的实时监测数据 List chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderInfo.getTransactionCode()); if (CollectionUtils.isNotEmpty(chargingRealTimeData)) { // 实时监测数据不为空说明已经在充电中了 status = Constants.ONE; } } Map resultMap = Maps.newHashMap(); resultMap.put("status", status); resultMap.put("reason", reason); resultMap.put("orderCode", orderInfo.getOrderCode()); resultMap.put("pileConnectorCode", orderInfo.getPileConnectorCode()); return resultMap; } /** * 关闭支付未启动的订单 * * @param dto */ public void closeStartFailedOrder(QueryOrderDTO dto) { orderBasicInfoService.closeStartFailedOrder(dto.getStartTime(), dto.getEndTime()); } /** * 人工结算订单 * * @param dto */ public boolean manualSettlementOrder(ManualSettlementDTO dto) { log.info("人工结算订单-begin param:{}", JSON.toJSONString(dto)); // 查询订单 OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderBasicInfo == null) { log.info("人工结算订单-根据订单号:{}, 查询为null", dto.getOrderCode()); return false; } // 当前登录用户,是否可以结算该订单 AuthorizedDeptVO authorizedMap = UserUtils.getAuthorizedMap(); if (authorizedMap == null) { log.info("人工结算订单-当前登录管理员无权限"); return false; } String pileSn = orderBasicInfo.getPileSn(); try { // 发送停止充电指令 pileRemoteService.remoteStopCharging(pileSn, orderBasicInfo.getConnectorCode(), orderBasicInfo.getTransactionCode()); }catch (Exception e) { log.error("人工结算订单-发送停止充电指令 error, ", e); } List stationDeptIds = authorizedMap.getStationDeptIds(); if (CollectionUtils.isEmpty(stationDeptIds)) { // 运营商管理员 List merchantDeptIds = authorizedMap.getMerchantDeptIds(); } // 初始化data TransactionRecordsData data = null; // 充电金额 String chargingAmount = dto.getChargingAmount(); // 充电度数 String chargingDegree = dto.getChargingDegree(); // 获取订单结算时间 // Date settlementTime = orderBasicInfo.getSettlementTime(); // 获取订单停止充电时间 // Date chargeEndTime = orderBasicInfo.getChargeEndTime(); // 如果订单结算时间与订单停止充电时间都为空,则打印错误信息并返回 // if (settlementTime == null && chargeEndTime == null) { // log.error("人工结算订单 error -订单结算时间与订单停止充电时间都为空"); // return false; // } // LocalDateTime localDateTime = DateUtils.date2LocalDateTime(settlementTime != null ? settlementTime : chargeEndTime); // 开始时间为localDateTime减30秒 // LocalDateTime startTime = localDateTime.minusSeconds(30); // 结束时间为localDateTime加30秒 // LocalDateTime endTime = localDateTime.plusSeconds(30); // 查询这笔订单的交易记录原始数据 // List pileFeedListV2 = pileMsgRecordService.getPileFeedListV2(orderBasicInfo.getPileSn(), "0x3B", startTime, endTime); List pileFeedListV2 = pileMsgRecordService.queryPileFeedList(orderBasicInfo.getPileSn(), "0x3B", orderBasicInfo.getTransactionCode()); for (PileMsgRecord pileMsgRecord : pileFeedListV2) { TransactionRecordsData parse = JSONObject.parseObject(pileMsgRecord.getJsonMsg(), TransactionRecordsData.class); log.info("人工结算订单-parse:{}, orderBasicInfo:{}", parse.getTransactionCode(), orderBasicInfo.getTransactionCode()); if (StringUtils.equals(parse.getTransactionCode(), orderBasicInfo.getTransactionCode())) { data = parse; data.setVinCode(""); } } // 如果订单的交易记录为空 if (data == null) { data = new TransactionRecordsData(); // TODO 以前端传的值为准,如果没有传值则查最后一次实时数据 if (StringUtils.equals(chargingAmount, Constants.ZERO) || StringUtils.equals(chargingDegree, Constants.ZERO)) { // 获取最后一次实时数据 List chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderBasicInfo.getTransactionCode()); if (CollectionUtils.isNotEmpty(chargingRealTimeData)) { RealTimeMonitorData realTimeMonitorData = chargingRealTimeData.get(0); chargingAmount = realTimeMonitorData.getChargingAmount(); chargingDegree = realTimeMonitorData.getChargingDegree(); data.setConsumptionAmount(chargingAmount); // 总消费金额 data.setTotalElectricity(chargingDegree); // 总用电量 data.setStopReasonMsg("人工结算订单,操作人:" + SecurityUtils.getUsername()); // 停止原因 } } } // 查询订单退款记录,如存在退款说明已经结算过,不能再次结算 List orderRefundInfoList = orderBasicInfoService.getOrderRefundInfoList(orderBasicInfo); if (CollectionUtils.isNotEmpty(orderRefundInfoList)) { // 已退款金额 BigDecimal refunded = orderRefundInfoList.stream() .map(x -> Objects.nonNull(x.getReverseAmt()) ? new BigDecimal(x.getReverseAmt()) : BigDecimal.ZERO) .reduce(BigDecimal.ZERO,BigDecimal::add); if (Objects.nonNull(orderBasicInfo.getPayAmount())) { chargingAmount = orderBasicInfo.getPayAmount().subtract(refunded).toString(); log.info("订单:{}, 已经存在退款记录:{}, 支付金额{}, 退款金额:{}, 重新计算消费金额为:{}", orderBasicInfo.getOrderCode(), JSON.toJSONString(orderRefundInfoList), orderBasicInfo.getPayAmount(), refunded, chargingAmount); } } // 结算订单 新逻辑 String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId()); AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode); // 判断汽车还是电单车 if (YouDianUtils.isEBikePileSn(pileSn)) { // 电单车桩 EBikeMessageCmd03 message = new EBikeMessageCmd03(new BigDecimal(chargingDegree), EBikeStopReasonEnum.EXTERNAL_OPERATION_STOPPED.getCode()); orderLogic.settleOrderForEBike(message, orderBasicInfo); } else { // 汽车桩 // 组装交易记录数据 // TransactionRecordsData data = new TransactionRecordsData(); // data.setConsumptionAmount(chargingAmount); // 总消费金额 // data.setTotalElectricity(chargingDegree); // 总用电量 // data.setStopReasonMsg("人工结算订单,操作人:" + SecurityUtils.getUsername()); // 停止原因 orderLogic.settleOrder(data, orderBasicInfo); } log.info("人工结算订单-end orderCode:{}", dto.getOrderCode()); // 异步推送第三方平台订单信息 CompletableFuture.runAsync(() -> { try { commonService.commonPushOrderInfo(orderBasicInfo); } catch (Exception e) { log.error("人工结算订单 推送第三方平台订单信息error, orderCode:{}", orderBasicInfo.getOrderCode(), e); } }, thirdpartyTaskExecutor); // TODO 测试mq // 向mq中发送实时数据消息,给第三方服务消费 // CompletableFuture.runAsync(() -> { // try { // rabbitTemplate.convertAndSend(ThirdPartyRabbitConstants.WCC_THIRDPARTY_NAME , ThirdPartyRabbitConstants.ROUTING_KEY_CHARGE_ORDER_PUSH ,orderBasicInfo ); // } catch (Exception e) { // log.error("向mq中发送实时数据消息供第三方服务消费 error, " , e); // } // }, thirdpartyTaskExecutor); return true; } /** * 当前登录会员 获取支付方式 * * @param dto */ public List getPayMode(GetPayModeDTO dto) { log.info("当前登录会员 获取支付方式, param:{}, 请求来源:{}", JSON.toJSONString(dto), dto.getRequestSource()); List result = Lists.newArrayList(); // 查询会员在站点是否是白名单用户 PileStationWhitelist whitelist = pileStationWhitelistService.queryWhitelistByMemberId(dto.getStationId(), dto.getMemberId()); // 查询是否为平台测试员 PlatformTesterVO platformTesterVO = memberBasicInfoService.selectPlatformTesterStatus(dto.getMemberId()); // 根据memberId查询该用户是否是希晓的会员 MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(dto.getMemberId()); boolean flag = whitelist != null || StringUtils.equals(platformTesterVO.getStatus(), Constants.ONE); if (flag) { result.add( PayModeVO.builder() .payModeCode(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue()) .payModeName(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getLabel()) .build() ); } else { // 微信支付 if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.WX_LITE.getValue())) { result.add( PayModeVO.builder() .payModeCode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .payModeName(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getLabel()) .build() ); } // 支付宝支付 if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) { result.add( PayModeVO.builder() .payModeCode(OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue()) .payModeName(OrderPayModeEnum.PAYMENT_OF_ALIPAY.getLabel()) .build() ); } // 如果是希晓的会员,将余额支付添加进去 // if (MerchantUtils.isXiXiaoMerchant(String.valueOf(memberBasicInfo.getMerchantId()))) { // 35-希晓 // // 余额支付 // result.add( // PayModeVO.builder() // .payModeCode(OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getValue()) // .payModeName(OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getLabel()) // .build() // ); // } // 2024年9月27日09点49分 开启余额支付 result.add( PayModeVO.builder() .payModeCode(OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getValue()) .payModeName(OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getLabel()) .build() ); } return result; } /** * 查询未开发票订单 * 时间限制15天内 * * @param dto * @return */ public List queryUninvoicedOrderList(QueryOrderDTO dto) { int i = 15; // 查询最近15天完成的订单 LocalDateTime dateTime = LocalDateTime.now().plusDays(-i); List orderList = orderBasicInfoService.getListByMemberIdAndOrderStatus(dto.getMemberId(), Lists.newArrayList("6"), dateTime); // 过滤掉订单金额为0的 orderList = orderList.stream() .filter(x -> x.getSettleAmount().compareTo(BigDecimal.ZERO) > 0) .collect(Collectors.toList()); if (CollectionUtils.isEmpty(orderList)) { return orderList; } // 查询最近60天申请开票记录 QueryInvoiceRecordDTO build = QueryInvoiceRecordDTO.builder() .memberId(dto.getMemberId()) .startTime(dateTime) .build(); List orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceRecordList(build); if (CollectionUtils.isEmpty(orderInvoiceRecords)) { return orderList; } // 排除掉已经申请过的订单 List orderCodeList = orderInvoiceRecords.stream() // 转化为 Stream .map(OrderInvoiceRecord::getOrderCodes) // 获取 OrderInvoiceRecord 中的 orderCodes 字符串 .flatMap(str -> Arrays.stream(str.split(Constants.DEFAULT_DELIMITER))) // 分隔逗号并转化为 Stream .collect(Collectors.toList()); // 收集为 List orderList = orderList.stream() .filter(x -> !orderCodeList.contains(x.getOrderCode())) .collect(Collectors.toList()); return orderList; } public List queryUninvoicedStationList(QueryOrderDTO dto) { return Lists.newArrayList(); } /** * 申请开票 * * @param dto */ public void applyOrderInvoice(ApplyOrderInvoiceDTO dto) { int i = 15; // 查询最近15天完成的订单 LocalDateTime dateTime = LocalDateTime.now().plusDays(-i); // 查询最近15天 会员的开票记录 List orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceRecordList(dto.getMemberId(), dateTime, LocalDateTime.now()); List orderCodeList = orderInvoiceRecords.stream() // 转化为 Stream .map(OrderInvoiceRecord::getOrderCodes) // 获取 OrderInvoiceRecord 中的 orderCodes 字符串 .flatMap(str -> Arrays.stream(str.split(Constants.DEFAULT_DELIMITER))) // 分隔逗号并转化为 Stream .collect(Collectors.toList()); // 收集为 List // 取交集 校验订单是否已经开票 Set intersection = Sets.intersection(Sets.newHashSet(orderCodeList), Sets.newHashSet(dto.getOrderCodes())); if (CollectionUtils.isNotEmpty(intersection)) { log.info("申请开票前端传的:{}订单号list, 包含已经申请的订单:{}", dto.getOrderCodes(), intersection); return; } // 查抬头信息 MemberInvoiceTitle invoiceTitle = memberInvoiceTitleService.selectMemberInvoiceTitleById(Long.parseLong(dto.getTitleId())); if (StringUtils.isNotEmpty(dto.getReception())) { boolean b = false; if (StringUtils.isEmail(dto.getReception()) && !StringUtils.equals(dto.getReception(), invoiceTitle.getEmail())) { invoiceTitle.setEmail(dto.getReception()); b = true; } if (StringUtils.isPhoneNumber(dto.getReception()) && !StringUtils.equals(dto.getReception(), invoiceTitle.getPhoneNumber())) { invoiceTitle.setPhoneNumber(dto.getReception()); b = true; } if (b) { memberInvoiceTitleService.updateMemberInvoiceTitle(invoiceTitle); } } // 整理数据 List orderVOList = orderBasicInfoService.getListByOrderCodes(dto.getOrderCodes()); // 根据运营商分组 Map> map = orderVOList.stream().collect(Collectors.groupingBy(OrderVO::getMerchantId)); BigDecimal totalAmount = null; BigDecimal totalElecAmount = null; BigDecimal totalServiceAmount = null; // 根据运营商创建多笔开票记录 for (Map.Entry> entry : map.entrySet()) { totalAmount = BigDecimal.ZERO; totalElecAmount = BigDecimal.ZERO; totalServiceAmount = BigDecimal.ZERO; List orders = entry.getValue(); for (OrderVO orderVO : orders) { totalAmount = totalAmount.add(orderVO.getOrderAmount()); totalElecAmount = totalElecAmount.add(orderVO.getTotalElectricityAmount()); totalServiceAmount = totalServiceAmount.add(orderVO.getTotalServiceAmount()); } // 入库 OrderInvoiceRecord orderInvoiceRecord = new OrderInvoiceRecord(); orderInvoiceRecord.setStatus(Constants.ZERO); orderInvoiceRecord.setMemberId(dto.getMemberId()); orderInvoiceRecord.setMerchantId(entry.getKey()); orderInvoiceRecord.setTitleId(dto.getTitleId()); orderInvoiceRecord.setOrderCodes(String.join(Constants.DEFAULT_DELIMITER, dto.getOrderCodes())); orderInvoiceRecord.setTotalAmount(totalAmount); orderInvoiceRecord.setTotalElecAmount(totalElecAmount); orderInvoiceRecord.setTotalServiceAmount(totalServiceAmount); orderInvoiceRecordService.insertOrderInvoiceRecord(orderInvoiceRecord); } } /** * 查询开票记录 * * @param dto * @return */ public PageResponse queryInvoiceRecord(QueryInvoiceRecordDTO dto) { QueryInvoiceRecordDTO build = QueryInvoiceRecordDTO.builder() .memberId(dto.getMemberId()) .build(); int pageNo = dto.getPageNo() == null ? 1 : dto.getPageNo(); int pageSize = dto.getPageSize() == null ? 10 : dto.getPageSize(); PageHelper.startPage(pageNo, pageSize); // List orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceRecordList(build); List orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceVOList(build); PageInfo pageInfo = new PageInfo<>(orderInvoiceRecords); List volist = Lists.newArrayList(); for (OrderInvoiceRecordVO vo : orderInvoiceRecords) { volist.add( InvoiceRecordVO.builder() .status(InvoiceRecordEnum.getLabel(vo.getStatus())) .totalAmount(vo.getTotalAmount()) .totalElecAmount(vo.getTotalElecAmount()) .totalServiceAmount(vo.getTotalServiceAmount()) .merchantName(vo.getMerchantName()) .merchantTel(vo.getMerchantTel()) .createTime(vo.getCreateTime()) .build() ); } return PageResponse.builder() .total(pageInfo.getTotal()) .pages(pageInfo.getPages()) .pageNum(pageInfo.getPageNum()) .pageSize(pageInfo.getPageSize()) .list(volist) .build(); } /** * 汇付支付 支付回调 * * @param request * @throws Exception */ public void adapayCallback(HttpServletRequest request) throws Exception { // 验签请参data String data = request.getParameter("data"); // 验签请参sign String sign = request.getParameter("sign"); // 验签请参publicKey String publicKey = AdapayCore.PUBLIC_KEY; log.info("汇付支付回调验签请参data={}, sign={}", data, sign); // 验签标记 boolean checkSign = AdapaySign.verifySign(data, sign, publicKey); if (!checkSign) { log.info("汇付支付回调验签失败:{}", data); return; } // type String type = request.getParameter("type"); // 根据type执行不同逻辑 if (AdapayEventEnum.payment_succeeded.getValue().equals(type)) { // 支付成功 paymentSucceeded(data); } else if (AdapayEventEnum.refund_succeeded.getValue().equals(type)) { // 退款成功 refundSucceeded(data); } else if (AdapayEventEnum.refund_failed.getValue().equals(type)) { // 退款失败 refundFailed(data); } else if (AdapayEventEnum.corp_member_failed.getValue().equals(type)) { // 开户失败 删除 corpMemberFailed(data); } else if (AdapayEventEnum.corp_member_succeeded.getValue().equals(type)) { // 开户成功 corpMemberSucceeded(data); } else if (AdapayEventEnum.payment_reverse_succeeded.getValue().equals(type)) { // 支付撤销成功 paymentReverseSucceeded(data); } else if (AdapayEventEnum.payment_reverse_failed.getValue().equals(type)) { // 支付撤销失败 paymentReverseFailed(data); } else if (AdapayEventEnum.cash_succeeded.getValue().equals(type)) { // 取现成功 cashSucceeded(data); } else if (AdapayEventEnum.cash_failed.getValue().equals(type)) { // 取现失败 cashFailed(data); } } /** * adapay支付成功回调 * * @param data * @throws JsonProcessingException */ @Transactional(rollbackFor = Exception.class) public void paymentSucceeded(String data) throws JsonProcessingException { // 验签成功 保存到回调记录表中 JSONObject jsonObject = JSON.parseObject(data); log.info("adapay支付成功回调:{}", jsonObject.toJSONString()); ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); AdapayCallbackRecord adapayCallbackRecord = mapper.readValue(jsonObject.toJSONString(), AdapayCallbackRecord.class); // 支付扩展域 adapayCallbackRecord.setExpend(jsonObject.getString("expend")); // 支付id String paymentId = jsonObject.getString("id"); adapayCallbackRecord.setPaymentId(paymentId); // 订单附加说明 JSONObject descJson = JSON.parseObject(adapayCallbackRecord.getDescription()); // 支付回调中包含的场景类型 String scenarioType = descJson.getString("type"); adapayCallbackRecord.setPayScenario(scenarioType); // 支付回调中包含的会员id String memberId = descJson.getString("memberId"); adapayCallbackRecord.setMemberId(memberId); // 支付回调中包含的订单编号 String orderCode = descJson.getString("orderCode"); adapayCallbackRecord.setOrderCode(orderCode); // 支付金额 BigDecimal amount = adapayCallbackRecord.getPayAmt(); // 保存到数据库 adapayCallbackRecordService.saveAdapayCallbackRecord(adapayCallbackRecord); // 保存MemberAdapayRecord MemberAdapayRecord memberAdapayRecord = new MemberAdapayRecord(); memberAdapayRecord.setMemberId(memberId); memberAdapayRecord.setPaymentId(paymentId); memberAdapayRecord.setPaymentOrderNo(adapayCallbackRecord.getOutTransId()); memberAdapayRecord.setScenarioType(scenarioType); memberAdapayRecord.setPayAmt(amount); memberAdapayRecord.setRefundAmt(BigDecimal.ZERO); memberAdapayRecord.setSpendAmt(BigDecimal.ZERO); memberAdapayRecord.setFreezeAmt(BigDecimal.ZERO); memberAdapayRecord.setBalanceAmt(amount); memberAdapayRecordService.insertSelective(memberAdapayRecord); // 微信支付订单 记录会员交易流水 MemberTransactionRecord record = MemberTransactionRecord.builder() .orderCode(orderCode) .scenarioType(scenarioType) .memberId(memberId) .actionType(ActionTypeEnum.FORWARD.getValue()) .payMode(PayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .paymentInstitutions(PaymentInstitutionsEnum.ADAPAY.getValue()) .amount(amount) // 单位元 .outTradeNo(adapayCallbackRecord.getPartyOrderId()) .transactionId(adapayCallbackRecord.getOutTransId()) .build(); memberTransactionRecordService.insertSelective(record); if (StringUtils.equals(scenarioType, ScenarioEnum.ORDER.getValue())) { // 1-订单支付 PaymentInfo paymentInfo = new PaymentInfo(); paymentInfo.setPaymentId(paymentId); paymentInfo.setAmount(amount.toString()); String payModel = OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue(); String payChannel = jsonObject.getString("pay_channel"); if (StringUtils.isNotEmpty(payChannel) && AdapayPayChannelEnum.ALIPAY_LITE.getValue().equals(payChannel)) { payModel = OrderPayRecordEnum.ALIPAY_PAYMENT.getValue(); } // 记录订单支付流水 OrderPayRecord orderPayRecord = OrderPayRecord.builder() .orderCode(orderCode) .payMode(payModel) .paymentId(paymentId) .payAmount(amount) .acquirer(AcquirerEnum.ADAPAY.getValue()) .deductionRecord(JSON.toJSONString(paymentInfo)) .createBy(memberId) .delFlag(DelFlagEnum.NORMAL.getValue()) .build(); orderPayRecordService.batchInsert(Lists.newArrayList(orderPayRecord)); // 更新冻结金额 支付成功后全部冻结 CompletableFuture.runAsync(() -> { try { memberAdapayRecordService.updateFreezeAmount(paymentId, amount); } catch (Exception e) { log.error("更新冻结金额 支付成功后全部冻结error", e); } }, executor); // 初始化充电金额 BigDecimal chargeAmount = amount; OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); BigDecimal insuranceAmount = orderBasicInfo.getInsuranceAmount(); if (insuranceAmount.compareTo(BigDecimal.ZERO) > 0) { // 如果用户支付了保险金额,则充电金额需将保险金额减去 chargeAmount = amount.subtract(insuranceAmount).setScale(2, RoundingMode.HALF_UP); } // 支付订单成功 PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(chargeAmount) // amount // .payMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .payMode(payModel) .acquirer(AcquirerEnum.ADAPAY.getValue()) .build(); // 订单支付成功 支付回调 orderBasicInfoService.payOrderSuccessCallback(callbackDTO); // 订单在线支付成功回调 // 异步判断是否对接了类似华为平台,如果是,走通用第三方平台启动充电逻辑 CompletableFuture.runAsync(() -> { try { checkThirdPartyQueryStartCharge(orderCode); } catch (Exception e) { log.error("异步推送第三方平台启动充电逻辑 error", e); } }, thirdpartyTaskExecutor); } else if (StringUtils.equals(scenarioType, ScenarioEnum.BALANCE.getValue())) { // 2-充值余额 // 充值余额成功 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); } else if (StringUtils.equals(scenarioType, ScenarioEnum.OCCUPY.getValue())) { // 占桩订单 // 通过订单号查询出占桩订单信息 OrderPileOccupy orderPileOccupy = orderPileOccupyService.queryByOccupyCode(orderCode); // 订单状态改为 1-订单完成 orderPileOccupy.setStatus(OccupyOrderStatusEnum.ORDER_COMPLETE.getCode()); // 支付状态改为 1-支付完成 orderPileOccupy.setPayStatus(OccupyOrderPayStatusEnum.PAYMENT_COMPLETION.getCode()); orderPileOccupyService.updateByPrimaryKey(orderPileOccupy); } } /** * 汇付退款成功 */ private void refundSucceeded(String data) { log.info("退款成功 data:{}", JSON.toJSONString(data)); // 保存退款回调记录 adapayRefundRecordService.saveAdapayRefundRecord(data); JSONObject jsonObject = JSON.parseObject(data); JSONObject reason = jsonObject.getJSONObject("reason"); if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) { // 这笔支付订单原来是充值余额的,退款成功了,需要扣掉会员的本金金额 UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO(); String memberId = reason.getString("memberId"); dto.setMemberId(memberId); dto.setUpdatePrincipalBalance(new BigDecimal(jsonObject.getString("refund_amt"))); // 更新会员本金金额,单位元 dto.setType(MemberWalletEnum.TYPE_OUT.getValue()); dto.setSubType(MemberWalletEnum.SUBTYPE_USER_REFUND.getValue()); memberBasicInfoService.updateMemberBalance(dto); // 收到回调,删除缓存 String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId; redisCache.deleteObject(redisKey); } } /** * 退款失败 * * @param data */ private void refundFailed(String data) { log.info("退款失败 data:{}", JSON.toJSONString(data)); JSONObject jsonObject = JSON.parseObject(data); JSONObject reason = jsonObject.getJSONObject("reason"); if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) { String memberId = reason.getString("memberId"); // 收到回调,删除缓存 String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId; redisCache.deleteObject(redisKey); } } /** * 对公账户创建失败 */ private void corpMemberFailed(String data) { log.info("对公账户创建失败 data:{}", JSON.toJSONString(data)); // 删除表中的记录 JSONObject jsonObject = JSON.parseObject(data); String memberId = jsonObject.getString("member_id"); if (StringUtils.isBlank(memberId)) { return; } AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByAdapayMemberId(memberId); if (adapayMemberAccount == null) { return; } adapayMemberAccount.setStatus(Constants.TWO); if (Objects.nonNull(jsonObject.getString("audit_desc"))) { adapayMemberAccount.setRemark(jsonObject.getString("audit_desc")); } // 逻辑删除记录,并删除缓存 adapayMemberAccountService.updateAdapayMemberAccount(adapayMemberAccount); } /** * 对公账户创建成功 */ private void corpMemberSucceeded(String data) { log.info("对公账户创建成功 data:{}", JSON.toJSONString(data)); JSONObject jsonObject = JSON.parseObject(data); String memberId = jsonObject.getString("member_id"); if (StringUtils.isBlank(memberId)) { return; } AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByAdapayMemberId(memberId); if (adapayMemberAccount == null) { return; } adapayMemberAccount.setStatus(Constants.ONE); if (Objects.nonNull(jsonObject.getString("audit_desc"))) { adapayMemberAccount.setRemark(jsonObject.getString("audit_desc")); } adapayMemberAccount.setDelFlag(DelFlagEnum.NORMAL.getValue()); adapayMemberAccountService.updateAdapayMemberAccount(adapayMemberAccount); } /** * 取现成功 */ private void cashSucceeded(String data) { log.info("取现成功 data:{}", JSON.toJSONString(data)); JSONObject jsonObject = JSON.parseObject(data); String withdrawCode = jsonObject.getString("id"); // 通过取现id查询取现数据 ClearingWithdrawInfo clearingWithdrawInfo = clearingWithdrawInfoService.selectByWithdrawCode(withdrawCode); if (clearingWithdrawInfo != null) { clearingWithdrawInfo.setWithdrawStatus(Constants.ONE); clearingWithdrawInfo.setUpdateTime(DateUtils.getNowDate()); clearingWithdrawInfoService.updateByPrimaryKeySelective(clearingWithdrawInfo); } // 清分账单数据更新 List clearingBillInfos = clearingBillInfoService.selectByWithdrawCode(withdrawCode); if (CollectionUtils.isNotEmpty(clearingBillInfos)) { for (ClearingBillInfo clearingBillInfo : clearingBillInfos) { clearingBillInfo.setBillStatus("4"); } clearingBillInfoService.updateBatchSelective(clearingBillInfos); } } /** * 取现失败 * * @param data */ private void cashFailed(String data) { log.info("取现失败 data:{}", JSON.toJSONString(data)); JSONObject jsonObject = JSON.parseObject(data); String withdrawCode = jsonObject.getString("id"); // 通过取现id查询取现数据 ClearingWithdrawInfo clearingWithdrawInfo = clearingWithdrawInfoService.selectByWithdrawCode(withdrawCode); clearingWithdrawInfo.setWithdrawStatus(Constants.TWO); clearingWithdrawInfo.setUpdateTime(DateUtils.getNowDate()); clearingWithdrawInfoService.updateByPrimaryKeySelective(clearingWithdrawInfo); } /** * 支付撤销成功 */ private void paymentReverseSucceeded(String data) { log.info("支付撤销成功 data:{}", JSON.toJSONString(data)); JSONObject jsonObject = JSON.parseObject(data); JSONObject reason = jsonObject.getJSONObject("reason"); if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) { // 这笔支付订单原来是充值余额的,退款成功了,需要扣掉会员的本金金额 UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO(); String memberId = reason.getString("memberId"); dto.setMemberId(memberId); dto.setUpdatePrincipalBalance(new BigDecimal(jsonObject.getString("reverse_amt"))); // 更新会员本金金额,单位元 dto.setType(MemberWalletEnum.TYPE_OUT.getValue()); dto.setSubType(MemberWalletEnum.SUBTYPE_USER_REFUND.getValue()); memberBasicInfoService.updateMemberBalance(dto); // 收到回调,删除缓存 String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId; redisCache.deleteObject(redisKey); } } /** * 支付撤销失败 */ private void paymentReverseFailed(String data) { log.info("支付撤销失败 data:{}", JSON.toJSONString(data)); JSONObject jsonObject = JSON.parseObject(data); JSONObject reason = jsonObject.getJSONObject("reason"); if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) { String memberId = reason.getString("memberId"); // 收到回调,删除缓存 String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId; redisCache.deleteObject(redisKey); } } public Map payOccupyPileOrder(PayOrderDTO dto) { return orderPileOccupyService.payOccupyPileOrder(dto); } /** * 判断是否对接了类似华为平台的第三方平台,并启动充电 * @param orderCode */ private boolean checkThirdPartyQueryStartCharge(String orderCode) { // 根据订单号查询订单信息 OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); String stationId = orderInfo.getStationId(); String pileSn = orderInfo.getPileSn(); // 根据 stationId 查询 pile_sn_relation 表 List snRelations = snRelationService.selectSnRelationListByParams(stationId, pileSn, null); if (CollectionUtils.isEmpty(snRelations)) { return false; } for (ThirdPartySnRelationVO snRelation : snRelations) { String startMode = snRelation.getStartMode(); String thirdPartyType = snRelation.getThirdPartyType(); if (StringUtils.equals(Constants.ONE, startMode)) { // 如果 startMode 为 1,则调用第三方平台启动充电接口 ThirdPartyCommonStartChargeDTO dto = new ThirdPartyCommonStartChargeDTO(); dto.setPayMode(orderInfo.getPayMode()); dto.setStationIds(Lists.newArrayList(stationId)); dto.setPileConnectorCode(orderInfo.getPileConnectorCode()); dto.setThirdPartyType(thirdPartyType); dto.setOrderCode(orderCode); String result = commonService.commonQueryStartCharge(dto); log.info("异步判断是否对接第三方平台 stationId:{}, thirdPartyType:{}, result:{}", stationId, thirdPartyType, result); } } // 判断是否对接了类似华为平台 // List relationInfoList = thirdPartyStationRelationService.getRelationInfoList(stationId); // if (CollectionUtils.isEmpty(relationInfoList)) { // return false; // } // for (ThirdPartyStationRelationVO vo : relationInfoList) { // String startMode = vo.getStartMode(); // if (StringUtils.equals(Constants.TWO, startMode)) { // continue; // } // ThirdPartyCommonStartChargeDTO dto = new ThirdPartyCommonStartChargeDTO(); // dto.setPayMode(orderInfo.getPayMode()); // dto.setStationIds(Lists.newArrayList(stationId)); // dto.setPileConnectorCode(orderInfo.getPileConnectorCode()); // dto.setThirdPartyType(vo.getThirdPartyType()); // // String result = commonService.commonQueryStartCharge(dto); // log.info("异步判断是否对接第三方平台 result:{}", result); // } return true; } /** * 保存蓝牙充电记录 * @param dto */ public void saveBluetoothChargingRecord(BluetoothChargingRecordDTO dto) { PersonalChargingRecord record = new PersonalChargingRecord(); record.setTransactionCode(dto.getTrxSN()); record.setStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); record.setMemberId(dto.getMemberId()); // record.setStationId(dto.getStationId()); // record.setMerchantId(dto.getMerchantId()); record.setPileSn(dto.getPileNo()); record.setConnectorCode(dto.getPlugNo()); record.setPileConnectorCode(record.getPileSn() + record.getConnectorCode()); record.setLogicCard(dto.getPCardID()); record.setVinCode(dto.getVin()); record.setStartMode(dto.getStartMode()); // record.setPlateNumber(dto.getPlateNumber()); record.setChargeStartTime(DateUtils.parseDate(dto.getStartTime())); record.setChargeEndTime(DateUtils.parseDate(dto.getEndTime())); // record.setStartType(dto.getStartType()); // record.setReservationStartTime(DateUtils.parseDate(dto.getReservationStartTime())); // record.setReservationEndTime(DateUtils.parseDate(dto.getReservationEndTime())); // record.setStartSoc(dto.getst()); // record.setEndSoc(dto.getEndSoc()); record.setAmmeterTotalStart(dto.getStartKwh()); record.setAmmeterTotalEnd(dto.getStopKwh()); record.setTotalUsedElectricity(StringUtils.isNotBlank(dto.getTotalEnergy()) ? new BigDecimal(dto.getTotalEnergy()) : BigDecimal.ZERO); record.setSharpUsedElectricity(StringUtils.isNotBlank(dto.getEnergySharp()) ? new BigDecimal(dto.getEnergySharp()) : BigDecimal.ZERO); record.setPeakUsedElectricity(StringUtils.isNotBlank(dto.getEnergyPeak()) ? new BigDecimal(dto.getEnergyPeak()) : BigDecimal.ZERO); record.setFlatUsedElectricity(StringUtils.isNotBlank(dto.getEnergyFlat()) ? new BigDecimal(dto.getEnergyFlat()) : BigDecimal.ZERO); record.setValleyUsedElectricity(StringUtils.isNotBlank(dto.getEnergyValley()) ? new BigDecimal(dto.getEnergyValley()) : BigDecimal.ZERO); if (StringUtils.isNotBlank(dto.getStopReason())) { int i = Integer.parseInt(dto.getStopReason(), 16); String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(i); record.setStopReasonCode(dto.getStopReason()); // 故障原因码 record.setReason(stopReasonMsg); } record.setTradeDate(DateUtils.parseDate(dto.getTradeTime())); record.setSourceType("BT"); record.setCreateBy(dto.getMemberId()); record.setCreateTime(new Date()); // record.setUpdateBy(dto.getUpdateBy()); // record.setUpdateTime(new Date()); record.setDelFlag(DelFlagEnum.NORMAL.getValue()); personalChargingRecordService.insertOrUpdateSelective(record); } public static void main(String[] args) { } }