|
|
@@ -15,7 +15,10 @@ import org.dromara.main.domain.bo.CsOrderCardBo;
|
|
|
import org.dromara.main.domain.vo.CsOrderCardVo;
|
|
|
import org.dromara.main.mapper.CsMessageMapper;
|
|
|
import org.dromara.main.mapper.CsOrderCardMapper;
|
|
|
+import org.dromara.main.mapper.CsSessionMapper;
|
|
|
+import org.dromara.main.mapper.MainExamEvaluationMapper;
|
|
|
import org.dromara.main.mapper.MainOrderMapper;
|
|
|
+import org.dromara.main.mapper.MainPositionMapper;
|
|
|
import org.dromara.main.mapper.MainStudentMapper;
|
|
|
import org.dromara.main.service.ICsOrderCardService;
|
|
|
import org.dromara.main.service.ICsSessionService;
|
|
|
@@ -39,6 +42,9 @@ public class CsOrderCardServiceImpl implements ICsOrderCardService {
|
|
|
private final Converter converter;
|
|
|
private final MainOrderMapper orderMapper;
|
|
|
private final MainStudentMapper studentMapper;
|
|
|
+ private final CsSessionMapper sessionMapper;
|
|
|
+ private final MainExamEvaluationMapper examEvaluationMapper;
|
|
|
+ private final MainPositionMapper mainPositionMapper;
|
|
|
@Autowired
|
|
|
private WxPayConfig wxPayConfig;
|
|
|
|
|
|
@@ -62,6 +68,7 @@ public class CsOrderCardServiceImpl implements ICsOrderCardService {
|
|
|
orderCard.setOrderName(bo.getOrderName());
|
|
|
orderCard.setOrderPrice(bo.getOrderPrice());
|
|
|
orderCard.setOrderType(bo.getOrderType());
|
|
|
+ orderCard.setTenantId(bo.getTenantId());
|
|
|
orderCard.setStatus("pending");
|
|
|
orderCard.setExpireTime(LocalDateTime.now().plusSeconds(60));
|
|
|
orderCard.setCreateTime(LocalDateTime.now());
|
|
|
@@ -181,13 +188,20 @@ public class CsOrderCardServiceImpl implements ICsOrderCardService {
|
|
|
mainOrder.setPayStatus(0);
|
|
|
mainOrder.setBusinessId(orderCard.getId());
|
|
|
mainOrder.setProductId(orderCard.getId());
|
|
|
- mainOrder.setTenantId(student.getTenantId());
|
|
|
+ // 优先使用结算单上的tenantId,其次用学员的
|
|
|
+ String tenantId = StringUtils.isNotBlank(orderCard.getTenantId()) ? orderCard.getTenantId() : student.getTenantId();
|
|
|
+ mainOrder.setTenantId(tenantId);
|
|
|
mainOrder.setRemark(orderCard.getOrderName());
|
|
|
log.info("创建订单 - 结算单ID: {}, 结算单价格: {}, 转换后的订单价格: {}", orderCard.getId(), orderCard.getOrderPrice(), mainOrder.getTotalAmount());
|
|
|
orderMapper.insert(mainOrder);
|
|
|
|
|
|
+ // 回写主订单ID到结算单
|
|
|
+ orderCard.setOriginalOrderId(mainOrder.getId());
|
|
|
+ baseMapper.updateById(orderCard);
|
|
|
+
|
|
|
try {
|
|
|
- log.info("生成微信支付参数 - OpenID: {}, 传入价格: {}, 订单号: {}", student.getOpenid(), orderCard.getOrderPrice(), mainOrder.getOrderNo());
|
|
|
+ log.info("生成微信支付参数 - OpenID: {}, 传入价格: {}, 订单号: {}, notifyUrl: {}",
|
|
|
+ student.getOpenid(), orderCard.getOrderPrice(), mainOrder.getOrderNo(), wxPayConfig.getNotifyUrl());
|
|
|
Map<String, String> wxPayParams = wxPayConfig.createJsapiPayParams(
|
|
|
student.getOpenid(),
|
|
|
orderCard.getOrderPrice(),
|
|
|
@@ -222,7 +236,7 @@ public class CsOrderCardServiceImpl implements ICsOrderCardService {
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public void handlePaySuccess(String orderNo) {
|
|
|
- log.info("处理支付成功,订单号:{}", orderNo);
|
|
|
+ log.info("========== 开始处理支付成功,订单号:{} ==========", orderNo);
|
|
|
|
|
|
// 查找主订单
|
|
|
MainOrder mainOrder = orderMapper.selectOne(
|
|
|
@@ -233,24 +247,45 @@ public class CsOrderCardServiceImpl implements ICsOrderCardService {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ log.info("找到订单: id={}, orderNo={}, payStatus={}, orderStatus={}, businessId={}",
|
|
|
+ mainOrder.getId(), mainOrder.getOrderNo(), mainOrder.getPayStatus(), mainOrder.getOrderStatus(), mainOrder.getBusinessId());
|
|
|
+
|
|
|
// 防重复处理
|
|
|
- if (mainOrder.getPayStatus() == 1) {
|
|
|
- log.info("订单已处理过支付成功,订单号:{}", orderNo);
|
|
|
+ if (mainOrder.getPayStatus() != null && mainOrder.getPayStatus() == 1) {
|
|
|
+ log.info("订单已处理过支付成功,跳过,订单号:{}", orderNo);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 更新主订单状态(按你的业务逻辑)
|
|
|
+ // 更新主订单状态
|
|
|
mainOrder.setPayStatus(1); // 已支付
|
|
|
mainOrder.setOrderStatus(1); // 已完成
|
|
|
mainOrder.setPaidAmount(mainOrder.getTotalAmount());
|
|
|
orderMapper.updateById(mainOrder);
|
|
|
+ log.info("主订单状态已更新为已支付,订单号:{}", orderNo);
|
|
|
|
|
|
- // 更新结算单状态(按你的业务逻辑)
|
|
|
+ // 更新结算单状态
|
|
|
CsOrderCard orderCard = baseMapper.selectById(mainOrder.getBusinessId());
|
|
|
if (orderCard != null) {
|
|
|
+ log.info("找到结算单: id={}, status={}, sessionId={}", orderCard.getId(), orderCard.getStatus(), orderCard.getSessionId());
|
|
|
orderCard.setStatus("paid");
|
|
|
orderCard.setPayTime(LocalDateTime.now());
|
|
|
baseMapper.updateById(orderCard);
|
|
|
+ log.info("结算单状态已更新为已支付,结算单ID:{}", orderCard.getId());
|
|
|
+
|
|
|
+ // 同步更新聊天消息的payload状态
|
|
|
+ if (orderCard.getMsgId() != null) {
|
|
|
+ CsMessage msg = messageMapper.selectById(orderCard.getMsgId());
|
|
|
+ if (msg != null && StringUtils.isNotBlank(msg.getPayload())) {
|
|
|
+ try {
|
|
|
+ Map<String, Object> payload = JSONUtil.toBean(msg.getPayload(), Map.class);
|
|
|
+ payload.put("status", "paid");
|
|
|
+ msg.setPayload(JSONUtil.toJsonStr(payload));
|
|
|
+ messageMapper.updateById(msg);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("更新消息payload状态失败: {}", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
log.info("支付成功处理完成,订单号:{},结算单ID:{}", orderNo, orderCard.getId());
|
|
|
}
|
|
|
@@ -268,5 +303,125 @@ public class CsOrderCardServiceImpl implements ICsOrderCardService {
|
|
|
return amount == null ? BigDecimal.ZERO : amount;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public CsOrderCardVo autoCreateForAssessment(Long sessionId, Long studentId, String orderName, BigDecimal orderPrice, String orderType) {
|
|
|
+ // 检查该会话是否已有待支付的结算单,避免重复创建
|
|
|
+ CsOrderCard existing = baseMapper.selectOne(Wrappers.<CsOrderCard>lambdaQuery()
|
|
|
+ .eq(CsOrderCard::getSessionId, sessionId)
|
|
|
+ .eq(CsOrderCard::getStatus, "pending")
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (existing != null) {
|
|
|
+ CsOrderCardVo vo = converter.convert(existing, CsOrderCardVo.class);
|
|
|
+ if (vo != null && "pending".equals(vo.getStatus())) {
|
|
|
+ long seconds = Duration.between(LocalDateTime.now(), existing.getExpireTime()).getSeconds();
|
|
|
+ vo.setCountdownSeconds(Math.max(0, seconds));
|
|
|
+ }
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从会话获取tenantId、测评价格(结算单本质上是针对测评的)
|
|
|
+ String tenantId = "000000";
|
|
|
+ BigDecimal resolvedPrice = orderPrice; // 默认使用前端传入的价格
|
|
|
+ CsSession session = sessionMapper.selectById(sessionId);
|
|
|
+ if (session != null && StringUtils.isNotBlank(session.getSourceId())) {
|
|
|
+ String sourceId = session.getSourceId();
|
|
|
+ if (sourceId.startsWith("assessment_")) {
|
|
|
+ // 测评入口
|
|
|
+ try {
|
|
|
+ Long evalId = Long.parseLong(sourceId.substring("assessment_".length()));
|
|
|
+ MainExamEvaluation evaluation = examEvaluationMapper.selectById(evalId);
|
|
|
+ if (evaluation != null) {
|
|
|
+ if (evaluation.getPositionId() != null) {
|
|
|
+ MainPosition position = mainPositionMapper.selectById(evaluation.getPositionId());
|
|
|
+ if (position != null && StringUtils.isNotBlank(position.getTenantId())) {
|
|
|
+ tenantId = position.getTenantId();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 前端没传价或传了0时,用测评自身的price
|
|
|
+ if ((resolvedPrice == null || resolvedPrice.compareTo(BigDecimal.ZERO) <= 0)
|
|
|
+ && evaluation.getPrice() != null && evaluation.getPrice().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ resolvedPrice = evaluation.getPrice();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) { log.warn("从测评获取信息失败: {}", e.getMessage()); }
|
|
|
+ } else if (sourceId.startsWith("job_")) {
|
|
|
+ // 岗位入口 → 从岗位关联的测评获取价格
|
|
|
+ try {
|
|
|
+ Long posId = Long.parseLong(sourceId.substring("job_".length()));
|
|
|
+ MainPosition position = mainPositionMapper.selectById(posId);
|
|
|
+ if (position != null) {
|
|
|
+ if (StringUtils.isNotBlank(position.getTenantId())) {
|
|
|
+ tenantId = position.getTenantId();
|
|
|
+ }
|
|
|
+ // 查找该岗位下第一个有效测评的价格
|
|
|
+ if ((resolvedPrice == null || resolvedPrice.compareTo(BigDecimal.ZERO) <= 0)) {
|
|
|
+ List<MainExamEvaluation> evals = examEvaluationMapper.selectList(
|
|
|
+ Wrappers.<MainExamEvaluation>lambdaQuery()
|
|
|
+ .eq(MainExamEvaluation::getPositionId, posId)
|
|
|
+ .eq(MainExamEvaluation::getStatus, "1")
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ if (!evals.isEmpty()) {
|
|
|
+ MainExamEvaluation firstEval = evals.get(0);
|
|
|
+ if (firstEval.getPrice() != null && firstEval.getPrice().compareTo(BigDecimal.ZERO) > 0) {
|
|
|
+ resolvedPrice = firstEval.getPrice();
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(orderName)) {
|
|
|
+ orderName = firstEval.getEvaluationName() + "-测评服务费";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) { log.warn("从岗位获取信息失败: {}", e.getMessage()); }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建消息
|
|
|
+ CsMessage message = new CsMessage();
|
|
|
+ message.setSessionId(sessionId);
|
|
|
+ message.setMsgNo("ORDER_" + System.currentTimeMillis());
|
|
|
+ message.setSenderType(2);
|
|
|
+ message.setSenderId(session != null ? session.getWaiterId() : null);
|
|
|
+ message.setMsgType("order_card");
|
|
|
+ message.setStatus(1);
|
|
|
+ message.setIsRead(0);
|
|
|
+ message.setSendTime(LocalDateTime.now());
|
|
|
+ messageMapper.insert(message);
|
|
|
+
|
|
|
+ // 创建结算单(价格使用解析后的resolvedPrice,兜底0.01)
|
|
|
+ BigDecimal finalPrice = (resolvedPrice != null && resolvedPrice.compareTo(BigDecimal.ZERO) > 0) ? resolvedPrice : new BigDecimal("0.01");
|
|
|
+ CsOrderCard orderCard = new CsOrderCard();
|
|
|
+ orderCard.setMsgId(message.getId());
|
|
|
+ orderCard.setSessionId(sessionId);
|
|
|
+ orderCard.setOrderName(orderName);
|
|
|
+ orderCard.setOrderPrice(finalPrice);
|
|
|
+ orderCard.setOrderType(orderType);
|
|
|
+ orderCard.setTenantId(tenantId);
|
|
|
+ orderCard.setStatus("pending");
|
|
|
+ orderCard.setExpireTime(LocalDateTime.now().plusMinutes(30)); // 30分钟过期
|
|
|
+ orderCard.setCreateTime(LocalDateTime.now());
|
|
|
+ baseMapper.insert(orderCard);
|
|
|
+
|
|
|
+ // 回写payload到消息(同时写入price和amount,兼容前后端)
|
|
|
+ Map<String, Object> payload = new HashMap<>();
|
|
|
+ payload.put("orderCardId", orderCard.getId());
|
|
|
+ payload.put("name", orderCard.getOrderName());
|
|
|
+ payload.put("amount", orderCard.getOrderPrice().toString());
|
|
|
+ payload.put("price", orderCard.getOrderPrice().toString());
|
|
|
+ payload.put("status", "pending");
|
|
|
+ payload.put("expireTime", orderCard.getExpireTime().toString());
|
|
|
+ payload.put("countdownSeconds", 1800);
|
|
|
+ message.setPayload(JSONUtil.toJsonStr(payload));
|
|
|
+ messageMapper.updateById(message);
|
|
|
+
|
|
|
+ sessionService.updateLastMessage(sessionId, "[结算单]" + orderCard.getOrderName());
|
|
|
+
|
|
|
+ CsOrderCardVo vo = converter.convert(orderCard, CsOrderCardVo.class);
|
|
|
+ if (vo != null) {
|
|
|
+ vo.setCountdownSeconds(1800L);
|
|
|
+ }
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}
|