feat:fwd下单优化

This commit is contained in:
Zhujx
2025-09-30 15:54:52 +08:00
parent 387cbf4575
commit 876a0dbb81
8 changed files with 144 additions and 19 deletions

View File

@@ -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;
}

View File

@@ -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";
}

View File

@@ -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<FPerformProjectInfo> 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("请注意进行数据库配置的更改!");

View File

@@ -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);
}
}
}

View File

@@ -54,5 +54,11 @@ public interface IPerformServiceHttp {
*/
List<AudienceMemberInfo> getAudienceMemberInfo(String token);
/**
* http请求获取时间
* @return
*/
Long getServerTimeStamp();
}

View File

@@ -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<String, String> buildFWDHeaders(String token) {
Map<String, String> headers = Maps.newHashMap();
headers.put("Host", "api.livelab.com.cn");

View File

@@ -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,6 +88,23 @@ public class PerformServiceImpl implements IPerformService {
if (1 == fPerformSeatInfo.getSoldOut()) {
continue;
}
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)) {
log.info("下单成功,订单信息:{}", JSONObject.toJSONString(projectOrder));
String msg = "【芬玩岛】下单成功✅✅✅,演出名称:" + performByProjectId.getProjectName() + "请在2分钟内完成付款";
dingTalkService.sendScriptMsg(msg);
return Boolean.TRUE;
}
}
}
dingTalkService.sendScriptMsg("【芬玩岛】下单失败❌❌❌,演出名称:" + performByProjectId.getProjectName());
return Boolean.FALSE;
}
@NotNull
private static ProjectOrderCreateReq buildReq(Long projectId, List<Long> frequentIds, FPerformSeatInfo fPerformSeatInfo) {
ProjectOrderCreateReq projectOrderCreateReq = new ProjectOrderCreateReq();
projectOrderCreateReq.setDeliveryType(1);
projectOrderCreateReq.setContactName("朱吉祥");
@@ -102,18 +120,7 @@ public class PerformServiceImpl implements IPerformService {
projectOrderCreateReq.setBlackBox("0");
projectOrderCreateReq.setCombineTicketVos(null);
projectOrderCreateReq.setOrdinaryTicketVos(null);
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)) {
log.info("下单成功,订单信息:{}", JSONObject.toJSONString(projectOrder));
String msg = "【芬玩岛】下单成功✅✅✅,演出名称:" + performByProjectId.getProjectName() + "请在2分钟内完成付款";
dingTalkService.sendScriptMsg(msg);
return Boolean.TRUE;
}
}
}
dingTalkService.sendScriptMsg("【芬玩岛】下单失败❌❌❌,演出名称:" + performByProjectId.getProjectName());
return Boolean.FALSE;
return projectOrderCreateReq;
}
@Override

View File

@@ -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()
);
}
}