PaymentOrder.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. using System.ComponentModel.DataAnnotations;
  2. using System.ComponentModel.DataAnnotations.Schema;
  3. using Domain.Entities.Members;
  4. using Domain.Entities.Payments.ValueObject;
  5. namespace Domain.Entities.Payments;
  6. public class PaymentOrder
  7. {
  8. [ForeignKey(nameof(MemberID))]
  9. public virtual Member? Member { get; private set; }
  10. [Key]
  11. public int ID { get; private set; }
  12. public int MemberID { get; private set; }
  13. /// <summary>가맹점 주문번호 (unique, 중복 불가)</summary>
  14. public string OrderID { get; private set; } = default!;
  15. /// <summary>다날 CPID (계약 완료 후 발급)</summary>
  16. public string MerchantID { get; private set; } = default!;
  17. /// <summary>상품명</summary>
  18. public string OrderName { get; private set; } = "포인트 충전";
  19. /// <summary>다날 거래번호 (승인 후 저장)</summary>
  20. public string? TransactionID { get; private set; }
  21. /// <summary>결제 금액 (부가세 포함 총액)</summary>
  22. public int Amount { get; private set; }
  23. /// <summary>충전될 포인트 (= 결제금액, 1:1)</summary>
  24. public int PointAmount { get; private set; }
  25. /// <summary>부가세 (표시용)</summary>
  26. public int VatAmount { get; private set; }
  27. public PaymentMethod PaymentMethod { get; private set; }
  28. public PaymentStatus Status { get; private set; }
  29. public DateTime? PaidAt { get; private set; }
  30. public DateTime? CancelledAt { get; private set; }
  31. public string? FailReason { get; private set; }
  32. /// <summary>가상계좌: 계좌번호</summary>
  33. public string? VirtualAccountNumber { get; private set; }
  34. /// <summary>가상계좌: 은행명</summary>
  35. public string? VirtualAccountBank { get; private set; }
  36. /// <summary>가상계좌: 예금주</summary>
  37. public string? VirtualAccountHolder { get; private set; }
  38. /// <summary>가상계좌: 입금 기한</summary>
  39. public DateTime? VirtualAccountExpireAt { get; private set; }
  40. public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;
  41. private PaymentOrder() { }
  42. public static PaymentOrder Create(
  43. int memberID,
  44. string orderID,
  45. string merchantID,
  46. int amount,
  47. PaymentMethod method,
  48. string orderName = "포인트 충전"
  49. ) {
  50. ArgumentOutOfRangeException.ThrowIfNegativeOrZero(memberID);
  51. ArgumentOutOfRangeException.ThrowIfNegativeOrZero(amount);
  52. if (string.IsNullOrWhiteSpace(orderID)) {
  53. throw new ArgumentException("orderID required", nameof(orderID));
  54. }
  55. if (string.IsNullOrWhiteSpace(merchantID)) {
  56. throw new ArgumentException("merchantID required", nameof(merchantID));
  57. }
  58. var vat = (int)Math.Round(amount / 11.0);
  59. return new PaymentOrder
  60. {
  61. MemberID = memberID,
  62. OrderID = orderID,
  63. MerchantID = merchantID,
  64. OrderName = orderName,
  65. Amount = amount,
  66. PointAmount = amount,
  67. VatAmount = vat,
  68. PaymentMethod = method,
  69. Status = PaymentStatus.Pending
  70. };
  71. }
  72. public void MarkPaid(string transactionID)
  73. {
  74. if (Status is not PaymentStatus.Pending and not PaymentStatus.WaitingDeposit)
  75. {
  76. throw new InvalidOperationException($"Cannot mark as paid from status {Status}");
  77. }
  78. TransactionID = transactionID;
  79. Status = PaymentStatus.Paid;
  80. PaidAt = DateTime.UtcNow;
  81. }
  82. public void MarkFailed(string reason)
  83. {
  84. Status = PaymentStatus.Failed;
  85. FailReason = reason;
  86. }
  87. public void MarkCancelled()
  88. {
  89. if (Status != PaymentStatus.Paid)
  90. {
  91. throw new InvalidOperationException($"Cannot cancel from status {Status}");
  92. }
  93. Status = PaymentStatus.Cancelled;
  94. CancelledAt = DateTime.UtcNow;
  95. }
  96. public void MarkWaitingDeposit(string accountNumber, string bank, string holder, DateTime expireAt)
  97. {
  98. Status = PaymentStatus.WaitingDeposit;
  99. VirtualAccountNumber = accountNumber;
  100. VirtualAccountBank = bank;
  101. VirtualAccountHolder = holder;
  102. VirtualAccountExpireAt = expireAt;
  103. }
  104. }