2. 领域驱动设计基础:聚合、实体、值对象在支付订单中的概念映射

在支付订单领域,DDD 的三个核心构造块——实体(Entity)、值对象(Value Object)和聚合(Aggregate)——为复杂业务逻辑提供了清晰的建模框架。理解它们在支付场景中的具体映射,是后续实现幂等处理和防重策略的前提。

2.1 实体:具有唯一标识且可变的对象

实体通过 ID 而非属性值来区分,其状态会随时间或业务操作发生变化。在支付订单领域,以下对象应建模为实体:

实体名称 唯一标识 可变状态示例 DDD 角色
支付订单(PaymentOrder) paymentOrderId(全局唯一) 订单状态、支付金额、支付时间 聚合根
商户(Merchant) merchantId 结算费率、API 密钥 聚合根(独立聚合)
支付渠道(PaymentChannel) channelId 渠道状态、可用额度 实体(内部或外部)
退款记录(RefundRecord) refundId 退款状态、退款金额 实体(支付订单聚合内)
关键原则:支付订单的 paymentOrderId 必须在整个生命周期内保持不变。即使订单状态从“待支付”变为“已支付”,其 ID 依然唯一标识该笔交易。这是幂等处理的基础——通过 ID 识别同一笔请求。

2.2 值对象:描述属性,无唯一标识

值对象通过属性值来定义,两个值对象如果所有属性相同,则视为相等。它们通常是不可变的,用于描述实体的特征或业务概念。

  • 金额(Money):包含金额数值和币种(如 amount: 100.00, currency: "CNY")。两个金额对象如果数值和币种都相同,则相等。
  • 支付方式(PaymentMethod):描述支付工具类型(如 type: "WECHAT_PAY", account: "wx_12345")。
  • 地址(Address):包含省、市、区、详细地址等属性,用于订单配送或结算。
  • 时间范围(TimeRange):如 startTime: "2025-01-01 00:00:00", endTime: "2025-01-31 23:59:59",用于优惠活动有效期。
  • 幂等键(IdempotentKey):由调用方生成的唯一请求标识,作为值对象附加在支付请求中。
建模建议:将 Money 设计为值对象,可以避免金额计算中的精度丢失和币种混淆。在支付订单实体中,totalAmount 字段的类型应为 Money 而非原始数字。

2.3 聚合:事务一致性的边界

聚合是一组相关对象的集合,外部只能通过聚合根(Aggregate Root)访问内部对象。聚合边界内的所有修改必须在一次事务中完成,保证强一致性。

在支付订单领域,典型的聚合设计如下:

支付订单聚合边界与内部结构 聚合边界(事务一致性) 支付订单(聚合根) paymentOrderId: String (唯一标识) 退款记录(实体) refundId, status, amount 金额(值对象) amount, currency 支付方式(值对象) type, account 幂等键(值对象) idempotentKey, createdAt 商户(外部聚合根) merchantId(引用) 支付渠道(外部实体) channelId(引用) 说明:聚合根通过 ID 引用外部聚合(商户、渠道),不直接持有其内部状态,保证聚合边界清晰。

2.4 聚合设计原则在支付场景中的应用

支付订单聚合的设计需遵循以下原则,以确保数据一致性和系统可维护性:

  1. 聚合根唯一入口:所有对支付订单的修改(如支付、退款、关闭)必须通过 PaymentOrder 聚合根的方法执行,不允许直接操作内部实体或值对象。
  2. 事务边界最小化:一次支付操作只修改一个聚合实例。例如,支付成功时只更新 PaymentOrder 的状态,不直接更新商户的余额(通过领域事件异步处理)。
  3. 引用外部 ID:聚合内部只存储外部聚合的 ID(如 merchantId),而非整个对象。这避免了跨聚合的事务耦合。
  4. 幂等性内置:聚合根应提供幂等操作方法,接收 IdempotentKey 值对象作为参数,在聚合内部检查是否已处理。
常见误区:将支付订单、商户、渠道放在同一个大聚合中。这会导致每次支付操作都需要加载商户和渠道的全部数据,降低并发性能,且容易引发跨聚合的事务冲突。正确的做法是保持聚合独立,通过领域事件或最终一致性协调。

2.5 概念映射总结

下表总结了 DDD 核心概念在支付订单领域的具体映射:

DDD 概念 支付领域映射 关键特征 示例
聚合根 支付订单 全局唯一 ID,事务边界入口 PaymentOrder
实体 退款记录、支付通知 有 ID,状态可变 RefundRecord
值对象 金额、支付方式、幂等键 无 ID,不可变,按值相等 Money, IdempotentKey
领域服务 支付路由、风控校验 无状态,处理跨聚合逻辑 PaymentRoutingService
领域事件 支付成功事件、退款完成事件 记录已发生的事实,异步处理 PaymentSucceededEvent