×

《多平台ERP架构选型:五家API收费模型倒推出来的最优解》(附python源码)

万邦科技Lex 万邦科技Lex 发表于2026-07-26 09:49:50 浏览21 评论0

抢沙发发表评论

把前几篇拆开的计费口径倒推回来,多平台ERP的最优架构不是“能调通就行”,而是用各家的收费模型反推部署位置、同步方式与熔断策略。五家(淘宝TOP / 京东JOS / 1688 / 拼多多 / 抖店)的收费基因不同,但收敛出来是一套通用骨架。

一、五家收费模型 → 架构约束倒推

平台
收费基因
对架构的硬约束
淘宝TOP
基础超量¥0.02/百次(塔内)·¥0.20(塔外);增值禁外调;DSS推送¥0.12/百单
必须聚石塔内;订单优先DSS推送+增量API兜底;CRM/罗盘类增值必须签约入塔
京东JOS
联盟免费(抽佣);商家基础有日免额、超量¥0.02~0.10/百次;电子面单按单;增值包年
联盟与商家Key物理隔离;订单增量pop.order.search;库存用ware.read.get拿真stockNum
1688
基础免费+QPS 10/20;高级实时库存/提频买资源包(几百~几千/年)
批发同步别硬轮询,爆款用高级包或Webhook;多Key同企业轮询仅作兜底
拼多多
预充值;基础云内¥0.01/百次·云外¥0.10;增值禁外调
必须拼多多云内+余额守卫;欠费硬切断非限流,需本地计数器兜底
抖店
基础云内¥0.018/百次·云外¥0.18;增值禁外调;预充值
必须抖店云内;2026.7起商品发布也收费,发布流程合并调用
收敛出的三条铁律:
  1. 阿里系+抖系=强制云内(外调贵10倍或禁止),拼多多=强制云内(欠费断气)。

  2. 订单同步能推不拉——淘宝DSS、1688 Webhook、抖店消息推送优先,API增量仅作补偿。

  3. 配额/余额守卫是ERP的一部分,不是外围脚本


二、最优整体架构(分层+按平台着色)

┌─────────────────────────────────────────────┐
│ 业务层 ERP/OMS/WMS(统一订单/库存/商品域)     │
└───────────────┬─────────────────────────────┘
                │ 统一事件(OrderCreated/StockChanged)
┌───────────────┴─────────────────────────────┐
│ 适配层 Adapter(每平台一个Client)             │
│  TaobaoAdapter(聚石塔内)  JdAdapter           │
│  Ali1688Adapter(高级包/Webhook)               │
│  PddAdapter(云内+余额守卫)  DyAdapter(云内)    │
└───────────────┬─────────────────────────────┘
                │ MQ(Kafka) 削峰 + 令牌桶限速
┌───────────────┴─────────────────────────────┐
│ 调度层:增量时间窗 + 推送消费 + 失败补偿队列   │
│ Redis:幂等键 / 库存原子预扣 / 日调用计数      │
└───────────────┬─────────────────────────────┘
  部署:淘宝→聚石塔ECS │ 抖店→抖店云 │ 拼多多→拼多多云
        京东→京东云/聚石塔 │ 1688→阿里云(同主体VPC)
核心模块:
  • 统一模型:平台订单→内部OrderDTO,平台SKU→内部SkuInventory(区分可售/锁定/在途)。

  • 推送为主:淘宝DSS、抖店/1688消息订阅、拼多多订单推送(若有)走MQ consumer;API增量每5~30min补偿一次。

  • 令牌桶按Key:淘宝/京东/1688单Key限速在免费QPS的80%(如1688搜8/s、订单16/s)。

  • 余额/配额守卫:拼多多余额<3天预估消耗熔断非核心;淘宝/京东日调用达免额80%切纯增量。


三、Python:多平台统一 Guard 骨架(可直插ERP)

# multi_platform_erp_guard.py
"""五家API统一守卫:云内判定 + 日配额 + 余额预警 + 限流退避"""
import time, json, hashlib, requests
from abc import ABC, abstractmethod
from threading import Lock

class PlatformQuota:
    """各平台计费/限额元数据"""
    META = {
        "taobao":  {"free_daily": 80_000, "in_price": 0.02, "out_price": 0.20, "must_tower": True},
        "jd":      {"free_daily": 50_000, "in_price": 0.05, "out_price": 0.15, "must_tower": False},
        "ali1688": {"free_daily": 100_000, "qps": 10, "adv_pack": False, "must_tower": False},
        "pdd":     {"unit_in": 0.01/100, "unit_out": 0.10/100, "prepaid": True, "must_tower": True},
        "douyin":  {"unit_in": 0.018/100, "unit_out": 0.18/100, "prepaid": True, "must_tower": True},
    }


class BaseGuard(ABC):
    def __init__(self, name, app_key, app_secret, in_cloud: bool):
        self.name = name
        self.ak, self.as = app_key, app_secret
        self.in_cloud = in_cloud
        self.today_calls = 0
        self._lock = Lock()
        meta = PlatformQuota.META[name]
        if meta.get("must_tower") and not in_cloud:
            raise RuntimeError(f"{name} 必须云内部署,否则高价/禁调/欠费断气")

    def _roll_day(self):
        pass  # 简化:实际用日期判断重置today_calls

    def before_call(self, is_value=False):
        self._roll_day()
        m = PlatformQuota.META[self.name]
        # 1. 增值接口云外禁调
        if is_value and not self.in_cloud and m.get("must_tower"):
            raise PermissionError(f"{self.name} 增值接口禁止云外")
        # 2. 日免额预警(淘宝/京东/1688)
        if "free_daily" in m:
            if self.today_calls >= m["free_daily"]:
                print(f"⚠️ {self.name} 超免费日额,后续按量扣费")
            elif self.today_calls == int(m["free_daily"] * 0.8):
                print(f"⚠️ {self.name} 已达免费额80%,切纯增量")
        # 3. 拼多多余额守卫(外部注入)
        if self.name == "pdd" and hasattr(self, "balance"):
            est_day = (self.today_calls + 1) * m["unit_in" if self.in_cloud else m["unit_out"]
            if self.balance <= est_day * 3:
                raise RuntimeError("pdd 余额<3天预估,熔断非核心调用")

    def after_call(self, cost_unit=False):
        with self._lock:
            self.today_calls += 1

    @abstractmethod
    def sign(self, params): ...

    def safe_post(self, url, params, is_value=False, max_retry=4):
        self.before_call(is_value)
        params["sign"] = self.sign(params)
        for att in range(max_retry):
            try:
                r = requests.post(url, data=params, timeout=15)
                d = r.json()
                if "error_response" in d or "errorResponse" in d:
                    # 限流/欠费特征
                    blob = json.dumps(d)
                    if any(k in blob for k in ["FLOW_CONTROL", "limited-by", "50001", "no permission"]):
                        time.sleep(min(2**att, 8)); continue
                    raise Exception(blob)
                self.after_call()
                return d
            except requests.RequestException:
                time.sleep(2**att); continue
        raise RuntimeError("retry exhausted")


class TaobaoGuard(BaseGuard):
    def sign(self, p):
        f = sorted((k,v) for k,v in p.items() if k!="sign" and v is not None and str(v)!="")
        qs = "".join(f"{k}{v}" for k,v in f)
        return hashlib.md5(f"{self.as}{qs}{self.as}".encode()).hexdigest().upper()


class PddGuard(BaseGuard):
    def __init__(self, ak, ask, in_cloud, balance=None):
        super().__init__("pdd", ak, ask, in_cloud)
        self.balance = balance
    def sign(self, p):
        f = sorted((k,v) for k,v in p.items() if k!="sign" and v is not None and str(v)!="")
        qs = "".join(f"{k}{v}" for k,v in f)
        return hashlib.md5(f"{self.as}{qs}{self.as}".encode()).hexdigest().upper()


# 工厂
def make_guard(name, ak, ask, in_cloud, **kw):
    return {
        "taobao": TaobaoGuard(name, ak, ask, in_cloud),
        "pdd": PddGuard(ak, ask, in_cloud, balance=kw.get("balance")),
    }.get(name, BaseGuard(name, ak, ask, in_cloud))


if __name__ == "__main__":
    # 淘宝必须聚石塔内
    tb = make_guard("taobao", "AK", "AS", in_cloud=True)
    # 拼多多云内+余额守卫
    pdd = make_guard("pdd", "CK", "CS", in_cloud=True, balance=8.5)
    print("guards ready, 云内强制校验通过")
这段不是完整SDK,而是把“云内强制、免额预警、增值禁外、拼多多余额熔断”收进同一个before_call,接进你现有Client即可。

四、按规模给选型结论

  • 单店/小卖(日单<1000):各家都在免费额度内,本地服务端+增量modified拉取即可,不用迁云(但拼多多/抖店若用云外会悄悄烧钱,建议至少把拼多多/抖店丢进对应云)。

  • 中型(日单1万~5万)订单走推送(DSS/Webhook)+ 每5min增量补偿;淘宝/抖店/拼多多必须云内;1688买个提频包;京东商家Key单用。月API总账参考前篇:淘宝0/京东0/1688≈0/拼多多≈37/抖店≈12。

  • ISV/多店(>10店)每平台多AppKey轮询+Redis中心化令牌桶;增值数据(CRM/罗盘/竞品)单独签协议入塔;成本大头不是API费,是云主机+服务市场抽成(ISV)。


五、一句话收口

多平台ERP的最优解 = 阿里/抖/拼强制云内 + 京东联盟商家分流 + 1688高级包破QPS + 订单能推不拉 + 配额/余额守卫编进Client;架构不是被API能力推着走,是把五家收费模型当需求文档反推出来的。
要不要我接着把上面 BaseGuard 扩成带 Redis 日计数 + 按平台自动切换“推送消费/增量拉取”的调度骨架,直接可套进 APScheduler / Celery 里跑?


群贤毕至

访客