抢票日志
All checks were successful
continuous-integration/drone Build is passing

This commit is contained in:
liukang 2025-03-04 16:49:35 +08:00
parent cbc93e9f4e
commit ac39651378
8 changed files with 352 additions and 21 deletions

View File

@ -1,5 +1,6 @@
package com.ruoyi.web.task;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService;
@ -12,10 +13,15 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@ -35,6 +41,140 @@ public class RyTask {
private static final Logger log = LoggerFactory.getLogger(RyTask.class);
/**
* 获取wmd
*
* @return
*/
private String getWMD(String data) {
try {
// 密钥secret key
String secret = "1b9cb6378d959b45714bec49971ade22e6e24e42";
// 要哈希的消息数据
// 创建HMAC算法实例指定算法为HmacSHA1
Mac hmac = Mac.getInstance("HmacSHA1");
// 创建密钥对象
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(), "HmacSHA1");
// 初始化HMAC算法实例
hmac.init(secretKey);
// 计算消息的HMAC值结果是一个字节数组
byte[] hmacBytes = hmac.doFinal(data.getBytes());
// 将字节数组转换为Base64编码的字符串
String base64Hmac = Base64.getEncoder().encodeToString(hmacBytes);
// 输出生成的HMAC Base64编码值
System.out.println("HMAC-SHA1 (Base64): " + base64Hmac);
// 指定使用的字符编码如UTF-8
String charset = "UTF-8";
// 进行URL编码
return URLEncoder.encode(base64Hmac, charset);
} catch (Exception e) {
log.error(e.getMessage());
}
return null;
}
/**
* 获取参数
*
* @param pid
* @param jobId
* @throws Exception
*/
public void get(Long pid, Long jobId) throws Exception {
//执行完成停止任务
SysJob job = new SysJob();
job.setJobId(jobId);
job.setStatus("1");
jobService.changeStatus(job);
//演出
Perform perform = performMapper.selectPerformById(pid);
if (perform == null) {
throw new Exception("未找到演出");
}
long time = System.currentTimeMillis();
String data = "/notice/v1.0/notice-" + perform.getNotice() + "?fieldSet=noticeV1&appId=be4d79eb8fc7bd008ee82c8ec4ff6fd4&language=zh-cn&os=WEB&platform=WEB&wpf=pc";
String base = "https://global.apis.naver.com/weverse/wevweb";
String wmd = getWMD(data + time);
if (wmd == null || wmd.isEmpty()) {
throw new Exception("wmd解析失败");
}
// 创建HttpClient实例
HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
// 创建HttpRequest
String url = base + data + "&wmsgpad=" + time + "&wmd=" + wmd;
System.out.println(url);
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI(url))
.GET()
.header("Authorization", "Bearer " + "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIyMGI1YTU1Mjg4M2I0YzIxYjJlYzA2YTI0NjE4YmYwMzoxIiwic3ViIjoiNzNkOWJmZDc5NTk4NDBlODg5NGRhZDg5ODIwODNhNDk2MDMiLCJpYXQiOjE3NDA5ODYzMTksImV4cCI6MTc0MTI0NTUxOSwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50YXBpLndldmVyc2UuaW8vd2ViIiwiYXVkIjoiaHR0cHM6Ly9hY2NvdW50YXBpLndldmVyc2UuaW8iLCJ2ZXIiOjIsImNsaWVudF9pZCI6IndldmVyc2UiLCJwbGF0Zm9ybSI6IldFQiJ9.aQGNsvIRaUAwr9iFNOYsuTF69h_lIu2i6MDhq8JX9w4")
.header("Origin", "https://weverse.io")
.header("Referer", "https://weverse.io/")
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
.build();
// 发送请求并获取响应
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
String eValue = null;
// 检查响应状态码
if (response.statusCode() == 403) {
// 打印响应体
String responseBody = response.body();
WeverseResponse weverseResponse = JSONObject.parseObject(responseBody, WeverseResponse.class);
if (weverseResponse == null || weverseResponse.getData() == null ||
weverseResponse.getData().getButton() == null ||
weverseResponse.getData().getButton().getWebLink() == null ||
weverseResponse.getData().getButton().getWebLink().getUrl() == null ||
weverseResponse.getData().getButton().getWebLink().getUrl().isEmpty()) {
throw new Exception("button获取失败");
}
URI uri = new URI(weverseResponse.getData().getButton().getWebLink().getUrl());
String query = uri.getQuery();
String[] params = query.split("&");
Map<String, String> paramMap = new HashMap<>();
for (String param : params) {
String[] keyValue = param.split("=");
String key = URLDecoder.decode(keyValue[0], "UTF-8");
String value = URLDecoder.decode(keyValue[1], "UTF-8");
paramMap.put(key, value);
}
// 获取参数e的值
eValue = paramMap.get("e");
System.out.println(weverseResponse);
} else {
throw new Exception("button请求失败");
}
if (eValue == null || eValue.isEmpty()) {
throw new Exception("button为空");
}
Perform perform1 = new Perform();
perform1.setId(pid);
perform1.setNum(eValue);
performMapper.updatePerform(perform1);
}
/**
* 抢票
*
@ -115,13 +255,13 @@ public class RyTask {
Thread.sleep(start - now);
log.info("抢票开始了");
for (MyReq r : req) {
log.info("【用户】:"+r.getUser());
log.info("【用户】:" + r.getUser());
// 发起异步请求但不等待结果
CompletableFuture<HttpResponse<String>> future2 = r.getClient().sendAsync(r.getRequest(), HttpResponse.BodyHandlers.ofString());
future2.thenAccept(response -> {
// 处理响应例如记录日志
System.out.println("Response received: " + response.statusCode());
System.out.println(response.body());
log.info("Response received: " + response.statusCode());
log.info(response.body());
}).exceptionally(ex -> {
// 处理异常
ex.printStackTrace();
@ -135,4 +275,6 @@ public class RyTask {
pStatus2.setId(pid);
performMapper.updatePerform(pStatus2);
}
}

View File

@ -0,0 +1,30 @@
package com.ruoyi.web.task;
public class WeverseButton {
private String title;
private WeverseWebLink webLink;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public WeverseWebLink getWebLink() {
return webLink;
}
public void setWebLink(WeverseWebLink webLink) {
this.webLink = webLink;
}
@Override
public String toString() {
return "WeverseButton{" +
"title='" + title + '\'' +
", webLink=" + webLink +
'}';
}
}

View File

@ -0,0 +1,22 @@
package com.ruoyi.web.task;
import java.awt.*;
public class WeverseData {
private WeverseButton button;
public WeverseButton getButton() {
return button;
}
public void setButton(WeverseButton button) {
this.button = button;
}
@Override
public String toString() {
return "WeverseData{" +
"button=" + button +
'}';
}
}

View File

@ -0,0 +1,41 @@
package com.ruoyi.web.task;
public class WeverseResponse {
private String errorCode;
private String message;
private WeverseData data;
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public WeverseData getData() {
return data;
}
public void setData(WeverseData data) {
this.data = data;
}
@Override
public String toString() {
return "WeverseResponse{" +
"errorCode='" + errorCode + '\'' +
", message='" + message + '\'' +
", data=" + data +
'}';
}
}

View File

@ -0,0 +1,30 @@
package com.ruoyi.web.task;
public class WeverseWebLink {
private String type;
private String url;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "WeverseWebLink{" +
"type='" + type + '\'' +
", url='" + url + '\'' +
'}';
}
}

View File

@ -42,6 +42,26 @@ public class Perform extends BaseEntity
*/
private String agree;
private Long advTime;
private String notice;
public String getNotice() {
return notice;
}
public void setNotice(String notice) {
this.notice = notice;
}
public Long getAdvTime() {
return advTime;
}
public void setAdvTime(Long advTime) {
this.advTime = advTime;
}
public String getAgree() {
return agree;
}

View File

@ -80,29 +80,24 @@ public class PerformServiceImpl implements IPerformService {
if (perform.getStartTime().compareTo(new Date()) <= 0) {
throw new Exception("开始时间必须大于当前时间");
}
Perform query = new Perform();
query.setNum(perform.getNum());
List<Perform> performs = performMapper.selectPerformVerify(query);
if (!performs.isEmpty()) {
throw new Exception("演出Num已存在");
}
perform.setCreateTime(DateUtils.getNowDate());
//未开始
perform.setStatus("1");
int result = performMapper.insertPerform(perform);
initJob(perform.getId(), perform.getName(), perform.getStartTime(), userName);
initRobJob(perform.getId(), perform.getName(), perform.getStartTime(), userName);
initGetJob(perform.getId(), perform.getName(), perform.getStartTime(), perform.getAdvTime(), userName);
return result;
}
/**
* 任务
* 抢票任务
*/
private void initJob(Long pid, String name, Date date, String userName) throws SchedulerException, TaskException {
private void initRobJob(Long pid, String name, Date date, String userName) throws SchedulerException, TaskException {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.HOUR_OF_DAY, -1);
calendar.add(Calendar.MINUTE, -9);
calendar.add(Calendar.MINUTE, -2);
// 获取年
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // 月份从0开始所以加1
@ -133,6 +128,44 @@ public class PerformServiceImpl implements IPerformService {
jobService.updateJob(job);
}
/**
* 获取参数任务
*/
private void initGetJob(Long pid, String name, Date date, Long advTime, String userName) throws SchedulerException, TaskException {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.HOUR_OF_DAY, -1);
calendar.add(Calendar.MINUTE, -advTime.intValue());
// 获取年
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // 月份从0开始所以加1
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // 24小时制
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
String cron = String.format("%d %d %d %d %d ? %d", second, minute, hour, day, month, year);
// 定义日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化当前日期和时间
String formattedDate = sdf.format(date);
SysJob job = new SysJob();
job.setJobName("获取参数 " + name + " " + formattedDate);
job.setConcurrent("0");
job.setCronExpression(cron);
job.setInvokeTarget("ryTask.get(" + pid + "L)");
job.setJobGroup("DEFAULT");
job.setMisfirePolicy("3");
job.setStatus("0");
job.setCreateBy(userName);
jobService.insertJob(job);
job.setInvokeTarget("ryTask.get(" + pid + "L, " + job.getJobId() + "L)");
jobService.updateJob(job);
}
/**
* 修改演出
*
@ -144,13 +177,6 @@ public class PerformServiceImpl implements IPerformService {
if (perform.getStartTime().compareTo(new Date()) <= 0) {
throw new Exception("开始时间必须大于当前时间");
}
Perform query = new Perform();
query.setNum(perform.getNum());
query.setId(perform.getId());
List<Perform> performs = performMapper.selectPerformVerify(query);
if (!performs.isEmpty()) {
throw new Exception("演出Num已存在");
}
perform.setUpdateTime(DateUtils.getNowDate());
return performMapper.updatePerform(perform);
}

View File

@ -10,6 +10,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="name" column="name" />
<result property="startTime" column="start_time" />
<result property="status" column="status" />
<result property="advTime" column="adv_time" />
<result property="agree" column="agree" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
@ -19,7 +20,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectPerformVo">
select id, num, name, start_time, status, agree, create_by, create_time, update_by, update_time, remark from perform
select id,
num,
name,
start_time,
status,
agree,
notice,
adv_time,
create_by,
create_time,
update_by,
update_time,
remark
from perform
</sql>
<select id="selectPerformList" parameterType="Perform" resultMap="PerformResult">
@ -62,6 +76,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
insert into perform
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="num != null">num,</if>
<if test="advTime != null">adv_time,</if>
<if test="notice != null and notice != ''">notice,</if>
<if test="agree != null and agree != ''">agree,</if>
<if test="name != null and name != ''">name,</if>
<if test="startTime != null">start_time,</if>
@ -74,6 +90,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="num != null">#{num},</if>
<if test="advTime != null">#{advTime},</if>
<if test="notice != null and notice != ''">#{notice},</if>
<if test="agree != null and agree != ''">#{agree},</if>
<if test="name != null and name != ''">#{name},</if>
<if test="startTime != null">#{startTime},</if>
@ -90,6 +108,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update perform
<trim prefix="SET" suffixOverrides=",">
<if test="num != null">num = #{num},</if>
<if test="advTime != null">adv_time = #{advTime},</if>
<if test="notice != null and notice != ''">notice = #{notice},</if>
<if test="name != null and name != ''">name = #{name},</if>
<if test="startTime != null">start_time = #{startTime},</if>
<if test="status != null and status != ''">status = #{status},</if>