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