拼多多多多客CPS工具包实战:从SDK调用到订单对账
2026/9/16 12:45:50 网站建设 项目流程

简介:拼多多多多客联盟CPS工具包,面向拼多多推广者、电商运营及具备Python基础的开发者,围绕CPS按销售效果付费模式,提供对接多多客联盟营销的一站式技术方案。压缩包共47个文件,以43个Python脚本为主,辅以说明文档、开源许可和版本管理配置,整体仅63KB;脚本内容覆盖商品搜索、推广链接与小程序二维码生成、订单详情查询、推广位管理等接口调用场景,适合二次开发与自动化运营。目前已有340人学习,说明该工具包获得一定认可。通过它可直接运行现成脚本,快速理解多多客SDK的鉴权、请求与响应逻辑,免去阅读冗长官方文档的摸索成本,尤其适合希望提升推广效率、想在拼多多联盟生态中快速落地项目的个人或团队使用。

1. 解压后别急着翻代码,先跑通一条完整链路

拿到这份“拼多多-多多客联盟 CPS 工具包.zip”,第一件事不是把二十多个 Python 脚本挨个看一遍,而是把 demo.py 跑通,再用自己的 PID 跑一次商品搜索到转链的完整流程。这里面的 CPS 不是某种链接格式,而是按成交付费(Cost Per Sale)的联盟营销模式:推广者通过多多客接口拿到带自己标识的推广链接,用户点击并完成拼单后,平台按订单实际成交额结算佣金。工具包里的 DDK_SDK-master 就是对接这套链路的核心 SDK,而那一批脚本实际上是把官方 OpenAPI 按业务场景拆成了可直接改参运行的样例。

这个包适合两类人。一类是正在接入拼多多多多客联盟的开发者,需要搞清楚签名、转链、订单同步这些接口的调用边界;另一类是电商运营,想绕过文档直接看到“商品搜索返回什么字段”“佣金怎么算”“订单状态怎么判断”。对这份资源的第一判断别下在“能不能生成推广链接”,而应该下在“订单能不能回流、佣金对不对得上”这两件事上——链接生成只是入口,数据闭环才是这套工具包真正值钱的地方。

2. CPS 计费链路与 DDK_SDK 的模块拆分

2.1 联盟营销里的三个角色和一条计费闭环

多多客联盟的 CPS 模式里,角色分得很清楚:商家出佣金,推广者出流量,平台做撮合和结算。推广者通过多多客接口获取商品推广链接,链接里携带推广位标识(PID),用户点击后在下单时自动归因,订单状态变化后会通过订单接口回传给推广者,最终按“实际成交金额 × 佣金比例”结算。跟 CPC(按点击付费)最大的区别在于,CPS 模式下平台只对成交订单付佣金,所以推广者要关注的不只是流量,还有转化和退款。

这个模型里,技术侧的核心链路是:选品(商品搜索、商品推荐、主题活动)→ 生成推广链接(转链、店铺链接、红包链接)→ 推广投放 → 订单回流(订单列表、订单详情)→ 佣金结算。这套工具包里的脚本,基本就是按照这条链路排布的。你会发现它没有做界面,全是可独立运行的 Python 脚本,这是很典型的“接口先行”的工具包设计——先验证每个 API 的入参和返回值,再决定怎么集成到自己的系统里。

2.2 DDK_SDK-master 目录结构与脚本接口映射

DDK_SDK-master 的目录结构符合一个标准 Python SDK 的布局:setup.py 负责安装,LICENSE 声明使用协议,ddk 包内部按模块组织,__init__.py暴露统一入口,api 目录放具体接口封装。同级的还有一批xxx1.py脚本,每个脚本对应一个具体的多多客业务场景。把脚本名和接口类型对应起来看,整个包的意图会清晰很多:

脚本文件对应接口类型业务场景
商品关键词搜索1.py商品搜索按关键词查商品,选品入口
获取商品信息1.py商品详情查商品详情、佣金比例
根据商品ID查询相关商品-商品推荐1.py商品推荐相似商品推荐,扩充选品池
多多进宝主题列表查询1.py / 主题商品查询1.py主题活动按运营活动维度选品
生成普通商品推广链接1.py / 多多进宝转链接口1.py转链把商品 ID 变成带 PID 的推广链接
多多客工具生成店铺推广链接API1.py店铺推广生成某个店铺的整体推广链接
多多客工具生成转盘抽免单url1.py转盘抽免单生成转盘抽奖活动推广链接
生成红包推广链接1.py红包推广生成红包样式推广链接
多多客生成单品推广小程序二维码url1.py小程序码生成单品推广的微信小程序码
创建多多进宝推广位1.py / 查询已经生成的推广位信息1.py推广位生成和管理 PID
查询订单详情1.py / 同步推广订单列表1.py订单订单回流与对账
获取拼多多标准商品类目信息1.py商品类目同步平台标准类目

这个映射关系说明一个问题:工具包作者并不是把官方文档翻译了一遍,而是按照“选品 → 转链 → 推广 → 订单”这条运营路径重新组织了接口。你拿到包以后,建议也按这个顺序去读脚本,不要按文件名字母排序看。

2.3 一个请求从脚本到拼多多服务器的完整路径

SDK 的调用方式很统一,先配置 client,再调用对应方法。以 demo.py 为骨架,典型调用长这样:

from ddk import DDKClient client = DDKClient( client_id="你的 client_id", client_secret="你的 client_secret", pid="你的推广位 PID", ) # 搜索“蓝牙耳机”关键词下的商品 resp = client.execute( api_name="pdd.ddk.goods.search", params={ "keyword": "蓝牙耳机", "page": 1, "page_size": 10, } ) print(resp)

这段代码的关键在于execute方法:SDK 在内部完成了参数校验、签名生成、HTTP 请求、响应解析和错误码转换。你在脚本层只需要传api_nameparams,不需要关心签名怎么拼、timestamp 怎么传、返回的 JSON 怎么解。这也是为什么工具包里的脚本看起来都“很短”——真正的逻辑封装在ddk/api目录下。

从请求链路上看,一次完整的调用包括:脚本组织参数 → SDK 按规则生成签名 → HTTPS POST 到拼多多开放平台网关 → 网关验签并路由到具体服务 → 返回 JSON 数据 → SDK 把错误码翻译成异常信息。这里最容易踩的坑是签名错误,后面专门用一章拆解。

3. 签名机制与商品搜索接口实战

3.1 为什么拼多多的签名能拦住大部分“调不通”

拼多多开放平台用的签名算法是 MD5,规则跟多数国内电商平台类似但细节不同:除sign外的所有请求参数,按参数名 ASCII 升序排列,拼成key1value1key2value2的形式,然后在这个串的首尾分别加上client_secret,最后做 MD5 并转大写。也就是说,签名的核心是client_secret,它不会出现在请求参数里,只参与拼接。

很多开发者第一次调不通,问题都出在细节上:timestamp用的是秒级还是毫秒级(拼多多用秒级)、参数要不要做 URL 解码(不需要)、空值要不要参与签名(要参与,但要保证和服务端拿到的一致)、数组参数怎么拼(直接按 JSON 字符串处理)。工具包里的 SDK 把这层封装好了,但如果你要自己实现签名或者排查线上签名错误,必须知道拼多多网关那边是拿着同样的参数集合重新算了一遍签名再做比对,任何一边参数顺序或者值不一致,都会验签失败。

3.2 手写签名并用商品搜索验证

为了说清楚签名逻辑,我建议直接绕过 SDK 手写一次请求。下面这段代码实现了完整的签名和搜索请求:

import hashlib import json import time import requests CLIENT_ID = "your_client_id" CLIENT_SECRET = "your_client_secret" def sign(params: dict) -> str: """拼多多开放平台 MD5 签名""" # 过滤掉空值和 sign 本身 filtered = {k: v for k, v in params.items() if v is not None} # 按 key 的 ASCII 升序排列 sorted_keys = sorted(filtered.keys()) # 拼成 key1value1key2value2 形式 raw = "".join(f"{k}{filtered[k]}" for k in sorted_keys) # 首尾加 client_secret 后做 MD5 sign_str = CLIENT_SECRET + raw + CLIENT_SECRET return hashlib.md5(sign_str.encode("utf-8")).hexdigest().upper() params = { "client_id": CLIENT_ID, "type": "pdd.ddk.goods.search", "data_type": "JSON", "timestamp": int(time.time()), "keyword": "蓝牙耳机", "page": 1, "page_size": 10, } params["sign"] = sign(params) resp = requests.post( "https://gw-api.pinduoduo.com/api/router", data=params, timeout=10, ) result = resp.json() if result.get("error_response"): print("接口报错:", result["error_response"]) else: goods = result["goods_search_response"]["goods_list"] for g in goods: print(g["goods_id"], g["goods_name"], g["min_group_price"], g["promotion_rate"])

这段代码里,sign函数做了三件关键事:剔除空值、按 key 排序、拼接后加盐 MD5。这里特别要注意timestamp必须是当前秒级时间戳,拼多多网关对时间误差容忍度较低,偏差超过几分钟就会拒绝请求。另外data_type固定传JSON,虽然默认就是 JSON,但显式传上能省掉排查响应格式的麻烦。

3.3 搜索结果字段与佣金计算口径

商品搜索接口返回的字段值得逐个看,因为选品决策依赖这些数据。常用字段按类型可以分成三组:

字段组字段用途
商品信息goods_id/goods_name/goods_thumbnail_url商品的唯一标识与展示信息
价格信息min_group_price/min_normal_price拼团价和单独购买价,注意单位是分
佣金信息promotion_rate佣金比例,万分比,比如 500 表示 5%

这组字段里最容易搞错的是单位。min_group_price返回的是“分”而不是“元”,如果直接拿去做价格展示,页面上的价格会大 100 倍。佣金计算口径是“实际成交金额 × promotion_rate / 10000”,这个“实际成交金额”指的是用户实付金额,如果用了店铺优惠券,佣金按抵券后的金额计算。工具包里商品关键词搜索脚本把这几个字段直接打印出来,目的就是让你在选品阶段先建立“什么品佣金高、什么品有销量”的直觉。

4. 推广链接生成:转链、店铺链接、红包与小程序的参数差异

4.1 转链接口:把商品 ID 变成你的推广入口

商品搜索解决的是“推什么”,转链接口解决的是“怎么推”。pdd.ddk.goods.prom.url.generate的作用是把一个普通商品页转换成携带推广位标识的推广链接,用户点击这个链接下单,佣金才会归因到你的 PID 下。工具包里“多多进宝转链接口1.py”和“生成普通商品推广链接1.py”两个脚本,本质上都是调这个接口,区别只在于参数组合不同。

from ddk import DDKClient client = DDKClient( client_id="your_client_id", client_secret="your_client_secret", pid="你的推广位 PID", ) resp = client.execute( api_name="pdd.ddk.goods.prom.url.generate", params={ "goods_id_list": [123456789], # 商品 ID 列表,最多一次传 100 个 "generate_short_url": True, # 生成短链接,方便投放 "multi_weapp_encode": True, # 拼接微信小程序路径参数 "custom_parameters": "track_1001", # 自定义跟踪参数,最长 64 字符 }, ) # 取返回的推广链接 url_info = resp["goods_promotion_url_generate_response"]["goods_promotion_url_list"][0] print(url_info["short_url"]) print(url_info["mobile_url"]) print(url_info["we_app_info"])

转链接口的参数坑集中在custom_parameters上。这个参数会拼接到推广链接的末尾,用于渠道跟踪,比如你在抖音和朋友圈各投了一组链接,可以用不同的自定义参数来区分流量来源。注意它只能由字母、数字和下划线组成,不能带中文和特殊符号。另外multi_weapp_encode建议设置为true,这样返回的we_app_info里会带上小程序页面路径,后续要做小程序投放时不用重新转链。

4.2 店铺推广、红包链接与转盘抽免单的差异化选型

不是所有场景都适合用普通转链。工具包里单独拆出了“店铺推广链接”“红包推广链接”“转盘抽免单”三个脚本,它们对应的是不同转化逻辑的推广形式:

链接类型接口思路适用场景
普通商品转链goods.prom.url.generate单品投放、选品推荐
店铺推广链接按 mall_id 生成店铺落地页链接推店铺整体,让用户进店逛
红包推广链接带红包引导文案的推广链接拉新、促首单转化
转盘抽免单goods.zs.url.generate活动玩法,抽奖形式引导下单

店铺推广链接在工具包里对应“多多客工具生成店铺推广链接API1.py”,关键入参是mall_id,返回的链接落地到店铺首页,用户可以在店里一次浏览多个商品,适合做店铺整体推广而不是单品爆破。转盘抽免单的接口返回比较特殊,它给的不是直接可点的落地页链接,而是一段需要二次拼装的活动参数,通常要配合前端活动页使用。红包推广链接则更适合社交流量,用户点开看到红包样式,点击领取后跳转商品页。

4.3 单品推广小程序二维码的生成思路

“多多客生成单品推广小程序二维码url1.py”这个脚本容易被误以为调了一个“生成小程序码”的接口,实际上不是。拼多多接口体系里没有直接输入商品 ID 就返回小程序码的接口,常规做法是:先用转链接口拿到商品的推广 URL 和we_app_info,再把这个信息交给微信侧的小程序码接口去生成二维码。we_app_info里包含pagescene字段,scene里就携带了刚才说的custom_parameters跟踪信息。

我在实际项目中通常把这一步做成一个异步任务:用户在前端选好商品,后端调转链接口拿到we_app_info,然后调微信接口生成小程序码图片上传到对象存储,最后把图片 URL 返回给前端展示。这里有个容易踩的坑:微信小程序码的scene字段长度限制是 32 个字符,而拼多多的custom_parameters最长 64 字符,直接透传会被微信截断。常见做法是后端把custom_parameters映射成短码存 Redis,scene里只放短码,用户扫码后再通过短码还原完整跟踪参数。

5. 订单同步、推广位管理与主题活动:把数据闭环撑起来

5.1 推广位:佣金归因的身份证

推广位(PID)是拼多多 CPS 体系里佣金归因的最小单位,它的格式类似PID_你的ID_数字编号。同一个账号下可以创建多个推广位,用于区分不同的投放渠道。工具包里“创建多多进宝推广位1.py”对应pdd.ddk.goods.pid.generate,通常只需要传number(创建数量)和p_id_name_list(推广位名称)。“查询已经生成的推广位信息1.py”对应pdd.ddk.goods.pid.query,入参是pagepage_size,返回该账号下所有推广位及其状态。

from ddk import DDKClient client = DDKClient( client_id="your_client_id", client_secret="your_client_secret", ) # 创建 2 个推广位,按渠道命名 resp = client.execute( api_name="pdd.ddk.goods.pid.generate", params={ "number": 2, "p_id_name_list": ["微信-朋友圈", "公众号-底部菜单"], } ) pid_list = resp["p_id_generate_response"]["p_id_list"] for item in pid_list: print(item["p_id"], item["pid_name"]) # 查询已有推广位 query = client.execute( api_name="pdd.ddk.goods.pid.query", params={"page": 1, "page_size": 100}, ) for item in query["p_id_query_response"]["p_id_list"]: print(item["p_id"], item["pid_name"], item["status"])

创建推广位时要留意p_id_list返回结构,不同接口的返回字段名不太一样,生成接口是p_id_list,查询接口是p_id_list但嵌套层级不同。工具包作者特意把两个脚本分开写,就是为了让你看清楚这两种响应结构的差别。命名建议直接绑渠道,比如“知乎-文章底部”“抖音-直播间”,这样后续对账的时候一眼能看出每笔订单来自哪个渠道。

5.2 订单增量同步:佣金对账的数据底座

订单回流是整个 CPS 工具包里最核心的接口,没有之一。pdd.ddk.order.list.increment.get按更新时间增量拉取订单,要想不错单、不漏单,必须理解它的时间窗口机制。下面是从“同步推广订单列表1.py”里拆出来的核心逻辑:

import time from ddk import DDKClient client = DDKClient( client_id="your_client_id", client_secret="your_client_secret", ) # 拉取最近 5 分钟的增量订单 end_time = int(time.time()) start_time = end_time - 300 resp = client.execute( api_name="pdd.ddk.order.list.increment.get", params={ "start_update_time": start_time, # 起始更新时间(秒级) "end_update_time": end_time, # 结束更新时间(秒级) "return_count": 100, # 单次返回数量,上限 100 "query_order_type": 1, # 1-按更新时间查询,默认值 }, ) order_list = resp["order_list_increment_get_response"]["order_list"] for order in order_list: print( order["order_sn"], order["goods_name"], order["order_status"], order["promotion_amount"], )

增量接口的设计逻辑是“闭区间”:start_update_timeend_update_time包含边界,同一时间戳的订单可能在上一次同步和本次同步中都被拉到。所以我在落地时会给订单表加order_sn唯一索引,同步时用“先按订单号去重再更新”的策略,而不是简单地全量覆盖。query_order_type这个参数也值得注意,它控制查询维度是按订单更新时间还是按结算时间,对账场景下建议按结算时间查询,因为佣金结算时间和下单时间可能相差好几天。

订单状态枚举是另一组必须建立映射关系的字段:

order_status 值含义是否可结算
已支付用户已付款,等待成团
已成团拼单成功,进入发货流程
已确认收货用户确认收货是(等待结算)
已结算佣金已计入账户
已退款/售后订单取消或退款

5.3 主题活动与商品推荐补充选品维度

工具包里“多多进宝主题列表查询1.py”和“多多进宝主题商品查询1.py”对应的是主题玩法——拼多多运营会周期性推出专题活动,比如“夏季清凉节”“数码狂欢周”,活动里的商品通常有平台补贴或额外佣金加成。接口链路是先调pdd.ddk.theme.list.get拿到活动列表,再用主题 ID 调pdd.ddk.theme.goods.search查该主题下的商品。

我一般会把主题商品和关键词搜索的结果做一次交叉去重:主题活动的商品质量相对有平台背书,但未必覆盖所有品类;关键词搜索覆盖全,但需要自己过滤佣金过低或者销量刷水的商品。工具包里的“根据商品ID查询相关商品-商品推荐1.py”就是干这个的,调pdd.ddk.goods.recommend.get传入一个已知的优质商品 ID,拿回一批相似商品,可以快速扩充选品池。

6. 从“能跑”到“能结算”:订单对账的五个细节

脚本能跑通只是第一步,真正让 CPS 工具包产生价值的,是拿它产出的订单数据去和拼多多后台的结算单核对,保证每一笔佣金都对得上。这里把我用这套工具时沉淀下来的几个关键细节列出来。

第一,增量时间窗口必须做重叠处理。增量接口是闭区间,上一轮拉取最后一条订单的update_time要作为下一轮的start_update_time,且拉取频率要小于平台允许的最短窗口(一般建议 5 分钟一次)。如果中途服务重启,要允许从上次记录的时间点重拉,这块靠订单号唯一索引兜底。

第二,order_status是状态机不是终态。一笔订单从“已支付”到“已结算”之间会经历多次状态更新,增量接口会把这笔订单重复返回。如果直接按状态字段覆盖存储,可能把“已结算”覆盖回“已成团”。正确做法是只在状态向前推进时更新,或者保留完整的状态流转日志。

第三,退款订单不要手工剔除。已退款订单会在增量流里以新状态推送,order_status对应售后值。对账时直接过滤掉退款状态即可,但注意“部分退款”的订单状态可能保持不变,需要结合order_amount字段判断实际结算金额是否被调整。

第四,佣金按“实付金额”计算,不是按商品标价。用户在拼单基础上用了店铺券、平台券,实付金额都会变化,promotion_amount字段返回的才是最终计入结算的佣金金额。对账要按promotion_amount做加总,不要自己拿订单金额乘佣金比例去推算。

第五,写一个最小化的对账脚本来兜底。我不建议人工去拼多多后台翻订单,直接把本地订单表和后台结算单导出做差集:

-- 核对本地同步的订单号是否与结算单一致 SELECT local.order_sn FROM local_orders AS local LEFT JOIN settle_orders AS settle ON local.order_sn = settle.order_sn WHERE settle.order_sn IS NULL AND local.order_status NOT IN ('已退款', '售后');

这个 SQL 解决的是“本地有但结算单没有”的漏单问题;反向再查一遍“结算单有但本地没有”,能发现同步遗漏的订单。只要这两张表的差集为空,佣金数据就基本可信了。跑通工具包不是终点,每天一次对账、每周一次全量校验,才是做 CPS 该有的运维节奏。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询