diff --git a/src/main/java/com/acquirex/cardacquisition/controller/CardAcquisitionController.java b/src/main/java/com/acquirex/cardacquisition/controller/CardAcquisitionController.java new file mode 100644 index 0000000..6811d89 --- /dev/null +++ b/src/main/java/com/acquirex/cardacquisition/controller/CardAcquisitionController.java @@ -0,0 +1,91 @@ +package com.acquirex.cardacquisition.controller; + +import com.acquirex.cardacquisition.dto.AcquisitionRequest; +import com.acquirex.cardacquisition.dto.AcquisitionResponse; +import com.acquirex.cardacquisition.service.CardAcquisitionService; +import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** Spring Boot 3 전환: javax.servlet → jakarta.servlet */ +@RestController +@RequestMapping("/api/v1/acquisitions") +public class CardAcquisitionController { + + private final CardAcquisitionService service; + + public CardAcquisitionController(CardAcquisitionService service) { + this.service = service; + } + + @PostMapping + public ResponseEntity requestAcquisition(@Valid @RequestBody AcquisitionRequest request) { + return ResponseEntity.status(HttpStatus.CREATED).body(service.requestAcquisition(request)); + } + + @GetMapping("/{id}") + public ResponseEntity getAcquisition(@PathVariable Long id) { + return ResponseEntity.ok(service.getAcquisition(id)); + } + + @GetMapping("/merchant/{merchantId}") + public ResponseEntity> getAcquisitionsByMerchant(@PathVariable String merchantId) { + return ResponseEntity.ok(service.getAcquisitionsByMerchant(merchantId)); + } + + @GetMapping("/pending") + public ResponseEntity> getPendingAcquisitions() { + return ResponseEntity.ok(service.getPendingAcquisitions()); + } + + @PostMapping("/{id}/cancel") + public ResponseEntity cancelAcquisition(@PathVariable Long id) { + return ResponseEntity.ok(service.cancelAcquisition(id)); + } +} + +/** Spring Boot 3 전환: javax.validation → jakarta.validation */ +@RestControllerAdvice +class GlobalExceptionHandler { + + @ExceptionHandler(CardAcquisitionService.AcquisitionNotFoundException.class) + public ResponseEntity> handleNotFound(CardAcquisitionService.AcquisitionNotFoundException ex) { + return buildErrorResponse(HttpStatus.NOT_FOUND, ex.getMessage()); + } + + @ExceptionHandler(CardAcquisitionService.InvalidAcquisitionException.class) + public ResponseEntity> handleInvalid(CardAcquisitionService.InvalidAcquisitionException ex) { + return buildErrorResponse(HttpStatus.BAD_REQUEST, ex.getMessage()); + } + + @ExceptionHandler(IllegalStateException.class) + public ResponseEntity> handleIllegalState(IllegalStateException ex) { + return buildErrorResponse(HttpStatus.CONFLICT, ex.getMessage()); + } + + @ExceptionHandler(org.springframework.web.bind.MethodArgumentNotValidException.class) + public ResponseEntity> handleValidationErrors( + org.springframework.web.bind.MethodArgumentNotValidException ex) { + java.util.Map fieldErrors = new java.util.HashMap<>(); + ex.getBindingResult().getFieldErrors().forEach(e -> fieldErrors.put(e.getField(), e.getDefaultMessage())); + + java.util.Map body = new java.util.HashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", HttpStatus.BAD_REQUEST.value()); + body.put("error", "Validation Failed"); + body.put("fieldErrors", fieldErrors); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(body); + } + + private ResponseEntity> buildErrorResponse(HttpStatus status, String message) { + java.util.Map body = new java.util.HashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", status.value()); + body.put("error", status.getReasonPhrase()); + body.put("message", message); + return ResponseEntity.status(status).body(body); + } +} \ No newline at end of file