You've already forked FrameTour-BE
feat(payment): 支付与退款后清除景区统计缓存
- 在支付成功、取消、退款回调后增加缓存删除逻辑 - 新增 `invalidateStatisticsCache` 方法用于删除 Redis 缓存 - 定时任务中统计景区数据后也调用缓存清除方法 - 调整景区统计任务时间并扩展统计周期为近7天 - 增强定时任务日志记录和异常处理机制
This commit is contained in:
@@ -30,6 +30,7 @@ import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -60,6 +61,8 @@ public class WxPayServiceImpl implements WxPayService {
|
||||
private OrderMapper orderMapper;
|
||||
@Autowired
|
||||
private ScenicService scenicService;
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Override
|
||||
public Map<String, Object> createOrder(Long scenicId, WXPayOrderReqVO req) {
|
||||
@@ -100,10 +103,14 @@ public class WxPayServiceImpl implements WxPayService {
|
||||
long orderId = Long.parseLong(callbackResponse.getOrderNo());
|
||||
if (callbackResponse.isPay()) {
|
||||
orderBiz.paidOrder(orderId);
|
||||
// 支付成功后删除统计缓存,确保下次查询获取最新数据
|
||||
invalidateStatisticsCache(scenicId);
|
||||
} else if (callbackResponse.isCancel()) {
|
||||
orderBiz.cancelOrder(orderId);
|
||||
} else if (callbackResponse.isRefund()) {
|
||||
orderBiz.refundOrder(orderId);
|
||||
// 退款后删除统计缓存
|
||||
invalidateStatisticsCache(scenicId);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
@@ -165,6 +172,10 @@ public class WxPayServiceImpl implements WxPayService {
|
||||
statisticsRecordAddReq.setScenicId(order.getScenicId());
|
||||
statisticsRecordAddReq.setMorphId(orderId);
|
||||
statisticsMapper.addStatisticsRecord(statisticsRecordAddReq);
|
||||
|
||||
// 退款成功后删除统计缓存,确保下次查询获取最新数据
|
||||
invalidateStatisticsCache(scenicId);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("微信退款回调失败!", e);
|
||||
@@ -180,4 +191,15 @@ public class WxPayServiceImpl implements WxPayService {
|
||||
.setOrderNo(orderId);
|
||||
scenicPayAdapter.cancelOrder(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除景区统计缓存
|
||||
* 在支付或退款回调后调用,确保下次查询时重新计算统计数据
|
||||
* @param scenicId 景区ID
|
||||
*/
|
||||
private void invalidateStatisticsCache(Long scenicId) {
|
||||
String redisKey = "statistics:tmp_cache:" + scenicId;
|
||||
Boolean deleted = redisTemplate.delete(redisKey);
|
||||
log.info("[缓存删除] 景区 {} 的统计缓存删除结果: {}", scenicId, deleted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,10 @@ import com.ycwl.basic.model.pc.scenicDeviceStats.entity.ScenicDeviceStatsEntity;
|
||||
import com.ycwl.basic.repository.ScenicRepository;
|
||||
import com.ycwl.basic.service.mobile.AppStatisticsService;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -20,6 +22,7 @@ import org.springframework.stereotype.Component;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@EnableScheduling
|
||||
@Profile("prod")
|
||||
@@ -32,6 +35,8 @@ public class ScenicStatsTask {
|
||||
private AppStatisticsService statisticsService;
|
||||
@Autowired
|
||||
private ScenicRepository scenicRepository;
|
||||
@Autowired
|
||||
private RedisTemplate<String, String> redisTemplate;
|
||||
|
||||
@Scheduled(cron = "0 1 0 * * *")
|
||||
public void countDeviceStats() {
|
||||
@@ -55,23 +60,58 @@ public class ScenicStatsTask {
|
||||
});
|
||||
}
|
||||
}
|
||||
@Scheduled(cron = "0 20 0 * * *")
|
||||
@Scheduled(cron = "0 0 2 * * *")
|
||||
public void countScenicStats() {
|
||||
Date yesterdayStart = DateUtil.beginOfDay(DateUtil.yesterday());
|
||||
Date yesterdayEnd = DateUtil.endOfDay(yesterdayStart);
|
||||
log.info("开始执行景区统计任务,统计前7天至昨天的数据");
|
||||
|
||||
// 获取所有景区列表
|
||||
ScenicReqQuery query = new ScenicReqQuery();
|
||||
query.setPageSize(1000);
|
||||
List<ScenicV2DTO> scenicList = scenicRepository.list(query);
|
||||
|
||||
// 循环统计前7天(至昨天)的数据
|
||||
for (int daysAgo = 1; daysAgo <= 7; daysAgo++) {
|
||||
Date targetDate = DateUtil.offsetDay(new Date(), -daysAgo);
|
||||
Date startTime = DateUtil.beginOfDay(targetDate);
|
||||
Date endTime = DateUtil.endOfDay(targetDate);
|
||||
|
||||
log.info("正在统计第{}天前的数据,日期: {}", daysAgo, DateUtil.formatDate(startTime));
|
||||
|
||||
scenicList.forEach((scenic) -> {
|
||||
try {
|
||||
CommonQueryReq commonQueryReq = new CommonQueryReq();
|
||||
Long scenicId = Long.valueOf(scenic.getId());
|
||||
commonQueryReq.setScenicId(scenicId);
|
||||
commonQueryReq.setStartTime(yesterdayStart);
|
||||
commonQueryReq.setEndTime(yesterdayEnd);
|
||||
commonQueryReq.setStartTime(startTime);
|
||||
commonQueryReq.setEndTime(endTime);
|
||||
commonQueryReq.setRealtime(true);
|
||||
|
||||
// 执行统计查询
|
||||
ApiResponse<AppStatisticsFunnelVO> resp = statisticsService.userConversionFunnel(commonQueryReq);
|
||||
AppStatisticsFunnelVO data = resp.getData();
|
||||
statisticsMapper.insertStat(scenicId, yesterdayStart, data);
|
||||
|
||||
// 写入数据库(REPLACE INTO 会自动更新已存在的记录)
|
||||
statisticsMapper.insertStat(scenicId, startTime, data);
|
||||
|
||||
// 删除该景区的缓存,确保下次查询时获取最新数据
|
||||
invalidateStatisticsCache(scenicId);
|
||||
} catch (Exception e) {
|
||||
log.error("统计景区 {} 在日期 {} 的数据时发生错误", scenic.getId(), DateUtil.formatDate(startTime), e);
|
||||
}
|
||||
});
|
||||
|
||||
log.info("第{}天前的数据统计完成,日期: {}", daysAgo, DateUtil.formatDate(startTime));
|
||||
}
|
||||
|
||||
log.info("景区统计任务执行完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除景区统计缓存
|
||||
* @param scenicId 景区ID
|
||||
*/
|
||||
private void invalidateStatisticsCache(Long scenicId) {
|
||||
String redisKey = "statistics:tmp_cache:" + scenicId;
|
||||
redisTemplate.delete(redisKey);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user