You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DDD支付退款系统:跨聚合根的不变量建模与维护方案咨询

多收款人拆分支付与退款系统的DDD聚合设计方案

1. 重新划定聚合边界:让Payment成为唯一聚合根

别把Payment和Refund拆成两个独立聚合根,把Refund、PaymentSplit、RefundSplit全都归到Payment聚合里作为内部实体或值对象。这样所有需要校验的规则都能在聚合内部完成,不用跨聚合找数据,从根源上解决不变量难保障的问题。
Payment聚合根要管控全生命周期的核心数据:总支付金额、累计已退款金额、每个收款人的原始拆分记录、所有退款明细。

2. 把业务规则直接封装在聚合内部

支付拆分的校验(规则1)

创建Payment的时候,直接把总金额和拆分列表传给聚合根的构造方法。在构造逻辑里当场计算所有拆分金额的总和,要是超过总金额,直接抛出领域异常,拒绝创建该Payment实例。
PaymentSplit作为聚合内的实体,存储收款人ID、应得金额、已退款金额这些核心字段,完全依附于Payment存在。

退款拆分的双重校验(规则2、规则3)

发起退款别单独创建Refund聚合,而是调用Payment聚合根的createRefund方法,传入退款拆分列表。
方法内部先计算净支付金额(总支付金额减去累计已退款金额),先校验所有退款拆分的金额总和不能超过这个净金额(规则2);接着对每一笔退款拆分,找到对应的原始PaymentSplit,校验这笔退款的金额不能超过该收款人剩余可退额度(原始拆分金额减去该收款人已退款总额,规则3)。
所有校验通过后,生成Refund实体并添加到Payment的退款列表中,同时更新对应PaymentSplit的已退款金额,以及聚合根的累计已退款总额。

3. 用值对象强化金额约束

定义一个Money值对象,封装币种、数值属性,内部保证金额非负,且不同币种不能直接进行运算。所有涉及金额的字段(总支付金额、拆分金额、退款金额等)都使用这个类型,从底层避免低级计算错误。

4. 跨聚合的规则交给领域服务处理

如果存在跨多个Payment实例的业务规则(比如某收款人单日退款上限),可以编写PaymentService领域服务来协调处理,但这类规则不属于单个Payment的聚合不变量,适合放在服务层统一管控。

内容的提问来源于stack exchange,提问作者Kainar Masujima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 03:55:15