package com.jsowell.service; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.TypeReference; 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.ImmutableMap; 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.exception.BaseAdaPayException; import com.huifu.adapay.core.util.AdapaySign; import com.huifu.adapay.model.Payment; import com.jsowell.adapay.common.CreateAdaPaymentParam; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.entity.SysDictData; 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.InvoiceRecordEnum; import com.jsowell.common.enums.MemberWalletEnum; import com.jsowell.common.enums.ykc.*; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.*; import com.jsowell.common.util.bean.BeanUtils; import com.jsowell.common.util.id.IdUtils; import com.jsowell.pile.domain.*; import com.jsowell.pile.dto.*; import com.jsowell.pile.service.*; import com.jsowell.pile.transaction.dto.OrderTransactionDTO; 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.InvoiceRecordVO; import com.jsowell.pile.vo.uniapp.*; import com.jsowell.pile.vo.web.*; import com.jsowell.wxpay.dto.WeChatRefundDTO; import com.jsowell.wxpay.response.WechatPayNotifyParameter; import org.apache.commons.collections4.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cglib.beans.BeanMap; 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.concurrent.TimeUnit; 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; /** * 生成订单 * * @param dto * @return */ public String generateOrder(GenerateOrderDTO dto) throws ParseException { log.info("generateOrder param:{}", JSONObject.toJSONString(dto)); // 处理前端传的参数 analysisPileParameter(dto); // 校验充电桩相关的信息 checkPileInfo(dto); // 保存订单到数据库 saveOrder2Database String orderCode = saveOrder2Database(dto); return orderCode; } /** * 订单支付 * * @param dto */ public Map payOrder(PayOrderDTO dto) throws Exception { OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR); } if (!StringUtils.equals(orderInfo.getPayStatus(), "0")) { // 订单已支付 throw new BusinessException(ReturnCodeEnum.CODE_ORDER_IS_NOT_TO_BE_PAID_ERROR); } Map resultMap = Maps.newHashMap(); if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { // 余额支付 balancePayOrder(dto); } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { // 微信支付 dto.setOrderBasicInfo(orderInfo); // 从字典中获取使用汇付支付的站点 List adapay_station = DictUtils.getDictCache("adapay_station"); List stationIdList = Lists.newArrayList(); if (CollectionUtils.isNotEmpty(adapay_station)) { for (SysDictData sysDictData : adapay_station) { stationIdList.add(sysDictData.getDictValue()); } } Map weixinMap; if (stationIdList.contains(orderInfo.getStationId())) { log.info("该站点:{}在字典中配置了使用汇付支付", orderInfo.getStationId()); weixinMap = adapayPayOrder(dto); } else { log.info("该站点:{}使用微信支付", orderInfo.getStationId()); weixinMap = wechatPayOrder(dto); } // 返回微信支付参数 resultMap.put("weixinMap", weixinMap); } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())) { // 支付宝支付 // TODO 返回支付宝支付参数 } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue())) { // 白名单支付 // 白名单支付可以直接调支付回调方法 dto.setPayAmount(new BigDecimal("500")); whiteListPayOrder(dto); } return resultMap; } /** * 使用adapay支付订单 * @param dto * @return */ public Map payOrderWithAdapay(PayOrderDTO dto) { OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR); } if (!StringUtils.equals(orderInfo.getPayStatus(), "0")) { // 订单已支付 throw new BusinessException(ReturnCodeEnum.CODE_ORDER_IS_NOT_TO_BE_PAID_ERROR); } Map resultMap = Maps.newHashMap(); if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { // 余额支付 balancePayOrder(dto); } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { // 微信支付 使用adapay dto.setOrderBasicInfo(orderInfo); Map weixinMap = adapayPayOrder(dto); // 返回微信支付参数 resultMap.put("weixinMap", weixinMap); } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())) { // 支付宝支付 // TODO 返回支付宝支付参数 } else if (StringUtils.equals(dto.getPayMode(), OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue())) { // 白名单支付 // 白名单支付可以直接调支付回调方法 dto.setPayAmount(new BigDecimal("500")); whiteListPayOrder(dto); } return resultMap; } /** * 白名单支付订单逻辑 * @param dto */ private void whiteListPayOrder(PayOrderDTO dto) { String orderCode = dto.getOrderCode(); BigDecimal payAmount = dto.getPayAmount(); String payMode = dto.getPayMode(); PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(payAmount) .payMode(payMode) .build(); payOrderSuccessCallback(callbackDTO); } /** * 使用汇付支付 * @param dto * @return */ private Map adapayPayOrder(PayOrderDTO dto) { log.info("===============使用汇付支付"); // 相同参数重复请求,返回同一个支付对象 String redisKey = CacheConstants.ADAPAY_ORDER_PARAM + dto.getOrderCode(); Map cacheObject = redisCache.getCacheObject(redisKey); if (cacheObject != null) { return cacheObject; } OrderBasicInfo orderInfo = dto.getOrderBasicInfo(); if (orderInfo == null) { // 订单为空重新查询 orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); } // 获取openId String openId = memberService.getOpenIdByCode(dto.getCode()); if (StringUtils.isBlank(openId)) { throw new BusinessException(ReturnCodeEnum.CODE_GET_OPEN_ID_BY_CODE_ERROR); } // 封装对象 String amount = AdapayUtil.formatAmount(dto.getPayAmount()); // 用户支付金额 CreateAdaPaymentParam createAdaPaymentParam = new CreateAdaPaymentParam(); createAdaPaymentParam.setOrder_no(orderInfo.getOrderCode()); createAdaPaymentParam.setPay_amt(amount); createAdaPaymentParam.setApp_id(ADAPAY_APP_ID); createAdaPaymentParam.setPay_channel("wx_lite"); // todo 如果以后有支付宝等别的渠道,这里需要做修改,判断是什么渠道的请求 createAdaPaymentParam.setGoods_title("充电费用"); createAdaPaymentParam.setGoods_desc("充电桩预付款金额"); // 这个字段是微信支付凭证的商品名 Map map = Maps.newHashMap(); map.put("type", ScenarioEnum.ORDER.getValue()); map.put("orderCode", dto.getOrderCode()); createAdaPaymentParam.setDescription(JSON.toJSONString(map)); //异步通知地址,url为http/https路径,服务器POST回调,URL 上请勿附带参数 createAdaPaymentParam.setNotify_url(ADAPAY_CALLBACK_URL); createAdaPaymentParam.setExpend(JSONObject.toJSONString( ImmutableMap.of("open_id", openId))); // 分账对象信息 // String adapayMemberId = adapayMemberAccountService.selectAdapayMemberIdByStationId(orderInfo.getStationId()); // if (StringUtils.isNotBlank(adapayMemberId)) { // JSONObject jsonObject = new JSONObject(); // jsonObject.put("member_id", adapayMemberId); // jsonObject.put("amount", amount); // jsonObject.put("fee_flag", Constants.Y); // // // 分账对象信息列表,最多仅支持7个分账方,json 数组形式 // JSONArray jsonArray = new JSONArray(); // jsonArray.add(jsonObject); // createAdaPaymentParam.setDiv_members(jsonArray.toString()); // } // 延时分账 createAdaPaymentParam.setPay_mode("delay"); try { log.info("创建汇付支付参数:{}", JSONObject.toJSONString(createAdaPaymentParam)); Map response = Payment.create(BeanMap.create(createAdaPaymentParam)); if (response != null && !response.isEmpty()) { JSONObject expend = JSONObject.parseObject(response.get("expend").toString()); JSONObject pay_info = expend.getJSONObject("pay_info"); Map resultMap = JSONObject.parseObject(pay_info.toJSONString(), new TypeReference>() { }); if (resultMap != null) { // 表示已经获取到支付参数了,后续再有支付请求就拒绝 redisCache.setCacheObject(redisKey, resultMap, 15, TimeUnit.MINUTES); } return resultMap; } } catch (BaseAdaPayException e) { log.error("汇付-获取支付对象发生异常", e); } return null; } /** * 微信支付订单逻辑 获取支付参数 * @param dto * @return * @throws Exception */ private Map wechatPayOrder(PayOrderDTO dto) throws Exception { // 相同参数重复请求,返回同一个支付对象 String redisKey = CacheConstants.WECHAT_PAY_ORDER_PARAM + dto.getOrderCode(); Map cacheObject = redisCache.getCacheObject(redisKey); if (cacheObject != null) { return cacheObject; } OrderBasicInfo orderInfo = dto.getOrderBasicInfo(); if (orderInfo == null) { orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); } String openId = memberService.getOpenIdByCode(dto.getCode()); if (StringUtils.isBlank(openId)) { throw new BusinessException(ReturnCodeEnum.CODE_GET_OPEN_ID_BY_CODE_ERROR); } WeixinPayDTO weixinPayDTO = new WeixinPayDTO(); weixinPayDTO.setOpenId(openId); weixinPayDTO.setAmount(dto.getPayAmount().toString()); // 支付订单 附加参数 PaymentScenarioDTO paymentScenarioDTO = PaymentScenarioDTO.builder() .type(ScenarioEnum.ORDER.getValue()) .orderCode(dto.getOrderCode()) .memberId(orderInfo.getMemberId()) .build(); weixinPayDTO.setAttach(JSONObject.toJSONString(paymentScenarioDTO)); weixinPayDTO.setDescription("充电费用"); Map payV3 = this.weixinPayV3(weixinPayDTO); if (payV3 != null) { // 表示已经获取到支付参数了,后续再有支付请求就拒绝 redisCache.setCacheObject(redisKey, payV3, 15, TimeUnit.MINUTES); } return payV3; } /** * 余额支付订单逻辑 * @param dto */ private void balancePayOrder(PayOrderDTO dto) { // 记录支付流水 List payRecordList = Lists.newArrayList(); String orderCode = dto.getOrderCode(); BigDecimal chargeAmount = dto.getPayAmount(); // 查询该会员的余额 MemberVO memberVO = memberService.getMemberInfoByMemberId(dto.getMemberId()); BigDecimal totalAccountAmount = memberVO.getTotalAccountAmount(); if (totalAccountAmount.compareTo(chargeAmount) < 0) { // 总余额小于充电金额 throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT); } BigDecimal principalAmount = memberVO.getPrincipalBalance(); // 会员剩余本金金额 // BigDecimal giftAmount = memberVO.getGiftBalance(); // 会员剩余赠送余额 BigDecimal principalPay = null; // 30 BigDecimal giftPay = null; // 10 // 先扣除本金金额,再扣除赠送金额 BigDecimal subtract = principalAmount.subtract(chargeAmount); if (subtract.compareTo(BigDecimal.ZERO) >= 0) { principalPay = chargeAmount; } else { if (principalAmount.compareTo(BigDecimal.ZERO) > 0) { principalPay = principalAmount; } giftPay = subtract.negate(); } // 更新会员钱包 UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() .memberId(dto.getMemberId()) .type(MemberWalletEnum.TYPE_OUT.getValue()) .subType(MemberWalletEnum.SUBTYPE_PAYMENT_FOR_ORDER.getValue()) .updatePrincipalBalance(principalPay) .updateGiftBalance(giftPay) .relatedOrderCode(orderCode) .build(); memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO); // 记录流水 if (principalPay != null) { payRecordList.add(OrderPayRecord.builder() .orderCode(orderCode) .payMode(OrderPayRecordEnum.PRINCIPAL_BALANCE_PAYMENT.getValue()) .payAmount(principalPay) .createBy(dto.getMemberId()) .build()); } if (giftPay != null) { payRecordList.add(OrderPayRecord.builder() .orderCode(orderCode) .payMode(OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue()) .payAmount(giftPay) .createBy(dto.getMemberId()) .build()); } // 余额支付可以直接调支付回调方法 PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(chargeAmount) .payMode(dto.getPayMode()) .build(); payOrderSuccessCallback(callbackDTO); // 余额支付订单 记录会员交易流水 MemberTransactionRecord record = MemberTransactionRecord.builder() .orderCode(orderCode) .scenarioType(ScenarioEnum.ORDER.getValue()) .memberId(memberVO.getMemberId()) .actionType(ActionTypeEnum.FORWARD.getValue()) .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue()) .paymentInstitutions(PaymentInstitutionsEnum.LOCAL_ACCOUNTS.getValue()) .amount(dto.getPayAmount()) // 单位元 .build(); memberTransactionRecordService.insertSelective(record); // 订单支付流水入库 if (CollectionUtils.isNotEmpty(payRecordList)) { orderPayRecordService.batchInsert(payRecordList); } } /** * 订单支付成功 支付回调 * 支付成功后掉用这个方法 * 1. 修改订单支付状态 * 2. 发送启动充电指令 */ public void payOrderSuccessCallback(PayOrderSuccessCallbackDTO dto) { OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); BigDecimal payAmount = dto.getPayAmount(); // 修改订单 orderInfo.setPayMode(dto.getPayMode()); orderInfo.setPayStatus(Constants.ONE); orderInfo.setPayAmount(payAmount); orderInfo.setPayTime(new Date()); orderBasicInfoService.updateOrderBasicInfo(orderInfo); if (StringUtils.equals(orderInfo.getStartType(), StartTypeEnum.NOW.getValue())) { // 立即启动充电 String pileSn = orderInfo.getPileSn(); // 发送启动充电指令前,再次下发计费模板 BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); if (billingTemplateVO != null) { pileRemoteService.publishPileBillingTemplate(pileSn, billingTemplateVO); } // 发送启动指令 pileRemoteService.remoteStartCharging(pileSn, orderInfo.getConnectorCode(), orderInfo.getTransactionCode(), orderInfo.getPayAmount()); } else { // 预约充电 // 修改枪口状态为 占用预约 // 下发修改充电桩设置指令 } } /** * 保存订单信息到数据库 * * @param dto * @return */ private String saveOrder2Database(GenerateOrderDTO dto) throws ParseException { String orderCode = IdUtils.getOrderCode(); String transactionCode = IdUtils.generateTransactionCode(dto.getPileSn(), dto.getConnectorCode()); if (StringUtils.isBlank(dto.getStartType())) { dto.setStartType(StartTypeEnum.NOW.getValue()); } String stationId = dto.getPileConnector().getStationId(); // 查询站点信息 PileStationInfo pileStationInfo = pileStationInfoService.selectPileStationInfoById(Long.valueOf(stationId)); String merchantId = pileStationInfo != null ? String.valueOf(pileStationInfo.getMerchantId()) : ""; // 订单基本信息 OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() .orderCode(orderCode) .transactionCode(transactionCode) .orderStatus(OrderStatusEnum.NOT_START.getValue()) .memberId(dto.getMemberId()) .stationId(stationId) .merchantId(merchantId) .pileSn(dto.getPileSn()) .connectorCode(dto.getConnectorCode()) .pileConnectorCode(dto.getPileSn() + dto.getConnectorCode()) .startMode(dto.getStartMode()) .payStatus(Constants.ZERO) .payAmount(dto.getChargeAmount()) .payMode(dto.getPayMode()) .orderAmount(BigDecimal.ZERO) .virtualAmount(BigDecimal.ZERO) .settleAmount(BigDecimal.ZERO) .startType(dto.getStartType()) .build(); if (StringUtils.equals(dto.getStartType(), StartTypeEnum.APPOINTMENT.getValue())) { orderBasicInfo.setAppointmentTime(DateUtils.parseDate(dto.getAppointmentTime(), DateUtils.YYYY_MM_DD_HH_MM_SS)); } // 订单详情 BillingTemplateVO billingTemplate = dto.getBillingTemplate(); log.info("订单使用的计费模板-orderCode:{}, billingTemplate:{}", orderCode, JSONObject.toJSONString(billingTemplate)); BigDecimal sharpElectricityPrice = billingTemplate.getSharpElectricityPrice() != null ? billingTemplate.getSharpElectricityPrice() : BigDecimal.ZERO; BigDecimal sharpServicePrice = billingTemplate.getSharpServicePrice() != null ? billingTemplate.getSharpServicePrice() : BigDecimal.ZERO; BigDecimal peakElectricityPrice = billingTemplate.getPeakElectricityPrice() != null ? billingTemplate.getPeakElectricityPrice() : BigDecimal.ZERO; BigDecimal peakServicePrice = billingTemplate.getPeakServicePrice() != null ? billingTemplate.getPeakServicePrice() : BigDecimal.ZERO; BigDecimal flatElectricityPrice = billingTemplate.getFlatElectricityPrice() != null ? billingTemplate.getFlatElectricityPrice() : BigDecimal.ZERO; BigDecimal flatServicePrice = billingTemplate.getFlatServicePrice() != null ? billingTemplate.getFlatServicePrice() : BigDecimal.ZERO; BigDecimal valleyElectricityPrice = billingTemplate.getValleyElectricityPrice() != null ? billingTemplate.getValleyElectricityPrice() : BigDecimal.ZERO; BigDecimal valleyServicePrice = billingTemplate.getValleyServicePrice() != null ? billingTemplate.getValleyServicePrice() : BigDecimal.ZERO; OrderDetail orderDetail = OrderDetail.builder() .orderCode(orderCode) .sharpPrice(sharpElectricityPrice.add(sharpServicePrice)) .sharpElectricityPrice(sharpElectricityPrice) .sharpServicePrice(sharpServicePrice) .peakPrice(peakElectricityPrice.add(peakServicePrice)) .peakElectricityPrice(peakElectricityPrice) .peakServicePrice(peakServicePrice) .flatPrice(flatElectricityPrice.add(flatServicePrice)) .flatElectricityPrice(flatElectricityPrice) .flatServicePrice(flatServicePrice) .valleyPrice(valleyElectricityPrice.add(valleyServicePrice)) .valleyElectricityPrice(valleyElectricityPrice) .valleyServicePrice(valleyServicePrice) .build(); OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() .orderBasicInfo(orderBasicInfo) .orderDetail(orderDetail) .build(); pileTransactionService.doCreateOrder(createOrderTransactionDTO); return orderCode; } /** * 校验充电桩相关的信息 * * @param dto */ private void checkPileInfo(GenerateOrderDTO dto) { // 查询充电桩状态 是否空闲 枪口是否占用 PileConnectorDetailVO pileConnector = pileService.queryPileConnectorDetail(dto.getPileSn() + dto.getConnectorCode()); if (pileConnector == null) { log.error("checkPileInfo充电枪口为空 pileSn:{}, connectorCode:{}", dto.getPileSn(), dto.getConnectorCode()); throw new BusinessException(ReturnCodeEnum.CODE_CONNECTOR_INFO_NULL_ERROR); } // 查询站点状态 PileStationVO stationInfo = pileStationInfoService.getStationInfo(pileConnector.getStationId()); if (stationInfo == null || StringUtils.equals(stationInfo.getOpenFlag(), Constants.ZERO)) { throw new BusinessException(ReturnCodeEnum.CODE_STATION_IS_NOT_OPEN); } // 判断枪口状态 if (!(StringUtils.equals(pileConnector.getConnectorStatus(), PileConnectorDataBaseStatusEnum.FREE.getValue()) || StringUtils.equals(pileConnector.getConnectorStatus(), PileConnectorDataBaseStatusEnum.OCCUPIED_NOT_CHARGED.getValue()))) { log.error("checkPileInfo充电枪口状态不正确,当前状态为:{}", pileConnector.getConnectorStatus()); throw new BusinessException(ReturnCodeEnum.CODE_PILE_CONNECTOR_STATUS_ERROR); } // 查询充电桩的计费模板 BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(dto.getPileSn()); if (billingTemplateVO == null) { throw new BusinessException(ReturnCodeEnum.CODE_BILLING_TEMPLATE_NULL_ERROR); } dto.setPileConnector(pileConnector); dto.setBillingTemplate(billingTemplateVO); } /** * 处理前端传的参数 * pileConnectorCode = pileSn + connectorCode * * @param dto */ public void analysisPileParameter(BasicPileDTO dto) { if (StringUtils.isBlank(dto.getPileSn()) || StringUtils.isBlank(dto.getConnectorCode())) { // 从pileConnectorCode解析 String pileConnectorCode = dto.getPileConnectorCode(); if (StringUtils.isNotEmpty(pileConnectorCode) && pileConnectorCode.length() == Constants.PILE_CONNECTOR_CODE_LENGTH) { dto.setPileSn(StringUtils.substring(pileConnectorCode, 0, pileConnectorCode.length() - 2)); dto.setConnectorCode(StringUtils.substring(pileConnectorCode, pileConnectorCode.length() - 2, pileConnectorCode.length())); } else { throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR); } } else { // 说明pileSn 和 connectorCode前端传了,那就校验一下长度 if (dto.getPileSn().length() != Constants.PILE_SN_LENGTH || dto.getConnectorCode().length() != Constants.CONNECTOR_CODE_LENGTH) { throw new BusinessException(ReturnCodeEnum.CODE_DATA_LENGTH_ERROR); } } } /** * 结算订单 * endCharging * * @param dto 结算订单参数 */ public void settleOrderForWeb(SettleOrderDTO dto) { analysisPileParameter(dto); // 查询订单详情,验证订单中的桩编号是否正确 OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode()); if (orderBasicInfo == null) { throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_NULL_ERROR); } if (!(StringUtils.equals(orderBasicInfo.getPileSn(), dto.getPileSn()) && StringUtils.equals(orderBasicInfo.getConnectorCode(), dto.getConnectorCode()))) { throw new BusinessException(ReturnCodeEnum.CODE_ORDER_PILE_MAPPING_ERROR); } // push远程停机指令 pileRemoteService.remoteStopCharging(dto.getPileSn(), dto.getConnectorCode()); } /** * 通过会员Id查询订单列表 * * @param memberId 会员Id * @return 订单信息集合 */ public PageResponse getListByMemberIdAndOrderStatus(String memberId, UniAppQueryOrderDTO dto) throws ParseException { String orderStatus = dto.getOrderStatus(); if (StringUtils.isBlank(orderStatus)) { throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR); } ArrayList orderStatusList = Lists.newArrayList(); if (StringUtils.equals("2", orderStatus)) { // 查未完成订单 CollectionUtils.addAll(orderStatusList, "0", "1", "2", "3", "4", "5"); } else if (StringUtils.equals("3", orderStatus)) { // 查已完成订单 orderStatusList.add("6"); }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.getMemberId(), dto.getMemberId())) { throw new BusinessException(ReturnCodeEnum.CODE_ORDER_MEMBER_NOT_MATCH_ERROR); } // 发送停止指令 pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode()); log.info("订单号:{}发送停机指令成功", dto.getOrderCode()); } /** * 微信支付回调 * * @param request * @param body * @throws Exception */ public void wechatPayCallback(HttpServletRequest request, WechatPayNotifyParameter body) throws Exception { // 获取微信支付成功返回的信息 Map map = wechatPayService.wechatPayCallbackInfo(request, body); String type = (String) map.get("type"); BigDecimal amount = (BigDecimal) map.get("amount"); // 微信给的amount单位是分 amount = amount.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP); // 转换为元 String orderCode = (String) map.get("orderCode"); String memberId = (String) map.get("memberId"); if (StringUtils.equals(type, ScenarioEnum.ORDER.getValue())) { // 1-订单支付 // 支付订单成功 // orderCode = (String) map.get("orderCode"); PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(amount) .payMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .build(); // 订单支付成功 支付回调 payOrderSuccessCallback(callbackDTO); // 记录订单支付流水 OrderPayRecord orderPayRecord = OrderPayRecord.builder() .orderCode(orderCode) .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue()) .payAmount(amount) .createBy(null) .build(); orderPayRecordService.batchInsert(Lists.newArrayList(orderPayRecord)); } else if (StringUtils.equals(type, ScenarioEnum.BALANCE.getValue())) { // 2-充值余额 // 充值余额成功 // memberId = (String) map.get("memberId"); UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO(); dto.setMemberId(memberId); dto.setType(MemberWalletEnum.TYPE_IN.getValue()); dto.setSubType(MemberWalletEnum.SUBTYPE_TOP_UP.getValue()); dto.setUpdatePrincipalBalance(amount); memberBasicInfoService.updateMemberBalance(dto); } // 微信支付订单 记录会员交易流水 MemberTransactionRecord record = MemberTransactionRecord.builder() .orderCode(orderCode) .scenarioType(type) .memberId(memberId) .actionType(ActionTypeEnum.FORWARD.getValue()) .payMode(PayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .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); } public void weChatRefund(WeChatRefundDTO dto) { log.info("微信退款接口 param:{}", JSONObject.toJSONString(dto)); orderBasicInfoService.weChatRefund(dto); } public void adapayRefund(WeChatRefundDTO dto) { log.info("汇付退款 param:{}", JSON.toJSONString(dto)); // 退款有两种情况 1-订单结算退款 2-用户余额退款 String refundType = dto.getRefundType(); if (StringUtils.equals(refundType, "1")) { orderBasicInfoService.refundForOrderWithAdapay(dto); } else if (StringUtils.equals(refundType, "2")) { orderBasicInfoService.refundForBalanceWithAdapay(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); 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; } 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; } /** * 根据订单号查询充电桩启动状态 * @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; } 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; } 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(","))) // 分隔逗号并转化为 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天申请开票记录 QueryInvoiceRecordDTO build = QueryInvoiceRecordDTO.builder() .memberId(dto.getMemberId()) .startTime(dateTime) .build(); List orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceRecordList(build); List orderCodeList = orderInvoiceRecords.stream() // 转化为 Stream .map(OrderInvoiceRecord::getOrderCodes) // 获取 OrderInvoiceRecord 中的 orderCodes 字符串 .flatMap(str -> Arrays.stream(str.split(","))) // 分隔逗号并转化为 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; } // 整理数据 List orderVOList = orderBasicInfoService.getListByOrderCodes(dto.getOrderCodes()); BigDecimal totalAmount = BigDecimal.ZERO; BigDecimal totalElecAmount = BigDecimal.ZERO; BigDecimal totalServiceAmount = BigDecimal.ZERO; for (OrderVO orderVO : orderVOList) { totalAmount = totalAmount.add(orderVO.getOrderAmount()); totalElecAmount = totalElecAmount.add(orderVO.getTotalElectricityAmount()); totalServiceAmount = totalServiceAmount.add(orderVO.getTotalServiceAmount()); } // 查抬头信息 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); } } // 入库 OrderInvoiceRecord orderInvoiceRecord = new OrderInvoiceRecord(); orderInvoiceRecord.setStatus("0"); orderInvoiceRecord.setMemberId(dto.getMemberId()); orderInvoiceRecord.setTitleId(dto.getTitleId()); orderInvoiceRecord.setOrderCodes(String.join(",", dto.getOrderCodes())); orderInvoiceRecord.setTotalAmount(totalAmount); orderInvoiceRecord.setTotalElecAmount(totalElecAmount); orderInvoiceRecord.setTotalServiceAmount(totalServiceAmount); orderInvoiceRecordService.insertOrderInvoiceRecord(orderInvoiceRecord); } 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; } //验签成功 保存到回调记录表中 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); if (StringUtils.equals(type, ScenarioEnum.ORDER.getValue())) { // 1-订单支付 // 支付订单成功 PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder() .orderCode(orderCode) .payAmount(amount) .payMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue()) .build(); // 订单支付成功 支付回调 payOrderSuccessCallback(callbackDTO); // 记录订单支付流水 OrderPayRecord orderPayRecord = OrderPayRecord.builder() .orderCode(orderCode) .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue()) .payAmount(amount) .createBy(null) .build(); orderPayRecordService.batchInsert(Lists.newArrayList(orderPayRecord)); } else if (StringUtils.equals(type, ScenarioEnum.BALANCE.getValue())) { // 2-充值余额 // 充值余额成功 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.ADAPAY.getValue()) .amount(amount) // 单位元 .outTradeNo(adapayCallbackRecord.getPartyOrderId()) .transactionId(adapayCallbackRecord.getOutTransId()) .build(); memberTransactionRecordService.insertSelective(record); } /** * 汇付支付 退款回调 * @param request * @throws Exception */ public void adapayRefundCallback(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; } adapayRefundRecordService.saveAdapayRefundRecord(data); } }