using Application.Abstractions.Payment;
namespace Application.Tests;
///
/// ITossPaymentService 수제 fake — PG 호출 횟수를 기록하고 설정된 결과/예외를 반환한다.
///
internal sealed class FakeTossPaymentService : ITossPaymentService
{
public TossPaymentResult ConfirmResult { get; set; } = Done();
public Exception? ConfirmException { get; set; }
public TossPaymentResult CancelResult { get; set; } = Cancelled();
public Exception? CancelException { get; set; }
public TossPaymentResult GetPaymentResult { get; set; } = Done();
public Exception? GetPaymentException { get; set; }
public int ConfirmCallCount { get; private set; }
public int CancelCallCount { get; private set; }
public int GetPaymentCallCount { get; private set; }
public Task GetClientConfigAsync(CancellationToken ct)
=> Task.FromResult(new TossClientConfig("test_ck_fake"));
public Task ConfirmAsync(string paymentKey, string orderID, int amount, CancellationToken ct)
{
ConfirmCallCount++;
if (ConfirmException is not null)
{
throw ConfirmException;
}
return Task.FromResult(ConfirmResult);
}
public Task CancelAsync(string paymentKey, string cancelReason, int? cancelAmount, CancellationToken ct)
{
CancelCallCount++;
if (CancelException is not null)
{
throw CancelException;
}
return Task.FromResult(CancelResult);
}
public Task GetPaymentAsync(string paymentKey, CancellationToken ct)
{
GetPaymentCallCount++;
if (GetPaymentException is not null)
{
throw GetPaymentException;
}
return Task.FromResult(GetPaymentResult);
}
/// 승인/조회 성공 (status=DONE)
public static TossPaymentResult Done(string? paymentKey = null, string? orderID = null, int? totalAmount = null) => new(
Success: true, Code: null, Message: null,
PaymentKey: paymentKey, OrderID: orderID, Status: "DONE",
TotalAmount: totalAmount, Method: "카드", ApprovedAt: DateTime.UtcNow, ReceiptUrl: "https://receipt.antooza.test",
VirtualAccountNumber: null, VirtualAccountBankCode: null, VirtualAccountHolder: null, VirtualAccountDueDate: null,
Cancels: [], RawJson: "{}");
/// 토스의 명시적 거절 {code, message}
public static TossPaymentResult Fail(string code = "REJECT_CARD_COMPANY", string message = "승인 거절")
=> Done() with { Success = false, Code = code, Message = message, Status = null };
/// 가상계좌 발급 (status=WAITING_FOR_DEPOSIT)
public static TossPaymentResult WaitingDeposit() => Done() with
{
Status = "WAITING_FOR_DEPOSIT",
VirtualAccountNumber = "9-4444-0000-1234",
VirtualAccountBankCode = "20",
VirtualAccountHolder = "개미투자",
VirtualAccountDueDate = DateTime.UtcNow.AddDays(7)
};
/// 취소 성공 (status=CANCELED, cancels[] 1건)
public static TossPaymentResult Cancelled(int cancelAmount = 0) => Done() with
{
Status = "CANCELED",
Cancels = new List { new("CANCEL-TX", cancelAmount, "취소", DateTime.UtcNow) }
};
}