vendredi 8 septembre 2023

Domain-Driven Design: How to Handle External Payment Gateway in Domain Layer?

I'm designing a payment system that uses different gateways. I'm facing an architectural challenge when trying to adhere strictly to Domain-Driven Design principles:

I need to create a payment intent on the external gateway first. Then, I want to create my internal PaymentIntent, which will contain the external gateway's payment intent as a child entity. Before creating an external gateway payment intent, I have specific domain rules that need to be checked.

My dilemma:

Injecting Services into Entities: If I were to check these rules inside the entity, I'd need to inject the gateway service into the domain entity, which violates the principle of model purity.

Always-Valid Domain Model: If I first create the PaymentIntent and then set the external gateway payment intent, I violate the always-valid domain model principle.

Domain Logic in Service: Currently, I'm checking these rules in a domain service. However, I'm concerned this approach leaks domain logic. Here's a simplified version of my code:

export class PaymentIntentService {
  async create({
    marketplaceId, gateway, customerId, amount, 
    paymentMethodType, paymentSplitsData,
  }: CreatePaymentIntentParams) {
    checkRules(
      new TotalPaymentSplitsEqualsIntentAmountRule(amount, paymentSplitsData),
      new PaymentSplitReceiversMustBeUniqueRule(paymentSplitsData),
    );

    const externalGatewayPaymentIntent = await this.gatewayService.createPaymentIntent({
      amount, paymentMethodType, gatewayCustomerId,
    });

    const paymentIntent = PaymentIntent.create({
      paymentSplitsData, marketplaceId, customerId, amount,
      paymentMethodType, gateway, businessEntityId: '', 
      gatewayPaymentIntent: externalGatewayPaymentIntent,
    });

    await this.paymentIntentRepository.create(paymentIntent);
    return paymentIntent;
  }
}

How should I structure this to best adhere to DDD principles while ensuring proper domain logic encapsulation and always-valid state?

Aucun commentaire:

Enregistrer un commentaire