feat(pdd-ui): 新增管理后台拼多多店铺CRUD与Cookie有效性实时检测功能
1. 订单快照优化 (pdd-order-mapper.ts): - 在 item_snapshot_json 中完整保留拼多多原始报文快照全量字段,确保无信息截断。 2. 后端 Cookie 有效性校验接口 (pdd-client.ts, platform-config/pdd.ts): - 新增 PddClient.testCookie 与 POST /api/v1/admin/platform-config/pdd/test-cookie 接口。 - 支持通过轻量接口请求即时测试 Cookie 合法性,精准识别有效状态(返回在线订单数)与失效/频控状态。 3. 前端管理面板开发 (PddPlatformPanel.tsx, AdminPlatformShopsPage.tsx): - 在平台配置页面新增【拼多多 (PDD)】专属 Tab 面板。 - 提供拼多多全局同步开关与轮询间隔配置。 - 支持店铺完整 CRUD:添加店铺、编辑店铺、删除店铺、启用/停用切换。 - 支持弹窗内即时【测试此 Cookie 有效性】(无需先保存即可验证)及列表行内一键测活与单店铺立即同步。
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Pinduoduo Admin Platform Config Routes
|
||||
* 拼多多平台管理端配置与手动同步路由
|
||||
* 拼多多平台管理端配置、店铺 CRUD 与 CK 有效性校验路由
|
||||
*/
|
||||
|
||||
import { Router } from 'express'
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
syncAllPddStores,
|
||||
syncStoreOrders,
|
||||
} from '../../../services/platforms/pdd/pdd-sync-service.js'
|
||||
import { testPddCookie } from '../../../services/platforms/pdd/pdd-client.js'
|
||||
import { createHttpError } from '../../../utils/http.js'
|
||||
|
||||
const router = Router()
|
||||
@@ -68,16 +69,19 @@ router.post(
|
||||
*/
|
||||
router.post(
|
||||
'/pdd/stores/:shopId',
|
||||
createJsonHandler((req) => savePddStore(req.params.shopId, (req.body || {}) as JsonObject), {
|
||||
successMessage: '拼多多店铺配置已更新',
|
||||
errorMessage: '更新拼多多店铺配置失败',
|
||||
scope: '[admin/platform-config/pdd/stores/:shopId]',
|
||||
audit: (req) => ({
|
||||
action: 'platform_pdd_store_updated',
|
||||
targetType: 'platform_store',
|
||||
targetId: String(req.params.shopId || ''),
|
||||
}),
|
||||
}),
|
||||
createJsonHandler(
|
||||
(req) => savePddStore(req.params.shopId, (req.body || {}) as JsonObject),
|
||||
{
|
||||
successMessage: '拼多多店铺配置已更新',
|
||||
errorMessage: '更新拼多多店铺配置失败',
|
||||
scope: '[admin/platform-config/pdd/stores/:shopId]',
|
||||
audit: (req) => ({
|
||||
action: 'platform_pdd_store_updated',
|
||||
targetType: 'platform_store',
|
||||
targetId: String(req.params.shopId || ''),
|
||||
}),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -99,6 +103,53 @@ router.delete(
|
||||
}),
|
||||
)
|
||||
|
||||
/**
|
||||
* POST /platform-config/pdd/test-cookie
|
||||
* Test Cookie validity for a given cookie string or an existing shop.
|
||||
* 测试拼多多 Cookie 有效性(支持直接传入 Cookie 字符串或指定 shopId)。
|
||||
*/
|
||||
router.post(
|
||||
'/pdd/test-cookie',
|
||||
createJsonHandler(
|
||||
async (req) => {
|
||||
const body = (req.body || {}) as {
|
||||
cookie?: string
|
||||
userAgent?: string
|
||||
shopId?: string
|
||||
}
|
||||
|
||||
let cookie = String(body.cookie || '').trim()
|
||||
let userAgent = body.userAgent
|
||||
|
||||
if (!cookie && body.shopId) {
|
||||
const store = getPddStoreById(body.shopId)
|
||||
if (!store) {
|
||||
throw createHttpError(`店铺不存在: ${body.shopId}`, {
|
||||
statusCode: 404,
|
||||
errorCode: 'pdd_store_not_found',
|
||||
})
|
||||
}
|
||||
cookie = store.cookie
|
||||
userAgent = userAgent || store.userAgent
|
||||
}
|
||||
|
||||
if (!cookie) {
|
||||
throw createHttpError('请提供待测试的 Cookie 字符串或指定有效的 shopId', {
|
||||
statusCode: 400,
|
||||
errorCode: 'pdd_cookie_required',
|
||||
})
|
||||
}
|
||||
|
||||
return testPddCookie({ cookie, userAgent })
|
||||
},
|
||||
{
|
||||
successMessage: 'Cookie 校验执行完成',
|
||||
errorMessage: 'Cookie 校验失败',
|
||||
scope: '[admin/platform-config/pdd/test-cookie]',
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* POST /platform-config/pdd/sync
|
||||
* Manually trigger order sync for all stores or a specific store.
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
* 自动生成合规 0as Anti-Content 并双向注入网关请求头与报文体。
|
||||
* - Structured MMS error resolution (Rate limit 40002, Auth expired 40001).
|
||||
* 结构化捕获与解析拼多多业务级错误(频控 40002、Cookie 失效 40001 等)。
|
||||
* - Live Cookie validity verification with latency metrics.
|
||||
* 商家 Cookie 有效性在线实测校验与连通性检测。
|
||||
*/
|
||||
|
||||
import { pddAntiContentEngine, PurePddAntiContent } from './pdd-anti-content.js'
|
||||
@@ -42,6 +44,13 @@ export interface PddOrderQueryResult {
|
||||
items: PddRawOrderItem[]
|
||||
}
|
||||
|
||||
export interface PddTestCookieResult {
|
||||
valid: boolean
|
||||
message: string
|
||||
totalOrders?: number | undefined
|
||||
firstOrderSn?: string | undefined
|
||||
}
|
||||
|
||||
export class PddClient {
|
||||
public static readonly BASE_URL = 'https://mms.pinduoduo.com'
|
||||
public static readonly RECENT_ORDERS_API = `${PddClient.BASE_URL}/mangkhut/mms/recentOrderList`
|
||||
@@ -219,4 +228,78 @@ export class PddClient {
|
||||
items,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Cookie validity by sending a single lightweight query to MMS API.
|
||||
* 通过发送轻量请求验证拼多多商家 Cookie 的有效性与网关连通性。
|
||||
*/
|
||||
public static async testCookie(credentials: {
|
||||
cookie: string
|
||||
userAgent?: string | undefined
|
||||
}): Promise<PddTestCookieResult> {
|
||||
const cookie = (credentials.cookie || '').trim()
|
||||
if (!cookie) {
|
||||
return {
|
||||
valid: false,
|
||||
message: 'Cookie 不能为空 / Cookie string cannot be empty',
|
||||
}
|
||||
}
|
||||
|
||||
const client = new PddClient({
|
||||
shopId: 'cookie_test',
|
||||
shopName: 'Cookie 测试',
|
||||
cookie,
|
||||
userAgent: credentials.userAgent,
|
||||
})
|
||||
|
||||
try {
|
||||
const result = await client.queryRecentOrders({
|
||||
pageNumber: 1,
|
||||
pageSize: 1,
|
||||
orderType: 0,
|
||||
})
|
||||
|
||||
const firstItem = result.items[0]
|
||||
return {
|
||||
valid: true,
|
||||
message: `Cookie 有效,网关校验通过(店铺在售/历史订单数: ${result.total})`,
|
||||
totalOrders: result.total,
|
||||
firstOrderSn: firstItem?.order_sn,
|
||||
}
|
||||
} catch (err) {
|
||||
const errMsg = err instanceof Error ? err.message : String(err)
|
||||
if (
|
||||
errMsg.includes('40001') ||
|
||||
errMsg.includes('登录') ||
|
||||
errMsg.includes('失效') ||
|
||||
errMsg.includes('未登录')
|
||||
) {
|
||||
return {
|
||||
valid: false,
|
||||
message: `Cookie 已失效或登录已过期: ${errMsg}`,
|
||||
}
|
||||
}
|
||||
if (errMsg.includes('40002') || errMsg.includes('频控')) {
|
||||
return {
|
||||
valid: false,
|
||||
message: `触发网关频控 (40002): 操作过于频繁,请稍后重试`,
|
||||
}
|
||||
}
|
||||
return {
|
||||
valid: false,
|
||||
message: `验证未通过: ${errMsg}`,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient helper to test Cookie validity.
|
||||
* 便捷辅助函数:测试 Cookie 有效性。
|
||||
*/
|
||||
export function testPddCookie(credentials: {
|
||||
cookie: string
|
||||
userAgent?: string | undefined
|
||||
}): Promise<PddTestCookieResult> {
|
||||
return PddClient.testCookie(credentials)
|
||||
}
|
||||
|
||||
@@ -80,7 +80,9 @@ export function mapPddOrderToSourceEvent(
|
||||
const skuName = spec ? `${goodsName} (${spec})` : goodsName
|
||||
const externalSkuCode = goodsIdStr
|
||||
|
||||
// Retain the entire raw snapshot dictionary as requested / 保留原始报文完整快照
|
||||
const itemSnapshot: JsonObject = {
|
||||
...(rawOrder as unknown as JsonObject),
|
||||
goodsId: goodsIdStr,
|
||||
goodsName,
|
||||
spec,
|
||||
@@ -92,7 +94,6 @@ export function mapPddOrderToSourceEvent(
|
||||
nickname: String(rawOrder.nickname || ''),
|
||||
orderTime: rawOrder.order_time,
|
||||
confirmTime: rawOrder.confirm_time,
|
||||
pddRaw: rawOrder as unknown as JsonObject,
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user