尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

原生双端淘宝客APP源码拆解:淘宝联盟API与代理分佣系统设计

原生双端淘宝客APP源码拆解:淘宝联盟API与代理分佣系统设计 简介淘宝客原生双端APP源码搭配代理系统是市面上少见的移动端淘客项目资源。面向想搭建自有淘宝客应用的开发者、产品运营或创业者适合有一定Android/iOS基础、希望直接获取完整工程源码并快速上手的用户。压缩包共2045个文件约704.64MB文件类型涵盖734个Java、717个XML、284个JSON、92个M与89个H等其中Java与XML构成安卓客户端主体JSON多用于接口数据配置M与H对应iOS端源码整体结构完整另有txt、properties、md等说明文档。资源配有清晰安装教程及多份docx开发文档、接口文档、账号替换说明和申请材料清单便于按步骤完成环境配置与上线发布。已有131人学习下载适合需要参考原生APP架构、UI界面与代理系统联动逻辑的淘客从业者可据此节省从零开发成本快速搭建自己的推广分发平台。1. 原生双端淘宝客APP源码为何比WebView套壳更值得拆把“淘宝客APP源码”丢进搜索框能翻出来的工程十个里有九个是WebView套壳壳子包一个H5页面改个URL就算新版本。这套不一样。700多MB的交付体积Android和iOS各一套原生工程接口文档迭代到v1.45.1版本代理系统和安装教程一并给出。它不是开箱即用的SaaS需要你有Android或iOS的编译能力但胜在完整——UI原生绘制、网络层真实请求、代理分佣逻辑齐全。适合拿原生工程做二次开发的技术团队也适合想研究淘宝联盟OpenAPI在移动端如何被客户端拉起来的开发者。下面按工程结构、API调用链、代理系统、账号替换与部署几个方向拆开聊。2. 双端工程结构与淘宝联盟API v1.45.1的调用链2.1 原生工程里先看network模块而不是Activity解包Android端源码后不要急着点开MainActivity先看工程根目录的module划分。原生双端项目的标准做法是把代码拆成common公共基础库、network网络层、widget自定义控件、module-user用户模块、module-order订单模块这几块。这是一套主干分层原生APP最忌讳Activity里堆一万行业务代码工程规范度第一眼从模块划分就能判断。这套源码能看出同样的分层习惯common里放工具类和Base基类network独立成模块页面模块依赖network模块而不是反着来。先说看network模块的理由。淘宝客APP本质上是淘宝联盟OpenAPI的移动端客户端商品列表、订单状态、佣金金额都要通过接口拉取。network模块里包含着Retrofit/OkHttp的封装方式、签名拦截器、加密参数处理逻辑这些是淘宝客源码和普通APP源码差异最大的地方。iOS端对应的位置是APIManager目录同样把网络请求收敛在一个核心类里。我见过不少二次开发的人直接绕过network模块在页面里重写一个请求结果签名参数缺失或渠道参数丢失线上收不到佣金账单排查时全部乱套。所以第一个建议是改动前把network模块当成本工程的地基不要在它之外另起网络请求。2.2 商品、订单、授权三类接口的映射关系v1.45.1的接口文档结构很清晰把接口按业务拆成三类商品信息类、订单查询类、授权绑定类。理解这三类的落点客户端代码就找到路标了。下面的映射表是我对照文档和工程代码整理出来的做二次开发时直接拿这张表当索引比在工程里一个个翻方法快得多。接口分类客户端对应模块返回数据典型用途商品信息类首页推荐、搜索、商品详情商品标题、券后价、佣金率展示订单查询类个人中心-订单列表、结算页预估佣金、订单状态、结算时间授权绑定类登录注册、绑定上下级代理生成推广位、关联代理关系这套映射关系在双端实现上是对齐的Android端所有接口请求都收敛在DataRepository类里iOS端对应APIManager层。新加页面时理论上只需要调用仓库类暴露的方法不需要各处散写请求代码。如果你从文档里看到一个新接口第一件事就是在DataRepository里找有没有对应方法没有的话按现有风格补一个而不是直接在页面里写Retrofit调用。这个习惯能保证后续签名逻辑和埋点逻辑不会被绕过去。2.3 签名拦截器的实现与时间戳坑点淘宝联盟这类平台接口对签名要求严格这套源码在Android端的实现方式是拦截器统一处理。我摘一段重构过的核心逻辑class TbkApiInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val original chain.request() val ts System.currentTimeMillis() / 1000 // 附加时间戳、签名和渠道标识缺一服务端直接拒绝 val signedUrl original.url.newBuilder() .addQueryParameter(timestamp, ts.toString()) .addQueryParameter(sign, genSign(original, ts)) .addQueryParameter(channel, android_double_side) .build() return chain.proceed(original.newBuilder().url(signedUrl).build()) } private fun genSign(request: Request, ts: Long): String { // 从安全存储读取 app_secret参数排序后拼接做MD5 val secret KeyStoreHelper.get(tbk_secret) val pairs request.url.queryParameterNames.sorted() .map { it to request.url.queryParameter(it) } val raw pairs.joinToString() { ${it.first}${it.second} } ts return MD5Util.md5(raw secret) } }这段代码做了三件事第一在每个请求上自动附加时间戳timestamp服务端用它校验请求时间是否在允许窗口内第二按参数名排序拼接后加上app_secret生成签名保证参数不被篡改第三追加渠道号channel方便服务端按渠道统计App来源。如果服务端升级为HMAC-MD5或者RSA签名也只需要替换genSign内部实现对调用方无感知。最容易被忽略的是时间戳。手机本地时间和服务器时间偏差超过5分钟接口会直接返回签名错误。这种报错不是签名算法的问题而是时间同步问题。常见做法是在冷启动时从服务器时间接口校准一次本地时间偏移量后续所有请求时间戳都加上这个偏移。另一个坑是queryParameterNames在URL有重复参数时会丢值如果有相同参数名以不同值出现要改成手动解析原URL的query字符串。iOS端封装思路一致只是用NSURLSession的代理方法统一附加参数。3. 代理系统设计分佣等级、结算链路与数据库落表3.1 代理等级怎么定决定了分佣比例的边界代理系统是这套源码里最贴近商业逻辑的部分模型很直接用户通过代理的推广链接或二维码下载App并产生购买平台从淘宝联盟拿到的佣金按比例分给代理平台自己留一部分作为运营成本。这里最关键的是等级体系——不同等级对应不同分佣比例也是代理长期推广的动力来源。等级定得不好要么平台利润被吃掉要么代理觉得赚不到钱而流失。源码配套的开发文档对等级模型的说明很明确我把它转成了一张可以直接落库的等级表CREATE TABLE agent_level ( id tinyint NOT NULL AUTO_INCREMENT, level_name varchar(32) DEFAULT NULL COMMENT 等级名称普通代理/金牌代理/合伙人, commission_rate decimal(5,2) DEFAULT NULL COMMENT 代理可分成比例0到1之间, invite_required int DEFAULT 0 COMMENT 需要邀请的有效下级数, order_required int DEFAULT 0 COMMENT 需要完成的累计有效订单数, wx_withdraw_limit decimal(10,2) DEFAULT 0.00 COMMENT 单次提现最小金额, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;几个字段的设计点值得注意。commission_rate存的是代理拿走的比例例如0.70表示这单佣金里代理拿70%平台留30%比例一定控制在0到1之间后台配置时做好范围校验。invite_required和order_required是升级条件两个条件同时满足才会触发升级这是防止“邀了一堆僵尸号就升金牌”的常用设计。wx_withdraw_limit是单次提现门槛低于该金额不允许发起提现目的是减少小额提现带来的手续费损耗。这套字段设计可以直接挪用到其他返利类项目里。3.2 订单归因与回传的时序问题代理推广的核心问题是一笔订单到底算谁的。常规做法是用户第一次点代理的链接时客户端带着代理的PID去调用绑定关系接口把用户和代理的绑定关系记在后台之后用户一段时间内下的订单都归这个代理。这里有三个容易踩的坑。第一绑定关系必须只建立一次。代码里要做幂等处理同一个用户重复打开不同代理的链接以第一次绑定为准后面只更新不覆盖。用数据库唯一索引来控制是兜底方案ALTER TABLE user_agent_relation ADD UNIQUE KEY uk_user_agent (user_id, agent_id);第二订单回流有延迟。淘宝联盟的订单查询接口一般T1才返回完整佣金数据当天显示的金额是预估不是最终结算。客户端如果直接展示实时佣金到账后对不上账客诉就来了。我一般会把客户端文案定为“预估佣金”后台只在状态变为已结算时才累加可提现余额。第三代理等级在订单产生后也可能变化。如果用户在A等级时下单付款时升到了B等级佣金按哪个等级算业界通用做法是按下单当日的等级结算而不是按付款或确认收货时的等级。这样对用户和平台都公平也不会因为等级变化引发退款纠纷。3.3 佣金结算批量处理的实现与参数解释结算逻辑我按源码的文档思路写一个统计伪代码方便理解整个链条from decimal import Decimal def settle_daily_orders(agent, orders): # 每天跑一次把所有已确认收货订单算出来 gross Decimal(0.00) settled [] for order in orders: # pub_share_fee 是淘宝联盟实际结算的佣金总额 share_fee Decimal(order[pub_share_fee]) rate agent.level.commission_rate platform_fee share_fee * Decimal(0.04) # 平台运营成本固定抽4% agent_income share_fee * Decimal(str(rate)) - platform_fee if agent_income 0: agent_income Decimal(0.00) settled.append({ order_id: order[order_id], agent_id: agent.id, amount: agent_income.quantize(Decimal(0.01)), status: pending_withdraw, }) gross agent_income return settled为什么单拆一个platform_fee代理拿的比例基于淘宝联盟结算的佣金总额但平台本身有服务器成本、证书成本、运营人工不做抽成一个月下来大概率是负利润。固定抽4%是比较常见的做法也有人按代理等级递减这是运营策略改代码里的系数就行。max兜底负数防止佣金率配置错误导致负数入账。这里有一个经验金额计算一律用Decimal不要用floatfloat的二进制精度问题在金额累加时会放大到分对账时候非常头疼。结算跑批建议放在凌晨淘宝联盟订单数据回传稳定之后用定时任务触发。注意跑批时要加分布式锁或数据库行锁避免同一笔订单被重复结算重复结算一次财务那边就得人工冲账一次。3.4 提现记录与账务一致性结算完成之后还要有一张提现记录表。这里最容易被忽略的是账单号字段每次提现应该生成全局唯一的流水号同时关联原始订单明细。用户看到的是提现记录财务看的是订单明细两者对不上就出大事了。如果后台用PHP源码来写这种结算模块尤其要提前把事务边界定义清楚把入账、提现、手续费三条记录放到同一个事务里提交。对账SQL是最常用的排查手段后台如果接MySQL可以这么查SELECT DATE(settlement_date) AS day, SUM(amount) AS total_income, COUNT(*) AS order_cnt FROM agent_settlement WHERE agent_id 123 AND settlement_date 2024-06-01 GROUP BY DATE(settlement_date) ORDER BY day DESC;按日期分组之后如果平台后台的金额和淘宝联盟后台的金额对不上逐日缩小范围查订单这是最直接的排查路径。还有一种情况是两个平台显示的时间口径不同一个按下单时间一个按确认收货时间对账时先把两边的时间字段统一后再比对。4. Android账号替换、签名构建与安装部署全流程4.1 替换账号前先准备这些申请材料安装教程文档里第一批强调的是“替换账号”原因是源码里默认带的AppKey和PID不能直接商用必须换成你自己的淘宝联盟账号。账号替换之前需要备齐下面这些申请材料材料说明来源淘宝联盟账号用于登录联盟后台创建媒体备案淘宝或支付宝账号实名AppKey / AppSecret创建应用后获取接口调用的唯一凭据开放平台应用管理媒体备案ID备案通过后获取绑定推广位的前提联盟后台-媒体备案推广位PID格式形如mm_123_456_789创建媒体后自动生成材料清单在源码附带的《淘宝客客户需要申请材料》文档里写得很全照着清单一项项办就行。以Android端为例这些参数在工程里的位置一般在网络层可能是res/values下的一个XML或者assets下的配置文件源码文档里专门有一份《安卓淘宝客APP相关账号替换》说明顺着它改就可以。关键点是AppSecret不能硬编码在Java代码里最低限度也要放到加密存储类包一层这一点在提交应用市场审核时是重点核查项。4.2 账号配置与替换操作步骤第一步打开Android工程的配置文件把AppKey、AppSecret、PID替换成自己的!-- res/values/tbk_config.xml -- resources string nametbk_appkey已申请的AppKey/string string nametbk_secret已申请的AppSecret/string string nametbk_adzone_id推广位ID/string string nametbk_pidmm_111_222_333/string /resources第二步如果之前运行过签名过的安装包替换账号后建议卸载旧版本再安装。账号信息会缓存在SharedPreferences里不卸载直接覆盖安装旧账号的缓存可能覆盖掉新配置。这一步在安装教程里没有特别强调但实际部署时踩过太多次直接卸载重装是成本最低的验证方式。第三步检查权限配置。Android 12及以上版本安装来源管理和文件访问权限需要在系统设置里手动开启。应用中如果包含版本升级下载功能要主动引导用户跳转系统原生设置页if (Build.VERSION.SDK_INT Build.VERSION_CODES.R) { Intent intent new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse(package:com.tbk.app)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }这里使用ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION而不是直接写死代码打开某个厂商ROM的设置页是为了适配不同厂商的Android 11系统。部分国产ROM对权限管理做了定制标准Intent可能会失效这种情况要再包一层异常捕获兜底跳转到App详情页的ACTION_APPLICATION_DETAILS_SETTINGS。如果目标是小米、OPPO这些机型测试时必须真机跑一遍这个流程模拟器上是测不出问题的。4.3 构建签名与安装命令双端源码里Android端用Gradle构建直接执行# 在android目录下执行 ./gradlew clean assembleRelease # 无签名信息的话生成release包后再手动签名 jarsigner -verbose -keystore tbk.keystore \ -storepass 你的密码 -keypass 你的密码 \ -signedjar tbk_signed.apk \ app-release-unsigned.apk tbk_alias # 对测试机安装 adb install -r tbk_signed.apk这里有几个容易踩的点。第一Gradle构建时如果报Invalid signature先检查Gradle版本与JDK版本是否匹配用JDK 17构建老工程经常遇到这个问题把JDK切换到11或8可以快速绕过。第二jarsigner和apksigner两种签名工具选一个就好优先用apksigner它兼容新的签名方案v2/v3提交到应用市场时不会被要求重新签名。第三release包构建完成后用aapt dump badging命令确认包名和版本号没问题再安装不要拿一个配置错误的包做全量测试。部署到服务器端的代理系统如果团队拿到的是PHP源码实现直接把代码包解压到Web目录配置伪静态规则和数据库连接即可。这里多说一句后台和App之间的接口通信建议加一层sign验证否则代理后台的提现接口被遍历调用是这类源码最常见的安全漏洞。5. 上线前的实战自检接口联通性与佣金链路闭环验证5.1 三分钟接口状态验证正式上线前先用最直接的方式验证接口可用性不要等用户反馈问题。在Android端跑一遍完整请求链路打开Logcat过滤TbkApi观察三类请求是否都返回HTTP 200。检查优先级如下表按顺序一项项过检查项预期结果失败时的常见原因AppKey / AppSecret 是否还有效无401账号续约过期或密钥被误删PID与媒体备案是否对应无业务错误码PID未通过媒体备案时间戳误差无签名错误手机时间不准未做时间偏移校准订单接口返回数据有新增订单数据结算期间拉取失败隔几分钟重试5.2 佣金链路闭环验证选一个测试账号模拟完整的推广到结算流程。假设代理A邀请用户B购买一件商品。步骤是登录后台确认A和B的绑定关系已经写入user_agent_relation表等淘宝联盟T1回流订单查询agent_settlement表是否有A的入账记录检查A的累计收入、分佣比例、平台抽成三个数是否符合预期。手工验证时有个细节用转链接口生成测试链接商品不要拿已成交过的商品做验证否则订单归因可能命中历史绑定关系导致看不出问题。如果测试中发现绑定关系没建立第一反应是检查淘宝联盟的授权接口是否有重复回调问题——用户点链接后拉起的授权WebView如果被重复回调后端可能把已绑定关系覆盖成新代理。解决思路维持“第一次绑定为准”原则业务层加逻辑判断数据层加唯一索引双保险。最后送一个排查技巧当用户反馈“订单没佣金”时优先查后台日志里淘宝联盟接口的授权token是否过期而不是查代码逻辑。这类平台接口的token有效期通常只有几天过期次数比代码bug高一个数量级。本文还有配套的精品资源点击获取
返回列表