TossCancel.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System.ComponentModel.DataAnnotations;
  2. using System.ComponentModel.DataAnnotations.Schema;
  3. using Domain.Entities.Members;
  4. namespace Domain.Entities.Payments.Toss;
  5. /// <summary>
  6. /// 토스페이먼츠 결제 취소 요청 + 응답 통합
  7. /// 전체 취소 / 부분 취소 모두 지원
  8. /// </summary>
  9. public class TossCancel
  10. {
  11. [ForeignKey(nameof(MemberID))]
  12. public virtual Member? Member { get; private set; }
  13. [ForeignKey(nameof(PaymentOrderID))]
  14. public virtual PaymentOrder? PaymentOrder { get; private set; }
  15. [Key]
  16. public int ID { get; private set; }
  17. public int MemberID { get; private set; }
  18. public int PaymentOrderID { get; private set; }
  19. /// <summary>원거래 결제 키 (취소 대상 paymentKey)</summary>
  20. public string PaymentKey { get; private set; } = default!;
  21. /// <summary>가맹점 주문번호</summary>
  22. public string OrderID { get; private set; } = default!;
  23. /// <summary>취소 요청 금액</summary>
  24. public int CancelAmount { get; private set; }
  25. /// <summary>취소 사유 (Toss cancelReason — 최대 200자)</summary>
  26. public string CancelReason { get; private set; } = default!;
  27. /// <summary>취소 요청자 (admin / system / member / webhook)</summary>
  28. public string? CancelRequester { get; private set; }
  29. // ── 응답 필드 ────────────────────────────────────────────────────
  30. /// <summary>응답 코드 (SUCCESS = 성공, 그 외 = Toss 에러 코드/EXCEPTION)</summary>
  31. public string? ResponseCode { get; private set; }
  32. /// <summary>응답 메시지 (실패 사유)</summary>
  33. public string? ResponseMessage { get; private set; }
  34. /// <summary>취소 거래 키 (Toss cancels[].transactionKey)</summary>
  35. public string? TransactionKey { get; private set; }
  36. /// <summary>취소 후 Payment.status (CANCELED / PARTIAL_CANCELED)</summary>
  37. public string? Status { get; private set; }
  38. /// <summary>취소 일시 (UTC)</summary>
  39. public DateTime? CanceledAt { get; private set; }
  40. /// <summary>Toss Payment 객체 원문 JSON — 대사/CS 용</summary>
  41. public string? RawResponse { get; private set; }
  42. public DateTime CreatedAt { get; private set; } = DateTime.UtcNow;
  43. public DateTime? UpdatedAt { get; private set; }
  44. private TossCancel() { }
  45. public static TossCancel CreateRequest(
  46. int memberID,
  47. int paymentOrderID,
  48. string paymentKey,
  49. string orderID,
  50. int cancelAmount,
  51. string cancelReason,
  52. string? cancelRequester = null
  53. ) {
  54. return new TossCancel
  55. {
  56. MemberID = memberID,
  57. PaymentOrderID = paymentOrderID,
  58. PaymentKey = paymentKey,
  59. OrderID = orderID,
  60. CancelAmount = cancelAmount,
  61. CancelReason = cancelReason.Length > 200 ? cancelReason[..200] : cancelReason,
  62. CancelRequester = cancelRequester
  63. };
  64. }
  65. /// <summary>취소 성공 응답 수신 시 업데이트</summary>
  66. public void SetResponse(
  67. string status,
  68. string? transactionKey = null,
  69. DateTime? canceledAt = null,
  70. string? rawResponse = null
  71. ) {
  72. ResponseCode = "SUCCESS";
  73. ResponseMessage = null;
  74. Status = status;
  75. TransactionKey = transactionKey;
  76. CanceledAt = canceledAt;
  77. RawResponse = rawResponse;
  78. UpdatedAt = DateTime.UtcNow;
  79. }
  80. /// <summary>취소 실패/예외 시 업데이트</summary>
  81. public void SetError(string code, string message)
  82. {
  83. ResponseCode = code;
  84. ResponseMessage = message.Length > 500 ? message[..500] : message;
  85. UpdatedAt = DateTime.UtcNow;
  86. }
  87. public bool IsSuccess => ResponseCode == "SUCCESS";
  88. }