|
|
@@ -47,8 +47,8 @@ public class KaoshixingService {
|
|
|
private static final String ACTION_ID_LOGIN = "201";
|
|
|
// 查询考生信息 action_id
|
|
|
private static final String ACTION_ID_QUERY_USER = "209";
|
|
|
- // JWT过期时间(30秒,考虑网络延迟)
|
|
|
- private static final long EXPIRATION_SECONDS = 30L;
|
|
|
+ // JWT过期时间(5分钟,确保在高延迟网络下依然有效)
|
|
|
+ private static final long EXPIRATION_SECONDS = 300L;
|
|
|
|
|
|
// 固定的 appId / appKey(按需求写死)
|
|
|
private static final String FIXED_APP_ID = "631088";
|
|
|
@@ -113,18 +113,108 @@ public class KaoshixingService {
|
|
|
return sendPostRequest(requestUrl, requestBody);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 免注册登录:始终使用考生登录(201)
|
|
|
- */
|
|
|
public String fetchAutoLogin(KaoshixingAutoLoginRequest req) {
|
|
|
- // 始终走 201:由考试星侧完成已存在用户登录或首次注册后登录
|
|
|
+ validateAutoLoginParams(req);
|
|
|
+
|
|
|
+ // 直接执行 201:由考试星侧完成已存在用户登录或首次注册后登录
|
|
|
String loginJwt = generateJwt(FIXED_APP_KEY, ACTION_ID_LOGIN);
|
|
|
String loginUrl = String.format("%s%s/?jwt=%s", BASE_API_URL, FIXED_APP_ID, loginJwt);
|
|
|
String loginBody = buildLoginBody(req);
|
|
|
- log.info("考生登录(201)请求体:{}", loginBody);
|
|
|
+
|
|
|
+ log.info("直接发起考试星登录(201)请求,请求体:{}", loginBody);
|
|
|
return sendPostRequest(loginUrl, loginBody);
|
|
|
}
|
|
|
|
|
|
+ private String queryUser(KaoshixingAutoLoginRequest req) {
|
|
|
+ String jwtInfo = generateJwt(FIXED_APP_KEY, ACTION_ID_QUERY_USER);
|
|
|
+ String requestUrl = String.format("%s%s/?jwt=%s", BASE_API_URL, FIXED_APP_ID, jwtInfo);
|
|
|
+
|
|
|
+ Map<String, Object> payload = new HashMap<>();
|
|
|
+ payload.put("user_id", req.getUserId());
|
|
|
+
|
|
|
+ try {
|
|
|
+ String requestBody = objectMapper.writeValueAsString(payload);
|
|
|
+ log.info("查询考生(209)请求体:{}", requestBody);
|
|
|
+ return sendPostRequest(requestUrl, requestBody);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("构造209请求失败:" + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String buildSilentLoginBody(KaoshixingAutoLoginRequest req) {
|
|
|
+ try {
|
|
|
+ Map<String, Object> payload = new HashMap<>();
|
|
|
+ payload.put("user_id", req.getUserId());
|
|
|
+ if (!isBlank(req.getCustomUrl())) {
|
|
|
+ payload.put("custom_url", req.getCustomUrl());
|
|
|
+ }
|
|
|
+ return objectMapper.writeValueAsString(payload);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new RuntimeException("构造203请求体失败:" + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isUserExists(String resp) {
|
|
|
+ try {
|
|
|
+ JsonNode root = objectMapper.readTree(resp);
|
|
|
+ int code = root.path("code").asInt();
|
|
|
+ if (code != 10000) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ JsonNode data = root.path("data");
|
|
|
+ if (data.isMissingNode() || data.isNull()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data.isArray()) {
|
|
|
+ return data.size() > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return !data.isEmpty();
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("判断209是否存在用户失败", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private boolean isUserNotExists(String resp) {
|
|
|
+ try {
|
|
|
+ JsonNode root = objectMapper.readTree(resp);
|
|
|
+ int code = root.path("code").asInt();
|
|
|
+
|
|
|
+ if (code == 10000) {
|
|
|
+ JsonNode data = root.path("data");
|
|
|
+ if (data.isMissingNode() || data.isNull()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (data.isArray()) {
|
|
|
+ return data.isEmpty();
|
|
|
+ }
|
|
|
+ return data.isEmpty();
|
|
|
+ }
|
|
|
+
|
|
|
+ String msg = root.path("msg").asText("");
|
|
|
+ return msg.contains("不存在") || msg.contains("未找到") || msg.contains("无此用户");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("判断209是否为不存在用户失败", e);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateAutoLoginParams(KaoshixingAutoLoginRequest req) {
|
|
|
+ if (req == null || isBlank(req.getUserId())) {
|
|
|
+ throw new RuntimeException("user_id不能为空");
|
|
|
+ }
|
|
|
+ if (isBlank(req.getUserName())) {
|
|
|
+ req.setUserName("学员");
|
|
|
+ }
|
|
|
+ if (isBlank(req.getDepartment())) {
|
|
|
+ req.setDepartment("学员");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取考生可见考试和考试结果整合列表(action_id=702)
|
|
|
*/
|
|
|
@@ -204,12 +294,13 @@ public class KaoshixingService {
|
|
|
String jwt = Jwts.builder()
|
|
|
.claim("exp", expTimeMillis) // 考试星要求毫秒级时间戳,不是JWT标准的秒级
|
|
|
.claim("action_id", actionId)
|
|
|
+ .claim("app_id", FIXED_APP_ID)
|
|
|
.signWith(
|
|
|
SignatureAlgorithm.HS256,
|
|
|
appKey.getBytes(StandardCharsets.UTF_8)
|
|
|
)
|
|
|
.compact();
|
|
|
-
|
|
|
+
|
|
|
log.info("生成的JWT: {}", jwt);
|
|
|
return jwt;
|
|
|
}
|
|
|
@@ -328,6 +419,7 @@ public class KaoshixingService {
|
|
|
payload.put("user_id", req.getUserId());
|
|
|
payload.put("user_name", req.getUserName());
|
|
|
payload.put("department", req.getDepartment());
|
|
|
+ payload.put("app_id", FIXED_APP_ID);
|
|
|
if (!isBlank(req.getCustomUrl())) {
|
|
|
payload.put("custom_url", req.getCustomUrl());
|
|
|
}
|