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.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.Sets; import com.huifu.adapay.core.AdapayCore; import com.huifu.adapay.core.util.AdapaySign; 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.InvoiceRecordEnum; import com.jsowell.common.enums.MemberWalletEnum; import com.jsowell.common.enums.adapay.AdapayEventEnum; 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.pile.domain.*; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.transaction.service.TransactionService; 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.*; import com.jsowell.pile.vo.web.OrderDetailInfoVO; import com.jsowell.pile.vo.web.PileStationVO; import com.jsowell.pile.vo.web.PlatformTesterVO; import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO; import com.jsowell.pile.dto.ApplyRefundDTO; 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.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.text.ParseException; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @Service public class OrderService { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private TransactionService pileTransactionService; @Autowired private IPileBillingTemplateService pileBillingTemplateService; @Autowired private IOrderBasicInfoService orderBasicInfoService; @Autowired private PileRemoteService pileRemoteService; @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 IMemberTransactionRecordService memberTransactionRecordService; @Autowired private IPileStationInfoService pileStationInfoService; @Autowired private IOrderInvoiceRecordService orderInvoiceRecordService; @Autowired private IPileStationWhitelistService pileStationWhitelistService; @Autowired private RedisCache redisCache; @Autowired private AdapayCallbackRecordService adapayCallbackRecordService; @Autowired private IMemberInvoiceTitleService memberInvoiceTitleService; @Autowired private IAdapayRefundRecordService adapayRefundRecordService; @Value("${adapay.appId}") private String ADAPAY_APP_ID; @Value("${adapay.callback}") private String ADAPAY_CALLBACK_URL; @Autowired private IAdapayMemberAccountService adapayMemberAccountService; @Autowired private ClearingWithdrawInfoService clearingWithdrawInfoService; /** * 生成订单 * * @param dto * @return */ public String generateOrder(GenerateOrderDTO dto) throws ParseException { OrderBasicInfo basicInfo = orderBasicInfoService.generateOrder(dto); if (basicInfo != null) { return basicInfo.getOrderCode(); } return null; } /** * 获取到vin 查询对应的用户,得到余额 * * 生成订单 * * 支付订单 * */ /** * 订单支付 * * @param dto */ public Map payOrder(PayOrderDTO dto) throws Exception { Map resultMap = orderBasicInfoService.payOrder(dto); return resultMap; } /** * 结算订单 * 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_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"); }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()); String chargingTime = "0分钟"; if (orderVO.getStartTime() != null) { Date startTimeDate = DateUtils.parseDate(orderVO.getStartTime()); Date endTimeDate; if (orderVO.getEndTime() != null) { endTimeDate = DateUtils.parseDate(orderVO.getEndTime()); } else { endTimeDate = new Date(); } // 计算出两个时间差 chargingTime = DateUtils.getDatePoor(endTimeDate, startTimeDate); } 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_NULL_ERROR); } // 判断订单状态是不是已经结算了 if (StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { throw new BusinessException(ReturnCodeEnum.CODE_ORDER_COMPLETE_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(); // 订单支付成功 支付回调 orderBasicInfoService.payOrderSuccessCallback(callbackDTO); // 记录订单支付流水 OrderPayRecord orderPayRecord = OrderPayRecord.builder() .orderCode(orderCode) .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue()) .payAmount(amount) .acquirer(AcquirerEnum.WECHAT_PAY.getValue()) .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()) .paymentInstitutions(PaymentInstitutionsEnum.WECHAT_PAY.getValue()) .amount(amount) // 单位元 .outTradeNo(String.valueOf(map.get("out_trade_no"))) .transactionId(String.valueOf(map.get("transaction_id"))) .build(); memberTransactionRecordService.insertSelective(record); } /** * 微信退款 * @param dto */ public void weChatRefund(ApplyRefundDTO dto) { log.info("微信退款接口 param:{}", JSONObject.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()); 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.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(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()); vo.setOrderRealTimeInfo(realTimeInfo); // 根据时间进行正序排序 infoList = infoList.stream() .sorted(Comparator.comparing(OrderDetailInfoVO.PileMonitorData::getTime)) .collect(Collectors.toList()); vo.setRealTimeMonitorDataList(infoList); // 最后一次实时数据 vo.setLastMonitorData(chargingRealTimeDataList.get(0)); } // 支付流水 List orderPayRecordList = orderPayRecordService.getOrderPayRecordList(orderCode); if (CollectionUtils.isNotEmpty(orderPayRecordList)) { List payRecordList = Lists.newArrayList(); for (OrderPayRecord orderPayRecord : orderPayRecordList) { 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())); if (orderPayRecord.getRefundAmount() != null) { payInfo.setRefundAmount(orderPayRecord.getRefundAmount().toString()); } 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()); // 判断是微信支付还是汇付支付 MemberTransactionRecord record = memberTransactionRecordService.selectByOrderCode(orderCode, ActionTypeEnum.FORWARD.getValue()); if (record != null) { String paymentInstitutions = record.getPaymentInstitutions(); if (StringUtils.equals(paymentInstitutions, PaymentInstitutionsEnum.WECHAT_PAY.getValue())) { // 查微信支付回调记录 WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService.selectByOrderCode(orderCode); if (wxpayCallbackRecord != null) { payInfo.setOutTradeNo(wxpayCallbackRecord.getOutTradeNo()); payInfo.setTransactionId(wxpayCallbackRecord.getTransactionId()); } } else if (StringUtils.equals(paymentInstitutions, PaymentInstitutionsEnum.ADAPAY.getValue())) { // 查询汇付支付回调 AdapayCallbackRecord adapayCallbackRecord = adapayCallbackRecordService.selectByOrderCode(orderCode); if (adapayCallbackRecord != null) { payInfo.setOutTradeNo(adapayCallbackRecord.getPaymentId()); payInfo.setTransactionId(adapayCallbackRecord.getOutTransId()); } } } // 查微信支付回调记录 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) { 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); } 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); 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); 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.setReason(orderBasicInfo.getReason()); vo.setOrderAmount(String.valueOf(orderBasicInfo.getOrderAmount())); vo.setPayAmount(String.valueOf(orderBasicInfo.getPayAmount())); vo.setPayMode(orderBasicInfo.getPayMode()); // 订单状态描述 String orderStatusDescribe = orderBasicInfoService.transformOrderStatusDescribe(orderStatus, orderBasicInfo.getPayStatus()); vo.setOrderStatusDescribe(orderStatusDescribe); // 获取充电桩枪口信息 PileConnectorDetailVO pileConnectorDetailVO = pileService.queryPileConnectorDetail(vo.getPileConnectorCode()); if (pileConnectorDetailVO != null) { vo.setPileConnectorStatus(pileConnectorDetailVO.getConnectorStatus()); } // 获取订单充电数据 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, 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) { OrderAmountDetailVO billingDetails = new OrderAmountDetailVO(); BeanUtils.copyBeanProp(billingDetails, orderDetail); vo.setBillingDetails(billingDetails); } 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); } return vo; } /** * 小程序订单详情V2 * @param orderCode * @return */ public UniAppOrderDetailVO getUniAppOrderDetailV2(String orderCode) { UniAppOrderDetailVO resultVO = new UniAppOrderDetailVO(); return resultVO; } /** * 根据订单号查询充电桩启动状态 * @param orderCode * @return */ public String selectPileStarterStatus(String orderCode) { OrderBasicInfo orderInfoByOrderCode = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); if (orderInfoByOrderCode == null) { return Constants.ZERO; } List chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderInfoByOrderCode.getTransactionCode()); // 只有充电桩上传的实时数据中的状态为充电,才能查到实时数据列表 return CollectionUtils.isNotEmpty(chargingRealTimeData) ? Constants.ONE : Constants.ZERO; } /** * 关闭支付未启动的订单 * @param dto */ public void closeStartFailedOrder(QueryOrderDTO dto) { orderBasicInfoService.closeStartFailedOrder(dto.getStartTime(), dto.getEndTime()); } /** * 人工结算订单 * @param dto */ public boolean manualSettlementOrder(ManualSettlementDTO dto) { log.info("人工结算订单-begin orderCode:{}", dto.getOrderCode()); // 查询订单 OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderBasicInfo == null) { log.info("人工结算订单-根据订单号:{}, 查询为null", dto.getOrderCode()); return false; } // 当前登录用户,是否可以结算该订单 AuthorizedDeptVO authorizedMap = SecurityUtils.getAuthorizedMap(); if (authorizedMap == null) { log.info("人工结算订单-当前登录管理员无权限"); return false; } List stationDeptIds = authorizedMap.getStationDeptIds(); if (CollectionUtils.isEmpty(stationDeptIds)) { // 运营商管理员 List merchantDeptIds = authorizedMap.getMerchantDeptIds(); } String chargingAmount = dto.getChargingAmount(); String chargingDegree = dto.getChargingDegree(); 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(); } } // 组装交易记录数据 TransactionRecordsData data = new TransactionRecordsData(); data.setConsumptionAmount(chargingAmount); // 总消费金额 data.setTotalElectricity(chargingDegree); // 总用电量 data.setStopReasonMsg("人工结算订单,操作人:" + SecurityUtils.getUsername()); // 停止原因 // 结算订单 orderBasicInfoService.settleOrder(data, orderBasicInfo); // 发送停止充电指令 pileRemoteService.remoteStopCharging(orderBasicInfo.getPileSn(), orderBasicInfo.getConnectorCode()); log.info("人工结算订单-end orderCode:{}", dto.getOrderCode()); return true; } /** * 当前登录会员 获取支付方式 * @param dto */ public List getPayMode(GetPayModeDTO dto) { List result = Lists.newArrayList(); // 查询会员在站点是否是白名单用户 PileStationWhitelist whitelist = pileStationWhitelistService.queryWhitelistByMemberId(dto.getStationId(), dto.getMemberId()); // 查询是否为平台测试员 PlatformTesterVO platformTesterVO = memberBasicInfoService.selectPlatformTesterStatus(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 { // 微信支付 result.add( PayModeVO.builder() .payModeCode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .payModeName(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getLabel()) .build() ); // 余额支付 result.add( PayModeVO.builder() .payModeCode(OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue()) .payModeName(OrderPayModeEnum.PAYMENT_OF_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.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); PageInfo pageInfo = new PageInfo<>(orderInvoiceRecords); List volist = Lists.newArrayList(); for (OrderInvoiceRecord orderInvoiceRecord : orderInvoiceRecords) { volist.add( InvoiceRecordVO.builder() .status(InvoiceRecordEnum.getLabel(orderInvoiceRecord.getStatus())) .totalAmount(orderInvoiceRecord.getTotalAmount()) .totalElecAmount(orderInvoiceRecord.getTotalElecAmount()) .totalServiceAmount(orderInvoiceRecord.getTotalServiceAmount()) .createTime(DateUtils.formatDateTime(orderInvoiceRecord.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.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)) { // 支付撤销成功 } 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 */ private void paymentSucceeded(String data) throws JsonProcessingException { //验签成功 保存到回调记录表中 JSONObject jsonObject = JSON.parseObject(data); ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); AdapayCallbackRecord adapayCallbackRecord = mapper.readValue(jsonObject.toJSONString(), AdapayCallbackRecord.class); adapayCallbackRecord.setExpend(jsonObject.getString("expend")); adapayCallbackRecord.setPaymentId(jsonObject.getString("id")); JSONObject descJson = JSON.parseObject(adapayCallbackRecord.getDescription()); String type = descJson.getString("type"); adapayCallbackRecord.setPayScenario(type); String memberId = descJson.getString("memberId"); adapayCallbackRecord.setMemberId(memberId); String orderCode = descJson.getString("orderCode"); adapayCallbackRecord.setOrderCode(orderCode); BigDecimal amount = adapayCallbackRecord.getPayAmt(); // 保存到数据库 adapayCallbackRecordService.saveAdapayCallbackRecord(adapayCallbackRecord); // 微信支付订单 记录会员交易流水 MemberTransactionRecord record = MemberTransactionRecord.builder() .orderCode(orderCode) .scenarioType(type) .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(type, ScenarioEnum.ORDER.getValue())) { // 1-订单支付 // 支付订单成功 PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(amount) .payMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .build(); // 订单支付成功 支付回调 orderBasicInfoService.payOrderSuccessCallback(callbackDTO); // 记录订单支付流水 OrderPayRecord orderPayRecord = OrderPayRecord.builder() .orderCode(orderCode) .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue()) .payAmount(amount) .acquirer(AcquirerEnum.ADAPAY.getValue()) .createBy(null) .build(); orderPayRecordService.batchInsert(Lists.newArrayList(orderPayRecord)); } else if (StringUtils.equals(type, 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); } } /** * 汇付退款成功 */ private void refundSucceeded(String data) { // 保存退款回调记录 adapayRefundRecordService.saveAdapayRefundRecord(data); } /** * 对公账户创建失败 * @param data */ private void corpMemberFailed(String data) { // 删除表中的记录 JSONObject jsonObject = JSON.parseObject(data); String memberId = jsonObject.getString("member_id"); if (StringUtils.isBlank(memberId)) { return; } AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMemberId(memberId); if (adapayMemberAccount == null) { return; } adapayMemberAccount.setStatus(Constants.TWO); // 逻辑删除记录,并删除缓存 adapayMemberAccountService.updateAdapayMemberAccount(adapayMemberAccount); } /** * 对公账户创建成功 * @param data */ private void corpMemberSucceeded(String data) { JSONObject jsonObject = JSON.parseObject(data); String memberId = jsonObject.getString("member_id"); if (StringUtils.isBlank(memberId)) { return; } AdapayMemberAccount adapayMemberAccount = new AdapayMemberAccount(); adapayMemberAccount.setAdapayMemberId(memberId); adapayMemberAccount.setStatus(Constants.ONE); adapayMemberAccountService.updateAdapayMemberAccountByMemberId(adapayMemberAccount); } /** * 取现成功 */ private void cashSucceeded(String data) { JSONObject jsonObject = JSON.parseObject(data); String withdrawCode = jsonObject.getString("id"); // 通过取现id查询取现数据 ClearingWithdrawInfo clearingWithdrawInfo = clearingWithdrawInfoService.selectByWithdrawCode(withdrawCode); clearingWithdrawInfo.setWithdrawStatus(Constants.ONE); clearingWithdrawInfo.setUpdateTime(DateUtils.getNowDate()); clearingWithdrawInfoService.updateByPrimaryKeySelective(clearingWithdrawInfo); } /** * 取现失败 * @param data */ private void cashFailed(String 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); } }