using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Domain.Entities.Members;
namespace Domain.Entities.Payments.Toss;
///
/// 토스페이먼츠 결제 승인 요청 + 응답 통합
/// confirm API 호출 시 요청 데이터를 먼저 저장하고, 응답 수신 시 업데이트
///
public class TossConfirm
{
[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; }
/// 토스 결제 키 (unique — 취소·조회 API 호출에 필요)
public string PaymentKey { get; private set; } = default!;
/// 가맹점 주문번호
public string OrderID { get; private set; } = default!;
/// 승인 요청 금액 (서버 저장 주문 금액)
public int Amount { get; private set; }
// ── 응답 필드 (승인 완료/실패 시 업데이트) ──────────────────────
/// 응답 코드 (SUCCESS = 성공, 그 외 = Toss 에러 코드/EXCEPTION)
public string? ResponseCode { get; private set; }
/// 응답 메시지 (실패 사유)
public string? ResponseMessage { get; private set; }
/// Toss Payment.status (DONE / WAITING_FOR_DEPOSIT / CANCELED / ABORTED / EXPIRED ...)
public string? Status { get; private set; }
/// 결제수단 (Toss method 문자열 — 카드/가상계좌/간편결제 등)
public string? Method { get; private set; }
/// 최종 승인 금액 (Toss totalAmount)
public int? TotalAmount { get; private set; }
/// 승인 일시 (UTC)
public DateTime? ApprovedAt { get; private set; }
/// 영수증 URL (Toss receipt.url)
public string? ReceiptUrl { 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 TossConfirm() { }
/// 승인 요청 시 생성 (응답 전)
public static TossConfirm CreateRequest(
int memberID,
int paymentOrderID,
string paymentKey,
string orderID,
int amount
) {
return new TossConfirm
{
MemberID = memberID,
PaymentOrderID = paymentOrderID,
PaymentKey = paymentKey,
OrderID = orderID,
Amount = amount
};
}
/// 승인 성공 응답 수신 시 업데이트
public void SetResponse(
string status,
string? method = null,
int? totalAmount = null,
DateTime? approvedAt = null,
string? receiptUrl = null,
string? rawResponse = null
) {
ResponseCode = "SUCCESS";
ResponseMessage = null;
Status = status;
Method = method;
TotalAmount = totalAmount;
ApprovedAt = approvedAt;
ReceiptUrl = receiptUrl;
RawResponse = rawResponse;
UpdatedAt = DateTime.UtcNow;
}
/// 승인 실패/예외 시 업데이트
public void SetError(string code, string message)
{
ResponseCode = code;
ResponseMessage = message.Length > 500 ? message[..500] : message;
UpdatedAt = DateTime.UtcNow;
}
///
/// 재승인(대사 재확인) 시 기존 요청 행을 재사용한다. PaymentKey/OrderID unique 인덱스 충돌을 피하려
/// 새 행을 만들지 않고, 결제 키를 갱신하고 이전 응답을 초기화해 "요청 후 응답 미수신" 상태로 되돌린다. (Phase 1.5 승계)
///
public void PrepareRetry(string paymentKey)
{
PaymentKey = paymentKey;
ResponseCode = null;
ResponseMessage = null;
UpdatedAt = DateTime.UtcNow;
}
public bool IsSuccess => ResponseCode == "SUCCESS";
}