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:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user