您现在的位置: 365建站网 > 365文章 > PHP 多用户商城系统怎么做?拆单、数据隔离与分账结算

PHP 多用户商城系统怎么做?拆单、数据隔离与分账结算

文章来源:365jz.com 点击数:10 更新时间:2025-12-07 08:56

“PHP 商城系统”从几百字的单店演示,到支持数百商家独立后台的多用户商城(B2B2C),中间的技术差异非常大。多数人卡在数据隔离、资金分账、以及商家权限边界这三处。本文给出可落地的模型设计与实现要点。

php多用户商城系统设计

一、先定义清楚“多用户”是哪一种

  • 多买家:只有客户注册,一个卖家。这是普通商城,不需要分账;
  • 多商家(B2B2C):商家可自主入驻、上架、发货、看自己订单,平台抽佣。这才是“多用户商城”的难点;
  • 多租户(SaaS 型):每个客户一套独立品牌店铺(域名/数据隔离),面向代理商卖软件。

三者的架构成本差一个数量级,选型前先确认需求属于哪一种。

二、核心数据模型

shop(id, name, domain, status, settle_rate)        -- 店铺
goods(id, shop_id, cat_id, title, price, status)   -- 商品,必带 shop_id
sku(id, goods_id, spec_json, price, stock)         -- 规格维度库存
order(id, order_no, uid, shop_id, total_amount, status, ...)
order_item(id, order_id, goods_id, sku_id, shop_id, price, qty, amount)
settlement(id, shop_id, order_id, amount, rate, fee, status)  -- 分账/结算
wallet(shop_id, balance, frozen)                   -- 商家钱包

三条关键原则:

  1. 订单按店铺拆分:用户一次买 A 店 + B 店的商品,要拆成两个父单两个子单(或一个 parent_order + 多个 order)。混在一张单里,发货、退款、分账全都会乱;
  2. order_item 冗余 shop_id:查询商家订单时避免 JOIN goods(商品可能改名、下架、删除);
  3. 价格与状态快照:订单项里必须存成交时的单价与商品标题,不能实时关联商品表。

三、数据隔离的实现(最容易出安全事故)

所有商家后台查询都必须强制带 shop_id,而不是“前端没传就查全部”。工程做法:

class GoodsRepo {
    public function __construct(private int $shopId) {}

    public function paginate(array $w, int $page = 1) {
        // 关键:shop_id 由会话注入,不接受请求参数
        $cond = array_merge($w, ['shop_id' => $this->shopId]);
        return DB::table('goods')->where($cond)->paginate(20, $page);
    }
}
// 服务层统一从登录态取
$repo = new GoodsRepo(session('shop_id'));

补充三条防线:① 更新/删除用双条件:WHERE id=? AND shop_id=?,只按 id 更新是越权读写的主要来源;② 全局中间件校验角色(平台管理员与商家是两套权限点,不要混用同一个“管理员”概念);③ 文件上传路径按店铺隔离 /uploads/{shop_id}/...,避免 A 店直接访问 B 店图片。

测试方法:用两个不同店铺账号交叉访问对方的 /goods/edit?id=对方ID,若成功就是越权漏洞。

四、资金:分账、退款、结算

  1. 抽佣计算:用整数分,fee = intdiv(amount * rate, 10000)(rate 为万分比),避免浮点误差;
  2. 支付通道选择:微信/支付宝官方都提供服务商模式的分账接口(微信“电商收付通”、支付宝“分账/间连”)。用分账接口才合规,自行“平台先收款、再私下转账给商家”会形成二清问题(无证从事资金结算),这是政策红线;
  3. 结算周期:常见做法是订单完成后 T+N(如 7/15 天)进入可提现,留出售后窗口;
  4. 退款分摊:退款要同时退“商家货款 + 平台佣金 + 优惠券承担部分”,三部分按当初的分账比例反向冲销,并在 settlement 表记红冲记录(不要直接 UPDATE 原记录);
  5. 对账:每日跑批比对“支付通道流水 ↔ 本地订单 ↔ 分账记录”三方,差异入异常表人工处理。
CREATE TABLE settlement (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  order_id BIGINT UNSIGNED NOT NULL,
  shop_id  BIGINT UNSIGNED NOT NULL,
  amount   INT UNSIGNED NOT NULL,   -- 分(订单实付)
  fee      INT UNSIGNED NOT NULL,   -- 平台佣金
  net      INT UNSIGNED NOT NULL,   -- 商家应得 = amount - fee
  type     TINYINT NOT NULL,        -- 1 正常 2 退款红冲
  status   TINYINT NOT NULL DEFAULT 0,
  UNIQUE KEY uk_order_type (order_id, type),
  KEY idx_shop_status (shop_id, status)
) ENGINE=InnoDB;

五、并发与库存(沿用单店方案,但要注意跨店券)

  • 库存扣减仍是原子 SQL:UPDATE sku SET stock=stock-? WHERE id=? AND stock>=?,判 rowCount();
  • 优惠券要区分平台券(全店通用,平台承担)与店铺券(单店,商家承担),成本归属不同,直接决定结算金额;
  • 满减/折扣叠加时统一在“下单快照”阶段算好并存进 order_item,后续不再重算。

六、要不要用现成开源系统

先看这些再决定自研:

  • Crmeb(PHP/Java,商用需授权)、Hive ERP、萤火小程序商城等国内常见;Magento(Adobe Commerce)、Sylius / Saleor 偏国际;
  • 成熟方案(有赞、微盟等 SaaS)适合快速上线,但数据在自己库里这一点需要评估;
  • 自研的成本常被低估:多用户商城涉及资金,安全(越权、SQL 注入、支付回调伪造)、发票、税务、《电子商务法》对平台的责任(商家资质审核、消费争议处理、违法商品信息处置)都要覆盖。

支付回调务必:验签 + 校验金额与订单号一致 + 幂等处理(用唯一索引 uk_order_no 防止重复入账)。

七、常见问题 FAQ

问:能不能用一个订单表存多店商品,简单点?
答:短期可以,长期一定改。发货单、物流、售后都按店铺维度,跨店混单会让这些流程无解。

问:商家能不能改自己商品的“已成交订单”?
答:绝对不能。订单金额与状态只能由系统流程变更,商家端仅“发货/备注”。

问:如何防止商家上传违规商品?
答:接入内容审核(图像识别 + 关键词)+ 先发后审或先审后发策略 + 举报入口,平台需留存商家资质,否则出事时责任在平台。

核心:多用户商城的技术难点不在商品与订单,而在“按店铺拆单 + 会话强制注入 shop_id + 走官方分账接口避开二清”这三条。

生产内容,同时打通搜索引擎(SEO)与AI搜索引擎(GEO)流量入口的软件! 点击进入365建站器 »