Appearance
概述
在 EBAOZU 租赁业务中,违约与逾期主要涵盖以下场景:
- 租金分期逾期(账单逾期):用户未在约定的账单应还款日前完成当期租金支付。
- 到期归还逾期(商品逾期):租期届满后,用户未在规定时间内归还商品且未办理续租/买断。
- 货损与折旧赔付:归还商品检验存在损坏、维修费用、缺失或折旧,产生赔付金。
违约记录统一持久化于 eb_store_order_deposit 表(type=2 货损/赔偿,type=3 逾期违约),并与支付宝租赁行业交易(check_type=3)售后赔付模块(aftersaleCreate / aftersaleConfirm / rentOrderPayCancel)双向联动。
核心数据结构
违约与押金主表(eb_store_order_deposit)
| 字段 | 类型 | 说明 |
|---|---|---|
id | int | 记录自增 ID |
uid | int | 用户 ID |
order_id | int | 关联主订单 ID(eb_store_order.id) |
type | tinyint | 类型:1=押金/资金授权押金,2=货损/赔偿金,3=逾期违约金 |
lease_id | int | 关联分期账单 ID(eb_store_order_installment.id),归还逾期为 0 |
out_trade_no | string | 违约商户单号(前缀 WY...) |
money | decimal | 违约金/赔偿金额 |
less_money | decimal | 待支付/待抵扣剩余金额 |
remark | string | 违约说明(如:归还逾期1天,每日租金: 14.92) |
status | tinyint | 状态:0=待支付, 1=已支付, 2=部分退款, 3=全部退款, -1=已取消 |
aftersale_id | string | 支付宝租赁交易售后单号(调用 aftersaleCreate 成功后回填) |
installment_order_id | string | 支付宝交易组件分期/账单单号 |
pay_time | int | 支付时间戳 |
配置项说明(lease_overdue_config)
系统通过后台配置项 lease_overdue_config 控制逾期金计算策略:
| 配置键 | 说明 | 取值范围 |
|---|---|---|
installment_overdue | 分期逾期违约金计费方式 | 1=每日租金, 2=账单逾期比例(%), 3=固定金额 |
return_overdue | 归还逾期违约金计费方式 | 1=每日租金, 2=账单逾期比例(%), 3=固定金额 |
return_max_rate | 归还逾期最大年化率(%) | 限制归还逾期累计违约金不超过租金年化率上限 |
must_pay | 完结前强制支付 | true=若存在未结清违约单,禁止完结订单;false=允许直接完结并解冻 |
违约金计算规则
入口:[app\services\order\StoreOrderDepositServices::getOverAmount](file:///www/wwwroot/ebaozu_v4/app/services/order/StoreOrderDepositServices.php)
分期账单逾期(inOrder 存在)
- 每日租金模式 (
value=1):$\text{违约金} = \text{分期日均租金} \times \text{逾期天数}$ - 逾期比例模式 (
value=2):$\text{违约金} = \text{当期租金} \times \text{逾期比例} \times \text{逾期天数}$ - 固定金额模式 (
value=3):$\text{违约金} = \text{固定日罚金} \times \text{逾期天数}$
归还逾期(!inOrder,商品未归还)
为符合监管及支付宝租赁行业交易官方规范,归还逾期计算受严格双重约束:
- 纯租金日均上限约束(支付宝
check_type=3): $$\text{日均纯租金} = \frac{\text{订单总额} - \text{运费}}{\text{租期天数}} = \frac{\text{total_price} - \text{pay_postage}}{\text{lease_days}}$$- 每日违约基数不得大于日均纯租金(运费/增值服务费等非租金项不计入违约基数)。
- 累计违约金上限约束: $$\text{累计违约金} \le \min\left(\text{日均纯租金} \times \text{逾期天数},\ \text{到期购买价} - \text{已付租金}\right)$$
- 若配置了
return_max_rate(年化率上限),累计金额亦不得超过租金的年化上限。
- 若配置了
支付宝租赁行业交易对接(CommerceRentServices)
针对 check_type = 3 的支付宝行业交易订单,违约与赔付通过支付宝售后履约组件处理:
管理后台操作「创建违约售后」
│
▼
StoreOrderDepositServices::createLateAftersale($id)
│
▼
CommerceRentServices::aftersaleCreate($oid, $type=2, $pay_type=2, $record)
│
├─ 1. 计算合规上限:min((纯租金 / 租期) * 逾期天数, 到期购买价)
├─ 2. 防御性自动截断:确保 pay_amount <= 允许上限
├─ 3. 组装 pay_items [{'type': 'LATE_FEE', 'pay_amount': $pay_amount}]
└─ 4. 调用支付宝 OpenAPI:alipay.commerce.rent.order.aftersale.create
│
├─ 成功 → 回填 aftersale_id 到 eb_store_order_deposit
└─ 失败 → 抛出异常并记录 dev_log赔付类型映射(aftersale_type = COMPENSATION)
| 业务类型 | 支付宝 reason_code | pay_items.type | 规则限制 |
|---|---|---|---|
| 逾期归还违约 | RETURN_OVERDUE | LATE_FEE | 不得大于 $\min((\text{订单总租金}/\text{租期}) \times \text{逾期天数}, \text{到期购买价})$ |
| 提前归还违约 | RETURN_EARLY | LATE_FEE | 违约金最高不超过剩余未交租金的 30% |
| 物品损坏/维修 | ITEM_DAMAGED / ITEM_REPAIR | INDEMNITY | 不得高于折旧损失,最高不超过当期购买价 |
| 物品丢失/折旧 | ITEM_LOST / ITEM_DEPRECIATION | INDEMNITY | 最高不超过当期购买价 |
接口清单
管理后台接口(route/admin.php)
| 请求方式 | 路由路径 | 控制器方法 | 功能说明 |
|---|---|---|---|
POST | order/create_late_aftersale/:id | v1.order.StoreOrder/createLateAftersale | 创建违约售后单并同步支付宝 |
POST | order/update_deposit_order/:id | v1.order.StoreOrder/updateDepositOrder | 调整违约单/押金单金额及备注 |
POST | order/cancel_deposit_order/:id | v1.order.StoreOrder/cancelDepositOrder | 取消违约单/押金记录 |
POST | order/ready_for_overdue_pay | v1.order.StoreOrder/readyForOverduePay | 发起违约金收银/扣款准备(生成新商户单号) |
关键设计与异常防护规范
取消违约单时的前置条件过滤:
- 仅当违约单已在支付宝成功建单(
!empty($record['aftersale_id'])或!empty($record['installment_order_id']))时,才调用CommerceRentServices::payCancel。 - 本地草稿或此前创建失败的单据直接本地置
-1取消,避免向支付宝发送未建单单号导致PARAMS_VALID_ERROR误报。
- 仅当违约单已在支付宝成功建单(
订单完结与解冻保护:
- 当管理员执行“确认收货”或“完结订单”时,若存在已取消(
status = -1)的违约记录,系统视同放弃追缴违约金,正常全额解冻预授权并完结订单。 - 若开启
must_pay,系统会在完结前阻断并提示:存在违约未支付记录,请处理后再完结订单。
- 当管理员执行“确认收货”或“完结订单”时,若存在已取消(