8.1 使用设计模式(责任链、策略模式、模板方法)优化退单流程
This commit is contained in:
parent
111f9e4181
commit
322f8d0f1e
@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
<insert id="insert" parameterType="edu.whut.infrastructure.dao.po.NotifyTask">
|
<insert id="insert" parameterType="edu.whut.infrastructure.dao.po.NotifyTask">
|
||||||
insert into notify_task(
|
insert into notify_task(
|
||||||
activity_id, team_id, notify_type, notify_mq, notify_url, notify_count,
|
activity_id, team_id, notify_category, notify_type, notify_mq, notify_url, notify_count,
|
||||||
notify_status, parameter_json,uuid, create_time, update_time)
|
notify_status, parameter_json,uuid, create_time, update_time)
|
||||||
values(#{activityId}, #{teamId}, #{notifyType}, #{notifyMQ}, #{notifyUrl},
|
values(#{activityId}, #{teamId}, #{notifyCategory}, #{notifyType}, #{notifyMQ}, #{notifyUrl},
|
||||||
#{notifyCount}, #{notifyStatus}, #{parameterJson},#{uuid},now(),now())
|
#{notifyCount}, #{notifyStatus}, #{parameterJson},#{uuid},now(),now())
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
@ -42,19 +42,19 @@
|
|||||||
<update id="updateNotifyTaskStatusSuccess" parameterType="java.lang.String">
|
<update id="updateNotifyTaskStatusSuccess" parameterType="java.lang.String">
|
||||||
update notify_task
|
update notify_task
|
||||||
set notify_count = notify_count + 1, notify_status = 1, update_time = now()
|
set notify_count = notify_count + 1, notify_status = 1, update_time = now()
|
||||||
where team_id = #{teamId}
|
where team_id = #{teamId} and uuid = #{uuid}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updateNotifyTaskStatusError" parameterType="java.lang.String">
|
<update id="updateNotifyTaskStatusError" parameterType="java.lang.String">
|
||||||
update notify_task
|
update notify_task
|
||||||
set notify_count = notify_count + 1, notify_status = 3, update_time = now()
|
set notify_count = notify_count + 1, notify_status = 3, update_time = now()
|
||||||
where team_id = #{teamId}
|
where team_id = #{teamId} and uuid = #{uuid}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updateNotifyTaskStatusRetry" parameterType="java.lang.String">
|
<update id="updateNotifyTaskStatusRetry" parameterType="java.lang.String">
|
||||||
update notify_task
|
update notify_task
|
||||||
set notify_count = notify_count + 1, notify_status = 2, update_time = now()
|
set notify_count = notify_count + 1, notify_status = 2, update_time = now()
|
||||||
where team_id = #{teamId}
|
where team_id = #{teamId} and uuid = #{uuid}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
@ -19,6 +19,7 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 锁单、恢复、锁单
|
* 锁单、恢复、锁单
|
||||||
|
* 测试退单流程:先下3单,再退一单,再下一单
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@ -34,8 +35,8 @@ public class ITradeReverseStockServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void test_refundOrder() throws Exception {
|
public void test_refundOrder() throws Exception {
|
||||||
TradeRefundCommandEntity tradeRefundCommandEntity = TradeRefundCommandEntity.builder()
|
TradeRefundCommandEntity tradeRefundCommandEntity = TradeRefundCommandEntity.builder()
|
||||||
.userId("smile11")
|
.userId("smile21")
|
||||||
.outTradeNo("690268736199")
|
.outTradeNo("910878918962")
|
||||||
.source("s01")
|
.source("s01")
|
||||||
.channel("c01")
|
.channel("c01")
|
||||||
.build();
|
.build();
|
||||||
@ -54,7 +55,7 @@ public class ITradeReverseStockServiceTest {
|
|||||||
String teamId = null;
|
String teamId = null;
|
||||||
for (int i = 1; i < 4; i++) {
|
for (int i = 1; i < 4; i++) {
|
||||||
LockMarketPayOrderRequestDTO lockMarketPayOrderRequestDTO = new LockMarketPayOrderRequestDTO();
|
LockMarketPayOrderRequestDTO lockMarketPayOrderRequestDTO = new LockMarketPayOrderRequestDTO();
|
||||||
lockMarketPayOrderRequestDTO.setUserId("smile1" + i);
|
lockMarketPayOrderRequestDTO.setUserId("smile2" + i);
|
||||||
lockMarketPayOrderRequestDTO.setTeamId(teamId);
|
lockMarketPayOrderRequestDTO.setTeamId(teamId);
|
||||||
lockMarketPayOrderRequestDTO.setActivityId(100123L);
|
lockMarketPayOrderRequestDTO.setActivityId(100123L);
|
||||||
lockMarketPayOrderRequestDTO.setGoodsId("9890001");
|
lockMarketPayOrderRequestDTO.setGoodsId("9890001");
|
||||||
@ -74,8 +75,8 @@ public class ITradeReverseStockServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void test_lockMarketPayOrder_reverse() throws InterruptedException {
|
public void test_lockMarketPayOrder_reverse() throws InterruptedException {
|
||||||
LockMarketPayOrderRequestDTO lockMarketPayOrderRequestDTO = new LockMarketPayOrderRequestDTO();
|
LockMarketPayOrderRequestDTO lockMarketPayOrderRequestDTO = new LockMarketPayOrderRequestDTO();
|
||||||
lockMarketPayOrderRequestDTO.setUserId("smile14");
|
lockMarketPayOrderRequestDTO.setUserId("smile24");
|
||||||
lockMarketPayOrderRequestDTO.setTeamId("56790750");
|
lockMarketPayOrderRequestDTO.setTeamId("68803511");
|
||||||
lockMarketPayOrderRequestDTO.setActivityId(100123L);
|
lockMarketPayOrderRequestDTO.setActivityId(100123L);
|
||||||
lockMarketPayOrderRequestDTO.setGoodsId("9890001");
|
lockMarketPayOrderRequestDTO.setGoodsId("9890001");
|
||||||
lockMarketPayOrderRequestDTO.setSource("s01");
|
lockMarketPayOrderRequestDTO.setSource("s01");
|
||||||
|
@ -36,11 +36,11 @@ public interface ITradeRepository {
|
|||||||
|
|
||||||
List<NotifyTaskEntity> queryUnExecutedNotifyTaskList(String teamId);
|
List<NotifyTaskEntity> queryUnExecutedNotifyTaskList(String teamId);
|
||||||
|
|
||||||
int updateNotifyTaskStatusSuccess(String teamId);
|
int updateNotifyTaskStatusSuccess(NotifyTaskEntity notifyTaskEntity);
|
||||||
|
|
||||||
int updateNotifyTaskStatusError(String teamId);
|
int updateNotifyTaskStatusError(NotifyTaskEntity notifyTaskEntity);
|
||||||
|
|
||||||
int updateNotifyTaskStatusRetry(String teamId);
|
int updateNotifyTaskStatusRetry(NotifyTaskEntity notifyTaskEntity);
|
||||||
|
|
||||||
boolean occupyTeamStock(String teamStockKey, String recoveryTeamStockKey, Integer target, Integer validTime);
|
boolean occupyTeamStock(String teamStockKey, String recoveryTeamStockKey, Integer target, Integer validTime);
|
||||||
|
|
||||||
|
@ -7,11 +7,14 @@ import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
|||||||
import edu.whut.domain.trade.model.valobj.TradeOrderStatusEnumVO;
|
import edu.whut.domain.trade.model.valobj.TradeOrderStatusEnumVO;
|
||||||
import edu.whut.domain.trade.service.ITradeRefundOrderService;
|
import edu.whut.domain.trade.service.ITradeRefundOrderService;
|
||||||
import edu.whut.domain.trade.service.refund.business.IRefundOrderStrategy;
|
import edu.whut.domain.trade.service.refund.business.IRefundOrderStrategy;
|
||||||
|
import edu.whut.domain.trade.service.refund.factory.TradeRefundRuleFilterFactory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.chain.BusinessLinkedList;
|
||||||
import edu.whut.types.enums.GroupBuyOrderStatusEnumVO;
|
import edu.whut.types.enums.GroupBuyOrderStatusEnumVO;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,53 +25,24 @@ import java.util.Map;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TradeRefundOrderService implements ITradeRefundOrderService {
|
public class TradeRefundOrderService implements ITradeRefundOrderService {
|
||||||
|
|
||||||
private final ITradeRepository repository;
|
|
||||||
//注入策略Map
|
//注入策略Map
|
||||||
private final Map<String, IRefundOrderStrategy> refundOrderStrategyMap;
|
private final Map<String, IRefundOrderStrategy> refundOrderStrategyMap;
|
||||||
|
|
||||||
|
private final BusinessLinkedList<TradeRefundCommandEntity, TradeRefundRuleFilterFactory.DynamicContext, TradeRefundBehaviorEntity> tradeRefundRuleFilter;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击退单主动触发=》更新数据库操(锁单量、完成量、退款、拼团状态、订单状态...)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TradeRefundBehaviorEntity refundOrder(TradeRefundCommandEntity tradeRefundCommandEntity) throws Exception {
|
public TradeRefundBehaviorEntity refundOrder(TradeRefundCommandEntity tradeRefundCommandEntity) throws Exception {
|
||||||
log.info("逆向流程,退单操作 userId:{} outTradeNo:{}", tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
log.info("逆向流程,退单操作 userId:{} outTradeNo:{}", tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
||||||
|
return tradeRefundRuleFilter.apply(tradeRefundCommandEntity, new TradeRefundRuleFilterFactory.DynamicContext());
|
||||||
// 1. 查询外部交易单,组队id、orderId、拼团状态
|
|
||||||
MarketPayOrderEntity marketPayOrderEntity = repository.queryMarketPayOrderEntityByOutTradeNo(tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
|
||||||
TradeOrderStatusEnumVO tradeOrderStatusEnumVO = marketPayOrderEntity.getTradeOrderStatusEnumVO();
|
|
||||||
String teamId = marketPayOrderEntity.getTeamId();
|
|
||||||
String orderId = marketPayOrderEntity.getOrderId();
|
|
||||||
|
|
||||||
// 返回幂等,已完成退单
|
|
||||||
if (TradeOrderStatusEnumVO.CLOSE.equals(tradeOrderStatusEnumVO)) {
|
|
||||||
log.info("逆向流程,退单操作(幂等-重复退单) userId:{} outTradeNo:{}", tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
|
||||||
return TradeRefundBehaviorEntity.builder()
|
|
||||||
.userId(tradeRefundCommandEntity.getUserId())
|
|
||||||
.orderId(orderId)
|
|
||||||
.teamId(teamId)
|
|
||||||
.tradeRefundBehaviorEnum(TradeRefundBehaviorEntity.TradeRefundBehaviorEnum.REPEAT)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 查询拼团状态
|
|
||||||
GroupBuyTeamEntity groupBuyTeamEntity = repository.queryGroupBuyTeamByTeamId(teamId);
|
|
||||||
GroupBuyOrderStatusEnumVO groupBuyOrderStatusEnumVO = groupBuyTeamEntity.getStatus();
|
|
||||||
|
|
||||||
// 3. 根据拼团状态和交易状态判断退单类型 -> 判断使用哪种策略模式
|
|
||||||
RefundTypeEnumVO refundType = RefundTypeEnumVO.getRefundStrategy(groupBuyOrderStatusEnumVO, tradeOrderStatusEnumVO);
|
|
||||||
IRefundOrderStrategy refundOrderStrategy = refundOrderStrategyMap.get(refundType.getStrategy());
|
|
||||||
refundOrderStrategy.refundOrder(TradeRefundOrderEntity.builder()
|
|
||||||
.userId(tradeRefundCommandEntity.getUserId())
|
|
||||||
.orderId(orderId)
|
|
||||||
.teamId(teamId)
|
|
||||||
.activityId(groupBuyTeamEntity.getActivityId())
|
|
||||||
.build());
|
|
||||||
|
|
||||||
return TradeRefundBehaviorEntity.builder()
|
|
||||||
.userId(tradeRefundCommandEntity.getUserId())
|
|
||||||
.orderId(orderId)
|
|
||||||
.teamId(teamId)
|
|
||||||
.tradeRefundBehaviorEnum(TradeRefundBehaviorEntity.TradeRefundBehaviorEnum.SUCCESS)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退单成功后,消息监听触发-》恢复锁单量
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void restoreTeamLockStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
public void restoreTeamLockStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
||||||
log.info("逆向流程,恢复锁单量 userId:{} activityId:{} teamId:{}", teamRefundSuccess.getUserId(), teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
log.info("逆向流程,恢复锁单量 userId:{} activityId:{} teamId:{}", teamRefundSuccess.getUserId(), teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package edu.whut.domain.trade.service.refund.business;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
||||||
|
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
||||||
|
import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
||||||
|
import edu.whut.domain.trade.service.ITradeTaskService;
|
||||||
|
import edu.whut.domain.trade.service.lock.factory.TradeLockRuleFilterFactory;
|
||||||
|
import edu.whut.types.exception.AppException;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退单策略抽象基类
|
||||||
|
* 提供共用的依赖注入和MQ消息发送功能
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public abstract class AbstractRefundOrderStrategy implements IRefundOrderStrategy {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected ITradeRepository repository;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected ITradeTaskService tradeTaskService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected ThreadPoolExecutor threadPoolExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步发送MQ消息
|
||||||
|
* @param notifyTaskEntity 通知任务实体
|
||||||
|
* @param refundType 退单类型描述
|
||||||
|
*/
|
||||||
|
protected void sendRefundNotifyMessage(NotifyTaskEntity notifyTaskEntity, String refundType) {
|
||||||
|
if (null != notifyTaskEntity) {
|
||||||
|
threadPoolExecutor.execute(() -> {
|
||||||
|
Map<String, Integer> notifyResultMap = null;
|
||||||
|
try {
|
||||||
|
notifyResultMap = tradeTaskService.execNotifyJob(notifyTaskEntity);
|
||||||
|
log.info("回调通知交易退单({}) result:{}", refundType, JSON.toJSONString(notifyResultMap));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("回调通知交易退单失败({}) result:{}", refundType, JSON.toJSONString(notifyResultMap), e);
|
||||||
|
throw new AppException(e.getMessage());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用库存恢复逻辑
|
||||||
|
* @param teamRefundSuccess 团队退单成功信息
|
||||||
|
* @param refundType 退单类型描述
|
||||||
|
* @throws Exception 异常
|
||||||
|
*/
|
||||||
|
protected void doReverseStock(TeamRefundSuccess teamRefundSuccess, String refundType) throws Exception {
|
||||||
|
log.info("退单;恢复锁单量 - {} {} {} {}", refundType, teamRefundSuccess.getUserId(), teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
||||||
|
// 1. 恢复库存key
|
||||||
|
String recoveryTeamStockKey = TradeLockRuleFilterFactory.generateRecoveryTeamStockKey(teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
||||||
|
// 2. 退单恢复库存
|
||||||
|
repository.refund2AddRecovery(recoveryTeamStockKey, teamRefundSuccess.getOrderId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,21 +1,12 @@
|
|||||||
package edu.whut.domain.trade.service.refund.business.impl;
|
package edu.whut.domain.trade.service.refund.business.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import edu.whut.domain.trade.adapter.port.ITradePort;
|
|
||||||
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
|
||||||
import edu.whut.domain.trade.model.aggregate.GroupBuyRefundAggregate;
|
import edu.whut.domain.trade.model.aggregate.GroupBuyRefundAggregate;
|
||||||
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
||||||
import edu.whut.domain.trade.model.entity.TradeRefundOrderEntity;
|
import edu.whut.domain.trade.model.entity.TradeRefundOrderEntity;
|
||||||
import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
||||||
import edu.whut.domain.trade.service.ITradeTaskService;
|
import edu.whut.domain.trade.service.refund.business.AbstractRefundOrderStrategy;
|
||||||
import edu.whut.domain.trade.service.lock.factory.TradeLockRuleFilterFactory;
|
|
||||||
import edu.whut.domain.trade.service.refund.business.IRefundOrderStrategy;
|
|
||||||
import edu.whut.types.exception.AppException;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发起退单(未成团&已支付),锁单量-1、完成量-1、组队订单状态更新、发送退单消息(MQ)
|
* 发起退单(未成团&已支付),锁单量-1、完成量-1、组队订单状态更新、发送退单消息(MQ)
|
||||||
@ -23,13 +14,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service("paid2RefundStrategy")
|
@Service("paid2RefundStrategy")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class Paid2RefundStrategy implements IRefundOrderStrategy {
|
public class Paid2RefundStrategy extends AbstractRefundOrderStrategy {
|
||||||
|
|
||||||
private final ITradeRepository repository;
|
|
||||||
|
|
||||||
private final ITradeTaskService tradeTaskService;
|
|
||||||
|
|
||||||
private final ThreadPoolExecutor threadPoolExecutor;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refundOrder(TradeRefundOrderEntity tradeRefundOrderEntity) throws Exception {
|
public void refundOrder(TradeRefundOrderEntity tradeRefundOrderEntity) throws Exception {
|
||||||
@ -38,27 +23,12 @@ public class Paid2RefundStrategy implements IRefundOrderStrategy {
|
|||||||
// 1. 退单,已支付&未成团
|
// 1. 退单,已支付&未成团
|
||||||
NotifyTaskEntity notifyTaskEntity = repository.paid2Refund(GroupBuyRefundAggregate.buildPaid2RefundAggregate(tradeRefundOrderEntity, -1, -1));
|
NotifyTaskEntity notifyTaskEntity = repository.paid2Refund(GroupBuyRefundAggregate.buildPaid2RefundAggregate(tradeRefundOrderEntity, -1, -1));
|
||||||
|
|
||||||
// 2. 发送MQ消息
|
// 2. 发送MQ消息 - 发送MQ,恢复锁单库存量使用
|
||||||
if (null != notifyTaskEntity) {
|
sendRefundNotifyMessage(notifyTaskEntity, "已支付,未成团");
|
||||||
threadPoolExecutor.execute(() -> {
|
|
||||||
Map<String, Integer> notifyResultMap = null;
|
|
||||||
try {
|
|
||||||
notifyResultMap = tradeTaskService.execNotifyJob(notifyTaskEntity);
|
|
||||||
log.info("回调通知交易退单(已支付,未成团) result:{}", JSON.toJSONString(notifyResultMap));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("回调通知交易退单失败(已支付,未成团) result:{}", JSON.toJSONString(notifyResultMap), e);
|
|
||||||
throw new AppException(e.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void reverseStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
public void reverseStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
||||||
log.info("退单;恢复锁单量 - 已支付,未成团,但有锁单记录,要恢复锁单库存 {} {} {}", teamRefundSuccess.getUserId(), teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
doReverseStock(teamRefundSuccess, "已支付,未成团,但有锁单记录,要恢复锁单库存");
|
||||||
// 1. 恢复库存key
|
|
||||||
String recoveryTeamStockKey = TradeLockRuleFilterFactory.generateRecoveryTeamStockKey(teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
|
||||||
// 2. 退单恢复「已支付,未成团,有锁单记录,要恢复锁单库存」
|
|
||||||
repository.refund2AddRecovery(recoveryTeamStockKey, teamRefundSuccess.getOrderId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
package edu.whut.domain.trade.service.refund.business.impl;
|
package edu.whut.domain.trade.service.refund.business.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
|
||||||
import edu.whut.domain.trade.model.aggregate.GroupBuyRefundAggregate;
|
import edu.whut.domain.trade.model.aggregate.GroupBuyRefundAggregate;
|
||||||
import edu.whut.domain.trade.model.entity.GroupBuyTeamEntity;
|
import edu.whut.domain.trade.model.entity.GroupBuyTeamEntity;
|
||||||
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
||||||
import edu.whut.domain.trade.model.entity.TradeRefundOrderEntity;
|
import edu.whut.domain.trade.model.entity.TradeRefundOrderEntity;
|
||||||
import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
||||||
import edu.whut.domain.trade.service.ITradeTaskService;
|
import edu.whut.domain.trade.service.refund.business.AbstractRefundOrderStrategy;
|
||||||
import edu.whut.domain.trade.service.refund.business.IRefundOrderStrategy;
|
|
||||||
import edu.whut.types.enums.GroupBuyOrderStatusEnumVO;
|
import edu.whut.types.enums.GroupBuyOrderStatusEnumVO;
|
||||||
import edu.whut.types.exception.AppException;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发起退单(已成团&已支付),锁单量-1、完成量-1、组队订单状态更新、发送退单消息(MQ)
|
* 发起退单(已成团&已支付),锁单量-1、完成量-1、组队订单状态更新、发送退单消息(MQ)
|
||||||
@ -23,41 +17,23 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service("paidTeam2RefundStrategy")
|
@Service("paidTeam2RefundStrategy")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PaidTeam2RefundStrategy implements IRefundOrderStrategy {
|
public class PaidTeam2RefundStrategy extends AbstractRefundOrderStrategy {
|
||||||
|
|
||||||
private final ITradeRepository repository;
|
|
||||||
|
|
||||||
private final ITradeTaskService tradeTaskService;
|
|
||||||
|
|
||||||
private final ThreadPoolExecutor threadPoolExecutor;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refundOrder(TradeRefundOrderEntity tradeRefundOrderEntity) {
|
public void refundOrder(TradeRefundOrderEntity tradeRefundOrderEntity) {
|
||||||
log.info("退单;已支付,已成团 userId:{} teamId:{} orderId:{}", tradeRefundOrderEntity.getUserId(), tradeRefundOrderEntity.getTeamId(), tradeRefundOrderEntity.getOrderId());
|
log.info("退单;已支付,已成团 userId:{} teamId:{} orderId:{}", tradeRefundOrderEntity.getUserId(), tradeRefundOrderEntity.getTeamId(), tradeRefundOrderEntity.getOrderId());
|
||||||
|
|
||||||
GroupBuyTeamEntity groupBuyTeamEntity = repository.queryGroupBuyTeamByTeamId(tradeRefundOrderEntity.getTeamId());
|
GroupBuyTeamEntity groupBuyTeamEntity = repository.queryGroupBuyTeamByTeamId(tradeRefundOrderEntity.getTeamId());
|
||||||
// 当前拼团完成量
|
|
||||||
Integer completeCount = groupBuyTeamEntity.getCompleteCount();
|
Integer completeCount = groupBuyTeamEntity.getCompleteCount();
|
||||||
|
|
||||||
// 该拼团中最后一个用户也要退单,则更新拼团订单为失败
|
// 最后一笔也退单,则更新拼团订单为失败
|
||||||
GroupBuyOrderStatusEnumVO groupBuyOrderEnumVO = 1 == completeCount ? GroupBuyOrderStatusEnumVO.FAIL : GroupBuyOrderStatusEnumVO.COMPLETE_FAIL;
|
GroupBuyOrderStatusEnumVO groupBuyOrderEnumVO = 1 == completeCount ? GroupBuyOrderStatusEnumVO.FAIL : GroupBuyOrderStatusEnumVO.COMPLETE_FAIL;
|
||||||
|
|
||||||
// 1. 退单,已支付&已成团
|
// 1. 退单,已支付&已成团
|
||||||
NotifyTaskEntity notifyTaskEntity = repository.paidTeam2Refund(GroupBuyRefundAggregate.buildPaidTeam2RefundAggregate(tradeRefundOrderEntity, -1, -1, groupBuyOrderEnumVO));
|
NotifyTaskEntity notifyTaskEntity = repository.paidTeam2Refund(GroupBuyRefundAggregate.buildPaidTeam2RefundAggregate(tradeRefundOrderEntity, -1, -1, groupBuyOrderEnumVO));
|
||||||
|
|
||||||
// 2. 发送MQ消息
|
// 2. 发送MQ消息 - 发送MQ,恢复锁单库存量使用
|
||||||
if (null != notifyTaskEntity) {
|
sendRefundNotifyMessage(notifyTaskEntity, "已支付,已成团");
|
||||||
threadPoolExecutor.execute(() -> {
|
|
||||||
Map<String, Integer> notifyResultMap = null;
|
|
||||||
try {
|
|
||||||
notifyResultMap = tradeTaskService.execNotifyJob(notifyTaskEntity);
|
|
||||||
log.info("回调通知交易退单(已支付,已成团) result:{}", JSON.toJSONString(notifyResultMap));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("回调通知交易退单失败(已支付,已成团) result:{}", JSON.toJSONString(notifyResultMap), e);
|
|
||||||
throw new AppException(e.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void reverseStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
public void reverseStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
||||||
|
@ -1,22 +1,14 @@
|
|||||||
package edu.whut.domain.trade.service.refund.business.impl;
|
package edu.whut.domain.trade.service.refund.business.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
|
||||||
import edu.whut.domain.trade.model.aggregate.GroupBuyRefundAggregate;
|
import edu.whut.domain.trade.model.aggregate.GroupBuyRefundAggregate;
|
||||||
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
import edu.whut.domain.trade.model.entity.NotifyTaskEntity;
|
||||||
import edu.whut.domain.trade.model.entity.TradeRefundOrderEntity;
|
import edu.whut.domain.trade.model.entity.TradeRefundOrderEntity;
|
||||||
import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
import edu.whut.domain.trade.model.valobj.TeamRefundSuccess;
|
||||||
import edu.whut.domain.trade.service.ITradeTaskService;
|
import edu.whut.domain.trade.service.refund.business.AbstractRefundOrderStrategy;
|
||||||
import edu.whut.domain.trade.service.lock.factory.TradeLockRuleFilterFactory;
|
|
||||||
import edu.whut.domain.trade.service.refund.business.IRefundOrderStrategy;
|
|
||||||
import edu.whut.types.exception.AppException;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 未支付,未成团;发起退单(未支付),锁单量-1、组队订单状态更新
|
* 未支付,未成团;发起退单(未支付),锁单量-1、组队订单状态更新
|
||||||
@ -24,13 +16,7 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
@Service("unpaid2RefundStrategy")
|
@Service("unpaid2RefundStrategy")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class Unpaid2RefundStrategy implements IRefundOrderStrategy {
|
public class Unpaid2RefundStrategy extends AbstractRefundOrderStrategy {
|
||||||
|
|
||||||
private final ITradeRepository repository;
|
|
||||||
|
|
||||||
private final ITradeTaskService tradeTaskService;
|
|
||||||
|
|
||||||
private final ThreadPoolExecutor threadPoolExecutor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户未支付的退单流程,仅需更新订单状态为已退单,释放lockcount锁单量
|
* 用户未支付的退单流程,仅需更新订单状态为已退单,释放lockcount锁单量
|
||||||
@ -42,27 +28,12 @@ public class Unpaid2RefundStrategy implements IRefundOrderStrategy {
|
|||||||
NotifyTaskEntity notifyTaskEntity = repository.unpaid2Refund(GroupBuyRefundAggregate.buildUnpaid2RefundAggregate(tradeRefundOrderEntity, -1));
|
NotifyTaskEntity notifyTaskEntity = repository.unpaid2Refund(GroupBuyRefundAggregate.buildUnpaid2RefundAggregate(tradeRefundOrderEntity, -1));
|
||||||
|
|
||||||
// 2. 发送MQ消息 - 发送MQ,恢复锁单库存量使用
|
// 2. 发送MQ消息 - 发送MQ,恢复锁单库存量使用
|
||||||
if (null != notifyTaskEntity) {
|
sendRefundNotifyMessage(notifyTaskEntity, "未支付,未成团");
|
||||||
threadPoolExecutor.execute(() -> {
|
|
||||||
Map<String, Integer> notifyResultMap = null;
|
|
||||||
try {
|
|
||||||
notifyResultMap = tradeTaskService.execNotifyJob(notifyTaskEntity);
|
|
||||||
log.info("回调通知交易退单(未支付,未成团) result:{}", JSON.toJSONString(notifyResultMap));
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("回调通知交易退单失败(未支付,未成团) result:{}", JSON.toJSONString(notifyResultMap), e);
|
|
||||||
throw new AppException(e.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reverseStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
public void reverseStock(TeamRefundSuccess teamRefundSuccess) throws Exception {
|
||||||
log.info("退单;恢复锁单量 - 未支付,未成团,但有锁单记录,要恢复锁单库存 {} {} {}", teamRefundSuccess.getUserId(), teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
doReverseStock(teamRefundSuccess, "未支付,未成团,但有锁单记录,要恢复锁单库存");
|
||||||
// 1. 恢复库存key
|
|
||||||
String recoveryTeamStockKey = TradeLockRuleFilterFactory.generateRecoveryTeamStockKey(teamRefundSuccess.getActivityId(), teamRefundSuccess.getTeamId());
|
|
||||||
// 2. 退单恢复「未支付,未成团,但有锁单记录,要恢复锁单库存」
|
|
||||||
repository.refund2AddRecovery(recoveryTeamStockKey, teamRefundSuccess.getOrderId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package edu.whut.domain.trade.service.refund.factory;
|
||||||
|
import edu.whut.domain.trade.model.entity.GroupBuyTeamEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.MarketPayOrderEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRefundBehaviorEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRefundCommandEntity;
|
||||||
|
import edu.whut.domain.trade.service.refund.filter.DataNodeFilter;
|
||||||
|
import edu.whut.domain.trade.service.refund.filter.RefundOrderNodeFilter;
|
||||||
|
import edu.whut.domain.trade.service.refund.filter.UniqueRefundNodeFilter;
|
||||||
|
import edu.whut.types.design.framework.link.model2.LinkArmory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.chain.BusinessLinkedList;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 交易退单工程
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class TradeRefundRuleFilterFactory {
|
||||||
|
|
||||||
|
@Bean("tradeRefundRuleFilter")
|
||||||
|
public BusinessLinkedList<TradeRefundCommandEntity, DynamicContext, TradeRefundBehaviorEntity> tradeRefundRuleFilter(
|
||||||
|
DataNodeFilter dataNodeFilter,
|
||||||
|
UniqueRefundNodeFilter uniqueRefundNodeFilter,
|
||||||
|
RefundOrderNodeFilter refundOrderNodeFilter) {
|
||||||
|
|
||||||
|
// 组装链
|
||||||
|
LinkArmory<TradeRefundCommandEntity, DynamicContext, TradeRefundBehaviorEntity> linkArmory =
|
||||||
|
new LinkArmory<>("退单规则过滤链",
|
||||||
|
dataNodeFilter,
|
||||||
|
uniqueRefundNodeFilter,
|
||||||
|
refundOrderNodeFilter);
|
||||||
|
|
||||||
|
// 链对象
|
||||||
|
return linkArmory.getLogicLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class DynamicContext {
|
||||||
|
|
||||||
|
private MarketPayOrderEntity marketPayOrderEntity;
|
||||||
|
|
||||||
|
private GroupBuyTeamEntity groupBuyTeamEntity;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package edu.whut.domain.trade.service.refund.filter;
|
||||||
|
|
||||||
|
|
||||||
|
import edu.whut.domain.trade.adapter.repository.ITradeRepository;
|
||||||
|
import edu.whut.domain.trade.model.entity.GroupBuyTeamEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.MarketPayOrderEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRefundBehaviorEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRefundCommandEntity;
|
||||||
|
import edu.whut.domain.trade.service.refund.factory.TradeRefundRuleFilterFactory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据节点
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DataNodeFilter implements ILogicHandler<TradeRefundCommandEntity, TradeRefundRuleFilterFactory.DynamicContext, TradeRefundBehaviorEntity> {
|
||||||
|
|
||||||
|
private final ITradeRepository repository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TradeRefundBehaviorEntity apply(TradeRefundCommandEntity tradeRefundCommandEntity, TradeRefundRuleFilterFactory.DynamicContext dynamicContext) throws Exception {
|
||||||
|
log.info("逆向流程-退单操作,数据加载节点 userId:{} outTradeNo:{}", tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
||||||
|
|
||||||
|
// 1. 查询外部交易单,组队id、orderId、拼团状态
|
||||||
|
MarketPayOrderEntity marketPayOrderEntity = repository.queryMarketPayOrderEntityByOutTradeNo(tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
||||||
|
String teamId = marketPayOrderEntity.getTeamId();
|
||||||
|
|
||||||
|
// 2. 查询拼团状态
|
||||||
|
GroupBuyTeamEntity groupBuyTeamEntity = repository.queryGroupBuyTeamByTeamId(teamId);
|
||||||
|
|
||||||
|
// 3. 写入上下文;如果查询数据是比较多的,可以参考 MarketNode2CompletableFuture 通过多线程进行加载
|
||||||
|
dynamicContext.setMarketPayOrderEntity(marketPayOrderEntity);
|
||||||
|
dynamicContext.setGroupBuyTeamEntity(groupBuyTeamEntity);
|
||||||
|
|
||||||
|
return next(tradeRefundCommandEntity, dynamicContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package edu.whut.domain.trade.service.refund.filter;
|
||||||
|
|
||||||
|
import edu.whut.domain.trade.model.entity.*;
|
||||||
|
import edu.whut.domain.trade.model.valobj.RefundTypeEnumVO;
|
||||||
|
import edu.whut.domain.trade.model.valobj.TradeOrderStatusEnumVO;
|
||||||
|
import edu.whut.domain.trade.service.refund.business.IRefundOrderStrategy;
|
||||||
|
import edu.whut.domain.trade.service.refund.factory.TradeRefundRuleFilterFactory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
||||||
|
import edu.whut.types.enums.GroupBuyOrderStatusEnumVO;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退单节点
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RefundOrderNodeFilter implements ILogicHandler<TradeRefundCommandEntity, TradeRefundRuleFilterFactory.DynamicContext, TradeRefundBehaviorEntity> {
|
||||||
|
|
||||||
|
//依赖注入:策略选择map
|
||||||
|
private final Map<String, IRefundOrderStrategy> refundOrderStrategyMap;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TradeRefundBehaviorEntity apply(TradeRefundCommandEntity tradeRefundCommandEntity, TradeRefundRuleFilterFactory.DynamicContext dynamicContext) throws Exception {
|
||||||
|
log.info("逆向流程-退单操作,退单策略处理 userId:{} outTradeNo:{}", tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
||||||
|
|
||||||
|
// 上下文数据
|
||||||
|
MarketPayOrderEntity marketPayOrderEntity = dynamicContext.getMarketPayOrderEntity();
|
||||||
|
TradeOrderStatusEnumVO tradeOrderStatusEnumVO = marketPayOrderEntity.getTradeOrderStatusEnumVO();
|
||||||
|
|
||||||
|
GroupBuyTeamEntity groupBuyTeamEntity = dynamicContext.getGroupBuyTeamEntity();
|
||||||
|
GroupBuyOrderStatusEnumVO groupBuyOrderEnumVO = groupBuyTeamEntity.getStatus();
|
||||||
|
|
||||||
|
// 获取执行策略
|
||||||
|
RefundTypeEnumVO refundType = RefundTypeEnumVO.getRefundStrategy(groupBuyOrderEnumVO, tradeOrderStatusEnumVO);
|
||||||
|
IRefundOrderStrategy refundOrderStrategy = refundOrderStrategyMap.get(refundType.getStrategy());
|
||||||
|
|
||||||
|
// 执行退单操作
|
||||||
|
refundOrderStrategy.refundOrder(TradeRefundOrderEntity.builder()
|
||||||
|
.userId(tradeRefundCommandEntity.getUserId())
|
||||||
|
.orderId(marketPayOrderEntity.getOrderId())
|
||||||
|
.teamId(marketPayOrderEntity.getTeamId())
|
||||||
|
.activityId(groupBuyTeamEntity.getActivityId())
|
||||||
|
.build());
|
||||||
|
|
||||||
|
return TradeRefundBehaviorEntity.builder()
|
||||||
|
.userId(tradeRefundCommandEntity.getUserId())
|
||||||
|
.orderId(marketPayOrderEntity.getOrderId())
|
||||||
|
.teamId(marketPayOrderEntity.getTeamId())
|
||||||
|
.tradeRefundBehaviorEnum(TradeRefundBehaviorEntity.TradeRefundBehaviorEnum.SUCCESS)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package edu.whut.domain.trade.service.refund.filter;
|
||||||
|
|
||||||
|
import edu.whut.domain.trade.model.entity.MarketPayOrderEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRefundBehaviorEntity;
|
||||||
|
import edu.whut.domain.trade.model.entity.TradeRefundCommandEntity;
|
||||||
|
import edu.whut.domain.trade.model.valobj.TradeOrderStatusEnumVO;
|
||||||
|
import edu.whut.domain.trade.service.refund.factory.TradeRefundRuleFilterFactory;
|
||||||
|
import edu.whut.types.design.framework.link.model2.handler.ILogicHandler;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重复退单检查
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class UniqueRefundNodeFilter implements ILogicHandler<TradeRefundCommandEntity, TradeRefundRuleFilterFactory.DynamicContext, TradeRefundBehaviorEntity> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TradeRefundBehaviorEntity apply(TradeRefundCommandEntity tradeRefundCommandEntity, TradeRefundRuleFilterFactory.DynamicContext dynamicContext) throws Exception {
|
||||||
|
log.info("逆向流程-退单操作,重复退单检查 userId:{} outTradeNo:{}", tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
||||||
|
|
||||||
|
MarketPayOrderEntity marketPayOrderEntity = dynamicContext.getMarketPayOrderEntity();
|
||||||
|
TradeOrderStatusEnumVO tradeOrderStatusEnumVO = marketPayOrderEntity.getTradeOrderStatusEnumVO();
|
||||||
|
|
||||||
|
// 返回幂等,已完成退单
|
||||||
|
if (TradeOrderStatusEnumVO.CLOSE.equals(tradeOrderStatusEnumVO)) {
|
||||||
|
log.info("逆向流程,退单操作(幂等-重复退单) userId:{} outTradeNo:{}", tradeRefundCommandEntity.getUserId(), tradeRefundCommandEntity.getOutTradeNo());
|
||||||
|
return TradeRefundBehaviorEntity.builder()
|
||||||
|
.userId(tradeRefundCommandEntity.getUserId())
|
||||||
|
.orderId(marketPayOrderEntity.getOrderId())
|
||||||
|
.teamId(marketPayOrderEntity.getTeamId())
|
||||||
|
.tradeRefundBehaviorEnum(TradeRefundBehaviorEntity.TradeRefundBehaviorEnum.REPEAT)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(tradeRefundCommandEntity, dynamicContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -64,8 +64,7 @@ public class TradeTaskService implements ITradeTaskService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 公共逻辑抽取:遍历任务列表,调用外部服务,更新数据库并计数
|
* 公共逻辑抽取:遍历任务列表,调用外部服务,更新数据库并计数
|
||||||
* @param notifyTaskEntityList 待处理的通知任务列表
|
* 拼团成功消息 or 退单消息
|
||||||
* @return key——任务总量、successCount、errorCount、retryCount
|
|
||||||
*/
|
*/
|
||||||
private Map<String, Integer> execNotifyJob(List<NotifyTaskEntity> notifyTaskEntityList) throws Exception {
|
private Map<String, Integer> execNotifyJob(List<NotifyTaskEntity> notifyTaskEntityList) throws Exception {
|
||||||
//successCount:成功回调的任务数量
|
//successCount:成功回调的任务数量
|
||||||
@ -76,19 +75,19 @@ public class TradeTaskService implements ITradeTaskService {
|
|||||||
|
|
||||||
// 更新状态判断&变更数据库表回调任务状态
|
// 更新状态判断&变更数据库表回调任务状态
|
||||||
if (NotifyTaskHTTPEnumVO.SUCCESS.getCode().equals(response)) {
|
if (NotifyTaskHTTPEnumVO.SUCCESS.getCode().equals(response)) {
|
||||||
int updateCount = repository.updateNotifyTaskStatusSuccess(notifyTask.getTeamId());
|
int updateCount = repository.updateNotifyTaskStatusSuccess(notifyTask);
|
||||||
if (1 == updateCount) {
|
if (1 == updateCount) {
|
||||||
successCount += 1;
|
successCount += 1;
|
||||||
}
|
}
|
||||||
} else if (NotifyTaskHTTPEnumVO.ERROR.getCode().equals(response)) {
|
} else if (NotifyTaskHTTPEnumVO.ERROR.getCode().equals(response)) {
|
||||||
if (notifyTask.getNotifyCount() < 5) {
|
if (notifyTask.getNotifyCount() < 5) {
|
||||||
// 失败但可以重试 → 标记为 RETRY,等待下一次收集 “待处理的通知任务列表”
|
// 失败但可以重试 → 标记为 RETRY,等待下一次收集 “待处理的通知任务列表”
|
||||||
if (repository.updateNotifyTaskStatusRetry(notifyTask.getTeamId()) == 1) {
|
if (repository.updateNotifyTaskStatusRetry(notifyTask) == 1) {
|
||||||
retryCount++;
|
retryCount++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 已达最大重试次数 → 标记为 ERROR(不再重试)
|
// 已达最大重试次数 → 标记为 ERROR(不再重试)
|
||||||
if (repository.updateNotifyTaskStatusError(notifyTask.getTeamId()) == 1) {
|
if (repository.updateNotifyTaskStatusError(notifyTask) == 1) {
|
||||||
errorCount++;
|
errorCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,8 +309,8 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
NotifyTask task = new NotifyTask();
|
NotifyTask task = new NotifyTask();
|
||||||
task.setActivityId(team.getActivityId());
|
task.setActivityId(team.getActivityId());
|
||||||
task.setTeamId(team.getTeamId());
|
task.setTeamId(team.getTeamId());
|
||||||
task.setNotifyCategory(TaskNotifyCategoryEnumVO.TRADE_SETTLEMENT.getCode());
|
task.setNotifyCategory(TaskNotifyCategoryEnumVO.TRADE_SETTLEMENT.getCode()); //拼团成团消息
|
||||||
task.setNotifyType(notifyConfigVO.getNotifyType().getCode());
|
task.setNotifyType(notifyConfigVO.getNotifyType().getCode()); //HTTP or MQ
|
||||||
task.setNotifyMQ(NotifyTypeEnumVO.MQ.equals(notifyConfigVO.getNotifyType()) ? notifyConfigVO.getNotifyMQ() : null);
|
task.setNotifyMQ(NotifyTypeEnumVO.MQ.equals(notifyConfigVO.getNotifyType()) ? notifyConfigVO.getNotifyMQ() : null);
|
||||||
task.setNotifyUrl(NotifyTypeEnumVO.HTTP.equals(notifyConfigVO.getNotifyType()) ? notifyConfigVO.getNotifyUrl() : null);
|
task.setNotifyUrl(NotifyTypeEnumVO.HTTP.equals(notifyConfigVO.getNotifyType()) ? notifyConfigVO.getNotifyUrl() : null);
|
||||||
task.setNotifyCount(0);
|
task.setNotifyCount(0);
|
||||||
@ -386,6 +386,7 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
.notifyUrl(notifyTask.getNotifyUrl())
|
.notifyUrl(notifyTask.getNotifyUrl())
|
||||||
.notifyCount(notifyTask.getNotifyCount())
|
.notifyCount(notifyTask.getNotifyCount())
|
||||||
.parameterJson(notifyTask.getParameterJson())
|
.parameterJson(notifyTask.getParameterJson())
|
||||||
|
.uuid(notifyTask.getUuid())
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,24 +394,36 @@ public class TradeRepository implements ITradeRepository {
|
|||||||
* 更新指定 teamId 的通知任务状态为成功
|
* 更新指定 teamId 的通知任务状态为成功
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateNotifyTaskStatusSuccess(String teamId) {
|
public int updateNotifyTaskStatusSuccess(NotifyTaskEntity notifyTaskEntity) {
|
||||||
return notifyTaskDao.updateNotifyTaskStatusSuccess(teamId);
|
NotifyTask notifyTask = NotifyTask.builder()
|
||||||
|
.teamId(notifyTaskEntity.getTeamId())
|
||||||
|
.uuid(notifyTaskEntity.getUuid())
|
||||||
|
.build();
|
||||||
|
return notifyTaskDao.updateNotifyTaskStatusSuccess(notifyTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新指定 teamId 的通知任务状态为失败(不可重试)
|
* 更新指定 teamId 的通知任务状态为失败(不可重试)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateNotifyTaskStatusError(String teamId) {
|
public int updateNotifyTaskStatusError(NotifyTaskEntity notifyTaskEntity) {
|
||||||
return notifyTaskDao.updateNotifyTaskStatusError(teamId);
|
NotifyTask notifyTask = NotifyTask.builder()
|
||||||
|
.teamId(notifyTaskEntity.getTeamId())
|
||||||
|
.uuid(notifyTaskEntity.getUuid())
|
||||||
|
.build();
|
||||||
|
return notifyTaskDao.updateNotifyTaskStatusError(notifyTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新指定 teamId 的通知任务状态为重试
|
* 更新指定 teamId 的通知任务状态为重试
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateNotifyTaskStatusRetry(String teamId) {
|
public int updateNotifyTaskStatusRetry(NotifyTaskEntity notifyTaskEntity) {
|
||||||
return notifyTaskDao.updateNotifyTaskStatusRetry(teamId);
|
NotifyTask notifyTask = NotifyTask.builder()
|
||||||
|
.teamId(notifyTaskEntity.getTeamId())
|
||||||
|
.uuid(notifyTaskEntity.getUuid())
|
||||||
|
.build();
|
||||||
|
return notifyTaskDao.updateNotifyTaskStatusRetry(notifyTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,10 +16,10 @@ public interface INotifyTaskDao {
|
|||||||
|
|
||||||
NotifyTask queryUnExecutedNotifyTaskByTeamId(String teamId);
|
NotifyTask queryUnExecutedNotifyTaskByTeamId(String teamId);
|
||||||
|
|
||||||
int updateNotifyTaskStatusSuccess(String teamId);
|
int updateNotifyTaskStatusSuccess(NotifyTask notifyTask);
|
||||||
|
|
||||||
int updateNotifyTaskStatusError(String teamId);
|
int updateNotifyTaskStatusError(NotifyTask notifyTask);
|
||||||
|
|
||||||
int updateNotifyTaskStatusRetry(String teamId);
|
int updateNotifyTaskStatusRetry(NotifyTask notifyTask);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user