Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20240916 결제 연동 흐름의 보완점 본문

개발Article

[TIL]20240916 결제 연동 흐름의 보완점

최밤빵 2024. 9. 16. 22:34

포트원을 연동한 결제 시스템을 구현하면서, 흐름을 분석하고 몇 가지 보완해야 할 점을 알게됐다. 결제는 사용자가 직접적으로 자금과 관련된 매우 중요한 기능이고, 흐름의 안정성과 보안성, 그리고 사용자 측면에서 추가적인 보완이 필요하다. (결제 기능한다고 열심히 알아보던 동시성이슈나 락개념, 멱등성같은건 추가 할 엄두도 못내는 중...)

 

▶ 결제 실패에 대한 대응

현재 결제 성공에 대한 흐름은 잘 정의되어 있지만, 결제 실패 또는 예외 상황에 대한 처리가 조금 미흡하다. 결제 실패는 다양한 이유(카드 승인 거절, 네트워크 문제, 사용자 취소 등)로 발생할 수 있기때문에, 실패 시에도 명확한 처리와 사용자 안내가 필요하다.

 

▷ 개선 사항:

→ 결제 실패 처리 로직 강화:

결제 실패 시 어떤 조치를 취할 것인지 명확히 정의해야 한다. 예를 들어, 결제가 실패했을 때 사용자에게 명확한 메시지를 제공하고, 재시도 옵션을 제시하는 등 사용자 경험을 개선할 수 있다.

→ 로그 기록:

결제 실패나 오류가 발생한 경우에는 로그를 남겨야 한다. 이렇게 남겨진 로그는 이후 문제 분석과 해결에 큰 도움이 될 수 있다.

// 결제 실패 처리 예시
if (paymentFailed) {
        log.error("결제 실패: " + paymentResult.getErrorMessage());
        return new ResponseEntity<>("결제가 실패했습니다. 다시 시도해주세요.", HttpStatus.BAD_REQUEST);
        }

 

▶결제 검증 강화

현재 흐름에서 백엔드가 클라이언트로부터 결제 완료 결과를 받아 포트원 서버에 결제 정보를 조회하고 검증하는 과정을 거친다. 하지만 클라이언트로부터 전송된 결제 완료 결과에 의존하는 구조는 보안적으로 위험할 수 있다. 클라이언트가 데이터를 조작하여 서버에 잘못된 결제 정보를 보낼 수 있기 때문이다.

 

▷개선 사항:

서버에서 직접 결제 완료 검증 요청: 클라이언트로부터 결제 완료 정보를 받는 것만으로는 충분하지 않다. 백엔드는 포트원 서버에 직접 결제 상태를 확인하여 검증하는 과정을 반드시 추가해야 한다.

// 포트원 서버에서 결제 정보 검증
IamportResponse<Payment> paymentResponse = iamportClient.paymentByImpUid(impUid);
if (paymentResponse == null || !paymentResponse.isPaid()) {
        throw new IllegalArgumentException("결제 검증 실패: 결제가 완료되지 않았습니다.");
}

→ 이 과정에서 포트원 API로부터 응답받은 데이터가 실제로 결제가 성공적으로 완료되었는지 확인하고, 그 후에만 결제를 성공으로 처리해야 한다. 클라이언트 측 데이터를 신뢰하기보다는, 항상 포트원 API에서 검증된 데이터를 기반으로 결제 상태를 처리하는 것이 중요하다.

 

▶결제 상태 변경 시 알림 처리

결제 과정에서 네트워크 문제나 기타 예기치 않은 상황이 발생할 수 있다. 이런 경우 결제가 완료되지 않았거나, 반대로 결제가 중복 처리되는 문제가 발생할 수 있다. 이를 방지하기 위해, 포트원에서 제공하는 Webhook을 설정해 두면 백엔드가 결제 상태 변경을 실시간으로 감지할 수 있다.

 

▷개선 사항:

Webhook 설정: Webhook을 사용하면 포트원 서버가 결제 상태가 변경될 때마다 백엔드 서버에 알림을 보낸다. 중복 결제, 부분 결제 등의 상태를 실시간으로 처리할 수 있다.

@PostMapping("/payment/webhook")
public ResponseEntity<String> handlePaymentWebhook(@RequestBody PaymentResult paymentResult) {
    // 결제 상태 업데이트 처리
    if (paymentResult.isPaid()) {
        // 결제 완료 처리
    } else {
        // 결제 실패 처리
    }
    return ResponseEntity.ok("Webhook processed successfully.");
}

→ Webhook을 통해 결제 상태를 실시간으로 업데이트할 수 있어서, 결제 흐름이 더 견고해지고, 사용자가 중복 결제와 같은 문제를 겪을 가능성을 줄일 수 있다.

 

▶토큰 발급 실패 처리

포트원 API와 통신할 때 토큰 발급 과정이 필수적이다. 하지만 네트워크 문제나 기타 서버 문제로 인해 토큰 발급이 실패할 수 있다. 현재 토큰 발급 실패 시의 예외 처리가 부족한 경우, 결제 과정이 중단되거나 사용자가 결제 실패에 대한 명확한 안내를 받지 못할 수 있다.

 

▷개선 사항:

토큰 발급 실패 시 재시도 로직 추가: 포트원 API 호출 시 토큰 발급이 실패할 경우, 이를 감지하여 일정 횟수 재시도하는 로직을 추가할 필요가 있다. 네트워크 지연이나 일시적인 오류일 수 있으므로, 일정 횟수까지는 재시도하고, 실패할 경우 사용자에게 오류 메시지를 제공해야 한다.

public String getPortOneToken() {
    int retryCount = 0;
    while (retryCount < MAX_RETRY) {
        try {
            // 토큰 발급 요청
            return iamportClient.getToken();
        } catch (Exception e) {
            retryCount++;
            log.warn("토큰 발급 실패, 재시도 횟수: " + retryCount);
        }
    }
    throw new RuntimeException("토큰 발급 실패: 재시도 횟수를 초과했습니다.");
}

→ 이와 같은 로직을 통해 토큰 발급 과정에서 발생할 수 있는 오류에 보다 유연하게 대응할 수 있다.

 

▶결론

포트원 결제 연동을 통해 기본적인 결제 흐름을 구현하는 건 어찌저찌 진행되고있지만, 실제 서비스에서 안정적으로 동작하기 위해서는 위에서 제시한 보완점들이 반드시 필요할 것 같다. 결제 실패 처리, 서버에서의 결제 검증, Webhook 설정, 토큰 발급 실패 처리 등은 결제 기능의 신뢰성과 안정성을 높이기 위한 중요한 요소들이다.