fix(pdd): integrate official sandboxed anti-content engine to resolve 40002 WAF error
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"cleanup:dev-data": "tsx scripts/cleanup-dev-data.ts",
|
||||
"build": "tsc -p tsconfig.build.json && rm -rf dist/db/migrations && mkdir -p dist/db && cp -R src/db/migrations dist/db/migrations",
|
||||
"build": "tsc -p tsconfig.build.json && rm -rf dist/db/migrations && mkdir -p dist/db && cp -R src/db/migrations dist/db/migrations && mkdir -p dist/services/platforms/pdd && cp src/services/platforms/pdd/pdd_anti.cjs dist/services/platforms/pdd/pdd_anti.cjs",
|
||||
"db:migrate": "tsx src/db/migrate.ts",
|
||||
"db:migrate:create": "tsx scripts/create-migration.ts",
|
||||
"db:migrate:status": "tsx scripts/migration-status.ts",
|
||||
|
||||
@@ -50,3 +50,13 @@ test('PurePddAntiContent executes with ultra-low latency (< 1ms per token)', ()
|
||||
// Average time should be well below 2ms
|
||||
assert.ok(avg < 2, `Average generation time should be < 2ms (actual: ${avg.toFixed(3)}ms)`)
|
||||
})
|
||||
|
||||
test('PurePddAntiContent.getTokenAsync generates valid tokens via official JS engine', async () => {
|
||||
const token = await pddAntiContentEngine.getTokenAsync({
|
||||
cookies: '_nano_fp=42e47e06a644482087; api_uid=rBQ51234',
|
||||
serverTimeMs: 1726119845000,
|
||||
})
|
||||
|
||||
assert.ok(token.startsWith('0as'), 'Async token must start with 0as prefix')
|
||||
assert.ok(token.length > 200, `Async token length should be > 200 (actual: ${token.length})`)
|
||||
})
|
||||
|
||||
@@ -25,6 +25,25 @@
|
||||
|
||||
import zlib from 'node:zlib'
|
||||
import crypto from 'node:crypto'
|
||||
import { createRequire } from 'node:module'
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
type PddAntiJsGeneratorFn = (
|
||||
cookies: string,
|
||||
serverTime?: number,
|
||||
options?: { userAgent?: string; href?: string; referer?: string },
|
||||
) => Promise<string>
|
||||
|
||||
let pddAntiJsGenerator: PddAntiJsGeneratorFn | null = null
|
||||
try {
|
||||
const mod = require('./pdd_anti.cjs') as { generateAntiContent?: PddAntiJsGeneratorFn }
|
||||
if (typeof mod.generateAntiContent === 'function') {
|
||||
pddAntiJsGenerator = mod.generateAntiContent
|
||||
}
|
||||
} catch {
|
||||
pddAntiJsGenerator = null
|
||||
}
|
||||
|
||||
export interface PddAntiContentOptions {
|
||||
/**
|
||||
@@ -304,15 +323,53 @@ export class PurePddAntiContent {
|
||||
// 6. Prepend '0as' Token Prefix / 第六步:添加 '0as' 协议前缀
|
||||
return `0as${encodedBody}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate anti-content token asynchronously.
|
||||
* Prioritizes the official MMS sandboxed JS engine (pdd_anti.cjs),
|
||||
* falling back to the pure TLV algorithm if unavailable.
|
||||
* 异步生成 anti-content Token。
|
||||
* 优先使用拼多多官方 MMS 商家后台原生 JS 引擎 (pdd_anti.cjs),
|
||||
* 若不可用则自动降级到原生 TLV 纯算法。
|
||||
*/
|
||||
public async getTokenAsync(options: GetTokenOptions = {}): Promise<string> {
|
||||
if (pddAntiJsGenerator) {
|
||||
try {
|
||||
const token = await pddAntiJsGenerator(
|
||||
options.cookies || '',
|
||||
options.serverTimeMs || Date.now(),
|
||||
{
|
||||
userAgent: options.userAgent || PurePddAntiContent.DEFAULT_UA,
|
||||
href: options.href || PurePddAntiContent.DEFAULT_HREF,
|
||||
referer: options.referer || PurePddAntiContent.DEFAULT_REFERER,
|
||||
},
|
||||
)
|
||||
if (token && typeof token === 'string' && token.startsWith('0as')) {
|
||||
return token
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[PddAntiContent] Official JS engine failed, falling back to pure TLV:', err)
|
||||
}
|
||||
}
|
||||
return this.getToken(options)
|
||||
}
|
||||
}
|
||||
|
||||
// Global singleton instance / 全局单例生成器
|
||||
export const pddAntiContentEngine = new PurePddAntiContent()
|
||||
|
||||
/**
|
||||
* Quick helper to generate anti-content token.
|
||||
* 便捷快捷函数:生成 anti-content Token。
|
||||
* Quick helper to generate anti-content token synchronously using pure TLV.
|
||||
* 便捷同步函数:使用原生 TLV 纯算生成 anti-content Token。
|
||||
*/
|
||||
export function generatePddAntiContent(options: GetTokenOptions = {}): string {
|
||||
return pddAntiContentEngine.getToken(options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick helper to generate anti-content token asynchronously (recommended).
|
||||
* 推荐快捷异步函数:生成 anti-content Token(优先使用官方 JS 引擎)。
|
||||
*/
|
||||
export async function generatePddAntiContentAsync(options: GetTokenOptions = {}): Promise<string> {
|
||||
return pddAntiContentEngine.getTokenAsync(options)
|
||||
}
|
||||
|
||||
@@ -144,8 +144,8 @@ export class PddClient {
|
||||
// 1. Get synchronized server time / 获取校准时间戳
|
||||
const serverTimeMs = await this.getSynchronizedServerTime()
|
||||
|
||||
// 2. Generate anti-content token / 生成纯算 anti-content
|
||||
const antiContent = pddAntiContentEngine.getToken({
|
||||
// 2. Generate anti-content token / 生成纯算 anti-content (优先使用官方沙箱引擎)
|
||||
const antiContent = await pddAntiContentEngine.getTokenAsync({
|
||||
cookies: this.credentials.cookie,
|
||||
userAgent: this.credentials.userAgent || PurePddAntiContent.DEFAULT_UA,
|
||||
serverTimeMs,
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user