×

《1688跨境分销API踩坑:alibaba.cps.* 与 crossborder.* 的授权与佣金计算》(附Python源码)

万邦科技Lex 万邦科技Lex 发表于2026-09-30 09:39:43 浏览29 评论0

抢沙发发表评论

《1688跨境分销API踩坑:alibaba.cps.* 与 crossborder.* 的授权与佣金计算》(附Python源码)

先拍结论:
1688 跨境分销不是“普通 1688 代发 + 加个英文标题”这么简单。
alibaba.cps.* 是“分销/推广/选品视角”的读接口,佣金/严选价要从商品视图里取,不是自己算;
crossborder.* 是“跨境买家付款/寻源/跨境宝”能力,重点是授权主体、支付渠道、外币结算、订单必须走对 flow。
最坑的是:用错 flow → 拿不到 retailPrice;没签信息共享协议 → cps 商品字段不全;跨境宝不是支付宝 → 是 WorldFirst/外币账户代扣;佣金别用“下游售价×比例”反推,平台按“订单实付(不含运费)×费率”扣。

一、两条能力域先切干净

域
典型接口
角色
干啥
CPS / 分销商品
alibaba.cpsMedia.productInfo、alibaba.cps.queryOfferDetailActivity
分销商 / 推广者
拿分销价、活动价、包邮条件、推广佣金
Cross Border
alibaba.offer.search.crossborder、alibaba.crossBorderPay.url.get、alibaba.trade.payWay.query
跨境买家 / ERP
跨境货盘、外币支付、跨境宝收银台
分销严选交易
alibaba.trade.fastCreateOrder / alibaba.trade.fenxiaoOrder.create
分销商
用 boutiquefenxiao / ttpft 等 flow 锁价
别把 cpsMedia.productInfo 当成“下单接口”,也别把 crossBorderPay.url.get 当成“创建订单接口”。
cps 管“这货能赚多少”,crossborder 管“这单怎么付出去”。

二、授权层踩坑(比代码先炸)

1️⃣ 应用权限不是通用权限

  • 普通 1688 交易应用 ≠ 寻源通 ≠ 社交电商采购 ≠ 分销严选

  • cpsMedia.productInfo 通常要订购对应解决方案/分销能力

  • 图搜分销、跨境专供、密文面单、跨境宝各自单独开

2️⃣ access_token 是“买家授权”,不是商家 session

跨境分销里你是买家/分销商:
  • 用买家 access_token 调 cps / 下单 / 查单

  • 供应商那侧是商家 session,你调不到

  • token 过期不刷 → 下单直接 TOKEN_EXPIRED

3️⃣ 跨境宝授权是“账户绑定”,不是 OAuth scope 打勾

alibaba.crossBorderPay.url.get 背后是:
  • 1688 账号绑定 WorldFirst / 跨境收付账户

  • 用 CNH / 外币余额付 1688 订单

  • 没绑跨境宝 → 返回 400_4 无可使用支付渠道[跨境宝]付款的订单

4️⃣ 分销严选要先签《信息共享协议》

不签:
  • retailPrice / JxhyPrice / 佣金字段可能不返回

  • 你用 consignPrice 铺货 → 不是严选价 → 下游毛利算错


三、佣金与分销价:平台给,别自己编

价格优先级(cps 商品视图)

channelPrice      > 一件代发包邮价(跨境/抖快常用)
promotionPrice    > 营销活动价
consignPrice      > 分销基准价
retailPrice       > 分销严选铺货价(站外分销用这个)

佣金/服务费口径

1688 分销严选官方规则:
软件技术服务费 = 订单实付金额(不含运费) × 技术服务费率
站外分销:5%
生鲜/酒水:2.5%(即 5% 的一半)
运费不抽
同一笔订单不重复扣(严选/PLUS/行家选只收一次)
❌ 错误:佣金 = 下游售价 39.9 - 供货价 15 = 24.9 都是我赚的
✅ 正确:平台从分销商侧/供应商侧按规则扣费,ERP 要把“平台扣费”当成成本中心,不是事后惊喜。

四、flow 用错 = 价格崩了(重点)

商品标签
下单接口
flow
老严选 isPftOffer=true
fastCreateOrder / fenxiaoOrder.create
fenxiaonew / ttpft
新严选 isJxhyOffer=true
fastCreateOrder
1 件 boutiquefenxiao,多件 boutiquepifa
普通分销 consignPrice 有值
分销下单
fenxiaonew
混用分销创建
fenxiaoOrder.create
flow=fenxiao&isSplitJxhy=true 自动拆单
踩坑现象:
  • 商品明明是分销严选,你下出来是普通批发价

  • 毛利模型算 35%,实际成交价高 8%,运费还不包邮

  • 退款时平台说“非严选单不享受 48h/7 天无理由保障”


五、生产向:CPS 商品归一化 + 佣金预估

# ali1688/crossborder/cps_product.py
from dataclasses import dataclass
from typing import Optional


@dataclass
class CpsProductView:
    offer_id: str
    title: str
    channel_price: Optional[float] = None     # 一件代发包邮价
    promotion_price: Optional[float] = None   # 活动价
    consign_price: Optional[float] = None     # 分销基准价
    retail_price: Optional[float] = None      # 分销严选铺货价
    jxhy_price: Optional[float] = None        # 新严选专享价
    is_pft_offer: bool = False                # 老严选
    is_jxhy_offer: bool = False               # 新严选
    channel_free_postage: bool = False
    exclude_area_codes: list[str] = None
    commission_rate: Optional[float] = None   # 推广佣金(若有)
    activity_info: dict = None

    @property
    def distribution_price(self) -> float:
        """
        分销下单/铺货用哪个价:
        新严选 > retailPrice
        老严选 > consignPrice
        活动价仅做营销展示,不直接当代发成本
        """
        if self.is_jxhy_offer and self.retail_price:
            return self.retail_price
        if self.is_pft_offer and self.consign_price:
            return self.consign_price
        return self.channel_price or self.consign_price or self.promotion_price

# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
def normalize_cps(raw: dict) -> CpsProductView:
    price_model = raw.get("priceModel", {}) or raw.get("price", {}) or {}
    return CpsProductView(
        offer_id=str(raw.get("offerId") or raw.get("itemId")),
        title=raw.get("title", ""),
        channel_price=_f(price_model.get("channelPrice")),
        promotion_price=_f(price_model.get("promotionPrice")),
        consign_price=_f(price_model.get("consignPrice")),
        retail_price=_f(price_model.get("retailPrice")),
        jxhy_price=_f(price_model.get("JxhyPrice") or price_model.get("jxhyPrice")),
        is_pft_offer=bool(raw.get("isPftOffer")),
        is_jxhy_offer=bool(raw.get("isJxhyOffer")),
        channel_free_postage=bool(price_model.get("channelPriceFreePostage")),
        exclude_area_codes=price_model.get("channelPriceExcludeAreaCodes") or [],
        commission_rate=_f(raw.get("commissionRate")),
        activity_info=raw.get("activityInfo"),
    )


def _f(v) -> Optional[float]:
    try:
        return float(v)
    except (TypeError, ValueError):
        return None

佣金/平台费预估(站外分销)

PLATFORM_TECH_FEE_RATE = 0.05        # 站外分销严选
PLATFORM_TECH_FEE_RATE_FRESH = 0.025  # 生鲜/酒水

def calc_distribution_cost(
    paid_amount: float,          # 订单实付,不含运费
    freight: float,
    category: str = "normal",
    downstream_sell_price: float = 0.0,
):
    rate = PLATFORM_TECH_FEE_RATE_FRESH if category in ("fresh", "alcohol") else PLATFORM_TECH_FEE_RATE
    platform_fee = paid_amount * rate

    gross = downstream_sell_price - (paid_amount + freight) - platform_fee
    return {
        "paid_excl_freight": paid_amount,
        "freight": freight,
        "platform_fee_rate": rate,
        "platform_fee": round(platform_fee, 2),
        "gross_profit": round(gross, 2),
        "note": "平台费按实付不含运费计算,运费不抽成",
    }

六、跨境支付:crossborder 不是“再调一次 trade.pay”

# ali1688/crossborder/payment.py

class CrossBorderPayClient:
    def __init__(self, top_client):
        self.top = top_client

    def get_pay_url(self, access_token: str, order_ids: list[int]) -> dict:
        # 一次别塞 30 个,建议 10 个
        if len(order_ids) > 10:
            raise ValueError("crossBorderPay 建议一次 <=10 单")

        params = {
            "access_token": access_token,
            "orderIdList": order_ids,
        }
        # resp = self.top.execute("alibaba.crossBorderPay.url.get", params)
        resp = {"success": True, "payUrl": "https://trade.1688.com/order/cashier.htm?orderId=xxx"}

        if not resp.get("success"):
            return {"ok": False, "err": resp.get("errorCode"), "msg": resp.get("errorMsg")}

        return {
            "ok": True,
            "pay_url": resp["payUrl"],
            # 支付链接有效期约 30 分钟,禁止长期缓存
            "cant_pay_orders": resp.get("cantPayOrderList", []),
        }

    def ensure_payable(self, access_token: str, order_id: int) -> bool:
        # 先查渠道,再决定跳跨境宝 / 支付宝 / 账期
        pw = self.top.execute("alibaba.trade.payWay.query", {
            "access_token": access_token,
            "orderId": order_id,
        })
        channels = [c["payWayName"] for c in pw.get("payWays", [])]
        return "跨境宝" in channels or "crossBorderPay" in channels

跨境下单时序(一件代发到货代仓)

cpsMedia.productInfo  ──▶ 拿 retailPrice / 是否包邮 / 是否严选
        │
        ▼
fastCreateOrder(flow=boutiquefenxiao, receiver=国内货代仓)
        │
        ▼
payWay.query ──▶ 支持跨境宝?
        │
        ▼
crossBorderPay.url.get ──▶ 买家跳收银台 / WorldFirst 扣 CNH
        │
        ▼
供应商发货到货代仓 ──▶ 国内 track
        │
        ▼
货代集运/合箱/报关 ──▶ TikTok/Shopee/Mercari 国际段

七、隐藏约束清单(上线前必看)

  • [ ] 应用订购了“分销 / 寻源通 / 跨境 / 严选”对应能力,不是只有一个 AppKey

  • [ ] 买家 token 有刷新,跨境宝绑定在买家账号上

  • [ ] cpsMedia.productInfo 返回价格用优先级,不把 promotionPrice 当代发成本

  • [ ] 新严选用 boutiquefenxiao,老严选用 fenxiaonew/ttpft,混单用 isSplitJxhy=true

  • [ ] retailPrice 有值才铺货,无价 SKU 直接过滤

  • [ ] 平台佣金 = 实付不含运费 × 费率,不按下游售价算

  • [ ] 跨境宝支付链接 30 分钟过期,不落库复用

  • [ ] 非包邮区域(新疆/西藏/港澳台/海外)单独声明,不然毛利变负

  • [ ] 密文面单只在下游平台支持时传 encryptOutOrderInfo,不解密再传明文

  • [ ] 退款/退货时平台费是否退还,按账单明细核,不假设“全退”


八、和前几篇收口

  • 《1688 商品 API》:offer.get/product.get 是批发主数据;cpsMedia.productInfo 是“能分销吗、赚多少”

  • 《1688 订单 API》:下单后状态机不变,但跨境单多一层“是否已跨境宝支付”

  • 《统一采购适配层》:offerId+skuId 上要挂 distribution_view(retailPrice/flow/commission)

  • 《两套接口边界》:cps 是“推广/选品读通道”,crossborder 是“跨境付款/寻源能力”,都不是闲鱼/Mercari 的销售侧接口

  • 《六大坑》:这里新增——flow 错、协议没签、跨境宝没绑、佣金按售价算


九、一句话收口

1688 跨境分销的坑不在签名,而在:
cps 给你“能赚多少”的视图,crossborder 决定“钱怎么跨过去”;
retailPrice 是平台发的牌,flow 是发牌动作,佣金是实付不含运费的税式扣除。
ERP 别当“倒卖中间件”,要当“分销合规账房”:价格认平台、flow 认标签、佣金认实付、跨境认绑定。


群贤毕至

访客