- 拼多多进单 Cookie 失效即时拦截与告警修复(支持 43001 会话过期等错误识别) - 拼多多订单映射优先使用 out_sku_sn(外部商家编码)作为商品规格与工单匹配核心字段 - 新增 Chrome/Edge 浏览器扩展 (Manifest V3),支持端到端 RSA-OAEP + AES-256-GCM 信封加密自动保活 - 后台店铺管理新增插件配对面板、专属密钥管理与一键导入配置 JSON
152 lines
4.7 KiB
TypeScript
152 lines
4.7 KiB
TypeScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import express from 'express'
|
|
import http from 'node:http'
|
|
|
|
import pddExtensionRouter from './pdd-extension.js'
|
|
import {
|
|
getOrCreatePddRsaKeyPair,
|
|
testEncryptPddPayload,
|
|
} from '../services/platforms/pdd/pdd-crypto-service.js'
|
|
import {
|
|
generatePddStoreSyncToken,
|
|
getPddStoreById,
|
|
savePddSourcesConfig,
|
|
getPddSourcesConfig,
|
|
} from '../services/platforms/pdd/pdd-source-config-service.js'
|
|
import { PddClient } from '../services/platforms/pdd/pdd-client.js'
|
|
|
|
import { query } from '../db/client.js'
|
|
|
|
function makeTestApp() {
|
|
const app = express()
|
|
app.use(express.json())
|
|
app.use('/api/v1/pdd/extension', pddExtensionRouter)
|
|
return app
|
|
}
|
|
|
|
test('pdd-extension router: GET /public-key and POST /sync-cookie full flow', async (t) => {
|
|
let dbAvailable = false
|
|
try {
|
|
const check = await query('SELECT 1').catch(() => null)
|
|
dbAvailable = Boolean(check)
|
|
} catch {
|
|
dbAvailable = false
|
|
}
|
|
|
|
if (!dbAvailable) {
|
|
t.skip('Skipping integration test: PostgreSQL database is not reachable outside container')
|
|
return
|
|
}
|
|
|
|
const app = makeTestApp()
|
|
const server = http.createServer(app)
|
|
await new Promise<void>((resolve) => server.listen(0, resolve))
|
|
const addr = server.address()
|
|
const port = typeof addr === 'object' && addr ? addr.port : 0
|
|
const baseUrl = `http://127.0.0.1:${port}/api/v1/pdd/extension`
|
|
|
|
// Prepare a test store in config
|
|
const originalConfig = getPddSourcesConfig()
|
|
const testShopId = 'test_shop_router_01'
|
|
const mockConfig = {
|
|
...originalConfig,
|
|
stores: [
|
|
{
|
|
shopId: testShopId,
|
|
shopName: '测试路由店铺',
|
|
cookie: 'old_cookie=123;',
|
|
cookieValid: false,
|
|
enabled: true,
|
|
},
|
|
],
|
|
}
|
|
await savePddSourcesConfig(mockConfig)
|
|
|
|
// Generate sync token
|
|
const token = await generatePddStoreSyncToken(testShopId)
|
|
|
|
// Mock PddClient.testCookie
|
|
const originalTestCookie = PddClient.testCookie
|
|
PddClient.testCookie = async () => ({
|
|
valid: true,
|
|
totalOrders: 88,
|
|
})
|
|
|
|
try {
|
|
// 1. Test GET /public-key
|
|
const pkResp = await fetch(`${baseUrl}/public-key`)
|
|
assert.equal(pkResp.status, 200)
|
|
const pkData = await pkResp.json()
|
|
assert.equal(pkData.code, 0)
|
|
assert.ok(pkData.data.publicKeySpki)
|
|
assert.equal(pkData.data.algorithm, 'RSA-OAEP-256')
|
|
|
|
// 2. Test POST /sync-cookie with missing token
|
|
const kp = getOrCreatePddRsaKeyPair()
|
|
const payload = {
|
|
shopId: testShopId,
|
|
cookie: 'new_fresh_cookie=xyz;',
|
|
userAgent: 'Mozilla/5.0 Extension Test',
|
|
timestamp: Date.now(),
|
|
nonce: 'nonce_test_' + Math.random().toString(36).slice(2),
|
|
}
|
|
const envelope = testEncryptPddPayload(payload, kp.publicKeyPem)
|
|
|
|
const noTokenResp = await fetch(`${baseUrl}/sync-cookie`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ envelope }),
|
|
})
|
|
assert.equal(noTokenResp.status, 401)
|
|
|
|
// 3. Test POST /sync-cookie with wrong token
|
|
const wrongTokenResp = await fetch(`${baseUrl}/sync-cookie`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Shop-Token': 'wrong-token-abc',
|
|
},
|
|
body: JSON.stringify({
|
|
envelope: testEncryptPddPayload(
|
|
{ ...payload, nonce: 'nonce_wrong_' + Math.random().toString(36).slice(2) },
|
|
kp.publicKeyPem,
|
|
),
|
|
}),
|
|
})
|
|
assert.equal(wrongTokenResp.status, 403)
|
|
|
|
// 4. Test POST /sync-cookie with valid token and fresh nonce
|
|
const freshPayload = {
|
|
...payload,
|
|
nonce: 'nonce_fresh_' + Math.random().toString(36).slice(2),
|
|
}
|
|
const freshEnvelope = testEncryptPddPayload(freshPayload, kp.publicKeyPem)
|
|
const validResp = await fetch(`${baseUrl}/sync-cookie`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Shop-Token': token,
|
|
},
|
|
body: JSON.stringify({ envelope: freshEnvelope }),
|
|
})
|
|
assert.equal(validResp.status, 200)
|
|
const validData = await validResp.json()
|
|
assert.equal(validData.code, 0)
|
|
assert.equal(validData.data.shopId, testShopId)
|
|
assert.equal(validData.data.valid, true)
|
|
assert.equal(validData.data.totalOrders, 88)
|
|
|
|
// Verify store was updated in memory/config
|
|
const updatedStore = getPddStoreById(testShopId)
|
|
assert.ok(updatedStore)
|
|
assert.equal(updatedStore.cookie, 'new_fresh_cookie=xyz;')
|
|
assert.equal(updatedStore.cookieValid, true)
|
|
assert.ok(updatedStore.lastExtensionSyncAt)
|
|
} finally {
|
|
PddClient.testCookie = originalTestCookie
|
|
await savePddSourcesConfig(originalConfig)
|
|
await new Promise<void>((resolve) => server.close(() => resolve()))
|
|
}
|
|
})
|