카드 매입 승인 경로 Spring Boot 3 전환 (ACX-E2E-1785394564819)
Some checks are pending
Verify / source-contract (push) Waiting to run

This commit is contained in:
forge-bot 2026-07-30 13:00:25 +00:00
parent 49155eb293
commit 3890fe28fc

View file

@ -0,0 +1,115 @@
package com.acquirex.approval.service;
import com.acquirex.approval.domain.AcquisitionApproval;
import com.acquirex.approval.domain.AcquisitionApproval.ApprovalStatus;
import com.acquirex.approval.repository.AcquisitionApprovalRepository;
import jakarta.validation.constraints.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/** 카드 매입 승인 서비스 - Spring Boot 3 전환 적용 */
@Service
@Transactional(readOnly = true)
public class AcquisitionApprovalService {
private final AcquisitionApprovalRepository repository;
public AcquisitionApprovalService(AcquisitionApprovalRepository repository) {
this.repository = repository;
}
/** 매입 승인 요청 처리 */
@Transactional
public ApprovalResponse processApproval(ApprovalRequest request) {
String approvalNumber = generateApprovalNumber();
AcquisitionApproval approval = new AcquisitionApproval(
request.merchantId, maskCardNumber(request.cardNumber),
request.approvalAmount, approvalNumber, ApprovalStatus.APPROVED, LocalDateTime.now());
return toResponse(repository.save(approval));
}
/** 승인 번호로 조회 */
public ApprovalResponse findByApprovalNumber(String approvalNumber) {
return repository.findByApprovalNumber(approvalNumber)
.map(this::toResponse)
.orElseThrow(() -> new IllegalArgumentException("승인 번호를 찾을 수 없습니다: " + approvalNumber));
}
/** 가맹점별 승인 목록 조회 */
public List<ApprovalResponse> findByMerchantId(String merchantId, ApprovalStatus status) {
return repository.findByMerchantIdAndStatus(merchantId, status)
.stream().map(this::toResponse).collect(Collectors.toList());
}
/** 승인 취소 처리 */
@Transactional
public ApprovalResponse cancelApproval(Long id) {
AcquisitionApproval approval = repository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("승인 정보를 찾을 수 없습니다: " + id));
if (approval.getStatus() == ApprovalStatus.CANCELLED) {
throw new IllegalStateException("이미 취소된 승인입니다");
}
approval.setStatus(ApprovalStatus.CANCELLED);
return toResponse(repository.save(approval));
}
private String generateApprovalNumber() {
return "AP" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 4).toUpperCase();
}
private String maskCardNumber(String cardNumber) {
if (cardNumber == null || cardNumber.length() < 10) return cardNumber;
return cardNumber.substring(0, 6) + "****" + cardNumber.substring(cardNumber.length() - 4);
}
private ApprovalResponse toResponse(AcquisitionApproval a) {
return new ApprovalResponse(a.getId(), a.getMerchantId(), a.getCardNumber(),
a.getApprovalAmount(), a.getApprovalNumber(), a.getStatus(), a.getApprovalDatetime());
}
/** 카드 매입 승인 요청 DTO - Spring Boot 3: jakarta.validation 적용 */
public static class ApprovalRequest {
@NotBlank(message = "가맹점 ID는 필수입니다")
@Size(max = 20)
public String merchantId;
@NotBlank(message = "카드번호는 필수입니다")
@Pattern(regexp = "\\d{13,19}", message = "카드번호는 13~19자리 숫자입니다")
public String cardNumber;
@NotNull(message = "승인 금액은 필수입니다")
@DecimalMin(value = "0.01", message = "승인 금액은 0보다 커야 합니다")
@DecimalMax(value = "999999999.99")
public BigDecimal approvalAmount;
public ApprovalRequest() {}
public ApprovalRequest(String merchantId, String cardNumber, BigDecimal approvalAmount) {
this.merchantId = merchantId; this.cardNumber = cardNumber; this.approvalAmount = approvalAmount;
}
}
/** 카드 매입 승인 응답 DTO */
public static class ApprovalResponse {
public Long id;
public String merchantId;
public String cardNumber;
public BigDecimal approvalAmount;
public String approvalNumber;
public ApprovalStatus status;
public LocalDateTime approvalDatetime;
public ApprovalResponse() {}
public ApprovalResponse(Long id, String merchantId, String cardNumber, BigDecimal approvalAmount,
String approvalNumber, ApprovalStatus status, LocalDateTime approvalDatetime) {
this.id = id; this.merchantId = merchantId; this.cardNumber = cardNumber;
this.approvalAmount = approvalAmount; this.approvalNumber = approvalNumber;
this.status = status; this.approvalDatetime = approvalDatetime;
}
}
}