导读:停车不只是"停进去、开出来"那么简单,背后涉及计费规则、优惠活动、违约扣款、多方分账、退款与提现等复杂的资金逻辑。本文带你拆解这套系统的资金链路设计。
本文结合实际项目设计进行拆解,建议先看看设计成果《车位共享预约云平台》,再阅读本文。
一、计费引擎:单元化+动态定价
基础计费模型
系统的计费采用 单元计费 模式:
{
"UnitMinutes": 15, // 每个计费单元15分钟
"UnitPrice": 200, // 每单元200分(=2元)
"Discount": 1, // 折扣系数
"Deduction": 0.3 // 违约扣款30%
}
计算方式非常直白:
单元数 = Ceil(停车总分钟数 / UnitMinutes)
费用 = 单元数 × UnitPrice × Discount
举个例子:停了40分钟 → Ceil(40/15)=3个单元 → 3 × 200分 × 1 = 600分(6元)
超时双倍计费
如果超出预约时段,超出的部分按 双倍价格 计费:
decimal? overtimeUnits = Math.Ceiling(overtimeMinutes / um);
overtimeAmount = overtimeUnits * price * discount * multiple; // multiple=2
这种设计倒逼用户合理预估停车时间,超时越多,代价越大,也间接提高了车位周转率。
营销活动覆盖
系统的定价并非一成不变。ZnMarket 表(市场营销活动)可以覆盖全局定价:
当前时间是否在某个活动有效期内?
├── 是 → 使用活动的 UnitMinutes/UnitPrice/Discount/Deduction
└── 否 → 使用全局配置的默认值
这意味着运营人员可以在节假日设置"免费停车2小时"或者"夜间半价"等活动,无需修改代码。
二、违约风控:三种扣费场景
系统设计了三个维度的违约处理:
| 场景 | 触发条件 | 违约金 |
|---|---|---|
| 用户主动取消 | 入场前手动取消 | 预约开始前15分钟内取消,扣预缴×30% |
| 预约未到场 | AutoExpire定时任务 | 预缴×30%,退还70% |
| 超时停车 | 离场时自动计算 | 超时部分按双倍计费 |
违约金去向了哪里? 这部分费用会按分账比例分配给车位主(地产/物业/个人),作为"机会成本"的补偿。
三、多方分账模型:快照机制保公平
三个分账角色
每一个车位都有三个利益相关方:
车位(ZnParkingSpaceEntity)
├── PropComPercent — 地产公司收益比例
├── PropSerComPercent — 物业公司收益比例
└── PersonalPercent — 个人车位主收益比例
为什么用数据快照?
创建订单时,系统主动从车位实体复制这些比例到订单记录中:
entity.PropComPercent = spaceEntity.PropComPercent;
entity.PropSerComPercent = spaceEntity.PropSerComPercent;
entity.PersonalPercent = spaceEntity.PersonalPercent;
真实世界的业务场景是:今天的停车费,应该按今天的比例分。 如果某个车位明天改了分账比例,历史订单不应该受影响——这就是快照的价值。
分账计算
查询订单时,实时基于金额和比例计算各方分成:
x.PropComAmount = PropComPercent * Amount; // 地产公司
x.PropSerComAmount = PropSerComPercent * Amount; // 物业公司
x.PersonalAmount = PersonalPercent * Amount; // 个人
四、资金闭环:两条流水线
系统的资金流分为正向和反向两条链路:
正向链路:用户 → 多方
用户微信支付 → 预缴冻结
↓
离场结算 → 实付金额确定
↓
收益按比例拆分 → 地产公司 | 物业公司 | 个人车位主
↓
各方累计收益 → 每月可申请提现一次
反向链路:系统 → 用户
预约取消/超时 → 退款处理
↓
创建 ZnRefundListEntity(退款记录)
↓
微信支付退款 → 回调更新状态
欠费链路
超时停车 → 实付 > 预缴 → 创建 ZnDebtEntity(欠费记录)
↓
用户下次进入小程序 → 检测到未补缴欠费
↓
引导用户补缴 → 再次调用微信支付
五、提现设计:按月归集、满额起提
个人车位主的收益提现做了两个约束:
- 月度限制:每月只能提现一次
- 满额起提:累计收益满100元才能提现
// 本月是否已提现?
var flag = currentRepository.GetQuery(x => x.CreatedDate >= fd && x.CreatedDate <= ed).Any();
if (flag) return new ResultModel(false, "本月已提现,请于下月再试");
// 收益是否满100元?
if (amount < 100 * 100) return new ResultModel(false, "不满100元,暂无法提现");
提现时,系统将所有已结算但未提取的订单收益汇总为一笔,标记订单的 PersonalIncomeStatus = 1 防止重复提取。
六、设计亮点总结
- 单元化计费 + 可配置参数,适应多种计费策略
- 动态定价覆盖,运营活动无需改代码
- 数据快照机制,保证历史分账不可篡改
- 三资金实体(订单/退款/欠费),每笔资金变动独立可追溯
- 先走人后补缴,兼顾用户体验与资金安全
一个停车场的资金流转,映射的是一个复杂的多方利益分配模型。这套系统用精炼的数据结构和清晰的状态管理,实现了财务级的资金闭环。
(未完待续)有疑问或者想讨论的点,留言区见。