Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,14 @@
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.List;

import static com.permitseoul.permitserver.global.util.LogFormUtil.maskPaymentKey;
import static net.logstash.logback.argument.StructuredArguments.keyValue;

@Slf4j
Expand Down Expand Up @@ -130,14 +134,11 @@ public PaymentConfirmResponse getPaymentConfirm(final long userId,

final TossPaymentResponse tossPaymentResponse = getTossPaymentConfirm(authorizationHeader, paymentKey, reservation.getOrderId(), reservation.getTotalAmount());

log.info("ํ† ์Šค ๊ฒฐ์ œ ์Šน์ธ ์™„๋ฃŒ",
(Object[]) LogFormUtil.paymentLog(
userId,
tossPaymentResponse.orderId(),
tossPaymentResponse.paymentKey(),
reservation.getReservationId(),
tossPaymentResponse.totalAmount()
)
log.info("[Payment] ํ† ์Šค ๊ฒฐ์ œ ์Šน์ธ ์™„๋ฃŒ - orderId={}, paymentKey={}, reservationId={}, amount={}",
tossPaymentResponse.orderId(),
LogFormUtil.maskPaymentKey(tossPaymentResponse.paymentKey()),
reservation.getReservationId(),
tossPaymentResponse.totalAmount()
);

updateReservationStatusAndTossPaymentResponseTime(reservation.getReservationId(), ReservationStatus.PAYMENT_SUCCESS);
Expand Down Expand Up @@ -202,23 +203,25 @@ public PaymentConfirmResponse getPaymentConfirm(final long userId,
deleteReservationSessionByOrderId(orderId);
throw handleFeignException(e, orderId, userId);

} catch (AlgorithmException e) { //todo: ๊ฒฐ์ œ๋Š” ๋๋Š”๋ฐ, ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰ ๊ณผ์ •์—์„œ ์‹คํŒจํ–ˆ์œผ๋ฏ€๋กœ, ๋”ฐ๋กœ ์•Œ๋ฆผ ๊ตฌ์ถ•ํ•ด๋†”์•ผ๋ ๋“ฏ
logPaymentSuccessButTicketIssueFailed(userId, reservationSessionKey, orderId, totalAmount, paymentKey, reservation.getReservationId());
} catch (AlgorithmException e) {
logPaymentSuccessButTicketIssueFailed(orderId, totalAmount, paymentKey, reservation.getReservationId());
throw new TicketAlgorithmException(ErrorCode.INTERNAL_TICKET_ALGORITHM_ERROR);

} catch (IllegalEnumTransitionException e) { //todo: ๊ฒฐ์ œ๋Š” ๋๋Š”๋ฐ, ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰ ๊ณผ์ •์—์„œ ์‹คํŒจํ–ˆ์œผ๋ฏ€๋กœ, ๋”ฐ๋กœ ์•Œ๋ฆผ ๊ตฌ์ถ•ํ•ด๋†”์•ผ๋ ๋“ฏ
logPaymentSuccessButTicketIssueFailed(userId, reservationSessionKey, orderId, totalAmount, paymentKey, reservation.getReservationId());
} catch (IllegalEnumTransitionException e) {
logPaymentSuccessButTicketIssueFailed(orderId, totalAmount, paymentKey, reservation.getReservationId());
throw new ReservationIllegalException(ErrorCode.INTERNAL_TRANSITION_ENUM_ERROR);

} catch (ReservationSessionNotFoundAfterPaymentSuccessException e) { //๊ฒฐ์ œ๋Š” ๋๋Š”๋ฐ, ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰ ๊ณผ์ •์—์„œ ์‹คํŒจํ–ˆ์œผ๋ฏ€๋กœ, ๋”ฐ๋กœ ์•Œ๋ฆผ ๊ตฌ์ถ•ํ•ด๋†”์•ผ๋ ๋“ฏ
logPaymentSuccessButTicketIssueFailed(userId, reservationSessionKey, orderId, totalAmount, paymentKey, reservation.getReservationId());
} catch (ReservationSessionNotFoundAfterPaymentSuccessException e) {
logPaymentSuccessButTicketIssueFailed(orderId, totalAmount, paymentKey, reservation.getReservationId());
throw new NotFoundPaymentException(ErrorCode.NOT_FOUND_RESERVATION_SESSION_AFTER_PAYMENT_SUCCESS);
}
}

public void cancelPayment(final long userId, final String orderId) {
try {
final Payment payment = paymentRetriever.findPaymentByOrderId(orderId);
validateCancelAvailablePeriod(payment.getEventId());

final List<Ticket> ticketList = ticketRetriever.findAllTicketsByOrderIdAndUserId(payment.getOrderId(), userId);
validateTicketStatusForCancel(ticketList);

Expand All @@ -245,6 +248,8 @@ public void cancelPayment(final long userId, final String orderId) {

} catch (PaymentNotFoundException e) {
throw new NotFoundPaymentException(ErrorCode.NOT_FOUND_PAYMENT);
} catch (EventNotfoundException e) {
throw new NotFoundPaymentException(ErrorCode.NOT_FOUND_EVENT);
} catch(FeignException e) {
throw handleFeignException(e, orderId, userId);
} catch (TicketNotFoundException e) {
Expand All @@ -263,6 +268,23 @@ public void cancelPayment(final long userId, final String orderId) {
}
}

private void validateCancelAvailablePeriod(final long eventId) {
final Event event = eventRetriever.findEventById(eventId);

final LocalDate eventDate = event.getStartAt().toLocalDate();
final LocalDate today = LocalDate.now(ZoneId.of("Asia/Seoul"));

// ์˜ค๋Š˜๊ณผ ํ–‰์‚ฌ์ผ ์‚ฌ์ด์˜ ์ผ์ˆ˜ ๊ณ„์‚ฐ
long daysUntilEvent = ChronoUnit.DAYS.between(today, eventDate);

// 3์ผ ์ „๊นŒ์ง€๋งŒ ํ™˜๋ถˆ ๊ฐ€๋Šฅ
if (daysUntilEvent < 3) {
log.warn("[Payment Cancel] ์ทจ์†Œ ๊ธฐํ•œ ์ดˆ๊ณผ - eventId={}, eventDate={}, today={}, daysUntilEvent={}",
eventId, eventDate, today, daysUntilEvent);
throw new PaymentBadRequestException(ErrorCode.BAD_REQUEST_CANCEL_PERIOD_EXPIRED);
}
}

private void deleteReservationSessionByOrderId(final String orderId) {
try {
reservationSessionRemover.deleteByOrderId(orderId);
Expand Down Expand Up @@ -302,18 +324,15 @@ private void handleFailedTossPayment(final Reservation reservation,
}
}

private void logPaymentSuccessButTicketIssueFailed( final long userId,
final String sessionKey,
final String orderId,
final BigDecimal totalAmount,
final String paymentKey,
final long reservationId) {
log.error("ํ† ์Šค ๊ฒฐ์ œ ์Šน์ธ ์™„๋ฃŒ -> ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰ ์‹คํŒจ",
keyValue(Constants.USER_ID, userId),
keyValue(Constants.ORDER_ID, orderId),
keyValue(Constants.PAYMENT_KEY, LogFormUtil.maskPaymentKey(paymentKey)),
keyValue(Constants.RESERVATION_ID, reservationId),
keyValue(Constants.TOTAL_AMOUNT, totalAmount)
private void logPaymentSuccessButTicketIssueFailed(final String orderId,
final BigDecimal totalAmount,
final String paymentKey,
final long reservationId) {
log.error("[Payment] ํ† ์Šค ๊ฒฐ์ œ ์Šน์ธ ์™„๋ฃŒ -> ํ‹ฐ์ผ“ ๋ฐœ๊ธ‰ ์‹คํŒจ - orderId={}, paymentKey={}, reservationId={}, amount={}",
orderId,
LogFormUtil.maskPaymentKey(paymentKey),
reservationId,
totalAmount
);
}

Expand Down Expand Up @@ -341,7 +360,7 @@ private void logRollbackFailed(final long userId,
final BigDecimal totalAmount,
final String paymentKey) {
log.error("[๊ฒฐ์ œ ์Šน์ธ API - redis Rollback Failed] userId: {}, sessionKey: {}, orderId: {}, totalAmount: {}, paymentKey: {}",
userId, sessionKey, orderId, totalAmount, LogFormUtil.maskPaymentKey(paymentKey));
userId, sessionKey, orderId, totalAmount, maskPaymentKey(paymentKey));
}

private void updateReservationStatusAndTossPaymentResponseTime(final long reservationId, final ReservationStatus status) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum ErrorCode implements ApiCode {
BAD_REQUEST_MISMATCH_TICKET_TYPE_ROUND(HttpStatus.BAD_REQUEST, 40016, "ticketType์˜ roundId์™€ ๋‹ค๋ฅธ ticketRoundId ์ž…๋‹ˆ๋‹ค."),
BAD_REQUEST_MISMATCH_LIST_SIZE(HttpStatus.BAD_REQUEST, 40017, "list์˜ ๊ธธ์ด๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค."),
BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, 40018, "redis ticket tpye mismatch ์—๋Ÿฌ์ž…๋‹ˆ๋‹ค. "),
BAD_REQUEST_CANCEL_PERIOD_EXPIRED(HttpStatus.BAD_REQUEST, 40019, "ํ™˜๋ถˆ ๊ฐ€๋Šฅ ๊ธฐ๊ฐ„์ด ์•„๋‹™๋‹ˆ๋‹ค. ํ™˜๋ถˆ์€ ํ–‰์‚ฌ ์‹œ์ž‘์ผ ๊ธฐ์ค€ 3์ผ์ „๊นŒ์ง€๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.(ํ™˜๋ถˆ ์ •์ฑ… ์ฐธ๊ณ )."),



Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
package com.permitseoul.permitserver.global.util;

import com.permitseoul.permitserver.global.Constants;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.experimental.UtilityClass;
import net.logstash.logback.argument.StructuredArgument;

import java.math.BigDecimal;

import static net.logstash.logback.argument.StructuredArguments.keyValue;

@UtilityClass
public final class LogFormUtil {
Expand All @@ -22,22 +14,6 @@ public final class LogFormUtil {
private static final int PAYMENT_KEY_LONG_PREFIX = 4;
private static final int PAYMENT_KEY_LONG_SUFFIX = 5;

public static StructuredArgument[] paymentLog(
final long userId,
final String orderId,
final String paymentKey,
final long reservationId,
final BigDecimal totalAmount
) {
return new StructuredArgument[] {
keyValue(Constants.USER_ID, userId),
keyValue(Constants.ORDER_ID, orderId),
keyValue(Constants.PAYMENT_KEY, maskPaymentKey(paymentKey)),
keyValue(Constants.RESERVATION_ID, reservationId),
keyValue(Constants.TOTAL_AMOUNT, totalAmount)
};
}

public static String maskPaymentKey(final String paymentKey) {
if (paymentKey == null || paymentKey.isBlank()) {
return paymentKey;
Expand Down