Skip to content

Conversation

@hamedzsmm
Copy link
Collaborator

  • Added PaymentRequest and ValueObjects
  • Implemented validation logic for fields like MobileNumber, Email, and CallbackUrl.
  • Added behaviors to PaymentRequest, including:
    • SetCard, SetPayer, UpdatePaymentStatus, SetGatewayNote and other methods.
  • Introduced static factory method Create for controlled instantiation.
  • Developed comprehensive unit tests for PaymentRequest and their value objects
  • Ensured encapsulation and adherence to rich domain model principles.

@imhmdi imhmdi requested a review from Copilot May 16, 2025 08:36
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a rich domain model around payment requests with encapsulated value objects, enforced validation, and accompanying unit tests.

  • Defines value objects (Money, CardNumber, CVV, ExpiryDate, Payer, Card, BaseCurrency) with field validation.
  • Implements PaymentRequest entity behaviors (factory instantiation, setters, status updates) and validation.
  • Adds unit tests and a masking service for payment card fields.

Reviewed Changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/Tests/Honamic.PayMaster.Abstractions.UnitTest/CardNumberTest.cs Adds unit tests for CardNumber validation
src/Tests/Honamic.PayMaster.Abstractions.UnitTest/CardMaskingServiceTest.cs Adds unit tests for CardMaskingService
src/Tests/Honamic.PayMaster.Abstractions.UnitTest/CVVTest.cs Adds unit tests for CVV validation
src/PayMaster.sln Registers the new unit test project and solution folder
src/Abstractions/PaymentProviders/ValueObjects/Payer.cs Introduces Payer value object
src/Abstractions/PaymentProviders/ValueObjects/Money.cs Introduces Money value object with arithmetic methods
src/Abstractions/PaymentProviders/ValueObjects/ExpiryDate.cs Introduces ExpiryDate value object with expiry checks
src/Abstractions/PaymentProviders/ValueObjects/CardNumber.cs Introduces CardNumber value object with length validation
src/Abstractions/PaymentProviders/ValueObjects/Card.cs Introduces Card aggregate value object
src/Abstractions/PaymentProviders/ValueObjects/CVV.cs Introduces CVV value object with length validation
src/Abstractions/PaymentProviders/ValueObjects/BaseCurrency.cs Defines supported currencies and symbols
src/Abstractions/PaymentProviders/Services/CardMaskingService.cs Implements card number masking logic
src/Abstractions/PaymentProviders/Exceptions/PaymentNotFoundException.cs Adds PaymentNotFoundException
src/Abstractions/PaymentProviders/Exceptions/InvalidExpiryDateException.cs Adds InvalidExpiryDateException
src/Abstractions/PaymentProviders/Exceptions/InvalidCurrencyException.cs Adds InvalidCurrencyException
src/Abstractions/PaymentProviders/Exceptions/InvalidCardNumberException.cs Adds InvalidCardNumberException
src/Abstractions/PaymentProviders/Exceptions/InvalidCVVException.cs Adds InvalidCVVException
src/Abstractions/PaymentProviders/Exceptions/InvalidAmountException.cs Adds InvalidAmountException
src/Abstractions/PaymentProviders/Exceptions/DuplicatePaymentException.cs Adds DuplicatePaymentException
src/Abstractions/PaymentProviders/Entities/PaymentRequest.cs Implements PaymentRequest entity and validation methods
Comments suppressed due to low confidence (1)

src/Abstractions/PaymentProviders/ValueObjects/CardNumber.cs:36

  • Validation only checks length; consider stripping whitespace and verifying all characters are digits and potentially applying the Luhn algorithm to prevent invalid card numbers.
return Regex.Replace(number, "@\\s+", "").Length == 16;

/// <returns>A masked card number</returns>
public static string Mask(CardNumber cardNumber)
{
var visiblePart = cardNumber.Number.Substring(0 + cardNumber.Number.Length - UnmaskedDigits);
Copy link

Copilot AI May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 0 + in the Substring call is redundant; simplify to cardNumber.Number.Substring(cardNumber.Number.Length - UnmaskedDigits) for clarity.

Suggested change
var visiblePart = cardNumber.Number.Substring(0 + cardNumber.Number.Length - UnmaskedDigits);
var visiblePart = cardNumber.Number.Substring(cardNumber.Number.Length - UnmaskedDigits);

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +72
if (!string.IsNullOrEmpty(mobileNumber) && mobileNumber.Length != 11)
throw new ArgumentException("Mobile number must be 11 digits.", nameof(mobileNumber));
Copy link

Copilot AI May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mobile number is only length-checked; you should also enforce that it contains only digits (e.g. with a regex) to avoid invalid input.

Suggested change
if (!string.IsNullOrEmpty(mobileNumber) && mobileNumber.Length != 11)
throw new ArgumentException("Mobile number must be 11 digits.", nameof(mobileNumber));
if (!string.IsNullOrEmpty(mobileNumber))
{
if (mobileNumber.Length != 11 || !Regex.IsMatch(mobileNumber, @"^\d{11}$"))
throw new ArgumentException("Mobile number must be exactly 11 digits and contain only numeric characters.", nameof(mobileNumber));
}

Copilot uses AI. Check for mistakes.
{ "AUD", "Australian dollar (A$)" },
{ "BRL", "Brazilian real (R$)" },
{ "CAD", "Canadian dollar (C$)" },
{ "CNY", "Chinese Renmenbi (¥)" },
Copy link

Copilot AI May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in currency name: "Renmenbi" should be "Renminbi".

Suggested change
{ "CNY", "Chinese Renmenbi (¥)" },
{ "CNY", "Chinese Renminbi (¥)" },

Copilot uses AI. Check for mistakes.
throw new InvalidExpiryDateException($"{month}/{year} is not a valid expiry date");
}

//TODO: it works only on forieng countries cards, should be globalized by culture
Copy link

Copilot AI May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in comment: "forieng" should be "foreign".

Suggested change
//TODO: it works only on forieng countries cards, should be globalized by culture
//TODO: it works only on foreign countries' cards, should be globalized by culture

Copilot uses AI. Check for mistakes.
throw new InvalidAmountException();

if (string.IsNullOrEmpty(currency) || !BaseCurrency.CurrencySymbols.ContainsKey(currency.ToUpper()))
throw new InvalidCurrencyException();
Copy link

Copilot AI May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throwing InvalidCurrencyException without a message can make debugging harder; consider including the invalid currency code in the exception message.

Suggested change
throw new InvalidCurrencyException();
throw new InvalidCurrencyException($"Invalid currency code: '{currency}'.");

Copilot uses AI. Check for mistakes.
}

public void Validate()
{
Copy link

Copilot AI May 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation logic in Validate() duplicates the checks in Create; consider centralizing field validation in one place or reusing the factory checks to avoid drift.

Suggested change
{
{
ValidateFields();
}
private void ValidateFields()
{

Copilot uses AI. Check for mistakes.
@imhmdi imhmdi closed this May 24, 2025
@imhmdi imhmdi deleted the feat/create-domain-valueobjects-tests branch May 24, 2025 20:10
@imhmdi imhmdi restored the feat/create-domain-valueobjects-tests branch May 27, 2025 13:24
@imhmdi imhmdi reopened this May 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants