feat: 更新二维码和图片访问接口逻辑
主要修改:
1. 在QrProxyController中引入LinkStatusService,通过codeNo查询对应的machineId,优化二维码和图片的获取逻辑。
2. 更新所有相关的图片访问路径,确保使用新的/image/{codeNo}格式。
3. 在GameInterfaceResponse中新增machineId和completedPoints字段,提供更详细的游戏界面数据。
4. 更新SecurityConfig,允许/image/**路径的公开访问。
技术细节:
- 通过优化接口逻辑和数据结构,提升了系统的灵活性和用户体验,同时确保了安全性和可维护性。
This commit is contained in:
BIN
images/M44PACLD/firstReward.png
Normal file
BIN
images/M44PACLD/firstReward.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
BIN
images/M44PACLD/homepage.png
Normal file
BIN
images/M44PACLD/homepage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 398 KiB |
BIN
images/M44PACLD/midReward.png
Normal file
BIN
images/M44PACLD/midReward.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 391 KiB |
@@ -6,6 +6,7 @@ import com.gameplatform.server.model.dto.link.GameInterfaceResponse;
|
|||||||
import com.gameplatform.server.model.entity.agent.LinkBatch;
|
import com.gameplatform.server.model.entity.agent.LinkBatch;
|
||||||
import com.gameplatform.server.model.entity.agent.LinkTask;
|
import com.gameplatform.server.model.entity.agent.LinkTask;
|
||||||
import com.gameplatform.server.service.external.ScriptClient;
|
import com.gameplatform.server.service.external.ScriptClient;
|
||||||
|
import com.gameplatform.server.service.link.LinkStatusService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -32,24 +33,34 @@ public class QrProxyController {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(QrProxyController.class);
|
private static final Logger log = LoggerFactory.getLogger(QrProxyController.class);
|
||||||
|
|
||||||
private final ScriptClient scriptClient;
|
private final ScriptClient scriptClient;
|
||||||
|
private final LinkStatusService linkStatusService;
|
||||||
private final String appBaseUrl;
|
private final String appBaseUrl;
|
||||||
private final LinkTaskMapper linkTaskMapper;
|
private final LinkTaskMapper linkTaskMapper;
|
||||||
private final LinkBatchMapper linkBatchMapper;
|
private final LinkBatchMapper linkBatchMapper;
|
||||||
|
|
||||||
public QrProxyController(ScriptClient scriptClient,
|
public QrProxyController(ScriptClient scriptClient,
|
||||||
|
LinkStatusService linkStatusService,
|
||||||
@Value("${app.base-url}") String appBaseUrl,
|
@Value("${app.base-url}") String appBaseUrl,
|
||||||
LinkTaskMapper linkTaskMapper,
|
LinkTaskMapper linkTaskMapper,
|
||||||
LinkBatchMapper linkBatchMapper) {
|
LinkBatchMapper linkBatchMapper) {
|
||||||
this.scriptClient = scriptClient;
|
this.scriptClient = scriptClient;
|
||||||
|
this.linkStatusService = linkStatusService;
|
||||||
this.appBaseUrl = appBaseUrl;
|
this.appBaseUrl = appBaseUrl;
|
||||||
this.linkTaskMapper = linkTaskMapper;
|
this.linkTaskMapper = linkTaskMapper;
|
||||||
this.linkBatchMapper = linkBatchMapper;
|
this.linkBatchMapper = linkBatchMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/{codeNo}/qr.png", produces = MediaType.IMAGE_PNG_VALUE)
|
@GetMapping(value = "/image/{codeNo}/qr.png", produces = MediaType.IMAGE_PNG_VALUE)
|
||||||
@Operation(summary = "二维码图片代理")
|
@Operation(summary = "二维码图片代理")
|
||||||
public Mono<ResponseEntity<byte[]>> qr(@PathVariable("codeNo") String codeNo) {
|
public Mono<ResponseEntity<byte[]>> qr(@PathVariable("codeNo") String codeNo) {
|
||||||
String path = "/" + codeNo + "/二维码.png";
|
// 通过codeNo查询machineId
|
||||||
|
String machineId = linkStatusService.getMechainIdByCode(codeNo);
|
||||||
|
if (machineId == null) {
|
||||||
|
log.warn("无法找到codeNo对应的machineId: {}", codeNo);
|
||||||
|
return Mono.just(ResponseEntity.notFound().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = "/" + machineId + "/二维码.png";
|
||||||
return scriptClient.getQrPng(path)
|
return scriptClient.getQrPng(path)
|
||||||
.map(bytes -> ResponseEntity.ok()
|
.map(bytes -> ResponseEntity.ok()
|
||||||
.contentType(MediaType.IMAGE_PNG)
|
.contentType(MediaType.IMAGE_PNG)
|
||||||
@@ -58,10 +69,17 @@ public class QrProxyController {
|
|||||||
.body(bytes));
|
.body(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/{codeNo}/homepage.png", produces = MediaType.IMAGE_PNG_VALUE)
|
@GetMapping(value = "/image/{codeNo}/homepage.png", produces = MediaType.IMAGE_PNG_VALUE)
|
||||||
@Operation(summary = "首次主页图片代理")
|
@Operation(summary = "首次主页图片代理")
|
||||||
public Mono<ResponseEntity<byte[]>> homepage(@PathVariable("codeNo") String codeNo) {
|
public Mono<ResponseEntity<byte[]>> homepage(@PathVariable("codeNo") String codeNo) {
|
||||||
String path = "/" + codeNo + "/首次主页.png";
|
// 通过codeNo查询machineId
|
||||||
|
String machineId = linkStatusService.getMechainIdByCode(codeNo);
|
||||||
|
if (machineId == null) {
|
||||||
|
log.warn("无法找到codeNo对应的machineId: {}", codeNo);
|
||||||
|
return Mono.just(ResponseEntity.notFound().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = "/" + machineId + "/首次主页.png";
|
||||||
return scriptClient.getImagePng(path)
|
return scriptClient.getImagePng(path)
|
||||||
.map(bytes -> ResponseEntity.ok()
|
.map(bytes -> ResponseEntity.ok()
|
||||||
.contentType(MediaType.IMAGE_PNG)
|
.contentType(MediaType.IMAGE_PNG)
|
||||||
@@ -70,10 +88,17 @@ public class QrProxyController {
|
|||||||
.body(bytes));
|
.body(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/{codeNo}/first-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
|
@GetMapping(value = "/image/{codeNo}/first-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
|
||||||
@Operation(summary = "首次赏金图片代理")
|
@Operation(summary = "首次赏金图片代理")
|
||||||
public Mono<ResponseEntity<byte[]>> firstReward(@PathVariable("codeNo") String codeNo) {
|
public Mono<ResponseEntity<byte[]>> firstReward(@PathVariable("codeNo") String codeNo) {
|
||||||
String path = "/" + codeNo + "/首次赏金.png";
|
// 通过codeNo查询machineId
|
||||||
|
String machineId = linkStatusService.getMechainIdByCode(codeNo);
|
||||||
|
if (machineId == null) {
|
||||||
|
log.warn("无法找到codeNo对应的machineId: {}", codeNo);
|
||||||
|
return Mono.just(ResponseEntity.notFound().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = "/" + machineId + "/首次赏金.png";
|
||||||
return scriptClient.getImagePng(path)
|
return scriptClient.getImagePng(path)
|
||||||
.map(bytes -> ResponseEntity.ok()
|
.map(bytes -> ResponseEntity.ok()
|
||||||
.contentType(MediaType.IMAGE_PNG)
|
.contentType(MediaType.IMAGE_PNG)
|
||||||
@@ -82,10 +107,17 @@ public class QrProxyController {
|
|||||||
.body(bytes));
|
.body(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/{codeNo}/mid-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
|
@GetMapping(value = "/image/{codeNo}/mid-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
|
||||||
@Operation(summary = "中途赏金图片代理")
|
@Operation(summary = "中途赏金图片代理")
|
||||||
public Mono<ResponseEntity<byte[]>> midReward(@PathVariable("codeNo") String codeNo) {
|
public Mono<ResponseEntity<byte[]>> midReward(@PathVariable("codeNo") String codeNo) {
|
||||||
String path = "/" + codeNo + "/中途赏金.png";
|
// 通过codeNo查询machineId
|
||||||
|
String machineId = linkStatusService.getMechainIdByCode(codeNo);
|
||||||
|
if (machineId == null) {
|
||||||
|
log.warn("无法找到codeNo对应的machineId: {}", codeNo);
|
||||||
|
return Mono.just(ResponseEntity.notFound().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = "/" + machineId + "/中途赏金.png";
|
||||||
return scriptClient.getImagePng(path)
|
return scriptClient.getImagePng(path)
|
||||||
.map(bytes -> ResponseEntity.ok()
|
.map(bytes -> ResponseEntity.ok()
|
||||||
.contentType(MediaType.IMAGE_PNG)
|
.contentType(MediaType.IMAGE_PNG)
|
||||||
@@ -94,10 +126,17 @@ public class QrProxyController {
|
|||||||
.body(bytes));
|
.body(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping(value = "/{codeNo}/end-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
|
@GetMapping(value = "/image/{codeNo}/end-reward.png", produces = MediaType.IMAGE_PNG_VALUE)
|
||||||
@Operation(summary = "结束赏金图片代理")
|
@Operation(summary = "结束赏金图片代理")
|
||||||
public Mono<ResponseEntity<byte[]>> endReward(@PathVariable("codeNo") String codeNo) {
|
public Mono<ResponseEntity<byte[]>> endReward(@PathVariable("codeNo") String codeNo) {
|
||||||
String path = "/" + codeNo + "/结束赏金.png";
|
// 通过codeNo查询machineId
|
||||||
|
String machineId = linkStatusService.getMechainIdByCode(codeNo);
|
||||||
|
if (machineId == null) {
|
||||||
|
log.warn("无法找到codeNo对应的machineId: {}", codeNo);
|
||||||
|
return Mono.just(ResponseEntity.notFound().build());
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = "/" + machineId + "/结束赏金.png";
|
||||||
return scriptClient.getImagePng(path)
|
return scriptClient.getImagePng(path)
|
||||||
.map(bytes -> ResponseEntity.ok()
|
.map(bytes -> ResponseEntity.ok()
|
||||||
.contentType(MediaType.IMAGE_PNG)
|
.contentType(MediaType.IMAGE_PNG)
|
||||||
@@ -112,13 +151,13 @@ public class QrProxyController {
|
|||||||
Map<String, String> imageLinks = new HashMap<>();
|
Map<String, String> imageLinks = new HashMap<>();
|
||||||
|
|
||||||
// 添加二维码链接
|
// 添加二维码链接
|
||||||
imageLinks.put("qrCode", appBaseUrl + "/api/link/" + codeNo + "/qr.png");
|
imageLinks.put("qrCode", appBaseUrl + "/api/link/image/" + codeNo + "/qr.png");
|
||||||
|
|
||||||
// 添加其他图片链接
|
// 添加其他图片链接
|
||||||
imageLinks.put("homepage", appBaseUrl + "/api/link/" + codeNo + "/homepage.png");
|
imageLinks.put("homepage", appBaseUrl + "/api/link/image/" + codeNo + "/homepage.png");
|
||||||
imageLinks.put("firstReward", appBaseUrl + "/api/link/" + codeNo + "/first-reward.png");
|
imageLinks.put("firstReward", appBaseUrl + "/api/link/image/" + codeNo + "/first-reward.png");
|
||||||
imageLinks.put("midReward", appBaseUrl + "/api/link/" + codeNo + "/mid-reward.png");
|
imageLinks.put("midReward", appBaseUrl + "/api/link/image/" + codeNo + "/mid-reward.png");
|
||||||
imageLinks.put("endReward", appBaseUrl + "/api/link/" + codeNo + "/end-reward.png");
|
imageLinks.put("endReward", appBaseUrl + "/api/link/image/" + codeNo + "/end-reward.png");
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
return ResponseEntity.ok()
|
||||||
.cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES).cachePublic())
|
.cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES).cachePublic())
|
||||||
@@ -148,20 +187,22 @@ public class QrProxyController {
|
|||||||
// 构建响应对象
|
// 构建响应对象
|
||||||
GameInterfaceResponse response = new GameInterfaceResponse();
|
GameInterfaceResponse response = new GameInterfaceResponse();
|
||||||
response.setCodeNo(codeNo);
|
response.setCodeNo(codeNo);
|
||||||
|
response.setMachineId(linkTask.getMachineId());
|
||||||
response.setQuantity(linkBatch.getQuantity());
|
response.setQuantity(linkBatch.getQuantity());
|
||||||
response.setTimes(linkBatch.getTimes());
|
response.setTimes(linkBatch.getTimes());
|
||||||
response.setTotalPoints(linkBatch.getQuantity() * linkBatch.getTimes());
|
response.setTotalPoints(linkBatch.getQuantity() * linkBatch.getTimes());
|
||||||
|
response.setCompletedPoints(linkTask.getCompletedPoints());
|
||||||
|
|
||||||
// 设置游戏区域信息
|
// 设置游戏区域信息
|
||||||
response.setRegion(linkTask.getRegion());
|
response.setRegion(linkTask.getRegion());
|
||||||
response.setRegionDesc(getRegionDescription(linkTask.getRegion()));
|
response.setRegionDesc(getRegionDescription(linkTask.getRegion()));
|
||||||
|
|
||||||
// 设置图片链接
|
// 设置图片链接
|
||||||
response.setQrCodeUrl(appBaseUrl + "/api/link/" + codeNo + "/qr.png");
|
response.setQrCodeUrl(appBaseUrl + "/api/link/image/" + codeNo + "/qr.png");
|
||||||
response.setHomepageUrl(appBaseUrl + "/api/link/" + codeNo + "/homepage.png");
|
response.setHomepageUrl(appBaseUrl + "/api/link/image/" + codeNo + "/homepage.png");
|
||||||
response.setFirstRewardUrl(appBaseUrl + "/api/link/" + codeNo + "/first-reward.png");
|
response.setFirstRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/first-reward.png");
|
||||||
response.setMidRewardUrl(appBaseUrl + "/api/link/" + codeNo + "/mid-reward.png");
|
response.setMidRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/mid-reward.png");
|
||||||
response.setEndRewardUrl(appBaseUrl + "/api/link/" + codeNo + "/end-reward.png");
|
response.setEndRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/end-reward.png");
|
||||||
|
|
||||||
log.info("游戏界面数据构建完成: codeNo={}, totalPoints={}", codeNo, response.getTotalPoints());
|
log.info("游戏界面数据构建完成: codeNo={}, totalPoints={}", codeNo, response.getTotalPoints());
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
@Schema(description = "游戏界面数据")
|
@Schema(description = "游戏界面数据")
|
||||||
public class GameInterfaceResponse {
|
public class GameInterfaceResponse {
|
||||||
|
|
||||||
@Schema(description = "设备编号")
|
@Schema(description = "链接编号")
|
||||||
private String codeNo;
|
private String codeNo;
|
||||||
|
|
||||||
@Schema(description = "总点数 (quantity * times)")
|
@Schema(description = "总点数 (quantity * times)")
|
||||||
@@ -41,6 +41,12 @@ public class GameInterfaceResponse {
|
|||||||
@Schema(description = "结束赏金图片链接")
|
@Schema(description = "结束赏金图片链接")
|
||||||
private String endRewardUrl;
|
private String endRewardUrl;
|
||||||
|
|
||||||
|
@Schema(description = "机器编号")
|
||||||
|
private String machineId;
|
||||||
|
|
||||||
|
@Schema(description = "已经完成的点数")
|
||||||
|
private Integer completedPoints;
|
||||||
|
|
||||||
public String getCodeNo() {
|
public String getCodeNo() {
|
||||||
return codeNo;
|
return codeNo;
|
||||||
}
|
}
|
||||||
@@ -128,4 +134,20 @@ public class GameInterfaceResponse {
|
|||||||
public void setEndRewardUrl(String endRewardUrl) {
|
public void setEndRewardUrl(String endRewardUrl) {
|
||||||
this.endRewardUrl = endRewardUrl;
|
this.endRewardUrl = endRewardUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMachineId() {
|
||||||
|
return machineId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMachineId(String machineId) {
|
||||||
|
this.machineId = machineId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCompletedPoints() {
|
||||||
|
return completedPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompletedPoints(Integer completedPoints) {
|
||||||
|
this.completedPoints = completedPoints;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ public class SecurityConfig {
|
|||||||
.pathMatchers(HttpMethod.GET, "/api/link/poll-login").permitAll() // 用户端轮询登录接口,公开访问
|
.pathMatchers(HttpMethod.GET, "/api/link/poll-login").permitAll() // 用户端轮询登录接口,公开访问
|
||||||
.pathMatchers(HttpMethod.GET, "/api/link/qr/**").permitAll() // 二维码获取接口,公开访问
|
.pathMatchers(HttpMethod.GET, "/api/link/qr/**").permitAll() // 二维码获取接口,公开访问
|
||||||
.pathMatchers(HttpMethod.HEAD, "/api/link/qr/**").permitAll() // 二维码HEAD请求,公开访问
|
.pathMatchers(HttpMethod.HEAD, "/api/link/qr/**").permitAll() // 二维码HEAD请求,公开访问
|
||||||
|
.pathMatchers(HttpMethod.GET, "/api/link/image/**").permitAll() // 图片访问接口,公开访问
|
||||||
|
.pathMatchers(HttpMethod.HEAD, "/api/link/image/**").permitAll() // 图片HEAD请求,公开访问
|
||||||
.pathMatchers(HttpMethod.GET, "/api/link/*/game-interface").permitAll() // 游戏界面数据接口,公开访问
|
.pathMatchers(HttpMethod.GET, "/api/link/*/game-interface").permitAll() // 游戏界面数据接口,公开访问
|
||||||
.pathMatchers("/api/link/**").authenticated() // 其他链接接口需要认证
|
.pathMatchers("/api/link/**").authenticated() // 其他链接接口需要认证
|
||||||
.anyExchange().permitAll() // 其他接口后续再收紧
|
.anyExchange().permitAll() // 其他接口后续再收紧
|
||||||
@@ -72,6 +74,8 @@ public class SecurityConfig {
|
|||||||
log.info(" * GET /api/link/poll-login -> 允许所有 (用户端公开接口)");
|
log.info(" * GET /api/link/poll-login -> 允许所有 (用户端公开接口)");
|
||||||
log.info(" * GET /api/link/qr/** -> 允许所有 (二维码获取接口)");
|
log.info(" * GET /api/link/qr/** -> 允许所有 (二维码获取接口)");
|
||||||
log.info(" * HEAD /api/link/qr/** -> 允许所有 (二维码HEAD请求)");
|
log.info(" * HEAD /api/link/qr/** -> 允许所有 (二维码HEAD请求)");
|
||||||
|
log.info(" * GET /api/link/image/** -> 允许所有 (图片访问接口)");
|
||||||
|
log.info(" * HEAD /api/link/image/** -> 允许所有 (图片HEAD请求)");
|
||||||
log.info(" * GET /api/link/*/game-interface -> 允许所有 (游戏界面数据接口)");
|
log.info(" * GET /api/link/*/game-interface -> 允许所有 (游戏界面数据接口)");
|
||||||
log.info(" * /api/link/** -> 需要认证");
|
log.info(" * /api/link/** -> 需要认证");
|
||||||
log.info(" * 其他路径 -> 允许所有");
|
log.info(" * 其他路径 -> 允许所有");
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ public class ScriptClient {
|
|||||||
*/
|
*/
|
||||||
public String getProxyQrCodeUrl(String proxyCode) {
|
public String getProxyQrCodeUrl(String proxyCode) {
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
return String.format("%s/api/link/qr/%s?t=%d", appBaseUrl, proxyCode, timestamp);
|
return String.format("%s/api/link/image/%s/qr.png?t=%d", appBaseUrl, proxyCode, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ script:
|
|||||||
|
|
||||||
# 服务器配置
|
# 服务器配置
|
||||||
app:
|
app:
|
||||||
# base-url: "https://2.uzi0.cc" # 生产环境需要配置为实际域名
|
base-url: "https://2.uzi0.cc" # 生产环境需要配置为实际域名
|
||||||
base-url: "http://localhost:18080" # 本地测试环境
|
# base-url: "http://localhost:18080" # 本地测试环境
|
||||||
image-save-path: "./images" # 图片保存路径
|
image-save-path: "./images" # 图片保存路径
|
||||||
|
|
||||||
link:
|
link:
|
||||||
|
|||||||
Reference in New Issue
Block a user