본문으로 건너뛰기

결제 서비스 (Payment Service)

개요

결제 서비스는 주문에 대한 결제 처리, 환불을 담당하며 한국의 주요 결제 수단(카카오페이, 토스, KG이니시스)을 지원합니다.

항목내용
언어Java 17
프레임워크Spring Boot 3.2
데이터베이스Aurora PostgreSQL (Global Database)
네임스페이스mall-payment
포트8080
헬스체크/actuator/health

아키텍처

API 엔드포인트

메서드경로설명
POST/api/v1/payments결제 처리
GET/api/v1/payments/{id}결제 조회
POST/api/v1/payments/{id}/refund환불 처리

결제 처리

POST /api/v1/payments

요청:

{
"orderId": "550e8400-e29b-41d4-a716-446655440000",
"amount": 687000.00,
"currency": "KRW",
"paymentMethod": "KAKAO_PAY",
"idempotencyKey": "order-550e8400-payment-001"
}

지원 결제 수단:

  • KAKAO_PAY - 카카오페이
  • TOSS_PAY - 토스페이
  • KG_INICIS - KG이니시스
  • CREDIT_CARD - 신용카드

응답 (201 Created):

{
"id": "660e8400-e29b-41d4-a716-446655440001",
"orderId": "550e8400-e29b-41d4-a716-446655440000",
"amount": 687000.00,
"currency": "KRW",
"status": "COMPLETED",
"paymentMethod": "KAKAO_PAY",
"idempotencyKey": "order-550e8400-payment-001",
"createdAt": "2024-01-15T10:32:00",
"updatedAt": "2024-01-15T10:32:00"
}

결제 조회

GET /api/v1/payments/{id}

응답 (200 OK):

{
"id": "660e8400-e29b-41d4-a716-446655440001",
"orderId": "550e8400-e29b-41d4-a716-446655440000",
"amount": 687000.00,
"currency": "KRW",
"status": "COMPLETED",
"paymentMethod": "KAKAO_PAY",
"idempotencyKey": "order-550e8400-payment-001",
"createdAt": "2024-01-15T10:32:00",
"updatedAt": "2024-01-15T10:32:00"
}

환불 처리

POST /api/v1/payments/{id}/refund

응답 (200 OK):

{
"id": "660e8400-e29b-41d4-a716-446655440001",
"orderId": "550e8400-e29b-41d4-a716-446655440000",
"amount": 687000.00,
"currency": "KRW",
"status": "REFUNDED",
"paymentMethod": "KAKAO_PAY",
"idempotencyKey": "order-550e8400-payment-001",
"createdAt": "2024-01-15T10:32:00",
"updatedAt": "2024-01-15T12:00:00"
}

데이터 모델

Payment 엔티티

@Entity
@Table(name = "payments")
public class Payment {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

@Column(name = "order_id", nullable = false)
private UUID orderId;

@Column(precision = 12, scale = 2, nullable = false)
private BigDecimal amount;

@Column(length = 3)
private String currency = "USD";

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private PaymentStatus status = PaymentStatus.PENDING;

@Column(name = "idempotency_key", unique = true)
private String idempotencyKey;

@Column(name = "payment_method")
private String paymentMethod;

@Column(name = "created_at")
private LocalDateTime createdAt;

@Column(name = "updated_at")
private LocalDateTime updatedAt;
}

PaymentStatus 열거형

public enum PaymentStatus {
PENDING, // 대기 중
COMPLETED, // 완료
FAILED, // 실패
REFUNDED // 환불됨
}

데이터베이스 스키마

CREATE TABLE payments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
order_id UUID NOT NULL,
amount DECIMAL(12, 2) NOT NULL,
currency VARCHAR(3) DEFAULT 'KRW',
status VARCHAR(50) NOT NULL DEFAULT 'PENDING',
idempotency_key VARCHAR(255) UNIQUE,
payment_method VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_payments_order_id ON payments(order_id);
CREATE INDEX idx_payments_status ON payments(status);
CREATE INDEX idx_payments_idempotency_key ON payments(idempotency_key);

이벤트 (Kafka)

발행 토픽

토픽명이벤트설명
payments.completedpayment.completed결제 완료 시 발행
payments.failedpayment.failed결제 실패 시 발행
payments.refundedpayment.refunded환불 완료 시 발행

payments.completed 페이로드

{
"event": "payment.completed",
"payment": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"orderId": "550e8400-e29b-41d4-a716-446655440000",
"amount": 687000.00,
"currency": "KRW",
"status": "COMPLETED",
"paymentMethod": "KAKAO_PAY",
"idempotencyKey": "order-550e8400-payment-001",
"createdAt": "2024-01-15T10:32:00",
"updatedAt": "2024-01-15T10:32:00"
}
}

payments.refunded 페이로드

{
"event": "payment.refunded",
"payment": {
"id": "660e8400-e29b-41d4-a716-446655440001",
"orderId": "550e8400-e29b-41d4-a716-446655440000",
"amount": 687000.00,
"currency": "KRW",
"status": "REFUNDED",
"paymentMethod": "KAKAO_PAY",
"idempotencyKey": "order-550e8400-payment-001",
"createdAt": "2024-01-15T10:32:00",
"updatedAt": "2024-01-15T12:00:00"
}
}

환경 변수

변수명설명기본값
SPRING_DATASOURCE_URLAurora PostgreSQL 연결 URL-
SPRING_DATASOURCE_USERNAMEDB 사용자명-
SPRING_DATASOURCE_PASSWORDDB 비밀번호-
SPRING_KAFKA_BOOTSTRAP_SERVERSKafka 브로커 주소-
KAKAO_PAY_API_KEY카카오페이 API 키-
TOSS_PAY_SECRET_KEY토스페이 시크릿 키-
KG_INICIS_MIDKG이니시스 상점 ID-
SERVER_PORT서비스 포트8080

서비스 의존성

멱등성 (Idempotency)

결제 서비스는 idempotencyKey를 통해 중복 결제를 방지합니다:

  1. 클라이언트는 고유한 idempotencyKey를 생성하여 요청
  2. 동일한 키로 재요청 시 기존 결제 결과 반환
  3. 네트워크 오류 등으로 인한 중복 결제 방지

결제 흐름

에러 처리

HTTP 상태 코드에러설명
404PaymentNotFoundException결제 정보를 찾을 수 없음
400IllegalStateException잘못된 상태 전이 (예: 이미 환불된 결제 환불)
409DuplicatePaymentException중복 결제 시도 (동일 idempotencyKey)