feat(pdd): 拼多多订单支持 out_sku_sn 匹配与浏览器插件加密保活

- 拼多多进单 Cookie 失效即时拦截与告警修复(支持 43001 会话过期等错误识别)
- 拼多多订单映射优先使用 out_sku_sn(外部商家编码)作为商品规格与工单匹配核心字段
- 新增 Chrome/Edge 浏览器扩展 (Manifest V3),支持端到端 RSA-OAEP + AES-256-GCM 信封加密自动保活
- 后台店铺管理新增插件配对面板、专属密钥管理与一键导入配置 JSON
This commit is contained in:
yml2213
2026-09-14 12:24:48 +08:00
parent 38c0cf1223
commit 9fb27b0ad2
26 changed files with 2090 additions and 22 deletions
@@ -7,10 +7,12 @@ import {
ApiOutlined,
CheckCircleOutlined,
CloseCircleOutlined,
CopyOutlined,
DeleteOutlined,
EditOutlined,
FieldTimeOutlined,
GlobalOutlined,
LinkOutlined,
PlusOutlined,
ReloadOutlined,
SafetyCertificateOutlined,
@@ -48,6 +50,7 @@ import { showError, showSuccess } from '@/lib/feedback'
import {
deleteAdminPddStore,
fetchAdminPddConfig,
generateAdminPddStoreSyncToken,
saveAdminPddConfig,
saveAdminPddStore,
testAdminPddCookie,
@@ -118,6 +121,35 @@ export function PddPlatformPanel() {
const [modalTesting, setModalTesting] = useState(false)
const [modalTestResult, setModalTestResult] = useState<AdminPddTestCookieResult | null>(null)
// Extension Pairing Modal State / 浏览器插件配对弹窗状态
const [extensionModalStore, setExtensionModalStore] = useState<AdminPddStoreItem | null>(null)
const [generatingToken, setGeneratingToken] = useState(false)
/**
* Generate or rotate syncToken for the store
* 为当前店铺生成/重置插件配对密钥
*/
async function handleGenerateSyncToken(shopId: string) {
setGeneratingToken(true)
try {
const res = await generateAdminPddStoreSyncToken(shopId)
if (res?.data?.syncToken) {
showSuccess('插件配对密钥已生成')
if (extensionModalStore && extensionModalStore.shopId === shopId) {
setExtensionModalStore({
...extensionModalStore,
syncToken: res.data.syncToken,
})
}
await loadConfig()
}
} catch (err: any) {
showError(err.message || '生成插件配对密钥失败')
} finally {
setGeneratingToken(false)
}
}
useEffect(() => {
void loadConfig()
}, [])
@@ -520,6 +552,11 @@ export function PddPlatformPanel() {
{timeDisplay} 校验
</Text>
)}
{record.lastExtensionSyncAt && (
<Tag color="cyan" style={{ fontSize: '11px', margin: 0 }}>
插件保活: {formatDisplayTime(record.lastExtensionSyncAt)}
</Tag>
)}
</Space>
)
}
@@ -537,6 +574,11 @@ export function PddPlatformPanel() {
{timeDisplay} 校验
</Text>
)}
{record.lastExtensionSyncAt && (
<Tag color="orange" style={{ fontSize: '11px', margin: 0 }}>
插件上次: {formatDisplayTime(record.lastExtensionSyncAt)}
</Tag>
)}
</Space>
)
}
@@ -547,10 +589,19 @@ export function PddPlatformPanel() {
{
title: '操作',
key: 'action',
width: 300,
width: 360,
fixed: 'right',
render: (_, record) => (
<Space size={6} wrap={false}>
<Tooltip title="配置 Chrome/Edge 浏览器插件自动保活与端到端加密同步">
<Button
size="small"
icon={<LinkOutlined />}
onClick={() => setExtensionModalStore(record)}
>
插件配对
</Button>
</Tooltip>
<Tooltip title="通过 Pure TS 0as 引擎实时测试 MMS 商家 Cookie 有效性并持久化校验状态">
<Button
size="small"
@@ -1109,6 +1160,163 @@ export function PddPlatformPanel() {
</Form.Item>
</Form>
</Modal>
{/* 浏览器插件配对弹窗 */}
<Modal
title={`浏览器插件配对:${extensionModalStore?.shopName || ''} (${extensionModalStore?.shopId || ''})`}
open={Boolean(extensionModalStore)}
onCancel={() => setExtensionModalStore(null)}
footer={[
<Button key="close" onClick={() => setExtensionModalStore(null)}>
关闭
</Button>,
]}
width={680}
>
<Alert
type="info"
showIcon
message="无感自动保活:配合 Chrome / Edge 扩展程序使用"
description="在客服日常登录拼多多后台的浏览器中安装「拼多多 Cookie 自动保活」扩展后,插件会在后台自动捕获新鲜 Cookie 并通过 RSA-OAEP + AES-256-GCM 混合信封加密安全同步,免除每天人工复制抓包与漏单风险。"
style={{ marginBottom: 16 }}
/>
<div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
<div>
<Text strong>服务端接口地址 (Server API URL):</Text>
<div style={{ marginTop: 4 }}>
<Input
readOnly
value={window.location.origin}
addonAfter={
<Button
type="link"
size="small"
icon={<CopyOutlined />}
onClick={() => {
void navigator.clipboard.writeText(window.location.origin)
showSuccess('接口地址已复制')
}}
>
复制
</Button>
}
/>
</div>
</div>
<div>
<Text strong>店铺专属配对密钥 (Sync Token):</Text>
<div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
<Input
readOnly
value={extensionModalStore?.syncToken || '(未生成配对密钥)'}
placeholder="点击右侧按钮生成专属密钥"
style={{
fontFamily: 'monospace',
color: extensionModalStore?.syncToken ? '#1890ff' : '#8c8c8c',
}}
/>
<Button
type="primary"
loading={generatingToken}
onClick={() =>
extensionModalStore?.shopId && handleGenerateSyncToken(extensionModalStore.shopId)
}
>
{extensionModalStore?.syncToken ? '重新生成密钥' : '生成配对密钥'}
</Button>
</div>
<div style={{ fontSize: 12, color: '#8c8c8c', marginTop: 4 }}>
* 重新生成密钥后,旧插件配对将失效,需将新密钥填入插件中。
</div>
</div>
{extensionModalStore?.syncToken ? (
<Card size="small" style={{ background: '#f8fafc', borderColor: '#e2e8f0' }}>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 8,
}}
>
<Text strong style={{ fontSize: 13 }}>
一键导入插件配置 (JSON):
</Text>
<Button
size="small"
type="primary"
icon={<CopyOutlined />}
onClick={() => {
const cfg = JSON.stringify(
{
serverUrl: window.location.origin,
shopId: extensionModalStore.shopId,
shopName: extensionModalStore.shopName,
syncToken: extensionModalStore.syncToken,
},
null,
2,
)
void navigator.clipboard.writeText(cfg)
showSuccess('插件配置 JSON 已复制,打开插件点击【导入配置】即可!')
}}
>
一键复制完整配置
</Button>
</div>
<pre
style={{
margin: 0,
fontSize: 12,
fontFamily: 'monospace',
background: '#ffffff',
padding: '8px 12px',
borderRadius: 4,
border: '1px solid #e2e8f0',
maxHeight: 120,
overflow: 'auto',
}}
>
{JSON.stringify(
{
serverUrl: window.location.origin,
shopId: extensionModalStore.shopId,
shopName: extensionModalStore.shopName,
syncToken: extensionModalStore.syncToken,
},
null,
2,
)}
</pre>
</Card>
) : null}
<Card size="small" title="插件安装指引" style={{ background: '#fafafa' }}>
<ol
style={{
paddingLeft: 20,
margin: 0,
fontSize: 12,
color: '#475569',
lineHeight: 1.8,
}}
>
<li>
插件源码已存放在项目目录:
<Text code>apps/extensions/pdd-cookie-sync/</Text>
</li>
<li>
在 Chrome / Edge 浏览器打开:<Text code>chrome://extensions</Text>
</li>
<li>开启右上角【开发者模式】,点击左上角【加载已解压的扩展程序】并选择该目录;</li>
<li>点击浏览器工具栏扩展图标,点击【导入配置】并粘贴上述配置,保存即完成绑定!</li>
</ol>
</Card>
</div>
</Modal>
</section>
)
}
@@ -10,6 +10,7 @@ import type {
AdminPddTestCookieResult,
AdminPddSyncResult,
AdminPddSyncAllResponse,
AdminPddStoreSyncTokenResponse,
} from '@/types/admin/platform-config'
export function fetchAdminPddConfig() {
@@ -49,3 +50,9 @@ export function triggerAdminPddSync(
payload,
)
}
export function generateAdminPddStoreSyncToken(shopId: string) {
return apiPost<AdminPddStoreSyncTokenResponse>(
`/api/v1/admin/platform-config/pdd/stores/${encodeURIComponent(shopId)}/sync-token`,
)
}
@@ -85,4 +85,5 @@ export type {
AdminPddTestCookieResult,
AdminPddSyncResult,
AdminPddSyncAllResponse,
AdminPddStoreSyncTokenResponse,
} from './pdd'
@@ -15,6 +15,14 @@ export interface AdminPddStoreItem {
cookieValid?: boolean
cookieCheckMessage?: string
totalOrders?: number
syncToken?: string
lastExtensionSyncAt?: string
}
export interface AdminPddStoreSyncTokenResponse {
shopId: string
shopName: string
syncToken: string
}
export interface AdminPddConfig {