diff --git a/script/src/main/java/com/xiang/xservice/fwd/constants/CodeConstants.java b/script/src/main/java/com/xiang/xservice/fwd/constants/CodeConstants.java index 39c160b..66579ce 100644 --- a/script/src/main/java/com/xiang/xservice/fwd/constants/CodeConstants.java +++ b/script/src/main/java/com/xiang/xservice/fwd/constants/CodeConstants.java @@ -3,4 +3,8 @@ package com.xiang.xservice.fwd.constants; public class CodeConstants { public static final Integer SUCCESS = 10000; public static final Integer LIMIT = 47009; + + public static final Integer TOKEN_EXPIRED = 11004; + + public static final Integer SYSTEM_ERROR = 90008; } diff --git a/script/src/main/java/com/xiang/xservice/fwd/constants/UrlConstants.java b/script/src/main/java/com/xiang/xservice/fwd/constants/UrlConstants.java index c3af89a..5a1a7f8 100644 --- a/script/src/main/java/com/xiang/xservice/fwd/constants/UrlConstants.java +++ b/script/src/main/java/com/xiang/xservice/fwd/constants/UrlConstants.java @@ -37,4 +37,9 @@ public class UrlConstants { * 查询观影人列表 */ public final static String PROJECT_AUDIENCE_MEMBER_INFO = BASE_URL + "/member/member/bearer/app/list"; + + /** + * 服务端时间 + */ + public final static String PERFORMANCE_SERVER_TIME = BASE_URL + "/performance/app/project/serverTime"; } diff --git a/script/src/main/java/com/xiang/xservice/fwd/schedule/FwdImportantMsgJob.java b/script/src/main/java/com/xiang/xservice/fwd/schedule/FwdImportantMsgJob.java index 2693c5f..6cc6c17 100644 --- a/script/src/main/java/com/xiang/xservice/fwd/schedule/FwdImportantMsgJob.java +++ b/script/src/main/java/com/xiang/xservice/fwd/schedule/FwdImportantMsgJob.java @@ -21,6 +21,7 @@ import com.xiang.xservice.fwd.mapper.FwdUserConfigMapper; import com.xiang.xservice.fwd.service.DingTalkScriptFWDService; import com.xiang.xservice.fwd.service.IPerformService; import com.xiang.xservice.fwd.service.IPerformServiceHttp; +import com.xiang.xservice.fwd.utils.TimeSyncUtils; import com.xiang.xservice.schedule.core.DynamicTaskScheduler; import com.xiang.xservice.schedule.entity.ScheduledTaskEntity; import com.xiang.xservice.schedule.entity.TaskConfig; @@ -78,10 +79,11 @@ public class FwdImportantMsgJob { for (ScheduledTaskEntity taskEntity : taskList) { HashMap params = com.alibaba.fastjson2.JSON.parseObject(taskEntity.getParameters(), HashMap.class); FwdOrderTaskParam param = MapUtils.isEmpty(params) ? new FwdOrderTaskParam(null, taskEntity.getId()) : new FwdOrderTaskParam((Long) params.get("projectId"), taskEntity.getId()); - LocalDateTime runTime = taskEntity.getRunTime().isBefore(LocalDateTime.now()) ? LocalDateTime.now().plusMinutes(1) : taskEntity.getRunTime(); + LocalDateTime runTime = taskEntity.getRunTime().isBefore(TimeSyncUtils.now()) ? TimeSyncUtils.now() : taskEntity.getRunTime(); dynamicTaskScheduler.schedule( new TaskConfig(taskEntity.getId(), taskEntity.getTaskName(), taskEntity.getTaskGroup(), runTime, params), - new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService, param, dynamicTaskSchedulerService) + new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService, param, dynamicTaskSchedulerService), + TimeSyncUtils.now() ); } } @@ -95,7 +97,7 @@ public class FwdImportantMsgJob { performConfigMapper.delPerforms(); // 查询所有即将今天预售的演唱会信息 - LocalDate now = LocalDate.now(); + LocalDate now = TimeSyncUtils.now().toLocalDate(); List saleTodayData = performProjectInfoMapper.getPreSaleTodayData(now.atTime(0, 0, 0), now.atTime(23, 59, 59)); if (CollectionUtils.isEmpty(saleTodayData)) { log.info("【芬玩岛】 今天:{}暂无预售的演唱会门票信息.", now); @@ -124,7 +126,8 @@ public class FwdImportantMsgJob { new TaskConfig(taskId, "芬玩岛演唱会抢票-【" + data.getProjectName() + "】", TaskGroupEnum.SERVICE_FWD_SCHEDULE.getCode(), runTime, params), new TicketGrabTask(fwdUserConfigMapper, fwdAudienceConfigMapper, iPerformService, - new FwdOrderTaskParam(data.getProjectId(), taskId), dynamicTaskSchedulerService)); + new FwdOrderTaskParam(data.getProjectId(), taskId), dynamicTaskSchedulerService), + TimeSyncUtils.now()); savaTask(data, taskId, params); } msg.append("请注意进行数据库配置的更改!"); diff --git a/script/src/main/java/com/xiang/xservice/fwd/schedule/FwdTimeSyncJob.java b/script/src/main/java/com/xiang/xservice/fwd/schedule/FwdTimeSyncJob.java new file mode 100644 index 0000000..aa6fb58 --- /dev/null +++ b/script/src/main/java/com/xiang/xservice/fwd/schedule/FwdTimeSyncJob.java @@ -0,0 +1,36 @@ +package com.xiang.xservice.fwd.schedule; + +import com.xiang.xservice.fwd.service.IPerformServiceHttp; +import com.xiang.xservice.fwd.utils.TimeSyncUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * @Author: xiang + * @Date: 2025-09-30 14:56 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class FwdTimeSyncJob { + + private final IPerformServiceHttp performServiceHttp; + @Scheduled(fixedRate = 60_000) // 每分钟执行一次 + public void syncTime() { + try { + // 调用对方接口 + Long timeStamp = performServiceHttp.getServerTimeStamp(); + if (Objects.equals(timeStamp,-1L)) { + log.info("请求服务器时间失败!"); + return; + } + TimeSyncUtils.syncWithServer(timeStamp); + } catch (Exception e) { + log.error("同步时间失败", e); + } + } +} diff --git a/script/src/main/java/com/xiang/xservice/fwd/service/IPerformServiceHttp.java b/script/src/main/java/com/xiang/xservice/fwd/service/IPerformServiceHttp.java index fe88a32..06e9e50 100644 --- a/script/src/main/java/com/xiang/xservice/fwd/service/IPerformServiceHttp.java +++ b/script/src/main/java/com/xiang/xservice/fwd/service/IPerformServiceHttp.java @@ -54,5 +54,11 @@ public interface IPerformServiceHttp { */ List getAudienceMemberInfo(String token); + /** + * http请求获取时间 + * @return + */ + Long getServerTimeStamp(); + } diff --git a/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceHttpServiceImpl.java b/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceHttpServiceImpl.java index 9749518..80ca813 100644 --- a/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceHttpServiceImpl.java +++ b/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceHttpServiceImpl.java @@ -26,6 +26,7 @@ import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Random; @Service @Slf4j @@ -100,6 +101,11 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp { } return projectOrderCreateResp; } + if (Objects.nonNull(code) && Objects.equals(code, CodeConstants.LIMIT)) { + Integer waitTime = new Random().nextInt(10); + log.info("触发FWD限流机制,等待:{}秒后重新发送。", waitTime); + return null; + } return null; } @@ -170,6 +176,23 @@ public class PerformServiceHttpServiceImpl implements IPerformServiceHttp { return Lists.newArrayList(); } + @Override + public Long getServerTimeStamp() { + String respStr = HttpUtils.doGet(UrlConstants.PERFORMANCE_SERVER_TIME, buildFWDHeaders(null), null); + if (StringUtils.isBlank(respStr)) { + return -1L; + } + JSONObject jsonObject = JSON.parseObject(respStr); + if (Objects.nonNull(jsonObject)) { + Integer code = (Integer) jsonObject.get("code"); + if (Objects.equals(code, CodeConstants.SUCCESS)) { + Long timestamp = (Long) jsonObject.get("data"); + return timestamp; + } + } + return -1L; + } + private Map buildFWDHeaders(String token) { Map headers = Maps.newHashMap(); headers.put("Host", "api.livelab.com.cn"); diff --git a/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceImpl.java b/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceImpl.java index 90e776e..a07f07f 100644 --- a/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceImpl.java +++ b/script/src/main/java/com/xiang/xservice/fwd/service/impl/PerformServiceImpl.java @@ -19,6 +19,7 @@ import com.xiang.xservice.http.helper.HttpRequestHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Service; import java.math.BigDecimal; @@ -87,21 +88,7 @@ public class PerformServiceImpl implements IPerformService { if (1 == fPerformSeatInfo.getSoldOut()) { continue; } - ProjectOrderCreateReq projectOrderCreateReq = new ProjectOrderCreateReq(); - projectOrderCreateReq.setDeliveryType(1); - projectOrderCreateReq.setContactName("朱吉祥"); - projectOrderCreateReq.setContactPhone("15858717571"); - projectOrderCreateReq.setPayment(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2)); - projectOrderCreateReq.setTotalPrice(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2, BigDecimal.ROUND_HALF_UP)); - projectOrderCreateReq.setPerformId(fPerformSeatInfo.getPerformId()); - projectOrderCreateReq.setProjectId(projectId.toString()); - projectOrderCreateReq.setPrivilegeCodeList(new ArrayList<>()); - projectOrderCreateReq.setAudienceCount(frequentIds.size()); - projectOrderCreateReq.setFrequentIds(frequentIds); - projectOrderCreateReq.setSeatPlanIds(Collections.singletonList(fPerformSeatInfo.getSeatPlanId())); - projectOrderCreateReq.setBlackBox("0"); - projectOrderCreateReq.setCombineTicketVos(null); - projectOrderCreateReq.setOrdinaryTicketVos(null); + ProjectOrderCreateReq projectOrderCreateReq = buildReq(projectId, frequentIds, fPerformSeatInfo); for (int i = 1; i <= 10; i++) { ProjectOrderCreateResp projectOrder = httpRequestHelper.fetchWithRetry(() -> performServiceHttp.createProjectOrder(projectOrderCreateReq, availableUser.get(0).getToken()), "create-project-order"); if (Objects.nonNull(projectOrder)) { @@ -116,6 +103,26 @@ public class PerformServiceImpl implements IPerformService { return Boolean.FALSE; } + @NotNull + private static ProjectOrderCreateReq buildReq(Long projectId, List frequentIds, FPerformSeatInfo fPerformSeatInfo) { + ProjectOrderCreateReq projectOrderCreateReq = new ProjectOrderCreateReq(); + projectOrderCreateReq.setDeliveryType(1); + projectOrderCreateReq.setContactName("朱吉祥"); + projectOrderCreateReq.setContactPhone("15858717571"); + projectOrderCreateReq.setPayment(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2)); + projectOrderCreateReq.setTotalPrice(fPerformSeatInfo.getPrice().multiply(BigDecimal.valueOf(frequentIds.size())).setScale(2, BigDecimal.ROUND_HALF_UP)); + projectOrderCreateReq.setPerformId(fPerformSeatInfo.getPerformId()); + projectOrderCreateReq.setProjectId(projectId.toString()); + projectOrderCreateReq.setPrivilegeCodeList(new ArrayList<>()); + projectOrderCreateReq.setAudienceCount(frequentIds.size()); + projectOrderCreateReq.setFrequentIds(frequentIds); + projectOrderCreateReq.setSeatPlanIds(Collections.singletonList(fPerformSeatInfo.getSeatPlanId())); + projectOrderCreateReq.setBlackBox("0"); + projectOrderCreateReq.setCombineTicketVos(null); + projectOrderCreateReq.setOrdinaryTicketVos(null); + return projectOrderCreateReq; + } + @Override public List getAvailablePerform() { return fwdPerformConfigMapper.getAvailablePerform(); diff --git a/script/src/main/java/com/xiang/xservice/fwd/utils/TimeSyncUtils.java b/script/src/main/java/com/xiang/xservice/fwd/utils/TimeSyncUtils.java new file mode 100644 index 0000000..ba8fa5c --- /dev/null +++ b/script/src/main/java/com/xiang/xservice/fwd/utils/TimeSyncUtils.java @@ -0,0 +1,41 @@ +package com.xiang.xservice.fwd.utils; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; + +/** + * @Author: xiang + * @Date: 2025-09-30 14:58 + */ +public class TimeSyncUtils { + private static volatile long offset = 0; + + /** + * 初始化/更新偏移量 + */ + + public static void syncWithServer(long serverTime) { + long localTime = System.currentTimeMillis(); + offset = serverTime - localTime; + } + + /** + * 获取同步后的时间戳 + * @return + */ + public static long currentTimeMillis() { + return System.currentTimeMillis() + offset; + } + + /** + * 获取同步后的 LocalDateTime + * @return + */ + public static LocalDateTime now() { + return LocalDateTime.ofInstant( + Instant.ofEpochMilli(currentTimeMillis()), + ZoneId.systemDefault() + ); + } +}