using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Domain.Entities.Members; namespace Domain.Entities.Payments.Toss; /// /// 토스페이먼츠 결제 취소 요청 + 응답 통합 /// 전체 취소 / 부분 취소 모두 지원 /// public class TossCancel { [ForeignKey(nameof(MemberID))] public virtual Member? Member { get; private set; } [ForeignKey(nameof(PaymentOrderID))] public virtual PaymentOrder? PaymentOrder { get; private set; } [Key] public int ID { get; private set; } public int MemberID { get; private set; } public int PaymentOrderID { get; private set; } /// 원거래 결제 키 (취소 대상 paymentKey) public string PaymentKey { get; private set; } = default!; /// 가맹점 주문번호 public string OrderID { get; private set; } = default!; /// 취소 요청 금액 public int CancelAmount { get; private set; } /// 취소 사유 (Toss cancelReason — 최대 200자) public string CancelReason { get; private set; } = default!; /// 취소 요청자 (admin / system / member / webhook) public string? CancelRequester { get; private set; } // ── 응답 필드 ──────────────────────────────────────────────────── /// 응답 코드 (SUCCESS = 성공, 그 외 = Toss 에러 코드/EXCEPTION) public string? ResponseCode { get; private set; } /// 응답 메시지 (실패 사유) public string? ResponseMessage { get; private set; } /// 취소 거래 키 (Toss cancels[].transactionKey) public string? TransactionKey { get; private set; } /// 취소 후 Payment.status (CANCELED / PARTIAL_CANCELED) public string? Status { get; private set; } /// 취소 일시 (UTC) public DateTime? CanceledAt { get; private set; } /// Toss Payment 객체 원문 JSON — 대사/CS 용 public string? RawResponse { get; private set; } public DateTime CreatedAt { get; private set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; private set; } private TossCancel() { } public static TossCancel CreateRequest( int memberID, int paymentOrderID, string paymentKey, string orderID, int cancelAmount, string cancelReason, string? cancelRequester = null ) { return new TossCancel { MemberID = memberID, PaymentOrderID = paymentOrderID, PaymentKey = paymentKey, OrderID = orderID, CancelAmount = cancelAmount, CancelReason = cancelReason.Length > 200 ? cancelReason[..200] : cancelReason, CancelRequester = cancelRequester }; } /// 취소 성공 응답 수신 시 업데이트 public void SetResponse( string status, string? transactionKey = null, DateTime? canceledAt = null, string? rawResponse = null ) { ResponseCode = "SUCCESS"; ResponseMessage = null; Status = status; TransactionKey = transactionKey; CanceledAt = canceledAt; RawResponse = rawResponse; UpdatedAt = DateTime.UtcNow; } /// 취소 실패/예외 시 업데이트 public void SetError(string code, string message) { ResponseCode = code; ResponseMessage = message.Length > 500 ? message[..500] : message; UpdatedAt = DateTime.UtcNow; } public bool IsSuccess => ResponseCode == "SUCCESS"; }