cloudtentacles 增加登陆后持久化, 调试ok

This commit is contained in:
yml2213
2026-05-02 23:01:02 +08:00
parent a5b93b17f0
commit 4cc91bf194
17 changed files with 1365 additions and 6 deletions
@@ -20,11 +20,32 @@ import {
getCloudtentaclesSourcesFilePath,
saveCloudtentaclesSourceConfig,
} from '../platforms/cloudtentacles/source-config-service.js'
import {
clearCloudtentaclesSessionState,
getCloudtentaclesSessionFilePath,
getCloudtentaclesSessionState,
saveCloudtentaclesSessionState,
} from '../platforms/cloudtentacles/session-state-service.js'
import {
loginCloudtentaclesSession,
sendCloudtentaclesSmsCode,
validateCloudtentaclesSession,
} from '../platforms/cloudtentacles/session-service.js'
import {
buyCloudtentaclesSku,
getCloudtentaclesAsset,
getCloudtentaclesCategories,
listCloudtentaclesSku,
} from '../platforms/cloudtentacles/catalog-service.js'
import { getCloudtentaclesKnapsack } from '../platforms/cloudtentacles/knapsack-service.js'
import {
appointCloudtentaclesVirtualNumber,
fetchCloudtentaclesVirtualNumberCode,
generateCloudtentaclesLoginCode,
getCloudtentaclesBindUrl,
listCloudtentaclesVirtualNumbers,
verifyCloudtentaclesLoginCode,
} from '../platforms/cloudtentacles/virtual-number-service.js'
import { normalizeAgisoMessageTemplate } from '../platforms/agiso/xianyu/message-service.js'
import {
getOrderFulfillmentBindingConfigs,
@@ -46,6 +67,9 @@ import { resolveDisplayShopName } from './admin-read-shared-helpers.js'
/** @typedef {import('../../types/admin-write-inputs.js').AdminCloudtentaclesSendSmsCodeInput} AdminCloudtentaclesSendSmsCodeInput */
/** @typedef {import('../../types/admin-write-inputs.js').AdminCloudtentaclesTestLoginInput} AdminCloudtentaclesTestLoginInput */
/** @typedef {import('../../types/admin-write-inputs.js').AdminCloudtentaclesValidateSessionInput} AdminCloudtentaclesValidateSessionInput */
/** @typedef {import('../../types/admin-write-inputs.js').AdminCloudtentaclesCatalogQueryInput} AdminCloudtentaclesCatalogQueryInput */
/** @typedef {import('../../types/admin-write-inputs.js').AdminCloudtentaclesSkuBuyInput} AdminCloudtentaclesSkuBuyInput */
/** @typedef {import('../../types/admin-write-inputs.js').AdminCloudtentaclesVirtualNumberInput} AdminCloudtentaclesVirtualNumberInput */
/** @typedef {import('../../types/admin-write-inputs.js').AdminFulfillmentBindingConfigSaveInput} AdminFulfillmentBindingConfigSaveInput */
/** @typedef {import('../../types/admin-write-inputs.js').AdminFulfillmentBindingLookupInput} AdminFulfillmentBindingLookupInput */
@@ -352,9 +376,11 @@ export async function syncAdminKhhaoOrders(payload = /** @type {AdminKhhaoOrderQ
export function getAdminCloudtentaclesSourceConfig() {
const config = getCloudtentaclesSourceConfig()
const session = getCloudtentaclesSessionState()
return {
filePath: getCloudtentaclesSourcesFilePath(),
sessionFilePath: getCloudtentaclesSessionFilePath(),
source: {
enabled: config.enabled !== false,
baseUrl: String(config.baseUrl || '').trim(),
@@ -364,11 +390,13 @@ export function getAdminCloudtentaclesSourceConfig() {
deviceId: String(config.deviceId || '-').trim() || '-',
deviceType: Number(config.deviceType || 0),
},
session: mapAdminCloudtentaclesSession(session),
}
}
/** @param {AdminCloudtentaclesSourceConfigInput} [payload] */
export function updateAdminCloudtentaclesSourceConfig(payload = /** @type {AdminCloudtentaclesSourceConfigInput} */ ({})) {
const current = getCloudtentaclesSourceConfig()
const saved = saveCloudtentaclesSourceConfig({
enabled: payload.enabled !== false,
baseUrl: String(payload.baseUrl || '').trim() || 'https://123.207.217.176',
@@ -378,9 +406,12 @@ export function updateAdminCloudtentaclesSourceConfig(payload = /** @type {Admin
deviceId: String(payload.deviceId || '-').trim() || '-',
deviceType: Number(payload.deviceType || 0),
})
const shouldClearSession = hasCloudtentaclesCredentialContextChanged(current, saved)
const session = shouldClearSession ? clearCloudtentaclesSessionState() : getCloudtentaclesSessionState()
return {
filePath: getCloudtentaclesSourcesFilePath(),
sessionFilePath: getCloudtentaclesSessionFilePath(),
source: {
enabled: saved.enabled !== false,
baseUrl: String(saved.baseUrl || '').trim(),
@@ -390,6 +421,7 @@ export function updateAdminCloudtentaclesSourceConfig(payload = /** @type {Admin
deviceId: String(saved.deviceId || '-').trim() || '-',
deviceType: Number(saved.deviceType || 0),
},
session: mapAdminCloudtentaclesSession(session),
}
}
@@ -422,6 +454,15 @@ export async function testAdminCloudtentaclesLogin(payload = /** @type {AdminClo
deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']),
deviceType: payload.deviceType ?? savedSource.deviceType,
})
const savedSession = saveCloudtentaclesSessionState({
token: session.token,
baseUrl: session.baseUrl,
username: session.username,
phone: session.phone,
loggedInAt: session.loggedInAt,
deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']),
deviceType: payload.deviceType ?? savedSource.deviceType,
})
return {
baseUrl: session.baseUrl,
@@ -434,6 +475,7 @@ export async function testAdminCloudtentaclesLogin(payload = /** @type {AdminClo
tokenMasked: maskSecret(session.token),
permissionCount: session.permissions.length,
permissions: session.permissions,
persisted: Boolean(savedSession.token),
},
userInfo: session.userInfo,
asset: session.asset,
@@ -443,12 +485,22 @@ export async function testAdminCloudtentaclesLogin(payload = /** @type {AdminClo
/** @param {AdminCloudtentaclesValidateSessionInput} [payload] */
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: String(payload.token || '').trim(),
token: pickFirstNonEmpty([payload.token, persistedSession.token]),
deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, '-']),
deviceType: payload.deviceType ?? savedSource.deviceType,
})
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,
})
return {
baseUrl: session.baseUrl,
@@ -457,12 +509,106 @@ export async function validateAdminCloudtentaclesSession(payload = /** @type {Ad
tokenMasked: maskSecret(session.token),
permissionCount: session.permissions.length,
permissions: session.permissions,
persisted: Boolean(savedSession.token),
},
userInfo: session.userInfo,
asset: session.asset,
}
}
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesAsset(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return getCloudtentaclesAsset(context)
}
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesCategories(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return getCloudtentaclesCategories(context)
}
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesSkuList(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return listCloudtentaclesSku(context)
}
/** @param {AdminCloudtentaclesSkuBuyInput} [payload] */
export async function buyAdminCloudtentaclesSku(payload = /** @type {AdminCloudtentaclesSkuBuyInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return buyCloudtentaclesSku({
...context,
id: payload.id,
count: payload.count,
})
}
/** @param {AdminCloudtentaclesCatalogQueryInput} [payload] */
export async function getAdminCloudtentaclesKnapsack(payload = /** @type {AdminCloudtentaclesCatalogQueryInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return getCloudtentaclesKnapsack(context)
}
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function listAdminCloudtentaclesVirtualNumbers(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return listCloudtentaclesVirtualNumbers({
...context,
key: payload.key,
})
}
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function appointAdminCloudtentaclesVirtualNumber(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return appointCloudtentaclesVirtualNumber({
...context,
key: payload.key,
})
}
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function generateAdminCloudtentaclesLoginCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return generateCloudtentaclesLoginCode({
...context,
key: payload.key,
id: payload.id,
})
}
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function fetchAdminCloudtentaclesVirtualNumberCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return fetchCloudtentaclesVirtualNumberCode({
...context,
key: payload.key,
phone: payload.phone,
})
}
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function verifyAdminCloudtentaclesLoginCode(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return verifyCloudtentaclesLoginCode({
...context,
key: payload.key,
id: payload.id,
code: payload.code,
})
}
/** @param {AdminCloudtentaclesVirtualNumberInput} [payload] */
export async function getAdminCloudtentaclesBindUrl(payload = /** @type {AdminCloudtentaclesVirtualNumberInput} */ ({})) {
const context = resolveCloudtentaclesAdminContext(payload)
return getCloudtentaclesBindUrl({
...context,
key: payload.key,
id: payload.id,
})
}
export async function getAdminFulfillmentBindingConfigs() {
const bindings = getOrderFulfillmentBindingConfigs()
const rowsResult = await query(
@@ -825,6 +971,42 @@ function maskPhone(value) {
return `${normalized.slice(0, 3)}****${normalized.slice(-4)}`
}
function resolveCloudtentaclesAdminContext(payload = {}) {
const savedSource = getCloudtentaclesSourceConfig()
const persistedSession = getCloudtentaclesSessionState()
return {
baseUrl: pickFirstNonEmpty([payload.baseUrl, savedSource.baseUrl, 'https://123.207.217.176']),
token: pickFirstNonEmpty([payload.token, persistedSession.token]),
deviceId: pickFirstNonEmpty([payload.deviceId, savedSource.deviceId, persistedSession.deviceId, '-']),
deviceType: payload.deviceType ?? savedSource.deviceType ?? persistedSession.deviceType,
}
}
function hasCloudtentaclesCredentialContextChanged(current, next) {
return (
String(current.baseUrl || '').trim() !== String(next.baseUrl || '').trim()
|| String(current.username || '').trim() !== String(next.username || '').trim()
|| String(current.phone || '').trim() !== String(next.phone || '').trim()
|| String(current.deviceId || '').trim() !== String(next.deviceId || '').trim()
|| Number(current.deviceType || 0) !== Number(next.deviceType || 0)
)
}
function mapAdminCloudtentaclesSession(session = {}) {
return {
token: String(session.token || '').trim(),
tokenMasked: maskSecret(session.token),
baseUrl: String(session.baseUrl || '').trim(),
username: String(session.username || '').trim(),
phoneMasked: maskPhone(session.phone),
loggedInAt: String(session.loggedInAt || '').trim(),
deviceId: String(session.deviceId || '-').trim() || '-',
deviceType: Number(session.deviceType || 0),
hasToken: Boolean(String(session.token || '').trim()),
}
}
function isPlainObject(value) {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
}