카드 매입 승인 경로 Spring Boot 3 전환 (ACX-E2E-1785394564819)
Some checks are pending
Verify / source-contract (push) Waiting to run
Some checks are pending
Verify / source-contract (push) Waiting to run
This commit is contained in:
parent
33c469025d
commit
669cdbb6c2
1 changed files with 116 additions and 0 deletions
116
src/main/java/com/acquirex/service/CardAcquisitionService.java
Normal file
116
src/main/java/com/acquirex/service/CardAcquisitionService.java
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
package com.acquirex.service;
|
||||||
|
|
||||||
|
import com.acquirex.dto.AcquisitionDto.Request;
|
||||||
|
import com.acquirex.dto.AcquisitionDto.Response;
|
||||||
|
import com.acquirex.entity.CardAcquisition;
|
||||||
|
import com.acquirex.entity.CardAcquisition.AcquisitionStatus;
|
||||||
|
import com.acquirex.entity.CardAcquisition.CardAcquisitionRepository;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CardAcquisitionService {
|
||||||
|
|
||||||
|
private static final BigDecimal MAX_APPROVAL_AMOUNT = new BigDecimal("10000000");
|
||||||
|
private static final BigDecimal SUSPICIOUS_AMOUNT_THRESHOLD = new BigDecimal("5000000");
|
||||||
|
|
||||||
|
private final CardAcquisitionRepository repository;
|
||||||
|
private final Random approvalCodeGenerator = new Random();
|
||||||
|
|
||||||
|
public CardAcquisitionService(CardAcquisitionRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Response processAcquisition(Request request) {
|
||||||
|
CardAcquisition acquisition = createAcquisition(request);
|
||||||
|
CardAcquisition saved = repository.save(acquisition);
|
||||||
|
|
||||||
|
if (!validateCardNumber(request.getCardNumber())) {
|
||||||
|
return rejectAcquisition(saved, "유효하지 않은 카드번호입니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getAmount().compareTo(MAX_APPROVAL_AMOUNT) > 0) {
|
||||||
|
return rejectAcquisition(saved, "승인 한도를 초과했습니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSuspiciousTransaction(request)) {
|
||||||
|
return rejectAcquisition(saved, "의심스러운 거래로 거부되었습니다");
|
||||||
|
}
|
||||||
|
|
||||||
|
return approveAcquisition(saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CardAcquisition createAcquisition(Request request) {
|
||||||
|
CardAcquisition acquisition = new CardAcquisition();
|
||||||
|
acquisition.setCardNumber(maskCardNumber(request.getCardNumber()));
|
||||||
|
acquisition.setMerchantId(request.getMerchantId());
|
||||||
|
acquisition.setAmount(request.getAmount());
|
||||||
|
acquisition.setCurrency(request.getCurrency());
|
||||||
|
acquisition.setStatus(AcquisitionStatus.PENDING);
|
||||||
|
return acquisition;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean validateCardNumber(String cardNumber) {
|
||||||
|
if (cardNumber == null || cardNumber.length() < 13) return false;
|
||||||
|
int sum = 0;
|
||||||
|
boolean alternate = false;
|
||||||
|
for (int i = cardNumber.length() - 1; i >= 0; i--) {
|
||||||
|
int digit = Character.getNumericValue(cardNumber.charAt(i));
|
||||||
|
if (alternate) {
|
||||||
|
digit *= 2;
|
||||||
|
if (digit > 9) digit -= 9;
|
||||||
|
}
|
||||||
|
sum += digit;
|
||||||
|
alternate = !alternate;
|
||||||
|
}
|
||||||
|
return sum % 10 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSuspiciousTransaction(Request request) {
|
||||||
|
return request.getAmount().compareTo(SUSPICIOUS_AMOUNT_THRESHOLD) >= 0
|
||||||
|
&& request.getCardNumber().startsWith("9999");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateApprovalCode() {
|
||||||
|
return String.format("%06d", approvalCodeGenerator.nextInt(999999));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String maskCardNumber(String cardNumber) {
|
||||||
|
if (cardNumber == null || cardNumber.length() < 8) return cardNumber;
|
||||||
|
return cardNumber.substring(0, 4) + "****" + cardNumber.substring(cardNumber.length() - 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response approveAcquisition(CardAcquisition acquisition) {
|
||||||
|
String approvalCode = generateApprovalCode();
|
||||||
|
acquisition.setStatus(AcquisitionStatus.APPROVED);
|
||||||
|
acquisition.setApprovalCode(approvalCode);
|
||||||
|
acquisition.setApprovalTime(LocalDateTime.now());
|
||||||
|
repository.save(acquisition);
|
||||||
|
return Response.success(acquisition.getId(), approvalCode, acquisition.getAmount(), acquisition.getCurrency());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response rejectAcquisition(CardAcquisition acquisition, String reason) {
|
||||||
|
acquisition.setStatus(AcquisitionStatus.REJECTED);
|
||||||
|
acquisition.setRejectReason(reason);
|
||||||
|
acquisition.setApprovalTime(LocalDateTime.now());
|
||||||
|
repository.save(acquisition);
|
||||||
|
return Response.rejected(acquisition.getId(), reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public CardAcquisition findById(Long id) {
|
||||||
|
return repository.findById(id)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("매입 정보를 찾을 수 없습니다: " + id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public CardAcquisition findByApprovalCode(String approvalCode) {
|
||||||
|
return repository.findByApprovalCode(approvalCode)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("승인코드를 찾을 수 없습니다: " + approvalCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue