补充行业凭证授权换 token

This commit is contained in:
yml2213
2026-07-07 23:17:16 +08:00
parent 81bfd8b078
commit 3940e59df6
13 changed files with 491 additions and 41 deletions
@@ -1,11 +1,15 @@
import { maskSecret } from '../../../utils/masking.js'
import { createHttpError } from '../../../utils/http.js'
import {
getKuaishouIndustrySourceConfig,
getKuaishouIndustrySourceFilePath,
saveKuaishouIndustrySourceConfig,
type KuaishouIndustrySourceConfig,
} from '../../platforms/kuaishou-industry/source-config-service.js'
import { refreshKuaishouIndustryAccessToken } from '../../platforms/kuaishou-industry/token-service.js'
import {
exchangeKuaishouIndustryAuthorizationCode,
refreshKuaishouIndustryAccessToken,
} from '../../platforms/kuaishou-industry/token-service.js'
type JsonObject = Record<string, any>
@@ -36,7 +40,12 @@ export function updateAdminKuaishouIndustrySourceConfig(payload: JsonObject = {}
: current.sendCallbackEnabled === true,
baseUrl: readConfigString(payload, 'baseUrl', current.baseUrl),
authBaseUrl: readConfigString(payload, 'authBaseUrl', current.authBaseUrl),
redirectUri: readConfigString(payload, 'redirectUri', current.redirectUri, { allowBlank: true }),
scopes: normalizeScopeText(readConfigString(payload, 'scopes', current.scopes, { allowBlank: true })),
authState: readConfigString(payload, 'authState', current.authState, { allowBlank: true }),
appKey: readConfigString(payload, 'appKey', current.appKey, { allowBlank: true }),
openId: readConfigString(payload, 'openId', current.openId, { allowBlank: true }),
grantedScopes: normalizeScopeText(readConfigString(payload, 'grantedScopes', current.grantedScopes, { allowBlank: true })),
sellerId: readConfigString(payload, 'sellerId', current.sellerId, { allowBlank: true }),
provider: readConfigString(payload, 'provider', current.provider),
platform: readConfigString(payload, 'platform', current.platform),
@@ -64,6 +73,24 @@ export async function refreshAdminKuaishouIndustryAccessToken() {
}
}
export async function exchangeAdminKuaishouIndustryAuthorizationCode(payload: JsonObject = {}) {
const code = String(payload.code || '').trim()
if (!code) {
throw createHttpError('授权 code 未填写', {
statusCode: 400,
errorCode: 'kuaishou_industry_missing_authorization_code',
})
}
const result = await exchangeKuaishouIndustryAuthorizationCode(code)
return {
filePath: getKuaishouIndustrySourceFilePath(),
refreshed: result.refreshed,
source: mapAdminKuaishouIndustrySourceConfig(result.config),
}
}
function mapAdminKuaishouIndustrySourceConfig(config: KuaishouIndustrySourceConfig) {
const accessTokenStatus = resolveAccessTokenStatus(config)
@@ -72,6 +99,10 @@ function mapAdminKuaishouIndustrySourceConfig(config: KuaishouIndustrySourceConf
sendCallbackEnabled: config.sendCallbackEnabled === true,
baseUrl: config.baseUrl,
authBaseUrl: config.authBaseUrl,
redirectUri: config.redirectUri,
scopes: config.scopes,
authState: config.authState,
authorizationUrl: buildKuaishouIndustryAuthorizationUrl(config),
appKey: config.appKey,
appSecret: '',
appSecretMasked: maskSecret(config.appSecret),
@@ -92,6 +123,8 @@ function mapAdminKuaishouIndustrySourceConfig(config: KuaishouIndustrySourceConf
refreshTokenExpiresAt: config.refreshTokenExpiresAt,
accessTokenStatus: accessTokenStatus.status,
accessTokenExpiresInSeconds: accessTokenStatus.expiresInSeconds,
openId: config.openId,
grantedScopes: config.grantedScopes,
sellerId: config.sellerId,
provider: config.provider,
platform: config.platform,
@@ -103,6 +136,35 @@ function mapAdminKuaishouIndustrySourceConfig(config: KuaishouIndustrySourceConf
}
}
function buildKuaishouIndustryAuthorizationUrl(config: KuaishouIndustrySourceConfig): string {
if (!config.authBaseUrl || !config.appKey || !config.redirectUri || !config.scopes) {
return ''
}
try {
const url = new URL(`${String(config.authBaseUrl).replace(/\/+$/, '')}/oauth/authorize`)
url.searchParams.set('app_id', config.appKey)
url.searchParams.set('redirect_uri', config.redirectUri)
url.searchParams.set('scope', normalizeScopeText(config.scopes))
url.searchParams.set('response_type', 'code')
if (config.authState) {
url.searchParams.set('state', config.authState)
}
return url.toString()
} catch {
return ''
}
}
function normalizeScopeText(value: unknown): string {
return String(value || '')
.split(/[,\s]+/)
.map((item) => item.trim())
.filter(Boolean)
.join(',')
}
function resolveSecretPatch(
payload: JsonObject,
current: KuaishouIndustrySourceConfig,