比较提交

..

没有共同的提交。8f2f29170ec1e08207d863409f9698d38903b646 和 1a0ef7d8861b3ba238d23dcf8ab0d009d90447e8 的历史完全不同。

共有 3 个文件被更改,包括 27 次插入86 次删除

查看文件

@ -180,24 +180,13 @@ public class AppController {
* Used by the security center to verify license file information. * Used by the security center to verify license file information.
*/ */
@PostMapping("/license/parse") @PostMapping("/license/parse")
public ResponseEntity<ApiResponse<Map<String, Object>>> parseLicenseFile( public ResponseEntity<ApiResponse<Map<String, Object>>> parseLicenseFile(@RequestBody Map<String, String> body) {
@RequestBody Map<String, String> body,
@AuthenticationPrincipal String tenantId) {
String content = body.get("content"); String content = body.get("content");
if (content == null || content.isBlank()) { if (content == null || content.isBlank()) {
throw new BusinessException("License file content is required"); throw new BusinessException("License file content is required");
} }
try { try {
LicenseFileCrypto.LicensePayload payload = LicenseFileCrypto.decrypt(content.trim()); LicenseFileCrypto.LicensePayload payload = LicenseFileCrypto.decrypt(content.trim());
// Verify the license file belongs to the current tenant
try {
appService.getByAppKey(payload.appKey(), tenantId);
} catch (BusinessException e) {
if (e.getCode() == 403 || e.getCode() == 404) {
throw new BusinessException(403, "权限不足无法展示");
}
throw e;
}
Map<String, Object> data = new java.util.LinkedHashMap<>(); Map<String, Object> data = new java.util.LinkedHashMap<>();
data.put("appKey", payload.appKey()); data.put("appKey", payload.appKey());
data.put("appName", payload.appName()); data.put("appName", payload.appName());
@ -207,8 +196,6 @@ public class AppController {
data.put("baseUrl", payload.baseUrl()); data.put("baseUrl", payload.baseUrl());
data.put("serverUrl", payload.serverUrl()); data.put("serverUrl", payload.serverUrl());
return ResponseEntity.ok(ApiResponse.success(data)); return ResponseEntity.ok(ApiResponse.success(data));
} catch (BusinessException e) {
throw e;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new BusinessException("Invalid license file: " + e.getMessage()); throw new BusinessException("Invalid license file: " + e.getMessage());
} catch (Exception e) { } catch (Exception e) {

查看文件

@ -71,7 +71,7 @@ public class AppStoreService {
boolean enabled) { boolean enabled) {
boolean isCreate = configRepo.findTopByAppKeyAndStoreTypeOrderByUpdatedAtDesc(appKey, storeType).isEmpty(); boolean isCreate = configRepo.findTopByAppKeyAndStoreTypeOrderByUpdatedAtDesc(appKey, storeType).isEmpty();
AppStoreConfigEntity entity = configRepo AppStoreConfigEntity entity = configRepo
.findTopByAppKeyAndStoreTypeOrderByUpdatedAtDesc(appKey, storeType) .findByAppKeyAndStoreType(appKey, storeType)
.orElseGet(AppStoreConfigEntity::new); .orElseGet(AppStoreConfigEntity::new);
if (entity.getId() == null) { if (entity.getId() == null) {

查看文件

@ -200,7 +200,7 @@ public class StoreSubmissionService {
// no stale webhooks or poll cycles can trigger auto-publish from the old review. // no stale webhooks or poll cycles can trigger auto-publish from the old review.
if ("WITHDRAWN".equals(activeState)) { if ("WITHDRAWN".equals(activeState)) {
AppStoreConfigEntity withdrawCfg = configRepo AppStoreConfigEntity withdrawCfg = configRepo
.findTopByAppKeyAndStoreTypeOrderByUpdatedAtDesc(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(storeType)) .findByAppKeyAndStoreType(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(storeType))
.orElse(null); .orElse(null);
if (withdrawCfg != null && withdrawCfg.isEnabled()) { if (withdrawCfg != null && withdrawCfg.isEnabled()) {
try { try {
@ -220,7 +220,7 @@ public class StoreSubmissionService {
} }
AppStoreConfigEntity cfg = configRepo AppStoreConfigEntity cfg = configRepo
.findTopByAppKeyAndStoreTypeOrderByUpdatedAtDesc(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(storeType)) .findByAppKeyAndStoreType(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(storeType))
.orElse(null); .orElse(null);
if (cfg == null || !cfg.isEnabled()) { if (cfg == null || !cfg.isEnabled()) {
skippedCount.incrementAndGet(); skippedCount.incrementAndGet();
@ -432,16 +432,8 @@ public class StoreSubmissionService {
state.setCanSubmit(false); state.setCanSubmit(false);
state.setBlockReason("查询失败,不能确认状态"); state.setBlockReason("查询失败,不能确认状态");
} else if (!state.getOnlineVersionCode().isBlank() && !submittedCode.equals(state.getOnlineVersionCode())) { } else if (!state.getOnlineVersionCode().isBlank() && !submittedCode.equals(state.getOnlineVersionCode())) {
int cmp = compareVersionCodes(state.getOnlineVersionCode(), submittedCode);
if (cmp > 0) {
state.setNonCurrentRelease(true); state.setNonCurrentRelease(true);
state.setCanSubmit(false);
state.setBlockReason("应用商店已有更高版本上线,禁止提交更低版本");
} else {
// onlineVersionCode < submittedCode: normal new release, allow submit
state.setNonCurrentRelease(false);
state.setCanSubmit(true); state.setCanSubmit(true);
}
} else { } else {
state.setCanSubmit(true); state.setCanSubmit(true);
} }
@ -512,7 +504,7 @@ public class StoreSubmissionService {
reviewState, reviewState,
onShelfName, onShelfCode, onShelfName, onShelfCode,
versionName, versionCode, versionName, versionCode,
isLive, !isLive && !onShelfCode.isBlank() && compareVersionCodes(onShelfCode, submittedCode) > 0, isLive, !isLive && !onShelfCode.isBlank(),
true, "", sanitizeJson(resp.getBody())); true, "", sanitizeJson(resp.getBody()));
} }
@ -531,7 +523,7 @@ public class StoreSubmissionService {
// Only treat as live for the CURRENT submission when onlineVersionCode matches submittedCode. // Only treat as live for the CURRENT submission when onlineVersionCode matches submittedCode.
boolean currentSubmissionLive = submittedCode.equals(onlineVersionCode) && !submittedCode.isBlank(); boolean currentSubmissionLive = submittedCode.equals(onlineVersionCode) && !submittedCode.isBlank();
boolean hasOnlineVersion = updateVersion || !onlineVersionCode.isBlank(); boolean hasOnlineVersion = updateVersion || !onlineVersionCode.isBlank();
boolean nonCurrentRelease = hasOnlineVersion && !currentSubmissionLive && compareVersionCodes(onlineVersionCode, submittedCode) > 0; boolean nonCurrentRelease = hasOnlineVersion && !currentSubmissionLive;
StoreRemoteState.ReviewState reviewState; StoreRemoteState.ReviewState reviewState;
if (appStatus == 5 && currentSubmissionLive) { if (appStatus == 5 && currentSubmissionLive) {
reviewState = StoreRemoteState.ReviewState.REJECTED; reviewState = StoreRemoteState.ReviewState.REJECTED;
@ -575,15 +567,13 @@ public class StoreSubmissionService {
} }
log.info("OPPO remote state: versionId={} auditInt={} onlineCode={} submittedCode={} reviewState={}", log.info("OPPO remote state: versionId={} auditInt={} onlineCode={} submittedCode={} reviewState={}",
v.getId(), auditInt, onlineVersionCode, submittedCode, reviewState); v.getId(), auditInt, onlineVersionCode, submittedCode, reviewState);
boolean currentSubmissionLive = isLive && submittedCode.equals(onlineVersionCode);
boolean nonCurrentRelease = isLive && !submittedCode.equals(onlineVersionCode) && compareVersionCodes(onlineVersionCode, submittedCode) > 0;
return StoreRemoteState.ok( return StoreRemoteState.ok(
AppStoreConfigEntity.StoreType.OPPO, AppStoreConfigEntity.StoreType.OPPO,
reviewState, reviewState,
onlineVersionName, onlineVersionCode, onlineVersionName, onlineVersionCode,
"", "", "", "",
currentSubmissionLive, isLive && submittedCode.equals(onlineVersionCode),
nonCurrentRelease, isLive && !submittedCode.equals(onlineVersionCode),
true, "", sanitizeJson(appData)); true, "", sanitizeJson(appData));
} }
@ -621,7 +611,7 @@ public class StoreSubmissionService {
reviewState = StoreRemoteState.ReviewState.UNKNOWN; reviewState = StoreRemoteState.ReviewState.UNKNOWN;
} }
boolean currentSubmissionLive = isLive && submittedCode.equals(onlineVersionCode); boolean currentSubmissionLive = isLive && submittedCode.equals(onlineVersionCode);
boolean nonCurrentRelease = isLive && !submittedCode.equals(onlineVersionCode) && compareVersionCodes(onlineVersionCode, submittedCode) > 0; boolean nonCurrentRelease = isLive && !submittedCode.equals(onlineVersionCode);
log.info("VIVO remote state queried: versionId={} submittedCode={} onlineVersionCode={} onlineVersionName={} status={} reviewState={} currentSubmissionLive={} nonCurrentRelease={}", log.info("VIVO remote state queried: versionId={} submittedCode={} onlineVersionCode={} onlineVersionName={} status={} reviewState={} currentSubmissionLive={} nonCurrentRelease={}",
v.getId(), submittedCode, onlineVersionCode, onlineVersionName, status, reviewState, currentSubmissionLive, nonCurrentRelease); v.getId(), submittedCode, onlineVersionCode, onlineVersionName, status, reviewState, currentSubmissionLive, nonCurrentRelease);
StoreRemoteState state = StoreRemoteState.ok( StoreRemoteState state = StoreRemoteState.ok(
@ -664,15 +654,13 @@ public class StoreSubmissionService {
} else { } else {
reviewState = StoreRemoteState.ReviewState.UNKNOWN; reviewState = StoreRemoteState.ReviewState.UNKNOWN;
} }
boolean currentSubmissionLive = isLive && submittedCode.equals(onlineVersionCode);
boolean nonCurrentRelease = isLive && !submittedCode.equals(onlineVersionCode) && compareVersionCodes(onlineVersionCode, submittedCode) > 0;
return StoreRemoteState.ok( return StoreRemoteState.ok(
AppStoreConfigEntity.StoreType.HONOR, AppStoreConfigEntity.StoreType.HONOR,
reviewState, reviewState,
onlineVersionName, onlineVersionCode, onlineVersionName, onlineVersionCode,
"", "", "", "",
currentSubmissionLive, isLive && submittedCode.equals(onlineVersionCode),
nonCurrentRelease, isLive && !submittedCode.equals(onlineVersionCode),
true, "", sanitizeJson(body)); true, "", sanitizeJson(body));
} }
@ -722,14 +710,8 @@ public class StoreSubmissionService {
if (mappedState != AppVersionEntity.StoreReviewState.UNDER_REVIEW) { if (mappedState != AppVersionEntity.StoreReviewState.UNDER_REVIEW) {
log.info("Store review poll: {}/{} status changed to {}", v.getId(), storeType, mappedState); log.info("Store review poll: {}/{} status changed to {}", v.getId(), storeType, mappedState);
if (mappedState == AppVersionEntity.StoreReviewState.APPROVED) { if (mappedState == AppVersionEntity.StoreReviewState.APPROVED) {
int cmp = compareVersionCodes(polled.getOnlineVersionCode(), String.valueOf(v.getVersionCode()));
if (polled.isCurrentSubmissionLive() || cmp >= 0) {
storeService.updateStoreReviewLive(v.getId(), storeType, !polled.isCurrentSubmissionLive(), storeService.updateStoreReviewLive(v.getId(), storeType, !polled.isCurrentSubmissionLive(),
buildLiveReason(polled), buildExtra(polled)); buildLiveReason(polled), buildExtra(polled));
} else {
log.debug("Store review poll: {}/{} online {} < submitted {} — keeping current state",
v.getId(), storeType, polled.getOnlineVersionCode(), v.getVersionCode());
}
} else { } else {
storeService.updateStoreReview(v.getId(), storeType, mappedState, "厂商审核状态轮询检测"); storeService.updateStoreReview(v.getId(), storeType, mappedState, "厂商审核状态轮询检测");
} }
@ -738,17 +720,11 @@ public class StoreSubmissionService {
} }
} else { } else {
if (polled.getReviewState() == StoreRemoteState.ReviewState.ONLINE) { if (polled.getReviewState() == StoreRemoteState.ReviewState.ONLINE) {
int cmp = compareVersionCodes(polled.getOnlineVersionCode(), String.valueOf(v.getVersionCode()));
if (cmp >= 0) {
log.info("Store review poll: {}/{} was REJECTED but store has live version currentSubmissionLive={} nonCurrentRelease={} liveVersionName={} liveVersionCode={}", log.info("Store review poll: {}/{} was REJECTED but store has live version currentSubmissionLive={} nonCurrentRelease={} liveVersionName={} liveVersionCode={}",
v.getId(), storeType, polled.isCurrentSubmissionLive(), polled.isNonCurrentRelease(), v.getId(), storeType, polled.isCurrentSubmissionLive(), polled.isNonCurrentRelease(),
polled.getOnlineVersionName(), polled.getOnlineVersionCode()); polled.getOnlineVersionName(), polled.getOnlineVersionCode());
storeService.updateStoreReviewLive(v.getId(), storeType, !polled.isCurrentSubmissionLive(), storeService.updateStoreReviewLive(v.getId(), storeType, !polled.isCurrentSubmissionLive(),
buildLiveReason(polled), buildExtra(polled)); buildLiveReason(polled), buildExtra(polled));
} else {
log.debug("Store review poll: {}/{} was REJECTED but online {} < submitted {} — not marking pre-existing",
v.getId(), storeType, polled.getOnlineVersionCode(), v.getVersionCode());
}
} else if ("MI".equals(storeType) } else if ("MI".equals(storeType)
&& polled.getReviewState() == StoreRemoteState.ReviewState.UNDER_REVIEW_XIAOMI) { && polled.getReviewState() == StoreRemoteState.ReviewState.UNDER_REVIEW_XIAOMI) {
log.info("Store review poll: {}/{} was REJECTED but Xiaomi has no current-version reject signal — restoring UNDER_REVIEW", log.info("Store review poll: {}/{} was REJECTED but Xiaomi has no current-version reject signal — restoring UNDER_REVIEW",
@ -849,19 +825,11 @@ public class StoreSubmissionService {
buildLiveReason(polled), buildExtra(polled)); buildLiveReason(polled), buildExtra(polled));
} else if (!isApproved) { } else if (!isApproved) {
// Store has a different live version (preExisting) and we didn't have APPROVED yet. // Store has a different live version (preExisting) and we didn't have APPROVED yet.
// Only mark as pre-existing when the online version is >= submitted version. // Mark as pre-existing live so UI shows which version is actually on the store.
// If online < submitted, this is a normal new-release scenario do not write
// APPROVED+nonCurrentRelease which would block the submission UI.
int cmp = compareVersionCodes(polled.getOnlineVersionCode(), String.valueOf(v.getVersionCode()));
if (cmp >= 0) {
log.info("Manual refresh: {}/{} pre-existing live detected currentSubmissionLive={} liveVersionCode={}", log.info("Manual refresh: {}/{} pre-existing live detected currentSubmissionLive={} liveVersionCode={}",
v.getId(), storeType, false, polled.getOnlineVersionCode()); v.getId(), storeType, false, polled.getOnlineVersionCode());
storeService.updateStoreReviewLive(v.getId(), storeType, true, storeService.updateStoreReviewLive(v.getId(), storeType, true,
buildLiveReason(polled), buildExtra(polled)); buildLiveReason(polled), buildExtra(polled));
} else {
log.info("Manual refresh: {}/{} online version {} < submitted {} — normal new release, skipping pre-existing mark",
v.getId(), storeType, polled.getOnlineVersionCode(), v.getVersionCode());
}
} else { } else {
// Already APPROVED (from webhook): version approved but pending distribution. // Already APPROVED (from webhook): version approved but pending distribution.
// Do NOT overwrite with nonCurrentRelease=true that would show a misleading // Do NOT overwrite with nonCurrentRelease=true that would show a misleading
@ -1584,7 +1552,7 @@ public class StoreSubmissionService {
for (String storeType : targets) { for (String storeType : targets) {
try { try {
AppStoreConfigEntity cfg = configRepo AppStoreConfigEntity cfg = configRepo
.findTopByAppKeyAndStoreTypeOrderByUpdatedAtDesc(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(storeType)) .findByAppKeyAndStoreType(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(storeType))
.orElse(null); .orElse(null);
if (cfg != null && cfg.isEnabled()) { if (cfg != null && cfg.isEnabled()) {
try { try {
@ -1787,7 +1755,7 @@ public class StoreSubmissionService {
// Try to call HUAWEI API to update release plan if token available // Try to call HUAWEI API to update release plan if token available
try { try {
AppStoreConfigEntity cfg = configRepo AppStoreConfigEntity cfg = configRepo
.findTopByAppKeyAndStoreTypeOrderByUpdatedAtDesc(v.getAppKey(), AppStoreConfigEntity.StoreType.HUAWEI) .findByAppKeyAndStoreType(v.getAppKey(), AppStoreConfigEntity.StoreType.HUAWEI)
.orElse(null); .orElse(null);
if (cfg != null && cfg.isEnabled()) { if (cfg != null && cfg.isEnabled()) {
Map<String, String> creds = parseConfig(cfg.getConfigJson()); Map<String, String> creds = parseConfig(cfg.getConfigJson());
@ -2671,18 +2639,4 @@ public class StoreSubmissionService {
String full = root.getClass().getSimpleName() + ": " + message; String full = root.getClass().getSimpleName() + ": " + message;
return full.length() > 900 ? full.substring(0, 900) + "..." : full; return full.length() > 900 ? full.substring(0, 900) + "..." : full;
} }
/**
* Compare two version-code strings numerically.
* @return positive if online > submitted, negative if online < submitted, 0 if equal or unparseable.
*/
private static int compareVersionCodes(String onlineCode, String submittedCode) {
try {
int online = Integer.parseInt(onlineCode.trim());
int submitted = Integer.parseInt(submittedCode.trim());
return Integer.compare(online, submitted);
} catch (NumberFormatException | NullPointerException e) {
return 0;
}
}
} }