PHP分销系统怎么搭:从返佣规则到开发落地思路
Php分销怎么做:从业务模式到系统开发的完整方案
在电商、知识付费、本地生活、SaaS服务等业务场景中,“分销”是一种非常常见的增长方式。简单来说,分销就是通过用户、代理、渠道商帮助平台推广商品或服务,当产生订单后,平台按照规则给推广者发放佣金。对于很多企业来说,分销系统不仅可以降低获客成本,还能通过裂变传播扩大品牌影响力。
如果你想用 PHP 来做一套分销系统,不仅要考虑代码怎么写,还要先理解业务逻辑、佣金规则、用户关系、订单结算、提现审核以及风控机制。本文将从产品设计、数据库设计、核心流程、PHP实现思路、安全风控等方面,系统讲解“Php分销怎么做”。
一、先明确什么是分销系统
分销系统的核心是:用户通过分享链接、二维码或邀请码邀请新用户购买商品,平台根据推广关系和订单金额给相关推广人发放佣金。
常见分销模式包括:
1. 一级分销
用户A邀请用户B,B购买商品后,A获得佣金。
例如:
- 商品金额:100元
- 一级佣金比例:10%
- 用户B下单成功
- 用户A获得佣金:10元
一级分销逻辑最简单,适合初期业务使用。
2. 二级分销
用户A邀请用户B,用户B又邀请用户C。C购买商品后,B获得一级佣金,A获得二级佣金。
例如:
- C购买商品100元
- B获得一级佣金10元
- A获得二级佣金5元
二级分销在很多电商平台中比较常见,可以增强裂变动力。
3. 多级分销
多级分销理论上可以无限层级,但实际业务中一定要谨慎。因为过深的分销层级容易涉及合规风险。通常建议控制在一级或二级,并且佣金应基于真实商品交易,而不是单纯拉人头。
4. 区域代理或渠道分销
除了普通用户分销之外,还可以设计代理商模式。例如省级代理、市级代理、门店代理等。代理商根据其管辖区域内产生的订单获得收益。这类系统比普通分销更复杂,需要结合区域、门店、渠道归属等数据。
二、做PHP分销系统前要先设计业务规则
很多开发者一上来就想写代码,其实这是不合理的。分销系统最重要的是业务规则,如果规则不清晰,后面开发会非常混乱。
在正式开发之前,需要明确以下问题:
1. 谁可以成为分销员?
常见方式有三种:
-
注册即分销员
用户注册后自动具备推广资格。 -
申请审核成为分销员
用户提交申请,后台审核通过后才能推广。 -
购买指定商品后成为分销员
用户购买会员、礼包或课程后获得分销资格。
如果平台刚起步,可以采用“注册即分销员”,降低参与门槛;如果平台更重视质量,可以使用申请审核模式。
2. 分销关系如何绑定?
用户打开推广链接后,需要确定他与邀请人的关系。常见绑定方式包括:
- 邀请码绑定
- 分享链接参数绑定
- 二维码绑定
- 注册时填写推荐人手机号或邀请码
例如推广链接:
https://www.example.com/register?invite_code=ABC123
当新用户通过该链接注册时,系统根据 invite_code 找到上级用户,并建立上下级关系。
3. 关系是否永久绑定?
分销关系通常有两种策略:
永久绑定
用户B第一次通过A的邀请注册后,B以后所有消费都给A产生佣金。
优点是分销员积极性高;缺点是平台佣金支出较大。
临时绑定
用户B通过A的链接进入平台,在一定时间内购买才给A佣金。例如7天、15天或30天有效期。
这种方式适合广告推广场景,但开发逻辑会复杂一些,需要记录访问来源和有效时间。
4. 佣金如何计算?
佣金计算是分销系统的核心。常见计算方式包括:
- 按订单金额比例计算
- 按商品设置固定佣金
- 不同商品不同佣金比例
- 不同分销员等级不同佣金比例
- 一级、二级分别设置佣金比例
例如:
一级佣金:订单实付金额 × 10%
二级佣金:订单实付金额 × 5%
需要注意的是,佣金通常应该基于“实付金额”计算,而不是商品原价。因为订单可能存在优惠券、满减、积分抵扣等情况。
5. 什么时候结算佣金?
佣金不能在用户刚下单时立刻发放到可提现余额,否则会出现退款风险。常见做法是:
- 用户支付成功后,生成“待结算佣金”
- 订单完成且过售后期后,佣金变为“可提现”
- 用户申请提现
- 后台审核提现
- 打款成功后,记录提现流水
这样可以避免用户下单后退款,分销员却已经提现的情况。
三、PHP分销系统的核心功能模块
一套完整的PHP分销系统通常包括以下模块。
1. 用户模块
用户模块是基础,至少需要支持:
- 用户注册
- 用户登录
- 用户资料
- 邀请码生成
- 上级绑定
- 分销员身份
- 用户等级
用户表中可以增加字段:
id
username
mobile
password
invite_code
parent_id
is_distributor
distributor_level
created_at
updated_at
其中:
invite_code是用户自己的邀请码parent_id表示上级用户IDis_distributor表示是否是分销员distributor_level表示分销员等级
2. 商品模块
商品模块需要支持佣金设置。常见字段包括:
id
title
price
commission_type
commission_rate_level1
commission_rate_level2
commission_amount_level1
commission_amount_level2
status
说明:
commission_type可以表示按比例或固定金额commission_rate_level1表示一级佣金比例commission_rate_level2表示二级佣金比例commission_amount_level1表示一级固定佣金commission_amount_level2表示二级固定佣金
如果商品很多,也可以单独设计商品佣金表。
3. 订单模块
订单模块需要记录购买人、订单金额、支付状态、完成状态等信息。
常见字段:
id
order_no
user_id
total_amount
pay_amount
pay_status
order_status
refund_status
paid_at
completed_at
created_at
分销佣金通常基于 pay_amount 计算。
4. 分销关系模块
虽然用户表中可以用 parent_id 记录直接上级,但如果要查询完整关系链,建议设计单独的关系表。
例如:
id
user_id
parent_id
level
created_at
也可以设计为树形结构,只记录直接上级,然后通过递归查找上级。对于一级、二级分销来说,直接用 parent_id 就足够。
5. 佣金记录模块
佣金记录表非常重要,用于记录每一笔订单产生的佣金。
字段示例:
id
order_id
buyer_id
distributor_id
level
amount
status
created_at
settled_at
其中 status 可以包括:
- pending:待结算
- settled:已结算
- invalid:已失效
- withdrawn:已提现
需要注意:同一个订单不能重复生成佣金记录,因此要对 order_id + distributor_id + level 做唯一约束。
6. 提现模块
分销员获得可提现佣金后,可以提交提现申请。
提现表字段示例:
id
user_id
amount
account_type
account_name
account_no
status
remark
created_at
audited_at
paid_at
提现状态可以包括:
- pending:待审核
- approved:审核通过
- rejected:审核拒绝
- paid:已打款
四、PHP分销系统核心流程
1. 用户注册绑定上级
当用户通过推广链接注册时,系统需要读取邀请码,并绑定上级。
简单示例:
$inviteCode = $_GET['invite_code'] ?? '';
if ($inviteCode) {
$parent = User::where('invite_code', $inviteCode)->first();
if ($parent) {
$user->parent_id = $parent->id;
}
}
$user->invite_code = generateInviteCode();
$user->save();
这里需要注意几个问题:
- 不能绑定自己为上级
- 已经有上级的用户不能重复绑定
- 上级必须是合法用户
- 如果要求分销员资格,上级必须是分销员
例如:
if ($parent && $parent->id != $user->id && empty($user->parent_id)) {
if ($parent->is_distributor) {
$user->parent_id = $parent->id;
}
}
2. 生成邀请码
邀请码需要唯一,可以用用户ID加随机字符生成。
示例:
function generateInviteCode()
{
do {
$code = strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 8));
$exists = User::where('invite_code', $code)->exists();
} while ($exists);
return $code;
}
这种方式简单可用。如果用户量非常大,可以使用更稳定的短码生成算法。
3. 支付成功后生成佣金
订单支付成功后,系统需要查找购买人的上级,并生成佣金记录。
假设只做二级分销:
function createCommission($order)
{
$buyer = User::find($order->user_id);
if (!$buyer) {
return;
}
$level1 = User::find($buyer->parent_id);
if ($level1 && $level1->is_distributor) {
$amount1 = calculateCommission($order, 1);
Commission::create([
'order_id' => $order->id,
'buyer_id' => $buyer->id,
'distributor_id' => $level1->id,
'level' => 1,
'amount' => $amount1,
'status' => 'pending',
]);
$level2 = User::find($level1->parent_id);
if ($level2 && $level2->is_distributor) {
$amount2 = calculateCommission($order, 2);
Commission::create([
'order_id' => $order->id,
'buyer_id' => $buyer->id,
'distributor_id' => $level2->id,
'level' => 2,
'amount' => $amount2,
'status' => 'pending',
]);
}
}
}
4. 佣金计算方法
佣金计算一定要统一封装,避免散落在各个业务代码中。
例如:
function calculateCommission($order, $level)
{
if ($level == 1) {
$rate = 0.10;
} elseif ($level == 2) {
$rate = 0.05;
} else {
$rate = 0;
}
return round($order->pay_amount * $rate, 2);
}
实际项目中,不建议把比例写死在代码中,而应该放到后台配置表或商品佣金表中。
5. 订单完成后结算佣金
当订单完成并超过售后期后,可以把佣金状态从 pending 改为 settled,同时增加用户可提现余额。
示例:
function settleCommission($orderId)
{
DB::beginTransaction();
try {
$commissions = Commission::where('order_id', $orderId)
->where('status', 'pending')
->lockForUpdate()
->get();
foreach ($commissions as $commission) {
$commission->status = 'settled';
$commission->settled_at = date('Y-m-d H:i:s');
$commission->save();
UserWallet::where('user_id', $commission->distributor_id)
->increment('available_balance', $commission->amount);
}
DB::commit();
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
这里使用事务非常重要,避免佣金状态改了但钱包余额没加,或者钱包余额加了但佣金状态没改。
6. 退款时佣金失效
如果订单发生退款,待结算佣金应改为失效。如果佣金已经结算,需要根据业务规则扣回或冻结。
示例:
function invalidCommission($orderId)
{
Commission::where('order_id', $orderId)
->where('status', 'pending')
->update([
'status' => 'invalid',
]);
}
如果佣金已提现,处理会更复杂。一般建议设置售后期,售后期结束后再结算佣金,从源头减少问题。
五、PHP分销系统数据库设计建议
以下是一个简化版数据库结构。
1. 用户表 users
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50),
mobile VARCHAR(20),
password VARCHAR(255),
invite_code VARCHAR(20) UNIQUE,
parent_id INT DEFAULT NULL,
is_distributor TINYINT DEFAULT 0,
distributor_level INT DEFAULT 1,
created_at DATETIME,
updated_at DATETIME
);
2. 订单表 orders
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
order_no VARCHAR(50) UNIQUE,
user_id INT NOT NULL,
total_amount DECIMAL(10,2) DEFAULT 0.00,
pay_amount DECIMAL(10,2) DEFAULT 0.00,
pay_status TINYINT DEFAULT 0,
order_status TINYINT DEFAULT 0,
refund_status TINYINT DEFAULT 0,
paid_at DATETIME,
completed_at DATETIME,
created_at DATETIME
);
3. 佣金表 commissions
CREATE TABLE commissions (
id INT AUTO_INCREMENT PRIMARY KEY,
order_id INT NOT NULL,
buyer_id INT NOT NULL,
distributor_id INT NOT NULL,
level TINYINT NOT NULL,
amount DECIMAL(10,2) DEFAULT 0.00,
status VARCHAR(20) DEFAULT 'pending',
created_at DATETIME,
settled_at DATETIME,
UNIQUE KEY uniq_order_distributor_level (order_id, distributor_id, level)
);
4. 钱包表 user_wallets
CREATE TABLE user_wallets (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL UNIQUE,
available_balance DECIMAL(10,2) DEFAULT 0.00,
frozen_balance DECIMAL(10,2) DEFAULT 0.00,
total_income DECIMAL(10,2) DEFAULT 0.00,
updated_at DATETIME
);
5. 提现表 withdrawals
CREATE TABLE withdrawals (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
amount DECIMAL(10,2) DEFAULT 0.00,
account_type VARCHAR(20),
account_name VARCHAR(50),
account_no VARCHAR(100),
status VARCHAR(20) DEFAULT 'pending',
remark VARCHAR(255),
created_at DATETIME,
audited_at DATETIME,
paid_at DATETIME
);
六、PHP分销系统开发时的关键注意事项
1. 防止重复发佣金
支付回调可能重复通知,因此生成佣金时必须做幂等处理。
可以通过以下方式避免重复:
- 订单支付状态只允许从未支付变为已支付一次
- 佣金表增加唯一索引
- 生成佣金前检查是否已存在
- 支付回调逻辑加事务
2. 钱包金额必须用事务处理
钱包余额涉及资金,一定不能随便 update。结算佣金、提现冻结、提现成功、提现拒绝等操作都应使用数据库事务和行锁。
例如提现申请时:
- 检查可提现余额是否足够
- 扣减可用余额
- 增加冻结余额
- 创建提现记录
这些步骤必须在同一个事务中完成。
3. 佣金比例不要写死
早期测试可以写死佣金比例,但正式系统一定要放到后台配置中。常见配置包括:
- 一级佣金比例
- 二级佣金比例
- 最低提现金额
- 提现手续费
- 结算周期
- 售后保护期
- 分销员等级权益
这样运营人员可以灵活调整规则,不需要每次都修改代码。
4. 注意合规风险
分销系统必须基于真实商品或服务交易,不建议设计“拉人头奖励”“入门费返佣”“无限层级返利”等模式。建议:
- 控制分销层级,一般不超过二级
- 佣金来自真实订单利润
- 不承诺静态收益
- 不设置高额入门费
- 不鼓励囤货
- 保留完整订单、佣金、提现记录
合规是分销系统能长期运行的基础。
5. 做好数据统计
分销员后台应该提供清晰的数据统计,例如:
- 今日推广人数
- 累计推广人数
- 今日订单数
- 累计订单数
- 待结算佣金
- 可提现佣金
- 已提现金额
- 下级用户列表
- 推广订单明细
对平台后台来说,也需要统计:
- 总分销员数量
- 总佣金支出
- 待结算佣金
- 提现申请
- 分销订单占比
- 高贡献分销员排行
这些数据可以帮助运营优化分销策略。
七、适合PHP分销系统的技术架构
如果是中小型项目,可以选择以下架构:
PHP框架:Laravel / ThinkPHP / Yii
数据库:MySQL
缓存:Redis
队列:Redis Queue / RabbitMQ
前端:Vue / UniApp / 小程序
支付:微信支付 / 支付宝
部署:Nginx + PHP-FPM
如果项目使用 Laravel,可以充分利用:
- Eloquent ORM
- Migration
- Queue
- Event Listener
- Scheduler
- Transaction
- Middleware
如果项目使用 ThinkPHP,则可以结合:
- 模型
- 事件
- 队列
- 定时任务
- 中间件
- 缓存
对于分销佣金结算,可以使用定时任务每天扫描已完成且超过售后期的订单,然后统一结算佣金。
八、一个推荐的开发步骤
如果你要从零开始做PHP分销系统,可以按以下顺序开发:
- 开发用户注册登录功能
- 增加邀请码字段
- 实现推广链接注册绑定上级
- 开发商品和订单功能
- 接入支付回调
- 支付成功后生成佣金记录
- 订单完成后结算佣金
- 开发用户钱包
- 开发提现申请和审核
- 开发分销员中心
- 开发平台后台统计
- 增加风控和日志
- 优化性能和安全
不要一开始就做复杂的多等级代理、区域分润、团队业绩等功能。建议先完成一个稳定的一级或二级分销闭环,再逐步扩展。
九、总结
Php分销系统并不是简单地写一个“邀请人返佣”功能,而是一套完整的业务系统。它至少包括用户关系、推广绑定、订单支付、佣金计算、佣金结算、退款处理、钱包余额、提现审核、后台配置和数据统计等多个模块。
开发时要重点关注三个问题:
-
业务规则清晰
包括分销层级、绑定关系、佣金比例、结算周期和提现规则。 -
资金逻辑安全
涉及佣金和钱包的操作必须使用事务、唯一索引和幂等机制。 -
系统合规可持续
分销应基于真实交易,层级不宜过多,避免不合理的拉人头奖励。
如果是初期项目,建议使用 PHP + MySQL + Redis,基于 Laravel 或 ThinkPHP 开发一套二级分销系统。先保证注册绑定、订单返佣、佣金结算和提现审核流程稳定,再根据业务发展增加分销员等级、商品独立佣金、代理区域、团队业绩等高级功能。这样做出来的PHP分销系统,既能满足业务增长需求,也更安全、稳定、可维护。