From aa70d1c9c64737752f538ecfd2d14c9afa936c18 Mon Sep 17 00:00:00 2001 From: XXhaos Date: Tue, 2 Jun 2026 19:18:03 +0900 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20Scripts/NewAddToCart=5FWeb?= =?UTF-8?q?.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Scripts/NewAddToCart_Web.js | 146 ++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 7 deletions(-) diff --git a/Scripts/NewAddToCart_Web.js b/Scripts/NewAddToCart_Web.js index c179f7d..085eea5 100644 --- a/Scripts/NewAddToCart_Web.js +++ b/Scripts/NewAddToCart_Web.js @@ -72,6 +72,131 @@ const HEADERS = { "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1" }; +const normId = v => String(v ?? "").trim().toUpperCase(); +const arr = v => Array.isArray(v) ? v : []; + +function parseJsonBody(raw) { + if (raw && typeof raw === "object") return { ok: true, value: raw }; + try { + return { ok: true, value: JSON.parse(String(raw || "{}")) }; + } catch (e) { + return { ok: false, error: String(e) }; + } +} + +function getStatusCode(response) { + return Number(response && (response.status || response.statusCode)) || 0; +} + +function collectLineItems(cart) { + const out = []; + const addItems = items => { + for (const item of arr(items)) { + if (item && typeof item === "object") out.push(item); + } + }; + + addItems(cart && cart.lineItems); + addItems(cart && cart.bundleLineItems); + + for (const bundle of arr(cart && cart.bundleLineItems)) { + addItems(bundle && bundle.lineItems); + addItems(bundle && bundle.items); + } + + return out; +} + +function collectBusinessErrors(payload) { + const events = payload && payload.events; + if (!events || typeof events !== "object") return []; + + const found = []; + const visit = (section, value) => { + if (Array.isArray(value)) { + for (const event of value) visit(section, event); + return; + } + if (!value || typeof value !== "object") return; + + const data = value.data || {}; + const status = Number(data.httpStatusCode || value.httpStatusCode || 0); + const type = String(value.type || value.severity || "").toLowerCase(); + if (type === "error" || status >= 400) { + found.push({ section, event: value }); + return; + } + + for (const key of Object.keys(value)) { + if (Array.isArray(value[key])) visit(`${section}.${key}`, value[key]); + } + }; + + for (const key of Object.keys(events)) visit(key, events[key]); + return found; +} + +function formatBusinessError(item) { + const event = item.event || {}; + const data = event.data || {}; + const parts = []; + if (item.section) parts.push(item.section); + if (event.provider) parts.push(`provider=${event.provider}`); + if (event.code) parts.push(`code=${event.code}`); + if (data.reason) parts.push(`reason=${data.reason}`); + if (Array.isArray(data.subReasons) && data.subReasons.length) { + parts.push(`sub=${data.subReasons.filter(Boolean).join(" / ")}`); + } + if (data.httpStatusCode) parts.push(`http=${data.httpStatusCode}`); + return parts.join(", ") || "unknown business error"; +} + +function validateAddResult(rawBody, target) { + const parsed = parseJsonBody(rawBody); + if (!parsed.ok) { + return { ok: false, reason: `响应不是合法 JSON: ${parsed.error}` }; + } + + const payload = parsed.value || {}; + const cart = payload.cart || {}; + const market = cart.market ? String(cart.market).toUpperCase() : ""; + const language = cart.language ? String(cart.language).toLowerCase() : ""; + const contextProblems = []; + + if (market && market !== MARKET) contextProblems.push(`market=${cart.market}`); + if (language && language !== LOCALE.toLowerCase()) contextProblems.push(`language=${cart.language}`); + + const errors = collectBusinessErrors(payload); + const lineItems = collectLineItems(cart); + const matchedLine = lineItems.find(item => + normId(item.productId) === normId(target.productId) && + normId(item.skuId) === normId(target.skuId) && + normId(item.availabilityId) === normId(target.availabilityId) + ); + + if (errors.length > 0) { + const detail = errors.map(formatBusinessError).join(" | "); + const context = contextProblems.length ? ` | context: ${contextProblems.join(", ")}` : ""; + return { ok: false, reason: `${detail}${context} | lineItems=${lineItems.length}` }; + } + + if (contextProblems.length > 0) { + return { ok: false, reason: `购物车上下文不匹配: ${contextProblems.join(", ")} | lineItems=${lineItems.length}` }; + } + + if (!matchedLine) { + return { + ok: false, + reason: `HTTP 200 但未在 cart.lineItems 找到目标商品 | lineItems=${lineItems.length} | cartId=${cart.id || ""}` + }; + } + + const title = matchedLine.title ? ` | ${matchedLine.title}` : ""; + const qty = matchedLine.quantity ? ` | qty=${matchedLine.quantity}` : ""; + const amount = matchedLine.totalAmount ? ` | amount=${matchedLine.totalAmount}` : ""; + return { ok: true, detail: `${cart.language || ""}/${cart.market || ""}${title}${qty}${amount}` }; +} + function finalizeAndClean() { const successCount = results.success.length; const failureCount = results.failure.length; @@ -221,20 +346,27 @@ function sendRequest() { itemsToAdd: { items: [{ productId, skuId, availabilityId, campaignId: "xboxcomct", quantity: 1 }] } }; - $httpClient.put({ url: API_URL, headers: HEADERS, body: JSON.stringify(bodyObj) }, (error, response) => { + $httpClient.put({ url: API_URL, headers: HEADERS, body: JSON.stringify(bodyObj) }, (error, response, data) => { const idStr = `${productId}`; // 显示标签(序号+游戏名)和现价,取不到时回退到 bigId const priceNGN = (_remoteGroupRaw && key && _remoteGroupRaw[key]?.PriceNGN) ? ` | NGN ${Number(_remoteGroupRaw[key].PriceNGN).toFixed(2)}` : ''; const displayLabel = key ? `${key}${priceNGN}` : idStr; - if (error || response.status !== 200) { + const statusCode = getStatusCode(response); + if (error || statusCode !== 200) { results.failure.push(idStr); - log("error", "失败", displayLabel); + log("error", "失败", `${displayLabel} | HTTP ${statusCode || "ERR"} ${error ? String(error) : ""}`); } else { - results.success.push(idStr); - if (key) successKeys.push(key); - log("success", "成功", displayLabel); + const verdict = validateAddResult(data != null ? data : (response && response.body), { productId, skuId, availabilityId }); + if (verdict.ok) { + results.success.push(idStr); + if (key) successKeys.push(key); + log("success", "成功", `${displayLabel}${verdict.detail ? " | " + verdict.detail : ""}`); + } else { + results.failure.push(idStr); + log("error", "失败", `${displayLabel} | ${verdict.reason}`); + } } currentIndex++; setTimeout(sendRequest, 50); @@ -280,4 +412,4 @@ $httpClient.get(REMOTE_READ_URL, (error, response, data) => { } startTask(); } -}); \ No newline at end of file +});