> Java > java지도 시간 > 인터넷 크레딧 구매 시스템 설계

인터넷 크레딧 구매 시스템 설계

Susan Sarandon
풀어 주다: 2025-01-15 18:05:45
원래의
696명이 탐색했습니다.

제가 직면한 기술 인터뷰 중 저는 사용자가 제3자 제공업체로부터 인터넷 크레딧을 구매할 수 있는 전자상거래 시스템을 설계해 달라는 요청을 받았습니다.

저는 자신있게 간단한 솔루션을 제안했습니다. 사용 가능한 패키지를 표시하고, 사용자가 하나를 선택하도록 하고, 외부 게이트웨이를 통해 결제를 처리하고, 공급자와 상호 작용하여 크레딧을 제공하는 것입니다. 그러나 사용자가 결제를 완료한 후 제공업체의 재고가 소진되는 등의 실패 시나리오에 대해 질문을 받았을 때 저는 이러한 문제를 효과적으로 처리할 수 있는 복원력이 내 디자인에 부족하다는 것을 깨달았습니다.

몇 주 전, 저는 플래시 세일 시스템과 재고 예약 패턴, 특히 재고 예약 전략에 초점을 맞춰 연구를 진행했습니다. 반짝 세일은 높은 수요와 제한된 재고를 다루는 경우가 많으므로 시스템 안정성을 유지하고 고객 기대치를 관리하기 위한 정교한 메커니즘이 필요합니다. 제가 발견한 한 가지 개념은 피크 시간대에 과잉 판매를 방지하는 데 도움이 되는 임시 재고 예약이었습니다.

이 조사를 통해 저의 인터뷰 경험이 생각났습니다. 나는 이러한 재고 예약 전략을 적용하면 초기 디자인의 단점을 해결할 수 있다는 것을 인식했습니다. 결제 과정에서 재고에 대한 임시 보류를 통합함으로써 시스템은 제공업체의 재고가 고갈되는 시나리오를 효과적으로 처리할 수 있습니다.

이 연구 문서에서는 연구에서 얻은 통찰력을 공유하고 인터넷 신용 구매 시스템 설계에 대한 세련된 접근 방식을 제안하는 것을 목표로 합니다. 재고 예약 전략을 통합함으로써 다양한 실패 시나리오를 처리하는 동시에 원활한 경험을 제공할 수 있는 강력하고 사용자 친화적인 플랫폼을 구축할 수 있습니다.

1. 주요 설계 고려 사항

인터넷 크레딧 구매 시스템을 설계할 때 원활하고 안전하며 즐거운 사용자 경험을 보장하기 위해 고려해야 할 몇 가지 주요 요소가 있습니다. 분석해 보겠습니다.

1.1 할당량 관리

  • 실시간 할당량 확인: 시스템은 인터넷 크레딧 패키지의 재고가 있는지 즉시 확인해야 사용자가 실수로 사용할 수 없는 옵션을 선택하는 일이 발생하지 않습니다.
  • 임시 할당량 예약: 선택한 패키지를 짧은 기간 동안 보관하는 메커니즘을 추가하여 사용자가 항목 분실 위험 없이 구매를 완료할 수 있는 충분한 시간을 제공합니다.
  • 할당량 충돌 처리: 여러 사용자가 동시에 동일한 패키지를 구매하려고 하는 상황을 관리하여 공정한 할당을 보장하는 전략을 개발합니다.
  • 패키지 정보를 위한 캐시 관리: 캐시 데이터를 정확하고 최신 상태로 유지하여 사용자가 항상 올바른 세부정보와 가용성을 확인할 수 있습니다.

1.2 결제 처리

  • 안전한 결제 처리: 거래 중 사용자의 결제 세부정보를 보호하기 위해 강력한 보안 조치를 구현합니다.
  • 지불 보호를 위한 에스크로 시스템: 에스크로 서비스를 사용하여 크레딧이 전달될 때까지 자금을 보관하여 구매자와 제공자 모두를 안전하게 보호합니다.
  • 결제 게이트웨이 통합: 시스템이 신뢰할 수 있는 결제 게이트웨이와 원활하게 연결되어 번거로움 없는 거래를 보장합니다.
  • 환불 메커니즘: 결제 실패 또는 취소 시 환불 처리를 위한 명확하고 사용자 친화적인 프로세스를 만듭니다.

1.3 공급자 통합

  • 시스템 가용성: 구매가 중단 없이 처리될 수 있도록 안정적인 시스템을 갖춘 제공업체와 협력하세요.
  • API 신뢰성: 원활한 통합을 위해 안정적이고 잘 문서화된 API를 제공하는 제공업체와 협력하세요.
  • 서비스 활성화 확인: 구매한 크레딧이 적절하고 신속하게 활성화되었는지 확인하는 검사를 포함합니다.
  • 오류 처리 및 재시도: 실패한 프로세스에 대한 재시도 메커니즘을 사용하여 오류를 신속하게 포착하고 해결하는 프로토콜을 구현합니다.

1.4 거래 안전

  • 자금 흐름 제어: 거래가 성공적으로 완료된 후에만 자금이 방출되도록 합니다.
  • 거래 일관성: 오류를 방지하기 위해 모든 거래에 대한 정확하고 일관된 기록을 유지하세요.
  • 롤백 메커니즘: 문제가 발생할 경우 트랜잭션을 되돌려 사용자와 시스템을 모두 보호할 계획을 세웁니다.
  • 감사 추적: 모든 문제를 효과적으로 모니터링하고 해결하는 데 도움이 되는 자세한 로그를 유지합니다.

1.5 사용자 경험

  • 오류 메시지 지우기: 사용자에게 이해하기 쉽고 유익한 오류 메시지를 제공하여 발생한 문제를 안내합니다.
  • 거래 상태 가시성: 사용자가 실시간으로 구매 상태를 쉽게 추적할 수 있어 투명성이 향상됩니다.
  • 빠른 패키지 로드: 사용 가능한 패키지를 신속하게 로드하도록 시스템을 최적화하여 사용자 대기 시간을 줄입니다.
  • 실시간 업데이트: 거래 또는 사용 가능한 패키지에 대한 변경 사항이나 업데이트를 사용자에게 즉시 알려주세요.

이러한 사항을 고려하여 효율적이고 안전하며 사용자 친화적인 인터넷 신용 구매 시스템을 설계하여 사용자 만족도와 신뢰도를 높일 수 있습니다.

2. 시스템 설계 및 흐름

위에 설명된 기본 고려 사항을 바탕으로 다음 단계는 이러한 원칙을 강력하고 효과적인 시스템 설계로 변환하는 것입니다. 다양한 구성 요소 간의 상호 작용을 주의 깊게 매핑함으로써 시스템이 기능적 요구 사항을 충족할 뿐만 아니라 안정성과 확장성을 유지하면서 원활한 사용자 경험을 제공하도록 할 수 있습니다.

이 섹션에서는 시스템의 아키텍처와 흐름을 자세히 살펴보고 할당량 관리, 결제 처리, 서비스 활성화 등의 핵심 기능이 어떻게 일관되게 구현되는지 보여줍니다. 목표는 각 디자인 선택이 잠재적인 문제를 해결하고 신뢰할 수 있는 전자상거래 크레딧 구매 플랫폼을 제공하는 데 어떻게 기여하는지 강조하는 것입니다.

사용자가 처음부터 끝까지 시스템과 상호 작용하는 방식을 설명하기 위해 순서도를 통해 시각화된 시스템 흐름 개요부터 시작하겠습니다.

2.1 흐름도

Designing an Internet Credit Purchase System

명확성을 위해 시스템 흐름은 6단계로 구분됩니다.

패키지 선택 단계

  • 먼저 사용자가 앱이 캐시에서 패키지 데이터를 가져오는 패키지 선택 페이지를 방문합니다. 이 데이터에는 사용 가능한 패키지와 캐시된 할당량 정보가 포함되어 사용자에게 표시됩니다.
  • 사용자가 패키지를 선택하고 '구매'를 클릭합니다.
  • 해당 패키지의 할당량을 사용할 수 없는 경우 앱은 '사용할 수 없음' 메시지를 표시하고 사용자를 선택 페이지로 다시 이동시킵니다. 그렇지 않으면 시스템이 일시적으로 사용자에 대한 할당량을 예약합니다.

구매 개시

  • 다음으로 시스템은 선택한 패키지에 대한 할당량 예약을 시도합니다.
  • 예약이 실패하면 사용자에게 오류 메시지가 표시되고 선택 페이지로 다시 리디렉션됩니다.
  • 예약이 성공하면 결제 페이지로 이동합니다.
결제 단계
  • 이 단계에서 사용자는 결제 프로세스를 시작하고 제3자 결제 대행사로 리디렉션됩니다.
  • 앱은 결제 상태를 확인하기 위해 결제 게이트웨이의 응답(콜백)을 기다립니다.
결제 처리
  • 앱은 결제 게이트웨이의 콜백을 확인하여 결제를 확인합니다.
    • 잘못된 콜백의 경우 시스템에서 문제를 기록하고 추가 단계를 중단합니다.
    • 유효한 콜백의 경우:
      • 결제 실패 시: 시스템에서 예약된 할당량을 해제하고 사용자에게 문제를 알립니다.
      • 결제가 성공한 경우: 시스템에서 결제를 확인하고 에스크로에 자금을 보관한 후 새 주문을 생성합니다.
서비스 활성화
  • 결제가 완료되면 시스템은 서비스 제공자에게 서비스 활성화를 요청합니다.
    • 활성화 실패 시: 에스크로 자금은 고객에게 환불되며 실패 사실이 통보됩니다.
    • 활성화에 성공한 경우: 시스템이 활성화를 확인합니다.
      • 인증에 실패하면 고객은 환불을 받습니다.
      • 인증이 성공하면 에스크로 자금이 공급자에게 전달되고 고객은 알림을 받습니다.
백그라운드 프로세스
  • 정기적인 캐시 업데이트: 패키지 데이터 캐시는 정기적으로 업데이트됩니다.
  • 실시간 할당량 업데이트: 할당량 변경 사항은 WebSocket 연결을 통해 전달됩니다.

이 흐름은 사용자에게 원활하고 안정적인 경험을 보장하는 동시에 리소스와 잠재적인 오류를 효과적으로 관리합니다.

2.2 시퀀스 다이어그램

아래 시퀀스 다이어그램은 다양한 역할과 구성 요소 간의 상호 작용을 설명하는 데 도움이 됩니다.

Designing an Internet Credit Purchase System

명확성을 위해 시스템 흐름은 6단계로 구분됩니다.

패키지 선택 단계

  • 고객은 패키지 선택 페이지를 방문하여 시작합니다.
  • 프런트엔드는 캐시에서 패키지 데이터를 검색하고 사용 가능한 모든 패키지를 캐시된 할당량 정보와 함께 고객에게 표시합니다.

구매 개시

  • 고객이 패키지를 선택하고 "구매"를 클릭하면 프런트엔드가 백엔드에 구매 요청을 보냅니다.
  • 백엔드는 공급자에게 선택한 패키지의 할당량을 실시간으로 계속 사용할 수 있는지 확인합니다.
  • 할당량이 사용 가능한 경우 백엔드는 공급자에게 15분 동안 할당량을 임시로 예약합니다.
  • 백엔드는 예약 확인을 프런트엔드로 보내고 고객은 결제 페이지로 리디렉션됩니다.

결제 단계

  • 고객이 결제 페이지로 이동하여 결제 세부정보를 입력합니다.
  • 프런트엔드는 이 정보를 백엔드로 보내고 백엔드는 결제 게이트웨이와의 결제 세션을 초기화합니다.
  • 결제 세션이 준비되면 백엔드는 세션 세부정보를 프런트엔드와 공유합니다.
  • 프런트엔드는 결제를 완료하기 위해 고객을 결제 게이트웨이로 리디렉션합니다.

결제 처리

  • 결제 게이트웨이에서 고객이 결제 정보를 입력하고 결제 과정을 완료합니다.
  • 결제 게이트웨이는 콜백을 통해 백엔드에 결제 상태를 알립니다.
    • 결제가 성공한 경우:
      • 백엔드는 결제 게이트웨이를 통해 결제 상태를 확인합니다.
      • 결제는 에스크로로 이루어지며, 백엔드에서 에스크로 보류를 확인합니다.
    • 결제에 실패한 경우:
      • 백엔드는 공급자와 함께 예약된 할당량을 해제하고 실패를 반영하여 결제 상태를 업데이트합니다.
    • 예상 시간 내에 콜백을 받지 못한 경우:
      • 백엔드는 정기적으로 결제 게이트웨이를 폴링하여 결제 상태를 확인합니다. 결제가 실패하거나 시간이 초과되면 백엔드가 예약된 할당량을 해제합니다.

서비스 활성화

  • 결제가 성공하면 백엔드는 공급자에게 서비스 활성화를 요청합니다.
  • 제공자는 활성화 상태로 응답하고 백엔드는 활성화를 확인합니다.
    • 활성화에 성공한 경우:
      • 백엔드는 에스크로에서 공급자에게 지불금을 전달합니다.
      • 서비스가 준비되었음을 알리는 성공 알림이 고객에게 전송됩니다.
    • 활성화에 실패한 경우:
      • 백엔드는 에스크로된 자금을 고객에게 환불합니다.
      • 고객에게 문제를 알리기 위해 실패 알림이 전송됩니다.

백그라운드 프로세스

  • 공급자는 WebSocket 연결을 통해 백엔드에 패키지 할당량에 대한 실시간 업데이트를 보냅니다.
  • 이러한 업데이트를 통해 캐시가 항상 최신 상태로 유지되므로 고객은 탐색 시 가장 정확한 패키지 가용성을 확인할 수 있습니다.

3. 기술적 구현

이제 시스템의 흐름과 상호 작용을 개략적으로 설명했으므로 이제 모든 것이 코드에서 어떻게 통합되는지 알아볼 차례입니다. 이 섹션에서는 구현을 단계별로 분석하여 디자인이 주문 관리부터 공급자 및 결제 시스템과의 상호 작용까지 모든 것을 처리하는 작업 부분으로 변환되는 방법을 보여줍니다.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

이러한 수업은 다음과 같습니다.

  • 패키지: 사용자가 구매할 수 있는 인터넷 신용 패키지를 정의하는 곳입니다. 패키지 ID, 이름, 가격, 공급자 비용, 설명, 패키지 활성 여부 등의 세부 정보를 추적합니다.

  • 주문: 사용자의 구매 기록이라고 생각하세요. 여기에는 주문 ID, 고객 ID, 선택한 패키지 ID 등의 정보와 예약 ID, 결제 ID, 에스크로 ID, 주문 상태, 결제 금액, 제공업체 비용, 타임스탬프 등 관련 세부정보가 포함됩니다.

  • QuotaReservation: 패키지 할당량에 대한 임시 예약을 처리합니다. 예약 ID, 연결된 패키지, 만료 시기, 현재 상태(활성 또는 만료 등)를 기록합니다.

  • OrderStatus Enum: 이 열거형은 CREATED 및 RESERVED부터 PAYMENT_PENDING, COMPLETED 또는 REFUNDED까지 주문이 겪을 수 있는 모든 가능한 단계를 매핑합니다.

  • ReservationStatus Enum: 마찬가지로 이 열거형은 ACTIVE, EXPIRED, USED 또는 CANCELLED 등 할당량 예약 상태를 추적합니다.

이러한 클래스와 열거형은 함께 시스템의 패키지, 주문 및 할당량 예약을 관리하기 위한 백본을 구축합니다. 전자상거래 기능을 효과적으로 처리하기 위한 간단하면서도 구조화된 접근 방식입니다.

// Request/Response DTOs
@Getter @Setter
public class OrderRequest {
    private String customerId;
    private String packageId;
    private BigDecimal amount;
}

@Getter @Setter
public class PaymentCallback {
    private String orderId;
    private String paymentId;
    private String status;
    private BigDecimal amount;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class QuotaResponse {
    private String packageId;
    private boolean available;
    private Integer remainingQuota;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class ReservationResponse {
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

@Getter @Setter
public class ActivationResponse {
    private String orderId;
    private boolean success;
    private String activationId;
    private String errorCode;
    private String errorMessage;
}

@Getter @Setter
public class VerificationResponse {
    private String orderId;
    private String activationId;
    private boolean success;
    private String status;
    private LocalDateTime activatedAt;
}

@Getter @Setter
public class PaymentRequest {
    private String orderId;
    private BigDecimal amount;
    private String currency;
    private String customerId;
    private String returnUrl;
    private String callbackUrl;
}

@Getter @Setter
public class PaymentSession {
    private String sessionId;
    private String paymentUrl;
    private LocalDateTime expiresAt;
    private String status;
}

@Getter @Setter
public class EscrowResponse {
    private String id;
    private String paymentId;
    private BigDecimal amount;
    private String status;
    private LocalDateTime createdAt;
}
로그인 후 복사
로그인 후 복사

분석해 보겠습니다.

  • OrderRequest: 이는 새 주문을 생성하는 데 필요한 데이터에 관한 모든 것입니다. 여기에는 고객 ID, 구매하려는 패키지, 지불할 총액이 포함됩니다.

  • PaymentCallback: 이를 결제 게이트웨이의 알림이라고 생각하세요. 결제 시도 후에는 주문 ID, 결제 ID, 상태(성공 또는 실패), 결제 금액, 결제 시기 등의 세부정보가 제공됩니다.

  • QuotaResponse: 가용성 확인에 관한 것입니다. 패키지 사용 가능 여부, 남은 할당량, 정보가 마지막으로 업데이트된 시기 등을 알려줍니다.

  • ReservationResponse: 패키지가 예약되면 예약 ID, 관련 패키지, 예약 만료 시기, 현재 상태(예: 활성 또는 만료됨) 등 모든 세부 정보를 제공합니다. .

  • ActivationResponse: 서비스 활성화가 어떻게 진행되었는지 알려줍니다. 성공하거나 실패하면 활성화 ID와 문제가 발생한 경우 오류 세부 정보를 제공합니다.

  • 확인응답: 활성화 후 모든 것이 원활하게 진행되었는지 확인합니다. 여기에는 주문 ID, 활성화 ID, 성공 상태 및 활성화 시간이 포함됩니다.

  • PaymentRequest: 결제 프로세스를 시작하기 전에 이 DTO는 주문 ID, 결제 금액, 통화, 고객 ID 및 콜백 URL과 같은 필요한 세부 정보를 수집합니다.

  • PaymentSession: 결제 프로세스가 시작될 때 생성되는 세션입니다. 여기에는 세션 ID, 결제 URL(사용자가 결제하러 가는 위치), 만료 시기, 세션 상태가 포함됩니다.

  • EscrowResponse: 자금이 에스크로에 보관된 경우 에스크로 ID, 결제 ID, 보유 금액, 상태, 생성 시기 등 자금에 대한 모든 정보를 알려줍니다.

이러한 모든 클래스는 요청이 나가거나 되돌아오는 등 시스템의 여러 부분 간의 통신을 위한 구성 요소를 정의합니다. 모든 사람(그리고 모든 것)이 같은 내용을 공유하도록 보장합니다.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
캐시 서비스
1. 목적:

이 서비스는 패키지 데이터를 저장하는 로컬 캐시를 관리합니다. 목표는 시스템 속도를 높이고 공급자 API에 대한 불필요한 호출을 줄이는 것입니다.

2. 주요 특징:
  • updateCache(): 이 메서드는 공급자로부터 모든 패키지 데이터를 가져와 5분마다 로컬 캐시를 새로 고칩니다. 캐시가 최신 상태로 유지됩니다.
  • getPackage(): 이 메소드는 해당 ID를 사용하여 캐시에서 패키지 정보를 검색합니다.
  • updatePackageQuota(): 할당량 세부 정보가 변경되면 이 메소드는 특정 패키지에 대한 새 정보로 캐시를 업데이트합니다.
공급자 통합
1. 목적:

이 서비스는 공급자의 API와의 통신을 처리합니다. 할당량 확인, 패키지 예약, 서비스 활성화, 활성화 확인 등의 작업을 관리합니다.

2. 주요 특징:
  • checkQuota(): 이 메소드는 공급자의 API를 호출하여 패키지에 사용 가능한 할당량이 충분한지 확인합니다.
  • ReserveQuota(): 공급자에게 요청을 보내 고객을 위한 패키지 할당량을 예약합니다.
  • activateService(): 주문에 대한 서비스를 활성화할 때가 되면 이 메소드는 공급자에 대한 요청을 처리합니다.
  • verifyActivation(): 활성화 후 이 메소드는 모든 것이 성공했는지 확인합니다.
  • getAllPackages(): 이 메소드는 공급자로부터 사용 가능한 모든 패키지를 검색하며, 이는 캐시를 업데이트하거나 사용자에게 패키지 옵션을 표시하는 데 유용합니다.
3. 재시도 메커니즘:

이 서비스는 일시적인 문제가 있는 경우 RetryTemplate을 사용하여 공급자의 API에 대한 요청을 자동으로 재시도합니다. 이를 통해 사소한 문제가 발생하더라도 시스템의 안정성과 복원력이 유지됩니다.

이러한 기능을 결합함으로써 이 코드는 시스템이 패키지 데이터를 효율적으로 관리하는 동시에 공급자의 API와 원활하고 안정적인 통신을 유지하도록 보장합니다.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
결제 게이트웨이 통합

이 클래스는 금융 거래를 원활하고 안전하게 처리하기 위해 시스템이 결제 게이트웨이와 상호 작용하는 방식을 관리하는 데 핵심적인 역할을 합니다.

1. 초기화Payment(PaymentRequest 요청):
  • 결제 프로세스가 시작되는 과정이라고 생각하세요. 모든 결제 세부정보와 함께 결제 게이트웨이에 요청을 보냅니다.
  • 결제 URL 및 세션 상태와 같은 정보가 포함된 PaymentSession 객체를 반환합니다.
2.holdInEscrow(String PaymentId):
  • 이 방법은 지정된 결제 ID를 사용하여 에스크로 계좌에서 결제를 보호합니다.
  • 에스크로 자금에 대한 모든 세부정보가 포함된 EscrowResponse 개체를 제공합니다.
3. releaseToProvider(문자열 에스크로 ID):
  • 서비스가 성공적으로 활성화된 후 에스크로 자금이 서비스 제공자에게 전달되는 방식입니다.
  • 에스크로 ID는 올바른 자금을 식별하고 지급하는 데 사용됩니다.
4. 고객에게 환불(문자열 에스크로 ID):
  • 서비스 활성화 실패 등 문제가 발생하는 경우 이 방법을 사용하면 에스크로된 자금을 고객에게 다시 환불할 수 있습니다.
  • 환불 처리에는 에스크로 ID를 사용합니다.
주요 특징:
  • 클래스는 WebClient를 사용하여 결제 게이트웨이의 REST API에 HTTP 요청을 보내 원활한 통합을 보장합니다.
  • 결제 시작, 에스크로 관리, 환불 처리 등 중요한 작업을 처리합니다.
  • 모든 메소드는 동기식 호출(.block()을 통해)을 사용하여 계속 진행하기 전에 작업이 완료되었는지 확인하고 안정성을 보장합니다.

이 수업은 시스템에서 안전하고 효율적인 금융 거래를 관리하는 데 있어서 중요한 퍼즐 조각입니다.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
알림 DTO
1. 이메일 알림:
  • 이를 이메일 알림 전송에 대한 청사진으로 생각하세요. 여기에는 다음이 포함됩니다.
    • 받는 사람의 이메일(받는 사람)
    • 이메일 제목
    • 형식을 결정하는 템플릿 ID입니다.
    • 콘텐츠를 개인화하기 위한 동적 데이터(templateData)
2. SMS 알림:
  • 이메일 알림과 유사하지만 SMS에 맞게 조정되었습니다. 여기에는 다음이 포함됩니다.
    • 받는 사람의 전화번호(phoneNumber)입니다.
    • 메시지 형식의 템플릿 ID입니다.
    • 개인화를 위한 동적 데이터(templateData)
알림 서비스

이 서비스는 주문 상태에 대해 사용자에게 전송되는 모든 알림을 처리합니다. 작동 방식은 다음과 같습니다.

1.성공 알림 보내기(주문 주문):
  • 이 방법은 성공 알림 전송을 처리합니다. 다음을 사용합니다:
    • buildSuccessEmail을 사용하여 이메일 알림을 생성합니다.
    • buildSuccessSms를 사용하여 SMS 알림을 생성합니다.
    • 또한 QuotaWebSocketHandler를 사용하여 WebSocket을 통해 실시간 업데이트를 보냅니다.
2. sendFailureNotification(주문 주문):
  • 이것은 실패 알림을 처리합니다. 다음을 사용합니다:
    • 이메일 메시지용 buildFailureEmail.
    • SMS 메시지용 buildFailureSms.
    • 성공 알림과 마찬가지로 WebSocket 업데이트도 보냅니다.
3. 도우미 방법:
  • buildSuccessEmail 및 buildFailureEmail: 이 메소드는 주문의 성공 여부에 따라 이메일 알림을 생성합니다. 템플릿과 주문 세부정보를 사용합니다.
  • buildSuccessSms 및 buildFailureSms: 동일한 작업을 수행하지만 SMS 알림용입니다.
추가 기능:
  • WebSocket 업데이트: QuotaWebSocketHandler를 사용하여 프런트엔드를 실시간으로 업데이트합니다.
  • 오류 로깅: 문제가 발생하면 디버깅을 위해 오류를 기록합니다.

이 서비스를 통해 사용자는 이메일, SMS 또는 실시간 업데이트를 통해 항상 주문에 대한 정보를 얻을 수 있습니다.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
QuotaUpdate 클래스
  • 이 클래스를 할당량 업데이트를 위한 간단한 메신저로 생각하세요. 여기에는 세 가지 주요 정보가 포함됩니다.
    • packageId: 업데이트되는 패키지의 ID입니다.
    • availableQuota: 이 패키지에 남은 할당량입니다.
    • 타임스탬프: 업데이트가 이루어진 시간.
웹소켓 구성
1. 웹소켓 구성:
  • WebSocket 통신을 가능하게 하는 설정입니다.
  • /ws/quota에서 WebSocket 연결을 수신하기 위한 핸들러(quotaWebSocketHandler)를 등록합니다.
  • allowedOrigins("*")를 설정하여 모든 출처로부터의 연결도 허용합니다.
2. 할당량WebSocketHandler():
  • 이는 수신 메시지와 연결을 관리하는 WebSocket 핸들러 Bean을 정의합니다.
할당량WebSocketHandler

모든 WebSocket 마법이 일어나는 곳입니다! 서버와 클라이언트 간의 실시간 업데이트를 관리합니다.

1. 분야:
  • PackageCacheService: 할당량이 업데이트될 때마다 로컬 캐시를 업데이트하는 데 도움이 됩니다.
  • ObjectMapper: JSON 페이로드를 Java 객체로 또는 그 반대로 변환하는 작업을 처리합니다.
  • 세션: 모든 활성 WebSocket 세션(현재 연결된 클라이언트)을 추적합니다.
2. 방법:
  • afterConnection설립(WebSocketSession 세션):
    • 연결하자마자 새 클라이언트 세션을 활성 목록에 추가합니다.
  • afterConnectionClosed(WebSocketSession 세션, CloseStatus 상태):
    • 연결이 끊어지면 클라이언트 세션을 제거합니다.
  • handlerTextMessage(WebSocketSession 세션, TextMessage 메시지):
    • 수신 메시지를 처리합니다.
    • 수신된 JSON을 QuotaUpdate 개체로 변환하고 로컬 캐시를 업데이트합니다.
3. sendOrderUpdate(주문 주문):
  • 연결된 모든 고객에게 주문 변경에 대한 실시간 업데이트를 보냅니다.
  • Order 개체를 JSON으로 변환하여 활성 WebSocket 세션에 메시지로 보냅니다.
  • 열린 연결만 업데이트를 받도록 하세요.
코드의 주요 특징:
  • 실시간 업데이트:
    • 할당량 변경 및 주문 업데이트에 대해 고객에게 즉시 알립니다.
  • 스레드로부터 안전한 관리:
    • ConcurrentHashSet을 사용하여 연결된 클라이언트를 처리하므로 여러 클라이언트가 활성화되어 있을 때 충돌이 발생하지 않습니다.
  • 오류 처리:
    • 메시지 전송에 문제가 있을 때 오류를 기록하여 문제를 더 쉽게 해결할 수 있습니다.

이 설정은 백엔드와 프런트엔드 간의 원활하고 즉각적인 통신을 보장하므로 사용자는 항상 할당량 가용성 및 주문 상태에 대한 최신 정보를 얻을 수 있습니다.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

다음은 이러한 사용자 정의 예외 클래스에 대한 분석과 시스템의 특정 오류 시나리오를 처리하는 데 사용되는 방법입니다.

QuotaNotAvailableException:

  • 이 예외는 사용자가 패키지를 구매하려고 시도했지만 해당 패키지에 대한 할당량이 이미 사라진 경우에 발생합니다.
  • "패키지 할당량을 사용할 수 없습니다."라는 간단한 기본 메시지가 함께 제공되므로 개발자와 사용자 모두 문제를 명확하게 이해할 수 있습니다.

OrderNotFoundException:

  • 이 기능은 시스템이 제공된 주문 ID를 기반으로 주문을 찾을 수 없을 때 시작됩니다.
  • '주문을 찾을 수 없음: [orderId]'와 같은 자세한 오류 메시지가 포함되어 있어 어떤 주문이 ​​누락되었는지 쉽게 파악할 수 있습니다.

결제 확인 예외:

  • 결제 확인에 문제가 있는 경우(금액이 일치하지 않거나 결제 상태가 불분명할 수 있음) 이 예외가 발생합니다.
  • 맞춤 메시지를 전달할 수 있어 결제 문제 진단에 유연성과 컨텍스트가 추가됩니다.

이러한 예외를 사용함으로써 시스템은 명확하고 예측 가능한 방식으로 오류를 처리합니다. 이를 통해 개발자의 디버깅 효율성이 향상될 뿐만 아니라 문제가 발생했을 때 사용자가 명확하고 실행 가능한 피드백을 받을 수 있습니다.

// Request/Response DTOs
@Getter @Setter
public class OrderRequest {
    private String customerId;
    private String packageId;
    private BigDecimal amount;
}

@Getter @Setter
public class PaymentCallback {
    private String orderId;
    private String paymentId;
    private String status;
    private BigDecimal amount;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class QuotaResponse {
    private String packageId;
    private boolean available;
    private Integer remainingQuota;
    private LocalDateTime timestamp;
}

@Getter @Setter
public class ReservationResponse {
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

@Getter @Setter
public class ActivationResponse {
    private String orderId;
    private boolean success;
    private String activationId;
    private String errorCode;
    private String errorMessage;
}

@Getter @Setter
public class VerificationResponse {
    private String orderId;
    private String activationId;
    private boolean success;
    private String status;
    private LocalDateTime activatedAt;
}

@Getter @Setter
public class PaymentRequest {
    private String orderId;
    private BigDecimal amount;
    private String currency;
    private String customerId;
    private String returnUrl;
    private String callbackUrl;
}

@Getter @Setter
public class PaymentSession {
    private String sessionId;
    private String paymentUrl;
    private LocalDateTime expiresAt;
    private String status;
}

@Getter @Setter
public class EscrowResponse {
    private String id;
    private String paymentId;
    private BigDecimal amount;
    private String status;
    private LocalDateTime createdAt;
}
로그인 후 복사
로그인 후 복사

OrderService 클래스는 주문 관리와 관련된 무거운 작업을 처리합니다. 작동 방식을 자세히 살펴보겠습니다.

주요 책임
  1. createOrder(주문 요청 요청):

    • 이 방법은 새 광고주문을 만드는 것입니다. 패키지가 사용 가능한지 확인하고, 세부 정보를 수집하고, 할당량을 예약하고, RESERVED의 초기 상태로 데이터베이스에 주문을 저장합니다.
  2. processPayment(문자열 orderId, PaymentCallback 콜백):

    • 여기서 결제가 처리됩니다. 시스템은 결제 세부정보를 확인하고 주문을 업데이트하며 결제 금액을 에스크로에 넣고 서비스 활성화 프로세스를 시작합니다. 문제가 발생하면 우아하게 실패를 관리합니다.
  3. verifyActivation(주문 주문):

    • 서비스 활성화가 원활하게 진행되었는지 다시 한번 확인하는 방법입니다. 최대 3번까지 시도하고 여전히 실패할 경우 시스템이 다시 실패를 처리합니다.
  4. completeOrder(주문 주문):

    • 모든 것이 확인되면 이 방법으로 주문이 완료됩니다. 에스크로 자금을 공급자에게 릴리스하고 상태를 업데이트하며 사용자에게 성공을 알립니다.
  5. handleActivationFailure(주문 순서):

    • 활성화에 실패할 경우 이 방법을 사용하면 고객이 환불을 받고 무엇이 잘못되었는지 알림을 받을 수 있습니다.
  6. getOrder(문자열 주문 ID):

    • 이 간단한 방법은 ID로 주문을 검색합니다. 주문이 존재하지 않으면 특정 예외가 발생합니다.
작동하는 이유
  • 트랜잭션 특성 덕분에 트랜잭션이 완료되거나 롤백되도록 보장합니다.
  • 명확한 오류 처리 및 재시도 기능을 갖추고 있어 실제 문제를 처리할 만큼 강력합니다.
  • 알림을 통해 사용자는 모든 단계에서 최신 정보를 얻을 수 있습니다.

이 서비스는 주문 관리 프로세스의 중추로서 원활한 사용자 경험을 위해 모든 것을 하나로 묶습니다.

// Domain Models
@Getter @Setter
@Entity
public class Package {
    @Id
    private String id;
    private String name;
    private BigDecimal price;
    private BigDecimal providerCost;
    private String description;
    private boolean active;
}

@Getter @Setter
@Entity
public class Order {
    @Id
    private String id;
    private String customerId;
    private String packageId;
    private String reservationId;
    private String paymentId;
    private String escrowId;
    private OrderStatus status;
    private BigDecimal amount;
    private BigDecimal providerCost;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

@Getter @Setter
@Entity
public class QuotaReservation {
    @Id
    private String id;
    private String packageId;
    private LocalDateTime expiresAt;
    private ReservationStatus status;
}

// Enums
public enum OrderStatus {
    CREATED, RESERVED, PAYMENT_PENDING, PAYMENT_COMPLETED, 
    IN_ESCROW, ACTIVATING, ACTIVATION_FAILED, COMPLETED, REFUNDED
}

public enum ReservationStatus {
    ACTIVE, EXPIRED, USED, CANCELLED
}
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

OrderController 클래스는 시스템에서 주문을 관리하는 REST API 엔드포인트를 관리합니다. Think는 요청을 하는 클라이언트와 무거운 작업을 수행하는 백엔드 서비스 사이의 다리 역할을 합니다.

주요 종점
  1. POST /api/orders(createOrder):

    • 이 엔드포인트는 새 주문 생성을 처리합니다.
    • 상황은 다음과 같습니다.
      • 클라이언트로부터 OrderRequest를 받습니다.
      • OrderService.createOrder를 호출하여 요청을 처리하고 주문을 생성합니다.
      • 답변:
        • 모든 것이 순조롭게 진행된다면 새로 생성된 주문에 대해 200 OK 응답
        • 패키지 할당량을 사용할 수 없는 경우 409 충돌이 발생합니다.
        • 예상치 못한 문제로 인해 500 내부 서버 오류가 발생합니다.
  2. POST /api/orders/callback(PaymentCallback 처리):

    • 결제 게이트웨이에서 보낸 결제 업데이트를 처리합니다.
    • 흐름은 다음과 같습니다.
      • 모든 결제 세부정보가 포함된 PaymentCallback을 수신합니다.
      • OrderService.processPayment를 호출하여 결제를 처리하고 주문 상태를 업데이트합니다.
      • 가능한 응답은 다음과 같습니다.
        • 결제가 성공적으로 처리되면 200 OK
        • 404 제공된 주문 ID가 존재하지 않는 경우 찾을 수 없습니다.
        • 422 결제 확인에 불일치가 있는 경우 처리할 수 없는 항목입니다.
        • 예상치 못한 문제로 인해 500 내부 서버 오류가 발생했습니다.
  3. GET /api/orders/{orderId}(getOrder):

    • 이 엔드포인트는 ID별로 특정 주문의 세부정보를 가져옵니다.
    • 작동 방식은 다음과 같습니다.
      • OrderService.getOrder를 호출하여 주문을 검색합니다.
      • 반품:
        • 주문 세부정보가 발견되면 200 OK 응답
        • 주문 ID가 일치하는 기록이 없으면 404 Not Found입니다.
특징
  • 관심사항 분리: OrderController는 모든 비즈니스 로직을 OrderService에 위임하여 일을 깔끔하고 집중적으로 유지합니다.
  • 검증: 요청 페이로드는 @Valid 주석을 사용하여 검증되어 수신되는 데이터가 기대치를 충족하는지 확인합니다.
  • 오류 처리:
    • 사용할 수 없는 할당량이나 주문 누락과 같은 일반적인 문제에 대해 구체적이고 유용한 답변을 제공합니다.
    • 더 쉽게 디버깅할 수 있도록 모든 문제를 기록합니다.
  • 로깅: 더 나은 가시성을 위해 들어오는 요청, 오류, 주문 세부정보 등의 주요 이벤트를 추적합니다.

이 컨트롤러는 클라이언트와 백엔드의 원활한 통신을 보장하여 주문 관리를 최대한 원활하게 만듭니다.

결론

이 연구 문서는 할당량 관리, 결제 처리, 서비스 활성화와 같은 중요한 문제를 해결하면서 전자 상거래 신용 판매 시스템을 설계하기 위한 기반을 마련합니다. 이 디자인은 기본 사항을 다루지만 항상 더 나은 결과를 얻을 수 있는 여지가 있습니다!

다음은 이 디자인을 개선할 수 있는 몇 가지 아이디어입니다.

  • 이벤트 중심 아키텍처를 사용하여 시스템을 더욱 유연하고 확장 가능하게 만듭니다.
  • 메시지 대기열 기반 처리를 추가하여 많은 트랜잭션을 원활하게 처리합니다.
  • 고급 캐싱 전략을 탐색하여 작업 속도를 높이고 외부 API에 대한 종속성을 줄이세요.
  • 더 쉬운 확장과 더 나은 안정성을 위해 분산 시스템 패턴을 고려하세요.
  • 회로 차단기를 구현하여 타사 서비스 문제를 원활하게 처리하세요.
  • 모니터링 및 알림을 설정하여 문제를 조기에 파악하고 신속하게 해결하세요.
  • 보안 조치를 강화하여 사용자와 데이터를 보호합니다.

읽어주셔서 정말 감사합니다! 이 문서가 비슷한 문제를 탐구하는 모든 사람에게 유용하고 명확성을 제공하기를 바랍니다. 물론 이 디자인이 완벽하지는 않습니다. 항상 개선의 여지가 있습니다. 어떤 생각이나 제안이 있으시면 듣고 싶습니다.

자원:

  • 클린 아키텍처와 SOLID 원칙에 대한 심층 분석
  • 마이크로서비스 아키텍처로 전자상거래 애플리케이션 설계
  • Flash 판매를 위한 확장 가능한 백엔드 설계
  • Wikipedia의 에스크로

위 내용은 인터넷 크레딧 구매 시스템 설계의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿