feat(system): 新增方舟账号管理与任务接口

- 新增 MarkController 控制器,提供方舟任务列表获取和新建任务接口
- 实现 IMarkService 接口及 MarkServiceImpl 实现类,支持注册、登录和MD5加密功能
- 在 CacheConstants 中添加方舟账号 Redis key 常量
- 集成 RestTemplate用于调用方舟API,支持自动注册与登录机制- 添加文件上传支持,用于新建任务时提交文件
- 实现 token 失效自动重新登录逻辑,确保接口调用稳定性
This commit is contained in:
2025-10-30 13:55:07 +08:00
parent d0a930d4f2
commit 87a4a2fed0
16 changed files with 423 additions and 69 deletions

View File

@@ -0,0 +1,25 @@
package com.ruoyi.system.service;
/**
* 方舟Service接口
*/
public interface IMarkService {
/**
* 注册并保存到Redis
* @return token
*/
String reg() throws Exception;
/**
* MD5加密
* @param input 输入字符串
* @return MD5加密结果
*/
String md5(String input);
/**
* 登录
*/
String login();
}

View File

@@ -0,0 +1,123 @@
package com.ruoyi.system.service.impl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.system.service.IMarkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@Service
public class MarkServiceImpl implements IMarkService {
private static final String API_SECRET = "e10adc3949ba59abbe56e057f20f883e";
private final RestTemplate restTemplate = new RestTemplate();
private final ObjectMapper objectMapper = new ObjectMapper();
@Autowired
private RedisCache redisCache;
@Override
public String reg() throws Exception {
String randomAccount = generatePhoneNumber();
String password = "123456";
String d = String.format("{\"referrer_id\":0,\"domain\":\"user.fangzhoujingxuan.com\",\"customer\":\"\",\"account\":\"%s\",\"code\":\"\",\"password\":\"%s\"}", randomAccount, password);
long ts = System.currentTimeMillis();
String sign = md5(ts + d + API_SECRET);
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("c", "Register");
formData.add("d", d);
formData.add("s", sign);
formData.add("ts", String.valueOf(ts));
formData.add("website", "1");
formData.add("t", String.valueOf(ts + (int) (Math.random() * 1000)));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
String result = restTemplate.postForObject("https://api.fangzhoujingxuan.com/App", requestEntity, String.class);
JsonNode json = objectMapper.readTree(result);
int status = json.get("S").asInt();
if (status > 0) {
String token = json.get("D").get("key").asText();
Map<String, String> accountData = new HashMap<>();
accountData.put("account", randomAccount);
accountData.put("password", password);
accountData.put("token", token);
redisCache.setCacheMap(CacheConstants.MARK_ACCOUNT_KEY, accountData);
return token;
}
throw new RuntimeException("注册失败: " + json.get("M").asText());
}
@Override
public String login() {
try {
Map<String, String> accountData = redisCache.getCacheMap(CacheConstants.MARK_ACCOUNT_KEY);
String account = accountData.get("account");
String password = accountData.get("password");
String d = String.format("{\"account\":\"%s\",\"password\":\"%s\",\"domain\":\"user.fangzhoujingxuan.com\"}", account, password);
String ts = String.valueOf(System.currentTimeMillis());
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("c", "Login");
formData.add("d", d);
formData.add("s", md5(System.currentTimeMillis() + d + API_SECRET));
formData.add("ts", ts);
formData.add("website", "1");
formData.add("t", ts + (int) (Math.random() * 1000));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
String result = restTemplate.postForObject("https://api.fangzhoujingxuan.com/App", requestEntity, String.class);
JsonNode json = objectMapper.readTree( result);
String token = json.get("D").get("key").asText();
if( token !=null)redisCache.setCacheMapValue(CacheConstants.MARK_ACCOUNT_KEY, "token",token);
return token;
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* 生成11位手机号
*/
private String generatePhoneNumber() {
Random random = new Random();
String[] prefixes = {"130", "131", "132", "133", "134", "135", "136", "137", "138", "139", "150", "151", "152", "153", "155", "156", "157", "158", "159", "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", "170", "171", "172", "173", "174", "175", "176", "177", "178", "179"};
String prefix = prefixes[random.nextInt(prefixes.length)];
StringBuilder phoneNumber = new StringBuilder(prefix);
for (int i = 0; i < 8; i++) {
phoneNumber.append(random.nextInt(10));
}
return phoneNumber.toString();
}
@Override
public String md5(String input) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (Exception e) {
throw new RuntimeException("MD5加密失败", e);
}
}
}