qihang-ecom-erp-open/docs/yunxi-pdd-goods-listing-gat...

12 KiB
Raw Permalink Blame History

External 系统 → 启航ERP拼多多商品上架网关裁剪与改造方案

目标:在 qihang-ecom-erp-open 基础上,仅保留“商品上架/商品同步(仅商品域)/接口鉴权”能力,作为单体服务提供给外部系统调用。
首期平台:拼多多
调用方:外部系统(传入商品数据 + shopId + platform)。
店铺授权:由本服务维护(外部系统不传 appKey/appSecret/accessToken
鉴权:AK/SK 签名鉴权system-to-system

1. 范围与非目标

1.1 In Scope首期必须

  • 商品数据接入外部系统推送商品SPU + SKU到本服务创建/更新)。
  • 拼多多上架全链路
    • A 创建商品(首次发布)
    • B 更新商品信息(标题/主图/详情/属性等)
    • C 更新 SKU规格、价格等
    • D 更新库存
    • E 上架/下架
    • F 接收“已准备好的商品数据”(图片/详情为可访问 URL 或可上传的素材)并发起平台发布
  • 最小商品同步
    • 从拼多多拉取商品(用于对账/状态回写/增量同步),保留 pull_goods 能力即可
    • 同步结果落库,供外部系统查询/校验
  • 接口鉴权
    • 调用方 → 本服务 API 必须签名验证AK/SK
    • 失败拒绝401/403并记录审计日志

1.2 Out of Scope首期明确不做/可后置)

  • 订单/售后/发货/电子面单/仓库/采购等业务域
  • 多平台(淘宝/京东/抖店/快手/小红书/微信小店等)
  • 前端管理后台Vue与多租户/多商户能力
  • AI-agent 相关能力

2. 现状评估(基于当前开源代码)

2.1 已具备的基础能力

  • 商品库接入入口erp-api 下存在 POST /goods/add,并且模型存在 outerErpGoodsId 等外部标识字段,适合承接调用方商品数据。
  • 拼多多商品拉取(同步)oms-api 下存在 POST /pdd/goods/pull_goods,当前实现是“拉取列表并落库”。
  • 安全模块线索core/security 已存在并在 erp-api/oms-api 引用(但对调用方的 S2S 鉴权需要单独设计)。

2.2 关键缺口(必须改造/补齐)

  • 当前拼多多侧 open-sdk-2.1.12.jar 中公开的 PddGoodsApiHelper 仅暴露 pullGoodsList(拉取),未暴露“创建/更新/上下架/库存更新”等发布能力。
  • 因此,商品上架全链路需要新增拼多多发布适配层(可能复用已有签名/HTTP 基础设施,但要补齐 API

3. 目标架构(单体部署)

3.1 进程形态

单体 Spring Boot 应用Java 17对外提供 REST API

  • external-api:外部系统调用入口(推送商品/触发上架/查询结果)
  • admin-api(可选,首期可不暴露):用于运维/店铺授权维护/密钥配置

3.2 逻辑分层(建议)

  • API 层:只做参数校验、鉴权、幂等键处理、调用 Service、统一响应
  • Service 层
    • 统一商品模型校验与映射
    • 上架编排(创建→更新→库存→上架状态)
    • 与拼多多适配层交互
    • 任务化(可选):异步发布/重试/死信
  • Adapter 层PDD
    • HTTP + 签名 + 请求/响应模型
    • 平台错误码映射

4. 对外接口设计External/外部系统 → 本服务)

说明:下面是建议接口。落地时以外部系统现有调用规范为准,可在后续命令下达后再对齐路径/DTO 命名。

4.0 已确认口径(冻结)

  • shopId全平台唯一,可直接作为本服务店铺主键,不考虑跨平台撞号。
  • platform:由外部系统显式传入,取值采用 PDD/TAO/JD/DOU/WEIXIN/KWAI/XHS(后续平台新增再扩展枚举)。
  • AK/SK一套即可(外部系统作为单一调用方)。
  • X-Timestamp毫秒ms
  • X-SignatureBase64 编码HMAC-SHA256 输出 bytes → Base64
  • 签名 body使用原始请求体 raw bytes 计算 SHA-256不做 JSON 重排/字段排序)。
  • 参数形态:统一走 body(尽量避免 queryGET 若必须使用 query则改为 POST 查询接口更一致)。
  • 幂等:完全由本服务内部实现,不依赖调用方提供 X-Request-Id
  • 商品素材:首期按公网可访问 URL(不做素材代上传)。
  • 接口形态:首期按同步接口(直接返回发布结果或明确错误)。

4.1 统一返回

  • code: 0 成功;非 0 失败
  • msg: 错误信息
  • data: 业务数据

4.2 鉴权AK/SK 签名)

请求头

  • X-Api-Key: 分配给调用方的 AK
  • X-Timestamp: 毫秒时间戳(例如 1710000000000
  • X-Nonce: 随机串(建议 16~32
  • X-Signature: 签名串Base64
  • Content-Type: application/json

签名串构造(推荐)

canonical string

  1. HTTP_METHOD(大写)
  2. PATH(不含域名,不含 query
  3. timestamp
  4. nonce
  5. bodySha256Hex(请求体 raw bytes 的 SHA-256hex

拼接方式:

METHOD + "\n" +
PATH + "\n" +
timestamp + "\n" +
nonce + "\n" +
bodySha256Hex

签名算法:

  • signature = HMAC-SHA256(secret, canonicalString)
  • 输出:对 signature 的 bytes 做 Base64

校验规则

  • timestamp 与服务端时间偏差 ≤ 300 秒(按 ms 计算)
  • nonce 在时间窗内不可重复(需要缓存,例如 Redis/本地 Caffeine首期可先用 Redis
  • X-Api-Key 必须存在且有效(数据库/配置中)
  • X-Signature 校验失败直接拒绝

错误码建议

  • 401缺少必要头/签名参数
  • 403签名错误、AK 无效、nonce 重放
  • 429频控可选

4.3 商品接入与上架接口(建议)

4.3.1 推送/更新商品SPU + SKU

POST /external/goods/upsert

入参:

  • shopId(必填)
  • platform(必填,枚举,例如 PDD/TAO/JD…;首期仅允许 PDD
  • outGoodsId调用方侧商品ID用于幂等与映射
  • titlemainImages[]detail(富文本/图片 URL 列表等)
  • skus[]outSkuIdspecpricestockbarCode
  • categoryattrsbrandweightshipping

行为:

  • 本地保存/更新商品库(以 shopId + outGoodsId 幂等)
  • 返回本地 goodsId内部ID与当前状态

4.3.2 触发上架(编排)

POST /external/goods/listing/submit

入参:

  • shopId
  • platform(必填,首期仅允许 PDD
  • outGoodsId
  • mode: CREATE_OR_UPDATE(默认)

行为(同步/异步二选一,建议首期同步 + 超时控制,后续演进异步):

  • 若平台商品不存在:创建商品 → 创建/更新 SKU → 设置库存 → 上架
  • 若已存在:更新商品 → 更新 SKU → 库存 → 上架/保持

返回:

  • listingTaskId(若异步)
  • 或直接返回平台侧 goodsId/状态

4.3.3 上下架

POST /external/goods/listing/status

入参:

  • shopId
  • platform(必填,首期仅允许 PDD
  • outGoodsId
  • status: ON/OFF

4.3.4 库存更新(可被 submit 内部调用,也可单独暴露)

POST /external/goods/stock/update

入参:

  • shopId
  • platform(必填,首期仅允许 PDD
  • outGoodsId
  • skus[]: outSkuId + stock

4.3.5 查询发布状态/映射

GET /external/goods/listing/status?shopId=...&platform=...&outGoodsId=...

返回:

  • 平台商品ID、上下架状态、最后一次错误、最后同步时间

5. 领域模型(最小集合)

5.1 本地核心表(建议最小)

  • shop:店铺基础信息(含平台类型=PDD
  • shop_auth:拼多多 appKey/appSecret/accessToken/refreshToken/过期时间
  • goods:统一商品(承接调用方)
  • goods_sku:统一 SKU承接调用方
  • goods_platform_mapping:统一商品与平台商品映射(平台 goodsId、skuId 映射)
  • listing_task(可选):异步发布任务、重试次数、状态机
  • api_clientAK/SK、状态、权限范围、IP 白名单(可选)
  • api_request_log:审计(签名校验结果、请求摘要、耗时)

5.2 幂等策略(必须)

  • shopId + outGoodsId:商品幂等键
  • shopId + outSkuIdSKU 幂等键
  • 不依赖调用方幂等键:本服务内部需实现“请求去重/防重复上架”。
    • 推荐:落库 idempotency_key = sha256Hex(platform + shopId + outGoodsId + operation + normalizedBodyHash)
    • 同一 idempotency_key 在有效期内重复请求:直接返回第一次执行结果
    • 对“提交上架”类接口:至少保证不会重复创建平台商品

6. 拼多多适配PDD Adapter设计要点

6.1 适配层职责

  • 拼多多 API 签名、请求发送、响应解析
  • 平台错误码归一化
  • “创建/更新/上下架/库存”接口封装为内部方法:
    • createGoods(...)
    • updateGoods(...)
    • updateSku(...)
    • updateStock(...)
    • setGoodsOnSale(...) / setGoodsOffSale(...)

6.2 依赖策略(重要)

当前 oms-api 通过 systemPath 引入 open-sdk-2.1.12.jar

首期有两条路径(二选一):

  • 路径 1优先:在本仓库内新增 pdd-adapter(源码方式),不再依赖 open-sdk-2.1.12.jar 做发布能力(只保留 pull 同步可继续复用或也迁移)。
  • 路径 2备选:升级/替换 open-sdk,确保其暴露发布相关 API需要确认是否可获得源码/维护成本)。

推荐路径 1可控、可审计、便于后续扩展多平台。

7. 裁剪方案(保留/删除建议)

原项目是微服务结构gateway/sys-api/erp-api/oms-api 等)。你的目标是单体优先,因此裁剪思路是:

  1. 保留商品域 + 拼多多域 + 鉴权
  2. 其它域模块不编译/不启动/不暴露接口

7.1 建议保留(首期)

  • core/common通用工具、AjaxResult 等)
  • core/security(复用登录/权限基础设施的同时,新增 S2S AK/SK 鉴权)
  • model(实体/BO/VO
  • mapperDB 访问)
  • serviceserviceImpl 中与商品/店铺/拼多多相关的最小集合
  • api/erp-api(商品库接入:/goods/add 等入口可重构为 /external/goods/*
  • api/oms-api拼多多商品拉取(同步)相关接口(可改为内部任务或保留对外)

7.2 建议禁用/后置

  • api/ai-agent
  • api/sys-api(如仅对调用方开放,不需要后台用户体系,可后置)
  • api/gateway(若单体直连,不需要网关;若保留网关需把 TokenFilter 改为 AK/SK 校验)
  • oms-api 中非拼多多平台dou/jd/tao/wei/kwai…
  • 订单/售后/发货/库存出入库/采购等 Controller 与 Service

8. 安全与审计

  • 所有外部系统接口强制 AK/SK
  • 平台一致性校验(强制)
    • 调用方传入 platform
    • 服务端根据 shopId 查询数据库中的 shopType/platformType
    • 若两者不一致:直接拒绝(建议 400 或 403记录审计日志
    • 目的:避免“串平台/串店铺”导致误上架
  • shopId 必须存在且平台类型为 PDD
  • 店铺 accessToken 过期:返回明确错误码(例如 SHOP_TOKEN_EXPIRED),并支持后台刷新/重新授权流程(首期可人工)
  • 全链路日志:
    • requestIdshopIdoutGoodsId、平台错误码、耗时
  • 敏感信息保护:
    • appSecret/accessToken 加密存储KMS/本地对称加密;首期可用配置密钥 + AES
    • 严禁打印明文 token/secret

9. 验证与验收清单(首期)

  • 外部系统推送商品 → 本地入库(幂等生效)
  • 触发上架 → 拼多多创建/更新/库存/上下架成功(全链路)
  • 上架失败可返回可读错误(含平台原始信息可追踪)
  • pull_goods 同步可用(用于对账/状态回写)
  • AK/SK
    • 缺参拒绝
    • 签名错误拒绝
    • 超时拒绝
    • nonce 重放拒绝
    • 审计日志完整

10. 待你确认/后续落地前置

  • 拼多多商品发布所需字段“最小集”(类目、属性、物流、售后承诺、资质等)需要你提供调用方侧现有字段映射或样例 payload。
  • 是否需要“异步上架”(返回 taskId + 回调/轮询)。首期建议同步,但需要设定超时时间与重试策略。