From 132dd75efc2d88afe6ae44698d5521c56c9dcdc4 Mon Sep 17 00:00:00 2001 From: yml Date: Mon, 4 May 2026 15:18:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=BD=E7=A6=BB=E5=90=8E=E5=8F=B0=E4=BA=91?= =?UTF-8?q?=E8=A7=A6=E6=89=8B=E4=B8=8A=E4=B8=8B=E6=96=87=E7=BB=84=E8=A3=85?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin-platform-config-cloudtentacles.js | 44 +++++++ ...min-platform-config-cloudtentacles.test.js | 65 ++++++++++ .../admin/admin-platform-config-service.js | 112 +++++------------- 3 files changed, 136 insertions(+), 85 deletions(-) create mode 100644 apps/backend/src/services/admin/admin-platform-config-cloudtentacles.js create mode 100644 apps/backend/src/services/admin/admin-platform-config-cloudtentacles.test.js diff --git a/apps/backend/src/services/admin/admin-platform-config-cloudtentacles.js b/apps/backend/src/services/admin/admin-platform-config-cloudtentacles.js new file mode 100644 index 00000000..4c5eb627 --- /dev/null +++ b/apps/backend/src/services/admin/admin-platform-config-cloudtentacles.js @@ -0,0 +1,44 @@ +// @ts-check + +import { getCloudtentaclesSourceConfig } from '../platforms/cloudtentacles/source-config-service.js' +import { getCloudtentaclesSessionState } from '../platforms/cloudtentacles/session-state-service.js' +import { pickFirstNonEmpty, resolveCloudtentaclesAdminContext } from './admin-platform-config-context.js' + +const DEFAULT_CLOUDTENTACLES_BASE_URL = 'https://123.207.217.176' + +export function resolveAdminCloudtentaclesCredentialPayload( + payload = {}, + options = {}, +) { + const savedSource = /** @type {Record} */ ( + options.savedSource || getCloudtentaclesSourceConfig() + ) + const defaultBaseUrl = String(options.defaultBaseUrl || DEFAULT_CLOUDTENTACLES_BASE_URL).trim() + + return { + baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, defaultBaseUrl]), + username: pickFirstNonEmpty([payload.username, savedSource.username]), + password: pickFirstNonEmpty([payload.password, savedSource.password]), + phone: pickFirstNonEmpty([payload.phone, savedSource.phone]), + deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']), + deviceType: payload.deviceType ?? savedSource.deviceType, + } +} + +export function resolveAdminCloudtentaclesSessionPayload( + payload = {}, + options = {}, +) { + const savedSource = /** @type {Record} */ ( + options.savedSource || getCloudtentaclesSourceConfig() + ) + const persistedSession = /** @type {Record} */ ( + options.persistedSession || getCloudtentaclesSessionState() + ) + + return resolveCloudtentaclesAdminContext(payload, { + savedSource, + persistedSession, + defaultBaseUrl: options.defaultBaseUrl || DEFAULT_CLOUDTENTACLES_BASE_URL, + }) +} diff --git a/apps/backend/src/services/admin/admin-platform-config-cloudtentacles.test.js b/apps/backend/src/services/admin/admin-platform-config-cloudtentacles.test.js new file mode 100644 index 00000000..f643dc36 --- /dev/null +++ b/apps/backend/src/services/admin/admin-platform-config-cloudtentacles.test.js @@ -0,0 +1,65 @@ +import test from 'node:test' +import assert from 'node:assert/strict' + +import { + resolveAdminCloudtentaclesCredentialPayload, + resolveAdminCloudtentaclesSessionPayload, +} from './admin-platform-config-cloudtentacles.js' + +test('resolveAdminCloudtentaclesCredentialPayload merges payload and saved source defaults', () => { + assert.deepEqual( + resolveAdminCloudtentaclesCredentialPayload( + { + baseUrl: ' https://override.example.com ', + phone: ' 13800138000 ', + deviceId: ' custom-device ', + }, + { + savedSource: { + baseUrl: 'https://saved.example.com', + username: 'saved-user', + password: 'saved-pass', + phone: '13900000000', + deviceId: 'saved-device', + deviceType: 2, + }, + }, + ), + { + baseUrl: 'https://override.example.com', + username: 'saved-user', + password: 'saved-pass', + phone: '13800138000', + deviceId: 'custom-device', + deviceType: 2, + }, + ) +}) + +test('resolveAdminCloudtentaclesSessionPayload merges payload source and persisted session defaults', () => { + assert.deepEqual( + resolveAdminCloudtentaclesSessionPayload( + { + token: ' payload-token ', + }, + { + savedSource: { + baseUrl: 'https://saved.example.com', + deviceId: 'saved-device', + deviceType: 3, + }, + persistedSession: { + token: 'session-token', + deviceId: 'session-device', + deviceType: 5, + }, + }, + ), + { + baseUrl: 'https://saved.example.com', + token: 'payload-token', + deviceId: 'saved-device', + deviceType: 3, + }, + ) +}) diff --git a/apps/backend/src/services/admin/admin-platform-config-service.js b/apps/backend/src/services/admin/admin-platform-config-service.js index 95b5ee2b..6350e0d7 100644 --- a/apps/backend/src/services/admin/admin-platform-config-service.js +++ b/apps/backend/src/services/admin/admin-platform-config-service.js @@ -81,7 +81,6 @@ import { hasCloudtentaclesCredentialContextChanged, isPlainObject, pickFirstNonEmpty, - resolveCloudtentaclesAdminContext, resolveKuaishouEticketAdminContext, } from './admin-platform-config-context.js' import { @@ -89,6 +88,10 @@ import { normalizeFulfillmentLookupPayload, resolveFulfillmentLookupDetail, } from './admin-platform-config-fulfillment.js' +import { + resolveAdminCloudtentaclesCredentialPayload, + resolveAdminCloudtentaclesSessionPayload, +} from './admin-platform-config-cloudtentacles.js' import { listAdminObservedProducts } from './admin-platform-config-observed-products.js' import { assertAdminFulfillmentBindingsInput, @@ -463,14 +466,7 @@ export function updateAdminCloudtentaclesSourceConfig(payload = /** @type {Admin /** @param {AdminCloudtentaclesSendSmsCodeInput} [payload] */ export async function sendAdminCloudtentaclesSmsCode(payload = /** @type {AdminCloudtentaclesSendSmsCodeInput} */ ({})) { - const savedSource = getCloudtentaclesSourceConfig() - const result = await sendCloudtentaclesSmsCode({ - baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, 'https://123.207.217.176']), - username: pickFirstNonEmpty([payload.username, savedSource.username]), - phone: pickFirstNonEmpty([payload.phone, savedSource.phone]), - deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']), - deviceType: payload.deviceType ?? savedSource.deviceType, - }) + const result = await sendCloudtentaclesSmsCode(resolveAdminCloudtentaclesCredentialPayload(payload)) return { ...result, @@ -481,14 +477,10 @@ export async function sendAdminCloudtentaclesSmsCode(payload = /** @type {AdminC /** @param {AdminCloudtentaclesTestLoginInput} [payload] */ export async function testAdminCloudtentaclesLogin(payload = /** @type {AdminCloudtentaclesTestLoginInput} */ ({})) { const savedSource = getCloudtentaclesSourceConfig() + const credentialContext = resolveAdminCloudtentaclesCredentialPayload(payload, { savedSource }) const session = await loginCloudtentaclesSession({ - baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, 'https://123.207.217.176']), - username: pickFirstNonEmpty([payload.username, savedSource.username]), - password: pickFirstNonEmpty([payload.password, savedSource.password]), - phone: pickFirstNonEmpty([payload.phone, savedSource.phone]), + ...credentialContext, code: String(payload.code || '').trim(), - deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']), - deviceType: payload.deviceType ?? savedSource.deviceType, }) const savedSession = saveCloudtentaclesSessionState({ token: session.token, @@ -496,8 +488,8 @@ export async function testAdminCloudtentaclesLogin(payload = /** @type {AdminClo username: session.username, phone: session.phone, loggedInAt: session.loggedInAt, - deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']), - deviceType: payload.deviceType ?? savedSource.deviceType, + deviceId: credentialContext.deviceId, + deviceType: credentialContext.deviceType, }) return { @@ -522,20 +514,16 @@ export async function testAdminCloudtentaclesLogin(payload = /** @type {AdminClo export async function validateAdminCloudtentaclesSession(payload = /** @type {AdminCloudtentaclesValidateSessionInput} */ ({})) { const savedSource = getCloudtentaclesSourceConfig() const persistedSession = getCloudtentaclesSessionState() - const session = await validateCloudtentaclesSession({ - baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, 'https://123.207.217.176']), - token: pickFirstNonEmpty([payload.token, persistedSession.token]), - deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']), - deviceType: payload.deviceType ?? savedSource.deviceType, - }) + const sessionContext = resolveAdminCloudtentaclesSessionPayload(payload, { savedSource, persistedSession }) + const session = await validateCloudtentaclesSession(sessionContext) const savedSession = saveCloudtentaclesSessionState({ token: session.token, baseUrl: session.baseUrl, username: pickFirstNonEmpty([persistedSession.username, savedSource.username]), phone: pickFirstNonEmpty([persistedSession.phone, savedSource.phone]), loggedInAt: session.loggedInAt, - deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, persistedSession.deviceId, '-']), - deviceType: payload.deviceType ?? savedSource.deviceType ?? persistedSession.deviceType, + deviceId: sessionContext.deviceId, + deviceType: sessionContext.deviceType, }) return { @@ -554,37 +542,22 @@ export async function validateAdminCloudtentaclesSession(payload = /** @type {Ad /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ export async function getAdminCloudtentaclesAsset(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) - return getCloudtentaclesAsset(context) + return getCloudtentaclesAsset(resolveAdminCloudtentaclesSessionPayload(payload)) } /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ export async function getAdminCloudtentaclesCategories(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) - return getCloudtentaclesCategories(context) + return getCloudtentaclesCategories(resolveAdminCloudtentaclesSessionPayload(payload)) } /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ export async function getAdminCloudtentaclesSkuList(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) - return listCloudtentaclesSku(context) + return listCloudtentaclesSku(resolveAdminCloudtentaclesSessionPayload(payload)) } /** @param {AdminCloudtentaclesSkuBuyInput} [payload] */ export async function buyAdminCloudtentaclesSku(payload = /** @type {AdminCloudtentaclesSkuBuyInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return buyCloudtentaclesSku({ ...context, id: payload.id, @@ -594,10 +567,7 @@ export async function buyAdminCloudtentaclesSku(payload = /** @type {AdminCloudt /** @param {AdminCloudtentaclesSkuUseInput} [payload] */ export async function useAdminCloudtentaclesSku(payload = /** @type {AdminCloudtentaclesSkuUseInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return useCloudtentaclesSku({ ...context, id: payload.id, @@ -608,19 +578,12 @@ export async function useAdminCloudtentaclesSku(payload = /** @type {AdminCloudt /** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */ export async function getAdminCloudtentaclesKnapsack(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) - return getCloudtentaclesKnapsack(context) + return getCloudtentaclesKnapsack(resolveAdminCloudtentaclesSessionPayload(payload)) } /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ export async function listAdminCloudtentaclesVirtualNumbers(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return listCloudtentaclesVirtualNumbers({ ...context, key: payload.key, @@ -629,10 +592,7 @@ export async function listAdminCloudtentaclesVirtualNumbers(payload = /** @type /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ export async function appointAdminCloudtentaclesVirtualNumber(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return appointCloudtentaclesVirtualNumber({ ...context, key: payload.key, @@ -641,10 +601,7 @@ export async function appointAdminCloudtentaclesVirtualNumber(payload = /** @typ /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ export async function generateAdminCloudtentaclesLoginCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return generateCloudtentaclesLoginCode({ ...context, key: payload.key, @@ -654,10 +611,7 @@ export async function generateAdminCloudtentaclesLoginCode(payload = /** @type { /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ export async function fetchAdminCloudtentaclesVirtualNumberCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return fetchCloudtentaclesVirtualNumberCode({ ...context, key: payload.key, @@ -667,10 +621,7 @@ export async function fetchAdminCloudtentaclesVirtualNumberCode(payload = /** @t /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ export async function verifyAdminCloudtentaclesLoginCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return verifyCloudtentaclesLoginCode({ ...context, key: payload.key, @@ -681,10 +632,7 @@ export async function verifyAdminCloudtentaclesLoginCode(payload = /** @type {Ad /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ export async function getAdminCloudtentaclesBindUrl(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return getCloudtentaclesBindUrl({ ...context, key: payload.key, @@ -694,10 +642,7 @@ export async function getAdminCloudtentaclesBindUrl(payload = /** @type {AdminCl /** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */ export async function backAdminCloudtentaclesVirtualNumber(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return backCloudtentaclesVirtualNumber({ ...context, key: payload.key, @@ -707,10 +652,7 @@ export async function backAdminCloudtentaclesVirtualNumber(payload = /** @type { /** @param {AdminCloudtentaclesFullFlowInput} [payload] */ export async function runAdminCloudtentaclesFullFlow(payload = /** @type {AdminCloudtentaclesFullFlowInput} */ ({})) { - const context = resolveCloudtentaclesAdminContext(payload, { - savedSource: getCloudtentaclesSourceConfig(), - persistedSession: getCloudtentaclesSessionState(), - }) + const context = resolveAdminCloudtentaclesSessionPayload(payload) return runCloudtentaclesFullDebugFlow({ ...context, skuId: payload.skuId,