fix: remove unreliable post-failure live-check; restrict REJECTED poll to HUAWEI

Post-failure live check called pollStoreSingleReviewState on submission
failure, but for MI/VIVO/OPPO/HONOR the poll returns APPROVED for ANY
live version (not version-specific). This caused false positives: if an
older version was live on Xiaomi, the poll would return APPROVED and
incorrectly mark the new submission as 已上线(直接上传).

Changes:
- Remove post-failure live check from executeSinglePlan and sequential
  failure handler — submission failures are just marked REJECTED
- Restrict the REJECTED-store poll to HUAWEI only, since it is the only
  store where pollStoreSingleReviewState is version-specific
  (compares onShelfVersionCode against v.getVersionCode())
- Log full VIVO data response to capture versionCode field name for
  future version-specific detection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
XuqmGroup 2026-05-18 17:52:53 +08:00
父节点 8d46d21726
当前提交 b3b33dbb7b

查看文件

@ -308,30 +308,12 @@ public class StoreSubmissionService {
} catch (Exception logEx) { } catch (Exception logEx) {
log.warn("Failed to record store event for {}/{}: {}", v.getAppKey(), storeType, logEx.getMessage()); log.warn("Failed to record store event for {}/{}: {}", v.getAppKey(), storeType, logEx.getMessage());
} }
boolean seqAlreadyLive = false;
try { try {
AppStoreConfigEntity liveCfg = configRepo storeService.updateStoreReview(versionId, storeType,
.findByAppKeyAndStoreType(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(storeType)) AppVersionEntity.StoreReviewState.REJECTED,
.orElse(null); message.length() > 500 ? message.substring(0, 500) : message);
if (liveCfg != null && liveCfg.isEnabled()) {
Map<String, String> liveCreds = parseConfig(liveCfg.getConfigJson());
AppVersionEntity.StoreReviewState liveState = pollStoreSingleReviewState(storeType, v, liveCreds);
seqAlreadyLive = (liveState == AppVersionEntity.StoreReviewState.APPROVED);
}
} catch (Exception pollEx) {
log.debug("Post-failure live-check for {}/{} failed: {}", storeType, versionId, pollEx.getMessage());
}
try {
if (seqAlreadyLive) {
storeService.updateStoreReviewLive(versionId, storeType, true,
"版本已在应用商店上线(提交时检测到,可能为直接上传)");
} else {
storeService.updateStoreReview(versionId, storeType,
AppVersionEntity.StoreReviewState.REJECTED,
message.length() > 500 ? message.substring(0, 500) : message);
}
} catch (Exception ex) { } catch (Exception ex) {
log.warn("Failed to persist rejection/live-status for {}/{} batchId={}: {}", log.warn("Failed to persist rejection for {}/{} batchId={}: {}",
v.getAppKey(), storeType, batchId, ex.getMessage(), ex); v.getAppKey(), storeType, batchId, ex.getMessage(), ex);
} }
})); }));
@ -423,9 +405,13 @@ public class StoreSubmissionService {
log.debug("Store review poll: {}/{} still UNDER_REVIEW", v.getId(), storeType); log.debug("Store review poll: {}/{} still UNDER_REVIEW", v.getId(), storeType);
} }
} else { } else {
// REJECTED store check if it's actually live (pre-existing direct upload) // REJECTED store check if the specific submitted versionCode is now live.
if (polled == AppVersionEntity.StoreReviewState.APPROVED) { // Only HUAWEI has a reliable version-specific check (compares onShelfVersionCode).
log.info("Store review poll: {}/{} was REJECTED but is now live on store — marking pre-existing", v.getId(), storeType); // Other store polls return the live status for ANY version, so we can't trust
// their APPROVED result here without risking false positives (e.g. an older
// version is live but we'd incorrectly mark the new submission as pre-existing).
if (polled == AppVersionEntity.StoreReviewState.APPROVED && "HUAWEI".equals(storeType)) {
log.info("Store review poll: {}/{} was REJECTED but Huawei confirms this versionCode is on-shelf — marking pre-existing", v.getId(), storeType);
storeService.updateStoreReviewLive(v.getId(), storeType, true, storeService.updateStoreReviewLive(v.getId(), storeType, true,
"版本已在应用商店上线(提交失败但检测到相同版本已上线,可能为直接上传)"); "版本已在应用商店上线(提交失败但检测到相同版本已上线,可能为直接上传)");
} }
@ -452,7 +438,7 @@ public class StoreSubmissionService {
com.fasterxml.jackson.databind.JsonNode root = mapper.readTree(Objects.requireNonNull(resp.getBody())); com.fasterxml.jackson.databind.JsonNode root = mapper.readTree(Objects.requireNonNull(resp.getBody()));
// VIVO data.status: 1=待审核, 2=审核中, 3=已上线(审核通过), 4=审核驳回, 5=已下架 // VIVO data.status: 1=待审核, 2=审核中, 3=已上线(审核通过), 4=审核驳回, 5=已下架
int status = root.path("data").path("status").asInt(-1); int status = root.path("data").path("status").asInt(-1);
log.info("VIVO poll status={} for version={}", status, v.getId()); log.info("VIVO poll status={} data={} for version={}", status, root.path("data"), v.getId());
yield switch (status) { yield switch (status) {
case 3 -> AppVersionEntity.StoreReviewState.APPROVED; case 3 -> AppVersionEntity.StoreReviewState.APPROVED;
case 4 -> AppVersionEntity.StoreReviewState.REJECTED; case 4 -> AppVersionEntity.StoreReviewState.REJECTED;
@ -671,30 +657,12 @@ public class StoreSubmissionService {
} catch (Exception logEx) { } catch (Exception logEx) {
log.warn("Failed to record store event for {}/{}: {}", v.getAppKey(), plan.storeType, logEx.getMessage()); log.warn("Failed to record store event for {}/{}: {}", v.getAppKey(), plan.storeType, logEx.getMessage());
} }
boolean alreadyLive = false;
try { try {
AppStoreConfigEntity liveCfg = configRepo storeService.updateStoreReview(versionId, plan.storeType,
.findByAppKeyAndStoreType(v.getAppKey(), AppStoreConfigEntity.StoreType.valueOf(plan.storeType)) AppVersionEntity.StoreReviewState.REJECTED,
.orElse(null); message.length() > 500 ? message.substring(0, 500) : message);
if (liveCfg != null && liveCfg.isEnabled()) {
Map<String, String> liveCreds = parseConfig(liveCfg.getConfigJson());
AppVersionEntity.StoreReviewState liveState = pollStoreSingleReviewState(plan.storeType, v, liveCreds);
alreadyLive = (liveState == AppVersionEntity.StoreReviewState.APPROVED);
}
} catch (Exception pollEx) {
log.debug("Post-failure live-check for {}/{} failed: {}", plan.storeType, versionId, pollEx.getMessage());
}
try {
if (alreadyLive) {
storeService.updateStoreReviewLive(versionId, plan.storeType, true,
"版本已在应用商店上线(提交时检测到,可能为直接上传)");
} else {
storeService.updateStoreReview(versionId, plan.storeType,
AppVersionEntity.StoreReviewState.REJECTED,
message.length() > 500 ? message.substring(0, 500) : message);
}
} catch (Exception ex) { } catch (Exception ex) {
log.warn("Failed to persist rejection/live-status for {}/{} batchId={}: {}", log.warn("Failed to persist rejection for {}/{} batchId={}: {}",
v.getAppKey(), plan.storeType, batchId, ex.getMessage(), ex); v.getAppKey(), plan.storeType, batchId, ex.getMessage(), ex);
} }
} }