增加行业凭证后台 token 配置
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
import { maskSecret } from '../../../utils/masking.js'
|
||||
import {
|
||||
getKuaishouIndustrySourceConfig,
|
||||
getKuaishouIndustrySourceFilePath,
|
||||
saveKuaishouIndustrySourceConfig,
|
||||
type KuaishouIndustrySourceConfig,
|
||||
} from '../../platforms/kuaishou-industry/source-config-service.js'
|
||||
import { refreshKuaishouIndustryAccessToken } from '../../platforms/kuaishou-industry/token-service.js'
|
||||
|
||||
type JsonObject = Record<string, any>
|
||||
|
||||
const SECRET_FIELDS = [
|
||||
'appSecret',
|
||||
'signSecret',
|
||||
'messageSecret',
|
||||
'accessToken',
|
||||
'refreshToken',
|
||||
] as const
|
||||
|
||||
export function getAdminKuaishouIndustrySourceConfig() {
|
||||
const config = getKuaishouIndustrySourceConfig()
|
||||
|
||||
return {
|
||||
filePath: getKuaishouIndustrySourceFilePath(),
|
||||
source: mapAdminKuaishouIndustrySourceConfig(config),
|
||||
}
|
||||
}
|
||||
|
||||
export function updateAdminKuaishouIndustrySourceConfig(payload: JsonObject = {}) {
|
||||
const current = getKuaishouIndustrySourceConfig()
|
||||
const saved = saveKuaishouIndustrySourceConfig({
|
||||
...current,
|
||||
enabled: hasPayloadField(payload, 'enabled') ? payload.enabled !== false : current.enabled !== false,
|
||||
sendCallbackEnabled: hasPayloadField(payload, 'sendCallbackEnabled')
|
||||
? payload.sendCallbackEnabled === true
|
||||
: current.sendCallbackEnabled === true,
|
||||
baseUrl: readConfigString(payload, 'baseUrl', current.baseUrl),
|
||||
authBaseUrl: readConfigString(payload, 'authBaseUrl', current.authBaseUrl),
|
||||
appKey: readConfigString(payload, 'appKey', current.appKey, { allowBlank: true }),
|
||||
sellerId: readConfigString(payload, 'sellerId', current.sellerId, { allowBlank: true }),
|
||||
provider: readConfigString(payload, 'provider', current.provider),
|
||||
platform: readConfigString(payload, 'platform', current.platform),
|
||||
shopId: readConfigString(payload, 'shopId', current.shopId),
|
||||
shopName: readConfigString(payload, 'shopName', current.shopName),
|
||||
version: readConfigString(payload, 'version', current.version),
|
||||
accessTokenExpiresAt: readConfigString(payload, 'accessTokenExpiresAt', current.accessTokenExpiresAt, { allowBlank: true }),
|
||||
refreshTokenExpiresAt: readConfigString(payload, 'refreshTokenExpiresAt', current.refreshTokenExpiresAt, { allowBlank: true }),
|
||||
...resolveSecretPatch(payload, current),
|
||||
})
|
||||
|
||||
return {
|
||||
filePath: getKuaishouIndustrySourceFilePath(),
|
||||
source: mapAdminKuaishouIndustrySourceConfig(saved),
|
||||
}
|
||||
}
|
||||
|
||||
export async function refreshAdminKuaishouIndustryAccessToken() {
|
||||
const result = await refreshKuaishouIndustryAccessToken()
|
||||
|
||||
return {
|
||||
filePath: getKuaishouIndustrySourceFilePath(),
|
||||
refreshed: result.refreshed,
|
||||
source: mapAdminKuaishouIndustrySourceConfig(result.config),
|
||||
}
|
||||
}
|
||||
|
||||
function mapAdminKuaishouIndustrySourceConfig(config: KuaishouIndustrySourceConfig) {
|
||||
const accessTokenStatus = resolveAccessTokenStatus(config)
|
||||
|
||||
return {
|
||||
enabled: config.enabled !== false,
|
||||
sendCallbackEnabled: config.sendCallbackEnabled === true,
|
||||
baseUrl: config.baseUrl,
|
||||
authBaseUrl: config.authBaseUrl,
|
||||
appKey: config.appKey,
|
||||
appSecret: '',
|
||||
appSecretMasked: maskSecret(config.appSecret),
|
||||
hasAppSecret: Boolean(config.appSecret),
|
||||
signSecret: '',
|
||||
signSecretMasked: maskSecret(config.signSecret),
|
||||
hasSignSecret: Boolean(config.signSecret),
|
||||
messageSecret: '',
|
||||
messageSecretMasked: maskSecret(config.messageSecret),
|
||||
hasMessageSecret: Boolean(config.messageSecret),
|
||||
accessToken: '',
|
||||
accessTokenMasked: maskSecret(config.accessToken),
|
||||
hasAccessToken: Boolean(config.accessToken),
|
||||
refreshToken: '',
|
||||
refreshTokenMasked: maskSecret(config.refreshToken),
|
||||
hasRefreshToken: Boolean(config.refreshToken),
|
||||
accessTokenExpiresAt: config.accessTokenExpiresAt,
|
||||
refreshTokenExpiresAt: config.refreshTokenExpiresAt,
|
||||
accessTokenStatus: accessTokenStatus.status,
|
||||
accessTokenExpiresInSeconds: accessTokenStatus.expiresInSeconds,
|
||||
sellerId: config.sellerId,
|
||||
provider: config.provider,
|
||||
platform: config.platform,
|
||||
shopId: config.shopId,
|
||||
shopName: config.shopName,
|
||||
version: config.version,
|
||||
lastRefreshedAt: config.lastRefreshedAt,
|
||||
lastRefreshError: config.lastRefreshError,
|
||||
}
|
||||
}
|
||||
|
||||
function resolveSecretPatch(
|
||||
payload: JsonObject,
|
||||
current: KuaishouIndustrySourceConfig,
|
||||
): Partial<KuaishouIndustrySourceConfig> {
|
||||
const patch: Partial<KuaishouIndustrySourceConfig> = {}
|
||||
for (const field of SECRET_FIELDS) {
|
||||
const text = String(payload[field] || '').trim()
|
||||
patch[field] = text || current[field]
|
||||
}
|
||||
|
||||
return patch
|
||||
}
|
||||
|
||||
function resolveAccessTokenStatus(config: KuaishouIndustrySourceConfig) {
|
||||
if (!config.accessToken) {
|
||||
return {
|
||||
status: 'missing',
|
||||
expiresInSeconds: null,
|
||||
}
|
||||
}
|
||||
|
||||
const expiresAt = Date.parse(config.accessTokenExpiresAt || '')
|
||||
if (!Number.isFinite(expiresAt)) {
|
||||
return {
|
||||
status: 'unknown',
|
||||
expiresInSeconds: null,
|
||||
}
|
||||
}
|
||||
|
||||
const expiresInSeconds = Math.floor((expiresAt - Date.now()) / 1000)
|
||||
if (expiresInSeconds <= 0) {
|
||||
return {
|
||||
status: 'expired',
|
||||
expiresInSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
if (expiresInSeconds <= 30 * 60) {
|
||||
return {
|
||||
status: 'expiring',
|
||||
expiresInSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'valid',
|
||||
expiresInSeconds,
|
||||
}
|
||||
}
|
||||
|
||||
function readConfigString(
|
||||
payload: JsonObject,
|
||||
field: string,
|
||||
fallback: string,
|
||||
options: { allowBlank?: boolean } = {},
|
||||
): string {
|
||||
if (!hasPayloadField(payload, field)) {
|
||||
return fallback
|
||||
}
|
||||
|
||||
const text = String(payload[field] || '').trim()
|
||||
return text || (options.allowBlank ? '' : fallback)
|
||||
}
|
||||
|
||||
function hasPayloadField(payload: JsonObject, field: string): boolean {
|
||||
return Object.prototype.hasOwnProperty.call(payload, field)
|
||||
}
|
||||
Reference in New Issue
Block a user