feat(cloud-manage-server): 实现订单状态更新和费用结算功能

- 添加订单状态更新逻辑,处理不同状态下的订单
- 实现按电量和SOC计算订单费用的功能
- 优化换电步骤记录和电池状态更新
- 新增预约单过期检查和提醒功能
- 重构部分代码以提高可维护性
This commit is contained in:
tzy 2025-04-18 09:59:34 +08:00
parent 796e72cbfd
commit 9048b368d7
30 changed files with 783 additions and 343 deletions

View File

@ -0,0 +1,64 @@
package com.evotech.hd.common.core.entity.cloud.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@Schema(name = "账户列表返回结果")
public class WalletAccountVO {
@Schema(hidden = true)
private Integer pkId;
@Schema(description = "户主类型1-个人2-企业", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "类型不能为空")
private Integer ownerType;
@Schema(description = "户主ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "用户编码不能为空")
private String ownerId;
@Schema(description = "名称")
private String accName;
@Schema(description = "手机号")
private String phone;
@Schema(description = "编码", hidden = true)
private String code;
@Schema(description = "账户总金额,分:总金额=充值金额+赠送金额")
private Integer totalAmount;
@Schema(description = "充值余额,分")
private Integer rechargeAmount;
@Schema(description = "赠送金额,分")
private Integer giftAmount;
@Schema(description = "积分余额")
private Integer point;
@Schema(description = "押金")
private Integer deposit;
@Schema(description = "SN码")
private String snCode;
@Schema(description = "租金")
private Integer rent;
@Schema(description = "状态")
private Integer status;
@Schema(description = "引入站点")
private String stationCode;
@Schema(description = "创建人")
private String creater;
}

View File

@ -110,8 +110,8 @@ public class OrderSwapBatteryController {
@Operation(summary = "费用计算")
@PostMapping({"/cost"})
@ApiOperationSupport(order = 9)
public Result<String> calculateCost(@NotBlank @RequestParam String orderNo) {
return orderSwapBatteryService.calculateCost(orderNo);
public Result<String> calculateCost(@NotBlank @RequestParam OrderSwapBattery osb) {
return orderSwapBatteryService.calculateCost(osb);
}

View File

@ -2,6 +2,7 @@ package com.evotech.hd.cloud.controller.order;
import java.util.List;
import com.evotech.hd.common.core.entity.cloud.vo.WalletAccountVO;
import com.evotech.hd.common.core.entity.wechat.WechatPayAttach;
import jakarta.servlet.http.HttpServletRequest;
import org.springdoc.core.annotations.ParameterObject;
@ -57,7 +58,7 @@ public class WalletAccountController {
@Operation(summary = "查询")
@GetMapping("/list")
@ApiOperationSupport(order = 4)
public Result<List<WalletAccount>> list(@ParameterObject PageListWalletRequest plwr) {
public Result<List<WalletAccountVO>> list(@ParameterObject PageListWalletRequest plwr) {
return walletAccountService.list(plwr);
}

View File

@ -64,7 +64,7 @@ public class MqttMessageTestController {
@PostMapping("/orderStatus")
@ApiOperationSupport(order = 2)
public Result<String> orderStatus(@ParameterObject OrderStatus orderStatus, @ParameterObject OrderStatusData statusData, String stationCode) {
orderStatus.setStatusData(statusData);
JSONObject jo = JSONUtil.parseObj(orderStatus);
String topic = mqttTestUtil.getTopic(stationCode, MqttMessageTypeEnum.STATE.getType());
MqttMessageHeader header = mqttTestUtil.getHeader(StateFunctionTypesEnum.FUN_ORDERSTATUS.getFunction());

View File

@ -5,7 +5,7 @@ import java.util.Arrays;
public enum ConfirmFunctionTypesEnum {
FUN_CHARGE_RECORD_CONF("chargeRecordConf", "chargeRecord", "充电事件记录确认"),
FUN_SWAP_RECORD_CONF("swapRecordConf", "swapRecord", "换电事件记录确认"),
FUN_SWAP_RECORD_CONF("", "swapCompleteConfirm", "换电事件记录确认"),
FUN_FAULT_RECORD_CONF("faultRecordConf", "faultRecord", "故障告警事件记录确认");
String function;

View File

@ -1,15 +1,18 @@
package com.evotech.hd.cloud.mqtt.enums;
import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatusData;
import java.util.Arrays;
public enum EventFunctionTypesEnum {
FUN_CHARGE_RECORD("chargeRecord", "chargeRecordConf", "充电事件记录"),
FUN_SWAP_RECORD("swapRecord", "swapRecordConf", "换电事件记录"),
FUN_WARN_RECORD("faultRecord", "faultRecordConf", "故障告警事件记录");
FUN_WARN_RECORD("faultRecord", "faultRecordConf", "故障告警事件记录"),
FUN_ORDEREVENT("swapComplete", "swapCompleteConfirm", " 站端换电完成事件");
String function;
String reFunction;
String functionName;

View File

@ -0,0 +1,14 @@
package com.evotech.hd.cloud.mqtt.message.dto.newer.confirm;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class SwapCompleteConfirm {
@Schema(description = "订单号")
private String orderNo;
@Schema(description = "结果")
private Integer ackStatus;
@Schema(description = "失败原因 ")
private String error;
}

View File

@ -0,0 +1,23 @@
package com.evotech.hd.cloud.mqtt.message.dto.newer.event;
import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatusData;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
public class SwapComplete {
private String orderNo;
private Integer status;
@Schema(description = "时间", example = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date statusTime;
@Schema(hidden = true)
private OrderStatusData statusData;
}

View File

@ -7,7 +7,7 @@ import lombok.Data;
@Data
public class OrderStatusData {
@Schema(description = "充电电池编码 - 状态5 数据")
private String batCode;

View File

@ -0,0 +1,17 @@
package com.evotech.hd.cloud.mqtt.message.handle;
import cn.hutool.json.JSONObject;
import com.evotech.hd.cloud.mqtt.enums.EventFunctionTypesEnum;
import com.evotech.hd.cloud.mqtt.message.MessageTopic;
import com.evotech.hd.cloud.mqtt.message.MqttMessageHeader;
public class ConfirmMessageServeice {
public void event(MessageTopic topic, MqttMessageHeader header, JSONObject dataBody) {
switch (EventFunctionTypesEnum.getFunctionType(header.getFunction())) {
case FUN_WARN_RECORD:
default:
break;
}
}
}

View File

@ -1,5 +1,28 @@
package com.evotech.hd.cloud.mqtt.message.handle;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.evotech.hd.cloud.dao.BatteryStationDcDao;
import com.evotech.hd.cloud.dao.OrderSwapBatteryPreDao;
import com.evotech.hd.cloud.dao.OrderSwapBatteryStepDao;
import com.evotech.hd.cloud.dao.VehicleInfoDao;
import com.evotech.hd.cloud.mqtt.enums.ConfirmFunctionTypesEnum;
import com.evotech.hd.cloud.mqtt.enums.MqttMessageTypeEnum;
import com.evotech.hd.cloud.mqtt.enums.RequestFunctionTypesEnum;
import com.evotech.hd.cloud.mqtt.message.dto.newer.confirm.SwapCompleteConfirm;
import com.evotech.hd.cloud.mqtt.message.dto.newer.event.SwapComplete;
import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatus;
import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatusData;
import com.evotech.hd.cloud.service.BatteryStationDcService;
import com.evotech.hd.cloud.service.OrderSwapBatteryService;
import com.evotech.hd.cloud.utils.components.HDStepDictComponent;
import com.evotech.hd.common.core.dao.cloud.OrderSwapBatteryDao;
import com.evotech.hd.common.core.entity.cloud.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.evotech.hd.cloud.mqtt.enums.EventFunctionTypesEnum;
@ -8,40 +31,159 @@ import com.evotech.hd.cloud.mqtt.message.MqttMessageHeader;
import cn.hutool.json.JSONObject;
import jakarta.annotation.Resource;
import java.util.Date;
import java.util.Objects;
@Service
@Slf4j
public class EventMessageService {
@Resource
private MessageUtilService messageUtilService;
@Resource
private OrderSwapBatteryDao orderSwapBatteryDao;
@Resource
private OrderSwapBatteryStepDao orderSwapBatteryStepDao;
@Resource
private BatteryStationDcService batteryStationDcService;
@Resource
private HDStepDictComponent hdStepDictComponent;
@Resource
private VehicleInfoDao vehicleInfoDao;
@Resource
private BatteryStationDcDao batteryStationDcDao;
@Resource
private OrderSwapBatteryService orderSwapBatteryService;
/**
* event消息 处理
*/
public void event(MessageTopic topic, MqttMessageHeader header, JSONObject dataBody) {
switch (EventFunctionTypesEnum.getFunctionType(header.getFunction())) {
// // 这个事件不用了
// case FUN_CHARGE_RECORD:
// // TODO 写充电记录表
// // TODO 回复 confirm 消息
// // TODO 订单结算
//
// break;
// // 这个事件不用了
// case FUN_SWAP_RECORD:
// // TODO 写换电记录表
// // TODO 回复 confirm 消息
// // TODO 更新订单
// break;
switch (Objects.requireNonNull(EventFunctionTypesEnum.getFunctionType(header.getFunction()))) {
case FUN_WARN_RECORD:
// TODO 写预警记录表
// TODO 回复 confirm 消息
// TODO 业务处理
break;
// 站端反馈订单状态
case FUN_ORDEREVENT:
SwapComplete orderStatus = JSONUtil.toBean(dataBody, SwapComplete.class);
OrderStatusData statusData = JSONUtil.toBean(dataBody.getJSONObject("statusData"), OrderStatusData.class);
// 订单状态更新处理
handleOrderStatus(orderStatus, statusData);
Date d = new Date();
//回复 confirm 消息
SwapCompleteConfirm swapRecordConfirm = new SwapCompleteConfirm();
swapRecordConfirm.setAckStatus(1);
swapRecordConfirm.setOrderNo(orderStatus.getOrderNo());
swapRecordConfirm.setError("");
topic.setDataDirection("M2S");
topic.setMessageType(MqttMessageTypeEnum.CONFIRM.getType());
header.setFunction(ConfirmFunctionTypesEnum.FUN_SWAP_RECORD_CONF.getReFunction());
header.setTimeStamp(DateUtil.format(new Date(), DatePattern.NORM_DATETIME_FORMATTER));
log.info("\r\n=====>>>回复站端收到换电完成--MQTT发送到消息主题{},头部信息:{}订单编码;{},message:{}", topic,header, orderStatus.getOrderNo(),JSONUtil.parseObj(swapRecordConfirm, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
messageUtilService.publishAESMessage(topic, header, JSONUtil.parseObj(swapRecordConfirm, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
break;
default:
break;
}
}
/**
* 订单最终状态的更新
* @param orderStatus
* @param statusData
*/
private void handleOrderStatus(SwapComplete orderStatus, OrderStatusData statusData) {
// 换电步骤添加最后一条
if (orderStatus.getStatus() == 3){
OrderSwapBattery osb = alterOrderStatus(orderStatus, statusData);
OrderSwapBatteryStep step = new OrderSwapBatteryStep();
step.setOrderNo(orderStatus.getOrderNo());
step.setStep(8);
step.setStepTime(orderStatus.getStatusTime());
step.setCtime(new Date());
step.setCreater("SYS");
step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep()));
orderSwapBatteryStepDao.insert(step);
// 修改车上电池编码
VehicleInfo vi = new VehicleInfo();
vi.setBatCode(statusData.getRentBatCode());
vi.setBatSoc(statusData.getRentBatSoc());
vehicleInfoDao.update(vi, new QueryWrapper<VehicleInfo>().eq("plate_num", osb.getPlateNum()));
// 修改2块电池的信息
BatteryStationDc dc1 = new BatteryStationDc();
BatteryStationDc dc2 = new BatteryStationDc();
dc1.setStatus(1);
dc1.setSourceFrom(1);
dc1.setPointType(2);
dc1.setPointCode(osb.getPlateNum());
dc1.setPointName(osb.getPlateNum());
dc1.setSoc(statusData.getRentBatSoc());
dc1.setDccNo(0);
batteryStationDcDao.update(dc1, new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getRentBatCode()));
dc2.setStatus(2);
dc2.setSourceFrom(1);
dc2.setPointType(1);
dc2.setPointCode(osb.getStationCode());
dc2.setPointName(osb.getStationName());
dc2.setSoc(statusData.getReturnBatSoc());
dc2.setDccNo(statusData.getReturnBatNo());
batteryStationDcDao.update(dc2, new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getReturnBatCode()));
// 添加2块电池的溯源记录
addBatteryTrace(orderStatus, statusData, osb);
//计算费用方式
log.info("\r\n=====>>>订单状态更新处理订单状态开始结算:{},{}",orderStatus.getOrderNo(),orderStatus.getStatus() );
//费用结算
orderSwapBatteryService.calculateCost1(orderStatus.getOrderNo(), statusData);
}
}
/**
* 修改订单状态方法
*
* @param orderStatus
* @param statusData
* @return
*/
private OrderSwapBattery alterOrderStatus(SwapComplete orderStatus, OrderStatusData statusData) {
OrderSwapBattery osb = orderSwapBatteryDao.selectOne(new QueryWrapper<OrderSwapBattery>().eq("order_no", orderStatus.getOrderNo()));
osb.setStatus(orderStatus.getStatus());
if (orderStatus.getStatus() == 3) {
osb.setServiceTimeEnd(orderStatus.getStatusTime());
BeanUtils.copyProperties(statusData, osb);
}
osb.setUptime(null);
orderSwapBatteryDao.updateById(osb);
return osb;
}
/**
* 添加电池轨迹记录
*
* @param orderStatus
* @param statusData
* @param osb
*/
private void addBatteryTrace(SwapComplete orderStatus, OrderStatusData statusData, OrderSwapBattery osb) {
BatteryTrace bt1 = new BatteryTrace();
bt1.setOrderNo(orderStatus.getOrderNo());
bt1.setBatCode(statusData.getRentBatCode());
bt1.setSoc(statusData.getRentBatSoc());
bt1.setBeginTime(orderStatus.getStatusTime());
bt1.setPointType(2);
bt1.setPointCode(osb.getPlateNum());
bt1.setPointName(osb.getPlateNum());
bt1.setCreater("SYS");
BatteryTrace bt2 = new BatteryTrace();
BeanUtils.copyProperties(bt1, bt2);
bt2.setBatCode(statusData.getReturnBatCode());
bt2.setSoc(statusData.getRentBatSoc());
bt2.setPointType(1);
bt2.setPointCode(osb.getStationCode());
bt2.setPointName(osb.getStationName());
batteryStationDcService.addTrace(bt1);
batteryStationDcService.addTrace(bt2);
}
}

View File

@ -45,8 +45,6 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class StateMessageService {
@Resource
private MessageUtilService messageUtilService;
@Resource
private OrderSwapBatteryDao orderSwapBatteryDao;
@Resource
@ -57,23 +55,17 @@ public class StateMessageService {
private BatteryStationDcService batteryStationDcService;
@Resource
private HDStepDictComponent hdStepDictComponent;
@Resource
private VehicleInfoDao vehicleInfoDao;
@Resource
private BatteryStationDcDao batteryStationDcDao;
@Resource
private OrderSwapBatteryService orderSwapBatteryService;
@Async("taskExecutor")
public void state(MessageTopic topic, MqttMessageHeader header, JSONObject dataBody) {
switch (Objects.requireNonNull(StateFunctionTypesEnum.getFunctionType(header.getFunction()))) {
// 站端反馈订单状态
case FUN_ORDERSTATUS:
OrderStatus orderStatus = JSONUtil.toBean(dataBody, OrderStatus.class);
OrderStatusData statusData = JSONUtil.toBean(dataBody.getJSONObject("statusData"),
OrderStatusData.class);
OrderStatusData statusData = JSONUtil.toBean(dataBody.getJSONObject("statusData"), OrderStatusData.class);
// 订单状态更新处理
handleOrderStatus(orderStatus, statusData);
// TODO 回复一下收到了
handleOrderStatus(orderStatus);
break;
// 站端反馈换电步骤
case FUN_SWAPSTEP:
@ -86,10 +78,8 @@ public class StateMessageService {
step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep()));
log.info("\r\n=====>>>站端反馈换电步骤--MQTT收到消息主题{},换电步骤名称:{}",topic,hdStepDictComponent.hdStepDictName(step.getStep()) );
orderSwapBatteryStepDao.insert(step);
break;
case FUN_TEST:
break;
default:
break;
@ -100,15 +90,15 @@ public class StateMessageService {
/**
* 订单状态更新处理
* @param orderStatus
* @param statusData
*/
private void handleOrderStatus(OrderStatus orderStatus, OrderStatusData statusData) {
private void handleOrderStatus(OrderStatus orderStatus) {
switch (orderStatus.getStatus()) {
case 2:
orderStatus2(orderStatus);
break;
case 3:
// 修改订单状态和数据
/* // 修改订单状态和数据
OrderSwapBattery osb = alterOrderStatus(orderStatus, statusData);
// 换电步骤添加最后一条
OrderSwapBatteryStep step = new OrderSwapBatteryStep();
@ -119,6 +109,10 @@ public class StateMessageService {
step.setCreater("SYS");
step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep()));
orderSwapBatteryStepDao.insert(step);
//计算费用方式
log.info("\r\n=====>>>订单状态更新处理订单状态开始结算:{},{}",orderStatus.getOrderNo(),orderStatus.getStatus() );
//费用结算
orderSwapBatteryService.calculateCost1(orderStatus.getOrderNo(), statusData);
// 修改车上电池编码
VehicleInfo vi = new VehicleInfo();
vi.setBatCode(statusData.getRentBatCode());
@ -141,33 +135,24 @@ public class StateMessageService {
dc2.setPointName(osb.getStationName());
dc2.setSoc(statusData.getReturnBatSoc());
dc2.setDccNo(statusData.getReturnBatNo());
batteryStationDcDao.update(dc2,
new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getReturnBatCode()));
batteryStationDcDao.update(dc2, new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getReturnBatCode()));
// 添加2块电池的溯源记录
addBatteryTrace(orderStatus, statusData, osb);
break;
break;*/
case 4:
// 修改订单状态
alterOrderStatus(orderStatus, null);
alterOrderStatus(orderStatus);
break;
case 5:
/* case 5:
// 修改订单状态和数据
alterOrderStatus(orderStatus, statusData);
// 修改电池状态
BatteryStationDc dc = new BatteryStationDc();
dc.setStatus(3);
dc.setSoc(statusData.getSoc());
//电量结算
LambdaQueryWrapper<OrderSwapBattery> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(OrderSwapBattery::getOrderNo, orderStatus.getOrderNo());
OrderSwapBattery orderSwapBattery = orderSwapBatteryDao.selectOne(wrapper);
//计算费用方式
if (orderSwapBattery.getFeeType()==3){
log.info("\r\n=====>>>换电订单电量结算,订单号:{}",orderStatus.getOrderNo() );
orderSwapBatteryService.calculateCost(orderStatus.getOrderNo());
}
batteryStationDcDao.update(dc, new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getBatCode()));
break;
break;*/
default:
break;
}
@ -208,7 +193,7 @@ public class StateMessageService {
*/
private void orderStatus2(OrderStatus orderStatus) {
// 修改订单状态
OrderSwapBattery osb = alterOrderStatus(orderStatus, null);
OrderSwapBattery osb = alterOrderStatus(orderStatus);
// 添加换电步骤1-车辆进站
OrderSwapBatteryStep step = new OrderSwapBatteryStep();
step.setOrderNo(orderStatus.getOrderNo());
@ -229,28 +214,21 @@ public class StateMessageService {
* 修改订单状态方法
*
* @param orderStatus
* @param statusData
* @return
*/
private OrderSwapBattery alterOrderStatus(OrderStatus orderStatus, OrderStatusData statusData) {
private OrderSwapBattery alterOrderStatus(OrderStatus orderStatus) {
OrderSwapBattery osb = orderSwapBatteryDao
.selectOne(new QueryWrapper<OrderSwapBattery>().eq("order_no", orderStatus.getOrderNo()));
osb.setStatus(orderStatus.getStatus());
if (orderStatus.getStatus() == 2) {
osb.setServiceTimeBegin(orderStatus.getStatusTime());
}
if (orderStatus.getStatus() == 3) {
osb.setServiceTimeEnd(orderStatus.getStatusTime());
BeanUtils.copyProperties(statusData, osb);
}
if (orderStatus.getStatus() == 4) {
osb.setChargeTimeBegin(orderStatus.getStatusTime());
}
if (orderStatus.getStatus() == 5) {
osb.setChargeTimeEnd(orderStatus.getStatusTime());
osb.setElectAmount(statusData.getElectAmount());
}
osb.setUptime(null);
osb.setUptime(new Date());
orderSwapBatteryDao.updateById(osb);
return osb;
}

View File

@ -2,6 +2,7 @@ package com.evotech.hd.cloud.service;
import java.util.List;
import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatusData;
import com.evotech.hd.common.core.entity.cloud.request.BatterySwapResponse;
import com.evotech.hd.cloud.entity.vo.NativePayVO;
import com.evotech.hd.common.core.entity.Result;
@ -31,8 +32,8 @@ public interface OrderSwapBatteryService {
public Result<List<OrderSwapBatteryStep>> listStep(String orderNo);
public Result<String> calculateCost(String orderNo);
public Result<String> calculateCost1(String orderNo, OrderStatusData statusData);
public Result<String> calculateCost(OrderSwapBattery osb);
public Result<String> walletPay(String orderNo, String wuid, String uname);

View File

@ -6,6 +6,7 @@ import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.cloud.WalletAccount;
import com.evotech.hd.common.core.entity.cloud.WalletAccountDetail;
import com.evotech.hd.common.core.entity.cloud.request.PageListWalletRequest;
import com.evotech.hd.common.core.entity.cloud.vo.WalletAccountVO;
import com.evotech.hd.common.core.entity.wechat.WechatPayAttach;
public interface WalletAccountService {
@ -16,7 +17,7 @@ public interface WalletAccountService {
public Result<Integer> update(WalletAccount wa);
public Result<List<WalletAccount>> list(PageListWalletRequest plwr);
public Result<List<WalletAccountVO>> list(PageListWalletRequest plwr);
public Result<Integer> addDetail(WalletAccountDetail wad);

View File

@ -4,11 +4,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyPair;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
@ -159,8 +155,8 @@ public class BatteryStationServiceImpl implements BatteryStationService {
@Override
public Result<List<BatteryStationVO>> listStation(String plateNum) {
List<BatteryStation> list = batteryStationDao.selectList(new QueryWrapper<BatteryStation>().eq("del_flag", 0));
//过滤未营业的换电站
List<BatteryStation> list = batteryStationDao.selectList(new QueryWrapper<BatteryStation>().eq("del_flag", 0).eq("status", 1));
if (list.isEmpty()) {
return new Result<List<BatteryStationVO>>().error(CodeMsg.DATABASE_RESULT_NULL);
}
@ -177,16 +173,15 @@ public class BatteryStationServiceImpl implements BatteryStationService {
if (vi == null) {
return new Result<List<BatteryStationVO>>().error("无车辆信息!");
}
res = res.stream().map(i -> {
if (StringUtils.hasText(i.getCarTypeCode()) && i.getCarTypeCode().contains(vi.getTypeCode())) {
i.setIsSuitable(true);
} else {
i.setIsSuitable(false);
}
return i;
})
.sorted((i1, i2) -> i1.getIsSuitable().compareTo(i2.getIsSuitable()))
.toList();
// 过滤未营业的换电站并根据车辆类型过滤
res = res.stream()
.filter(i -> StringUtils.hasText(i.getCarTypeCode()) && i.getCarTypeCode().contains(vi.getTypeCode()))
.map(i -> {
i.setIsSuitable(true);
return i;
})
.sorted(Comparator.comparing(BatteryStationVO::getIsSuitable))
.toList();
}
return new Result<List<BatteryStationVO>>().success(res);

View File

@ -14,6 +14,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.evotech.hd.cloud.dao.*;
import com.evotech.hd.cloud.mqtt.message.dto.newer.state.OrderStatusData;
import com.evotech.hd.common.core.entity.cloud.request.BatterySwapResponse;
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.battery.BatterySwapReq;
import com.evotech.hd.cloud.mqtt.enums.MqttMessageTypeEnum;
@ -116,8 +117,8 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
.eq("order_pre_uid", osbp.getUcode())
.eq("status", 6)
.eq("order_pre_uname", osbp.getUname())
.eq("station_code", osbp.getStationCode()));
if (ordercount > 3){
);
if (ordercount >= 3){
return new Result<Integer>().error("您有未支付的订单,请先支付!");
}
// 是否需要验证人和车绑定关系
@ -131,6 +132,11 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
osbp.setCtime(d);
int n = orderSwapBatteryPreDao.insert(osbp);
if (n == 1) {
// 计算过期时间(预约时间后30分钟)
Date expireTime = DateUtil.offsetMinute(osbp.getReservationTime(), 90);
// 将预约单ID和过期时间存入Redis,设置过期时间为预约时间后30分钟
String redisKey = "preorder:expire:" + osbp.getPkId();
redisUtil.set(redisKey, expireTime);
// 发送服务号消息没有消息队列先用接口吧
templateMessageService.preOrderMessageSend(osbp);
return new Result<Integer>().success(n);
@ -170,6 +176,7 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
@Override
public Result<Integer> add(OrderSwapBattery osb) {
// 加上费用标准
osb = orderBasicFeeComponent.orderBasicFee(osb);
osb.setCtime(new Date());
@ -277,14 +284,14 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
}
@Override
public Result<String> calculateCost(String orderNo) {
public Result<String> calculateCost1(String orderNo, OrderStatusData statusData) {
OrderSwapBattery order = orderSwapBatteryDao.selectOne(new QueryWrapper<OrderSwapBattery>().eq("order_no", orderNo));
log.info("订单号:{}", JSONUtil.parseObj(order));
if (order == null) {
return new Result<String>().error("无此订单!");
}
// 1. 检查状态
if (order.getStatus() != 5) {
if (order.getStatus() != 3) {
return new Result<String>().error("订单状态异常!");
}
@ -295,27 +302,39 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
return new Result<String>().error("订单费用标准异常!");
}
}
BigDecimal fee;
// 3. 选择费用计算方式 计算费用
if (order.getFeeType()==3){
// 电量计算
if (order.getElectAmount() == null) {
return new Result<String>().error("充电订单充电量异常!");
}
BigDecimal fee = order.getServiceFee().add(order.getBasicFee().multiply(order.getElectAmount())).setScale(0, RoundingMode.HALF_UP);
// 4. 修改订单
order.setAmount(fee.intValue());
order.setStatus(6);
orderSwapBatteryDao.updateById(order);
log.info("订单费用计算完成:{}", JSONUtil.parseObj(order));
gzhTemplateMessageService.orderMessageSend2(order.getPkId(),2);
return new Result<String>().success(fee);
fee = order.getServiceFee().add(order.getBasicFee().multiply(order.getElectAmount())).setScale(0, RoundingMode.HALF_UP);
}else if (order.getFeeType() == 2) {
// TODO 按SOC
if (statusData.getRentBatSoc() == null || statusData.getReturnBatSoc() == null) {
return new Result<String>().error("充电订单 SOC 异常!");
}
// 计算 SOC
BigDecimal socDifference = new BigDecimal(statusData.getRentBatSoc() - statusData.getReturnBatSoc());
fee = order.getServiceFee().add(order.getBasicFee().multiply(socDifference)).setScale(0, RoundingMode.HALF_UP);
order.setElectAmount(socDifference);
}else {
return new Result<String>().error("此订单不是按照电量计算");
}
// 4. 修改订单
order.setAmount(fee.intValue());
order.setStatus(6);
orderSwapBatteryDao.updateById(order);
log.info("订单费用计算完成:{}", JSONUtil.parseObj(order));
gzhTemplateMessageService.orderMessageSend2(order.getPkId(),2);
return new Result<String>().success(fee);
}
@Override
public Result<String> calculateCost(OrderSwapBattery order) {
// 2. 检查数据

View File

@ -4,6 +4,10 @@ import java.util.Date;
import java.util.List;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.evotech.hd.cloud.service.newthread.GZHTemplateMessageService;
import com.evotech.hd.common.core.dao.cloud.OrderSwapBatteryDao;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
@ -28,8 +32,10 @@ public class TradeServiceImpl implements TradeService {
private TradeDetailDao tradeDetailDao;
@Resource
private WechatPayNotifyHandleService payNotifyHandleService;
@Resource
private GZHTemplateMessageService gzhTemplateMessageService;
@Resource
private OrderSwapBatteryDao orderSwapBatteryDao;
@Override
public Result<Integer> add(TradeDetail td) {
td.setCtime(new Date());
@ -91,12 +97,13 @@ public class TradeServiceImpl implements TradeService {
log.info("\r\n===>>>已处理过此回调:" + tradeDetail);
return new Result<String>().error("重复消息!");
}
// 添加交易
log.info("请求时间{} 是否存在交易{} 添加交易>>>>>{}" ,new Date() ,b, JSONUtil.toJsonStr(tradeDetail));
add(tradeDetail);
// 2. 业务类型处理
payNotifyHandleService.payNotifyBussinessHandle(tradeDetail);
return new Result<String>().success("OK");
}

View File

@ -72,7 +72,6 @@ public class VehicleServiceImpl implements VehicleService {
.eq(StringUtils.hasText(plvr.getFrameworkNo()), "framework_no", plvr.getFrameworkNo())
.eq(StringUtils.hasText(plvr.getPhone()), "phone", plvr.getPhone())
.eq(StringUtils.hasText(plvr.getCcode()), "ccode", plvr.getCcode())
.eq(StringUtils.hasText(plvr.getProxyOperaterId()), "proxy_operater_id", plvr.getProxyOperaterId())
.ne("del_flag", 1)
.orderByAsc("plate_num"));
if (page.getRecords().isEmpty()) {

View File

@ -4,13 +4,16 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.evotech.hd.cloud.dao.CompanyDao;
import com.evotech.hd.cloud.dao.TradeDetailDao;
import com.evotech.hd.common.core.dao.wechat.WechatUserDao;
import com.evotech.hd.common.core.entity.cloud.Company;
import com.evotech.hd.common.core.entity.cloud.TradeDetail;
import com.evotech.hd.common.core.entity.cloud.vo.WalletAccountVO;
import com.evotech.hd.common.core.entity.wechat.WechatPayAttach;
import com.evotech.hd.common.core.entity.wechat.WechatUser;
import org.springframework.stereotype.Service;
@ -37,246 +40,271 @@ import org.slf4j.LoggerFactory;
@Service
public class WalletAccountServiceImpl implements WalletAccountService {
private static final Logger log = LoggerFactory.getLogger(WalletAccountServiceImpl.class);
@Resource
private WalletAccountDao walletAccountDao;
@Resource
private WalletAccountDetailDao walletAccountDetailDao;
@Resource
private WechatUserDao wechatUserDao;
@Resource
private CompanyDao companyDao;
@Resource
private TradeDetailDao tradeDetailDao;
@Override
public Result<Integer> add(WalletAccount wa) {
// 查询是否有相同的账户信息
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wa.getOwnerId());
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
private static final Logger log = LoggerFactory.getLogger(WalletAccountServiceImpl.class);
if (walletAccount != null) {
return new Result<Integer>().error("该账户已存在,无法重复添加!");
}
LambdaQueryWrapper<WechatUser> eq = new LambdaQueryWrapper<>();
eq.eq(WechatUser::getWuid,wa.getOwnerId());
WechatUser wechatUser = wechatUserDao.selectOne(eq);
if (wa.getOwnerType()==1){
if (wechatUser.getName() != null){
//名称
wa.setAccName(wechatUser.getName());
}else {
if (wechatUser.getNickName() != null){
//昵称
wa.setAccName(wechatUser.getNickName());
}else {
wa.setAccName(null);
}
}
}else {
//查询是否有相同的账户信息
QueryWrapper<Company> wrapper = new QueryWrapper<>();
wrapper.eq("ccode",wa.getOwnerId());
Company company = companyDao.selectOne(wrapper);
if (company != null){
wa.setAccName(company.getCname());
}else {
return new Result<Integer>().error("公司编码不存在!");
}
}
wa.setCtime(new Date());
String prefix = "YTWA" + (wa.getOwnerType() == 1 ? "P" : "C");
wa.setCode(prefix + SnowflakeUtil.getIdStr() + RandomUtil.randomStringUpper(6));
int n = walletAccountDao.insert(wa);
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("添加资金账户出错!");
}
@Resource
private WalletAccountDao walletAccountDao;
@Resource
private WalletAccountDetailDao walletAccountDetailDao;
@Resource
private WechatUserDao wechatUserDao;
@Resource
private CompanyDao companyDao;
@Resource
private TradeDetailDao tradeDetailDao;
@Override
public Result<Integer> delete(Integer id, String code) {
Map<String, Object> m = new HashMap<String, Object>();
m.put("pk_id", id);
m.put("code", code);
int n = walletAccountDao.deleteByMap(m);
if (n == 1) {
return new Result<Integer>().success(n);
}
throw new RuntimeException("删除资金账户出错!-- " + n);
}
@Override
public Result<Integer> add(WalletAccount wa) {
// 查询是否有相同的账户信息
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wa.getOwnerId());
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
@Override
public Result<Integer> update(WalletAccount wa) {
WalletAccount wa1 = new WalletAccount();
wa1.setAccName(wa.getAccName());
wa1.setGiftAmount(wa.getGiftAmount());
wa1.setTotalAmount(wa.getTotalAmount());
wa1.setRechargeAmount(wa.getRechargeAmount());
int n = walletAccountDao.update(wa1, new QueryWrapper<WalletAccount>()
.eq("code", wa.getCode())
.eq("pk_id", wa.getPkId()));
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("更新资金账户失败!");
}
if (walletAccount != null) {
return new Result<Integer>().error("该账户已存在,无法重复添加!");
}
LambdaQueryWrapper<WechatUser> eq = new LambdaQueryWrapper<>();
eq.eq(WechatUser::getWuid, wa.getOwnerId());
WechatUser wechatUser = wechatUserDao.selectOne(eq);
if (wa.getOwnerType() == 1) {
if (wechatUser.getName() != null) {
//名称
wa.setAccName(wechatUser.getName());
} else {
if (wechatUser.getNickName() != null) {
//昵称
wa.setAccName(wechatUser.getNickName());
} else {
wa.setAccName(null);
}
}
} else {
//查询是否有相同的账户信息
QueryWrapper<Company> wrapper = new QueryWrapper<>();
wrapper.eq("ccode", wa.getOwnerId());
Company company = companyDao.selectOne(wrapper);
if (company != null) {
wa.setAccName(company.getCname());
} else {
return new Result<Integer>().error("公司编码不存在!");
}
}
wa.setCtime(new Date());
String prefix = "YTWA" + (wa.getOwnerType() == 1 ? "P" : "C");
wa.setCode(prefix + SnowflakeUtil.getIdStr() + RandomUtil.randomStringUpper(6));
int n = walletAccountDao.insert(wa);
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("添加资金账户出错!");
}
@Override
public Result<List<WalletAccount>> list(PageListWalletRequest plwr) {
Page<WalletAccount> page = new Page<WalletAccount>(plwr.getPageNo(), plwr.getPageSize());
page = walletAccountDao.selectPage(page, new QueryWrapper<WalletAccount>()
.eq(StringUtils.hasText(plwr.getCode()), "code", plwr.getCode())
.eq(StringUtils.hasText(plwr.getStationCode()), "station_code", plwr.getStationCode())
.eq(plwr.getOwnerType() != null, "owner_type", plwr.getOwnerType())
.eq(StringUtils.hasText(plwr.getOwnerId()), "owner_id", plwr.getOwnerId())
.orderByDesc("pk_id"));
//获取交易明细对应的微信用户
@Override
public Result<Integer> delete(Integer id, String code) {
Map<String, Object> m = new HashMap<String, Object>();
m.put("pk_id", id);
m.put("code", code);
int n = walletAccountDao.deleteByMap(m);
if (n == 1) {
return new Result<Integer>().success(n);
}
throw new RuntimeException("删除资金账户出错!-- " + n);
}
if (page.getRecords().isEmpty()) {
return new Result<List<WalletAccount>>().error(CodeMsg.DATABASE_RESULT_NULL);
}
return new Result<List<WalletAccount>>().success(page);
}
@Override
public Result<Integer> update(WalletAccount wa) {
WalletAccount wa1 = new WalletAccount();
wa1.setAccName(wa.getAccName());
wa1.setGiftAmount(wa.getGiftAmount());
wa1.setTotalAmount(wa.getTotalAmount());
wa1.setRechargeAmount(wa.getRechargeAmount());
int n = walletAccountDao.update(wa1, new QueryWrapper<WalletAccount>()
.eq("code", wa.getCode())
.eq("pk_id", wa.getPkId()));
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("更新资金账户失败!");
}
@Override
public Result<Integer> addDetail(WalletAccountDetail wad) {
wad.setCtime(new Date());
int n = walletAccountDetailDao.insert(wad);
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("添加资金账户明细出错!");
}
@Override
public Result<List<WalletAccountVO>> list(PageListWalletRequest plwr) {
Page<WalletAccount> page = new Page<WalletAccount>(plwr.getPageNo(), plwr.getPageSize());
@Override
public Result<Integer> deleteDetail(Integer id, String code) {
Map<String, Object> m = new HashMap<String, Object>();
m.put("pk_id", id);
m.put("code", code);
int n = walletAccountDetailDao.deleteByMap(m);
if (n == 1) {
return new Result<Integer>().success(n);
}
throw new RuntimeException("删除资金账户明细出错!-- " + n);
}
page = walletAccountDao.selectPage(page, new QueryWrapper<WalletAccount>()
.eq(StringUtils.hasText(plwr.getCode()), "code", plwr.getCode())
.eq(StringUtils.hasText(plwr.getStationCode()), "station_code", plwr.getStationCode())
.eq(plwr.getOwnerType() != null, "owner_type", plwr.getOwnerType())
.eq(StringUtils.hasText(plwr.getOwnerId()), "owner_id", plwr.getOwnerId())
.orderByDesc("pk_id"));
@Override
public Result<List<WalletAccountDetail>> listDetail(PageListWalletRequest plwr) {
Page<WalletAccountDetail> page = new Page<WalletAccountDetail>(plwr.getPageNo(), plwr.getPageSize());
page = walletAccountDetailDao.selectPage(page, new QueryWrapper<WalletAccountDetail>()
.eq(StringUtils.hasText(plwr.getCode()), "code", plwr.getCode())
.orderByDesc("pk_id"));
if (page.getRecords().isEmpty()) {
return new Result<List<WalletAccountDetail>>().error(CodeMsg.DATABASE_RESULT_NULL);
}
return new Result<List<WalletAccountDetail>>().success(page);
}
if (page.getRecords().isEmpty()) {
return new Result<List<WalletAccountVO>>().error(CodeMsg.DATABASE_RESULT_NULL);
}
// 2. 转换为VO并查询用户信息
List<WalletAccountVO> voList = page.getRecords().stream().map(account -> {
WalletAccountVO vo = new WalletAccountVO();
// 复制基本属性
BeanUtil.copyProperties(account, vo);
// 查询微信用户信息
if (StringUtils.hasText(account.getOwnerId())) {
WechatUser wechatUser = wechatUserDao.selectOne(
new QueryWrapper<WechatUser>()
.eq("wuid", account.getOwnerId())
);
if (wechatUser != null) {
vo.setAccName(wechatUser.getName());
vo.setPhone(wechatUser.getPhoneNumber());
}
}
return vo;
@Override
public Result<Boolean> isOpenAccount(String wuid) {
if (StrUtil.isBlank(wuid)) {
return new Result<Boolean>().error("用户ID不能为空");
}
}).collect(Collectors.toList());
try {
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wuid);
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
return new Result<Boolean>().success(walletAccount != null);
} catch (Exception e) {
log.error("查询用户钱包账户异常: wuid={}, error={}", wuid, e.getMessage(), e);
return new Result<Boolean>().error("查询钱包账户异常");
}
}
@Override
public Result<String> getWalleCode(String wuid) {
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wuid);
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
if (walletAccount==null){
WalletAccount walletAccount1 = new WalletAccount();
walletAccount1.setOwnerId(wuid);
walletAccount1.setOwnerType(1);
if (add(walletAccount1).getCode()== CodeMsg.SUCCESS.getCode()){
LambdaQueryWrapper<WalletAccount> queryWrapper1 = new LambdaQueryWrapper<>();
queryWrapper1.eq(WalletAccount::getOwnerId, wuid);
walletAccount = walletAccountDao.selectOne(queryWrapper1);
}
}
return new Result<String>().success("成功",(StringUtils.hasText(walletAccount.getAccName()) ? walletAccount.getAccName() : "")+"_"+walletAccount.getCode());
}
@Override
public Result<WechatPayAttach> getPayAttach(String wuid) {
try {
if (!StringUtils.hasText(wuid)) {
return new Result<WechatPayAttach>().error("WUID不能为空");
}
// 查询 WechatUser
WechatUser wechatUser = queryWechatUserByWuid(wuid);
if (wechatUser == null) {
log.warn("未找到对应的WechatUser, WUID: {}", wuid);
return new Result<WechatPayAttach>().error("未找到对应的WechatUser");
}
// 3. 创建新的分页对象
Page<WalletAccountVO> voPage = new Page<>();
BeanUtil.copyProperties(page, voPage, "records");
voPage.setRecords(voList);
// 查询 WalletAccount
WalletAccount walletAccount = queryWalletAccountByCode(wechatUser.getWuid());
if (walletAccount == null) {
log.warn("未找到对应的WalletAccount, Code: {}", walletAccount.getCode());
return new Result<WechatPayAttach>().error("未找到对应的WalletAccount");
}
return new Result<List<WalletAccountVO>>().success(voPage);
}
// 构建并返回结果
WechatPayAttach wechatPayAttach = buildWechatPayAttach( walletAccount,wechatUser);
return new Result<WechatPayAttach>().success(wechatPayAttach);
@Override
public Result<Integer> addDetail(WalletAccountDetail wad) {
wad.setCtime(new Date());
int n = walletAccountDetailDao.insert(wad);
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("添加资金账户明细出错!");
}
} catch (Exception e) {
log.error("获取支付附加信息失败, WUID: {}, 错误信息: {}", wuid, e.getMessage(), e);
return new Result<WechatPayAttach>().error("系统异常,请稍后再试");
}
}
@Override
public Result<Integer> deleteDetail(Integer id, String code) {
Map<String, Object> m = new HashMap<String, Object>();
m.put("pk_id", id);
m.put("code", code);
int n = walletAccountDetailDao.deleteByMap(m);
if (n == 1) {
return new Result<Integer>().success(n);
}
throw new RuntimeException("删除资金账户明细出错!-- " + n);
}
// 查询 WechatUser 的封装方法
private WechatUser queryWechatUserByWuid(String wuid) {
LambdaQueryWrapper<WechatUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WechatUser::getWuid, wuid);
return wechatUserDao.selectOne(queryWrapper);
}
@Override
public Result<List<WalletAccountDetail>> listDetail(PageListWalletRequest plwr) {
Page<WalletAccountDetail> page = new Page<WalletAccountDetail>(plwr.getPageNo(), plwr.getPageSize());
// 查询 TradeDetail 的封装方法
private TradeDetail queryTradeDetailByTraderCode(String traderCode) {
LambdaQueryWrapper<TradeDetail> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TradeDetail::getTraderCode, traderCode);
return tradeDetailDao.selectOne(queryWrapper);
}
page = walletAccountDetailDao.selectPage(page, new QueryWrapper<WalletAccountDetail>()
.eq(StringUtils.hasText(plwr.getCode()), "code", plwr.getCode())
.orderByDesc("pk_id"));
if (page.getRecords().isEmpty()) {
return new Result<List<WalletAccountDetail>>().error(CodeMsg.DATABASE_RESULT_NULL);
}
return new Result<List<WalletAccountDetail>>().success(page);
}
// 查询 WalletAccount 的封装方法
private WalletAccount queryWalletAccountByCode(String wuid) {
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wuid);
return walletAccountDao.selectOne(queryWrapper);
}
@Override
public Result<Boolean> isOpenAccount(String wuid) {
if (StrUtil.isBlank(wuid)) {
return new Result<Boolean>().error("用户ID不能为空");
}
// 构建 WechatPayAttach 的封装方法
private WechatPayAttach buildWechatPayAttach( WalletAccount walletAccount,WechatUser user) {
WechatPayAttach wechatPayAttach = new WechatPayAttach();
wechatPayAttach.setTrader(user.getName());
wechatPayAttach.setTraderCode(walletAccount.getOwnerId());
wechatPayAttach.setWalletCode(walletAccount.getCode());
return wechatPayAttach;
}
try {
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wuid);
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
return new Result<Boolean>().success(walletAccount != null);
} catch (Exception e) {
log.error("查询用户钱包账户异常: wuid={}, error={}", wuid, e.getMessage(), e);
return new Result<Boolean>().error("查询钱包账户异常");
}
}
@Override
public Result<String> getWalleCode(String wuid) {
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wuid);
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
if (walletAccount == null) {
WalletAccount walletAccount1 = new WalletAccount();
walletAccount1.setOwnerId(wuid);
walletAccount1.setOwnerType(1);
if (add(walletAccount1).getCode() == CodeMsg.SUCCESS.getCode()) {
LambdaQueryWrapper<WalletAccount> queryWrapper1 = new LambdaQueryWrapper<>();
queryWrapper1.eq(WalletAccount::getOwnerId, wuid);
walletAccount = walletAccountDao.selectOne(queryWrapper1);
}
}
return new Result<String>().success("成功", (StringUtils.hasText(walletAccount.getAccName()) ? walletAccount.getAccName() : "") + "_" + walletAccount.getCode());
}
@Override
public Result<WechatPayAttach> getPayAttach(String wuid) {
try {
if (!StringUtils.hasText(wuid)) {
return new Result<WechatPayAttach>().error("WUID不能为空");
}
// 查询 WechatUser
WechatUser wechatUser = queryWechatUserByWuid(wuid);
if (wechatUser == null) {
log.warn("未找到对应的WechatUser, WUID: {}", wuid);
return new Result<WechatPayAttach>().error("未找到对应的WechatUser");
}
// 查询 WalletAccount
WalletAccount walletAccount = queryWalletAccountByCode(wechatUser.getWuid());
if (walletAccount == null) {
log.warn("未找到对应的WalletAccount, Code: {}", walletAccount.getCode());
return new Result<WechatPayAttach>().error("未找到对应的WalletAccount");
}
// 构建并返回结果
WechatPayAttach wechatPayAttach = buildWechatPayAttach(walletAccount, wechatUser);
return new Result<WechatPayAttach>().success(wechatPayAttach);
} catch (Exception e) {
log.error("获取支付附加信息失败, WUID: {}, 错误信息: {}", wuid, e.getMessage(), e);
return new Result<WechatPayAttach>().error("系统异常,请稍后再试");
}
}
// 查询 WechatUser 的封装方法
private WechatUser queryWechatUserByWuid(String wuid) {
LambdaQueryWrapper<WechatUser> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WechatUser::getWuid, wuid);
return wechatUserDao.selectOne(queryWrapper);
}
// 查询 TradeDetail 的封装方法
private TradeDetail queryTradeDetailByTraderCode(String traderCode) {
LambdaQueryWrapper<TradeDetail> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TradeDetail::getTraderCode, traderCode);
return tradeDetailDao.selectOne(queryWrapper);
}
// 查询 WalletAccount 的封装方法
private WalletAccount queryWalletAccountByCode(String wuid) {
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId, wuid);
return walletAccountDao.selectOne(queryWrapper);
}
// 构建 WechatPayAttach 的封装方法
private WechatPayAttach buildWechatPayAttach(WalletAccount walletAccount, WechatUser user) {
WechatPayAttach wechatPayAttach = new WechatPayAttach();
wechatPayAttach.setTrader(user.getName());
wechatPayAttach.setTraderCode(walletAccount.getOwnerId());
wechatPayAttach.setWalletCode(walletAccount.getCode());
return wechatPayAttach;
}
}

View File

@ -1,28 +1,38 @@
package com.evotech.hd.cloud.task;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.evotech.hd.cloud.dao.OrderSwapBatteryPreDao;
import com.evotech.hd.cloud.service.OrderSwapBatteryService;
import com.evotech.hd.cloud.service.newthread.GZHTemplateMessageService;
import com.evotech.hd.common.core.dao.cloud.OrderSwapBatteryDao;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import com.evotech.hd.common.redis.utils.RedisUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
@Component
@Slf4j
public class OrderSwapBatteryTask {
@Resource
private OrderSwapBatteryPreDao orderSwapBatteryPreDao;
@Resource
private GZHTemplateMessageService templateMessageService;
@Resource
private RedisUtil redisUtil;
@Scheduled(cron = "0 0 * * * ?") // 每小时执行一次
@Scheduled(cron = "0 0 * * * ?") // 每小时执行一次
public void orderSwapBatteryExpired() {
log.info("\r\n===>>> 开始查找预约单更新预约状态..");
@ -51,7 +61,7 @@ public class OrderSwapBatteryTask {
expiredCount++;
log.info("预约单已过期订单ID: {}", order.getSourceId()); // 记录过期的订单ID
} catch (Exception e) {
log.error("更新预约单状态失败,预约人:{}订单ID: {}, 错误信息: {}",order.getUname(), order.getPkId(), e.getMessage());
log.error("更新预约单状态失败,预约人:{}订单ID: {}, 错误信息: {}", order.getUname(), order.getPkId(), e.getMessage());
}
}
}
@ -59,4 +69,45 @@ public class OrderSwapBatteryTask {
log.info("\r\n===>>> 预约单过期:{} 条数据", expiredCount);
}
// 每5分钟检查一次即将过期的预约单
@Scheduled(cron = "0 */5 * * * ?")
public void checkExpiringPreOrders() {
log.info("\r\n===>>> 开始检查即将过期的预约单..");
// 获取当前时间
Date currentTime = new Date();
int reminderCount = 0;
// 获取所有需要检查的预约单
Set<String> keys = redisUtil.keys("preorder:expire:*");
// 检查是否有未发送提醒的标记
if (CollectionUtil.isEmpty(keys)) {
log.info("没有需要提醒的预约单");
return;
}
for (String key : keys) {
try {
String id = key.substring(key.lastIndexOf(":") + 1);
OrderSwapBatteryPre order = orderSwapBatteryPreDao.selectById(id);
if (order != null && order.getStatus() == 1) { // 只处理状态为1的预约单
// 获取过期时间
Date expireTime = (Date) redisUtil.get(key);
// 如果当前时间接近过期时间(5分钟内)
if (expireTime != null && DateUtil.between(currentTime, expireTime, DateUnit.MINUTE) <= 5) {
// 发送微信公众号提醒
templateMessageService.preOrderMessageSend(order);
reminderCount++;
// 从Redis中删除该预约单
redisUtil.del(key);
log.info("发送微信公众号即将过期提醒,预约人:{}订单ID: {}", order.getUname(), order.getPkId());
}
}
} catch (Exception e) {
log.error("处理预约单提醒失败key: {}, 错误信息: {}", key, e.getMessage());
}
log.info("\r\n===>>> 发送微信公众号即将过期提醒:{} 条数据", reminderCount);
}
}
}

View File

@ -54,19 +54,19 @@ public class SwapOrderBasicFeeComponent {
log.info("当前时间在费用详情有效时间范围内=====>{}", JSONUtil.toJsonStr(detail));
// 设置基本费用和服务费用
osb.setFeeStandardJson(JSONUtil.toJsonStr(detail));
osb.setBasicFee(detail.getEachKwhFee());
osb.setBasicFee(detail.getEachSocFee());
osb.setServiceFee(detail.getTimeServiceFee());
} else {
// 如果没有有效的详细费用使用标准费用
osb.setFeeStandardJson(JSONUtil.toJsonStr(standard));
osb.setBasicFee(standard.getEachKwhFee());
osb.setBasicFee(standard.getEachSocFee());
osb.setServiceFee(standard.getCommonRemainFee());
}
} else {
osb.setFeeStandardJson(JSONUtil.toJsonStr(standard));
// 如果没有详细费用直接使用标准费用
log.info("没有详细费用,直接使用标准费用=====>{}", JSONUtil.toJsonStr(standard));
osb.setBasicFee(standard.getEachKwhFee());
osb.setBasicFee(standard.getEachSocFee());
osb.setServiceFee(standard.getCommonRemainFee());
}
}

View File

@ -6,6 +6,7 @@ import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
@ -35,6 +36,7 @@ import reactor.core.publisher.Mono;
* 资源服务的权限管理器
* 鉴权时统一抛出OAuth2AuthorizationException
*/
@Slf4j
@Component
public class AuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {
@ -104,6 +106,7 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
}
// 验证wuid
if (!redisUtil.hasKey(HDConstant.openidPrefix + wuid)) {
log.error("验证wuid===============>"+HDConstant.openidPrefix + wuid);
throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), uri));
}
// 验证token正确
@ -120,6 +123,7 @@ public class AuthorizationManager implements ReactiveAuthorizationManager<Author
m = asyncRes.get();
} catch (Exception e) {
e.printStackTrace();
log.error("token获取异常=================>"+asyncRes);
throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), "token异常"));
}
throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_EXPIRED.getCode(), CodeMsg.WECHAT_TOKEN_EXPIRED.getMsg(), JSONUtil.toJsonStr(m)));

View File

@ -78,6 +78,7 @@ public class WechatAuthorizationManager implements ReactiveAuthorizationManager<
}
// 验证wuid
if (!redisUtil.hasKey(HDConstant.openidPrefix + wuid)) {
log.error("-验证wiud***===================>"+HDConstant.openidPrefix + wuid);
throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), uri));
}
// 验证token正确
@ -98,6 +99,7 @@ public class WechatAuthorizationManager implements ReactiveAuthorizationManager<
log.error("\r\n---777---" + m);
} catch (Exception e) {
e.printStackTrace();
log.error("-验证wiud*21**===================>"+asyncRes);
throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_LOGIN_ERROR.getCode(), CodeMsg.WECHAT_LOGIN_ERROR.getMsg(), "token异常"));
}
throw new OAuth2AuthorizationException(new OAuth2Error(CodeMsg.WECHAT_TOKEN_EXPIRED.getCode(), CodeMsg.WECHAT_TOKEN_EXPIRED.getMsg(), JSONUtil.toJsonStr(m)));

View File

@ -31,4 +31,6 @@ public class GZHProperties {
private String orderEndTemplateId;
private String WalletRechargeTemplateId;
private String orderToPayTemplateId2;
}

View File

@ -0,0 +1,63 @@
package com.evotech.hd.wechat.entity.gzh.templatemessage;
import cn.hutool.json.JSONObject;
import lombok.Getter;
/**
* 充电完成SOC 模板消息 关键词
*/
@Getter
public class ChargeTemplateData2 {
/*
订单编号
*/
private JSONObject character_string2;
/*
耗电量
*/
private JSONObject number15;
/*
车牌号码
*/
private JSONObject car_number8;
/*
充电服务费
*/
private JSONObject thing34;
/*
消费金额
*/
private JSONObject amount5;
public void setCharacter_string2(String value1) {
JSONObject jo = new JSONObject();
jo.set("value", value1);
this.character_string2 = jo;
}
public void setNumber15(String value2) {
JSONObject jo = new JSONObject();
jo.set("value", value2);
this.number15 = jo;
}
public void setCar_number8(String value3) {
JSONObject jo = new JSONObject();
jo.set("value", value3);
this.car_number8 = jo;
}
public void setThing34(String value4) {
JSONObject jo = new JSONObject();
jo.set("value", value4);
this.thing34 = jo;
}
public void setAmount5(String value5) {
JSONObject jo = new JSONObject();
jo.set("value", value5);
this.amount5 = jo;
}
}

View File

@ -128,7 +128,7 @@ public class GZHMessageTemplateService {
log.info("付款完成推送公众号消息=======>{}", JSONUtil.parseObj(data));
sendData.setData(JSONUtil.parseObj(data));
break;
// 充电完成待结算
/* // 充电完成待结算
case 2:
templateId = gzhProperties.getOrderToPayTemplateId();
miniprogram.setPath(orderPage);
@ -136,11 +136,25 @@ public class GZHMessageTemplateService {
chargeData.setCharacter_string14(osb.getOrderNo());
chargeData.setCharacter_string31(osb.getReturnBatCode());
chargeData.setCharacter_string25(osb.getElectAmount() + "");
chargeData.setAmount34(osb.getServiceFee() != null ? osb.getServiceFee().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_DOWN).setScale(2, RoundingMode.HALF_EVEN).toString().toString() : "");
chargeData.setAmount34(osb.getServiceFee() != null ? osb.getServiceFee().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_DOWN).setScale(2, RoundingMode.HALF_EVEN).toString() : "");
chargeData.setAmount28(osb.getAmount() != null ? new BigDecimal(osb.getAmount()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_DOWN).setScale(2, RoundingMode.HALF_EVEN).toString(): "");
log.info("付款完成推送公众号消息=======>{}", JSONUtil.parseObj(chargeData));
sendData.setData(JSONUtil.parseObj(chargeData));
break;
break;*/
// 充电完成待结算(新模版SOC)
case 2:
templateId = gzhProperties.getOrderToPayTemplateId2();
miniprogram.setPath(orderPage);
ChargeTemplateData2 chargeData2 = new ChargeTemplateData2();
chargeData2.setCharacter_string2(osb.getOrderNo());
String soc = String.valueOf(osb.getRentBatSoc()- osb.getReturnBatSoc());
chargeData2.setNumber15(soc);
chargeData2.setCar_number8(osb.getPlateNum());
chargeData2.setThing34(osb.getStationName());
chargeData2.setAmount5(osb.getAmount() != null ? new BigDecimal(osb.getAmount()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_DOWN).setScale(2, RoundingMode.HALF_EVEN).toString(): "");
log.info("付款完成推送公众号消息=======>{}", JSONUtil.parseObj(chargeData2));
sendData.setData(JSONUtil.parseObj(chargeData2));
break;
// 付款完成
case 3:
templateId = gzhProperties.getOrderSwapEndTemplateId();
@ -154,6 +168,9 @@ public class GZHMessageTemplateService {
log.info("付款完成推送公众号消息=======>{}", JSONUtil.parseObj(payData));
sendData.setData(JSONUtil.parseObj(payData));
break;
//预约即将失效
case 4:
break;
default:
break;
}

View File

@ -4,6 +4,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
@ -32,6 +33,7 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
@ -57,6 +59,7 @@ public class LoginServiceImpl implements LoginService {
String res = LoginUtil.code2Session(xcxProperties.getAppid(), xcxProperties.getAppSecret(), js_code);
JSONObject jo = JSONUtil.parseObj(res);
if (StringUtils.hasText(jo.getStr("errcode"))) {
log.error("微信登陆失败=================>{}", jo);
return new Result<Map<String, String>>().error(CodeMsg.WECHAT_LOGIN_ERROR, jo);
}
String openid = jo.getStr("openid");

View File

@ -75,9 +75,9 @@ public class OrderServiceImpl implements OrderService {
@Override
public Result<Boolean> startSwap(String wuid ,String orderId ) throws Exception {
if (!wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
/*if (!wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
throw new Exception("账号错误");
}
}*/
return cloudService.startSwap(wuid,orderId);
}

View File

@ -104,7 +104,14 @@ public class WechatPayServiceImpl implements WechatPayService {
prePay.setAttach(JSONUtil.toJsonStr(entries.set("walletCode", split[1])));
}
//判断是充值订单还是订单支付
if (!StringUtils.hasText(entries.getStr("type"))){
String type = entries.getStr("type");
if (StringUtils.hasText(type) && type.equals("1")) {
// 充值订单
}
}
WechatPayPreOrder preOrder = new WechatPayPreOrder();
// 组装数据
PrepayRequest request = new PrepayRequest();
@ -147,9 +154,8 @@ public class WechatPayServiceImpl implements WechatPayService {
preOrder.setDeviceId(prePay.getDeviceId());
}
PrepayWithRequestPaymentResponse response = WechatPayUtil.jsapiPrepay(config, request);
//判断是充值订单还是订单支付
// System.out.println("\r\n=====response>>>>>" + response);
// 写表
BeanUtils.copyProperties(request, preOrder);
wechatPayComponent.wechatPrePayLog(prePay.getWuid(), prePay.getCcode(), prePay.getCostPrice(), preOrder, JSONUtil.toJsonStr(response));

View File

@ -74,9 +74,9 @@ public class WechatUserServiceImpl implements WechatUserService {
@Override
public Result<Integer> openWallet(String wuid, HttpServletRequest request) {
if (!wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
/*if (!wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
return new Result<Integer>().error("账号错误");
}
}*/
WalletAccount wa = new WalletAccount();
wa.setOwnerType(1);
wa.setOwnerId(wuid);
@ -112,9 +112,9 @@ public class WechatUserServiceImpl implements WechatUserService {
@Override
public Result<Boolean> isOpenAccount(String wuid, HttpServletRequest request) {
// 1. 从请求头获取 Token
if (wuid == null || !wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
/*if (wuid == null || !wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
return new Result<Boolean>().error("账号错误!");
}
}*/
return cloudService.isOpenAccount(wuid);
}