feat(pdd-cookie): 持久化保存Cookie校验状态时间并在失效时发送内部告警通知

This commit is contained in:
yml2213
2026-09-12 15:26:40 +08:00
parent ffa3374483
commit c8f7e48746
6 changed files with 241 additions and 48 deletions
@@ -22,6 +22,10 @@ export interface PddStoreConfigItem {
proxy?: string | undefined
etag?: string | undefined
enabled: boolean
lastCheckedAt?: string | undefined
cookieValid?: boolean | undefined
cookieCheckMessage?: string | undefined
totalOrders?: number | undefined
}
export interface PddSourcesConfig {
@@ -108,6 +112,38 @@ export async function savePddStore(
* Delete single store configuration by shopId.
* 删除指定店铺配置。
*/
/**
* Update and persist check status for a specific store.
* 更新并持久化保存指定店铺的 CK 测活状态与时间戳。
*/
export async function updatePddStoreCheckStatus(
shopId: unknown,
status: {
cookieValid: boolean
cookieCheckMessage: string
lastCheckedAt: string
totalOrders?: number | undefined
},
): Promise<PddStoreConfigItem | null> {
const key = String(shopId || '').trim()
if (!key) return null
const config = getPddSourcesConfig()
const store = config.stores.find((s) => s.shopId === key)
if (!store) return null
store.cookieValid = status.cookieValid
store.cookieCheckMessage = status.cookieCheckMessage
store.lastCheckedAt = status.lastCheckedAt
if (status.totalOrders !== undefined) {
store.totalOrders = status.totalOrders
}
await savePddSourcesConfig(config)
return store
}
export async function deletePddStore(shopId: unknown): Promise<PddSourcesConfig> {
const key = String(shopId || '').trim()
if (!key) {
@@ -141,6 +177,14 @@ export function normalizePddStoreItem(rawValue: unknown): PddStoreConfigItem {
const userAgent = String(source.userAgent || '').trim() || PurePddAntiContent.DEFAULT_UA
const proxy = String(source.proxy || '').trim()
const etag = String(source.etag || '').trim()
const lastCheckedAt = source.lastCheckedAt ? String(source.lastCheckedAt).trim() : undefined
const cookieValid = typeof source.cookieValid === 'boolean' ? source.cookieValid : undefined
const cookieCheckMessage = source.cookieCheckMessage
? String(source.cookieCheckMessage).trim()
: undefined
const totalOrders = Number.isInteger(Number(source.totalOrders))
? Number(source.totalOrders)
: undefined
return {
shopId,
@@ -150,6 +194,10 @@ export function normalizePddStoreItem(rawValue: unknown): PddStoreConfigItem {
proxy: proxy || undefined,
etag: etag || undefined,
enabled: source.enabled !== false,
lastCheckedAt,
cookieValid,
cookieCheckMessage,
totalOrders,
}
}
@@ -15,7 +15,12 @@
import { PddClient, type QueryOrdersOptions } from './pdd-client.js'
import { mapPddOrderToSourceEvent } from './pdd-order-mapper.js'
import { getPddSourcesConfig, type PddStoreConfigItem } from './pdd-source-config-service.js'
import {
getPddSourcesConfig,
updatePddStoreCheckStatus,
type PddStoreConfigItem,
} from './pdd-source-config-service.js'
import { notifyPddCookieExpired } from '../../notification/domain-notifications.js'
import { upsertOrderFromSource } from '../../order/order-service.js'
import { logError, logInfo, logWarn } from '../../../utils/logger.js'
@@ -91,6 +96,14 @@ export async function syncStoreOrders(
const queryResult = await client.queryRecentOrders(queryOptions)
// Update persistent check status to valid / 更新持久化校验状态为有效
await updatePddStoreCheckStatus(shopId, {
cookieValid: true,
cookieCheckMessage: `同步正常 (在售/历史: ${queryResult.total})`,
lastCheckedAt: new Date().toISOString(),
totalOrders: queryResult.total,
}).catch(() => null)
const { total, items } = queryResult
let upsertedCount = 0
let ignoredCount = 0
@@ -142,6 +155,28 @@ export async function syncStoreOrders(
shopId,
error: errMsg,
})
// If login expired or risk-controlled, mark cookie as invalid and notify admins
// 若登录过期或风控拦截,标记为失效并推送告警通知
if (
errMsg.includes('40001') ||
errMsg.includes('登录') ||
errMsg.includes('失效') ||
errMsg.includes('未登录') ||
errMsg.includes('40002')
) {
await updatePddStoreCheckStatus(shopId, {
cookieValid: false,
cookieCheckMessage: errMsg,
lastCheckedAt: new Date().toISOString(),
}).catch(() => null)
notifyPddCookieExpired({
shopId,
shopName,
message: errMsg,
})
}
return {
shopId,
shopName,