> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 자바

> 강력하고 타입 안전한 SDK로 Dodo Payments를 자바 애플리케이션에 통합하세요.

자바 SDK는 자바로 작성된 애플리케이션을 위한 Dodo Payments REST API에 편리하고 인체공학적으로 접근할 수 있게 해줍니다. Optional, Stream, CompletableFuture와 같은 자바 전용 기능을 활용하여 현대 자바 개발을 지원합니다.

## 설치

### Maven

의존성을 `pom.xml`에 추가하세요:

```xml pom.xml theme={null}
<dependency>
  <groupId>com.dodopayments.api</groupId>
  <artifactId>dodo-payments-java</artifactId>
  <version>1.97.1</version>
</dependency>
```

### Gradle

의존성을 `build.gradle`에 추가하세요:

```kotlin build.gradle.kts theme={null}
implementation("com.dodopayments.api:dodo-payments-java:1.97.1")
```

<Tip>
  가장 최신 Dodo Payments 기능에 액세스하려면 항상 최신 SDK 버전을 사용하세요. 최신 버전은 [Maven Central](https://central.sonatype.com/artifact/com.dodopayments.api/dodo-payments-java)에서 확인할 수 있습니다.
</Tip>

<Info>
  이 SDK는 Java 8과 그 이후 버전(예: Java 11, 17, 21)을 모두 지원합니다.
</Info>

## 빠른 시작

클라이언트를 초기화하고 체크아웃 세션을 생성하세요:

```java theme={null}
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionCreateParams;
import com.dodopayments.api.models.checkoutsessions.CheckoutSessionRequest;
import com.dodopayments.api.models.checkoutsessions.ProductItemReq;

// Configure using environment variables (DODO_PAYMENTS_API_KEY, DODO_PAYMENTS_BASE_URL)
// Or system properties (dodopayments.apiKey, dodopayments.baseUrl)
DodoPaymentsClient client = DodoPaymentsOkHttpClient.fromEnv();

CheckoutSessionRequest params = CheckoutSessionRequest.builder()
    .addProductCart(ProductItemReq.builder()
        .productId("product_id")
        .quantity(1)
        .build())
    .build();
    
CheckoutSessionResponse checkoutSessionResponse = client.checkoutSessions().create(params);
System.out.println(checkoutSessionResponse.sessionId());
```

<Warning>
  API 키는 환경 변수, 시스템 속성 또는 보안 구성 관리 시스템을 사용하여 항상 안전하게 보관하세요. 절대 소스 코드에 하드코딩하지 마세요.
</Warning>

## 주요 기능

<CardGroup cols={2}>
  <Card title="Type Safety" icon="shield-check">
    컴파일 시점 안전성을 제공하는 강한 타입의 API
  </Card>

  <Card title="Thread-Safe" icon="bolt">
    멀티스레드 애플리케이션에서 안전한 동시 사용 가능
  </Card>

  <Card title="Builder Pattern" icon="layer-group">
    요청을 구성하기 위한 직관적인 빌더 패턴
  </Card>

  <Card title="Async Support" icon="arrows-rotate">
    비동기 작업을 위한 CompletableFuture 지원
  </Card>
</CardGroup>

## 구성

### 환경 변수

환경 변수 또는 시스템 속성을 사용하여 구성하세요:

```bash .env theme={null}
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_BASE_URL=https://live.dodopayments.com
```

```java theme={null}
// Automatically reads from environment variables
DodoPaymentsClient client = DodoPaymentsOkHttpClient.fromEnv();
```

### 수동 구성

모든 옵션으로 수동으로 구성하세요:

```java theme={null}
import java.time.Duration;

DodoPaymentsClient client = DodoPaymentsOkHttpClient.builder()
    .bearerToken("your_api_key_here")
    .baseUrl("https://live.dodopayments.com")
    .maxRetries(4)
    .timeout(Duration.ofSeconds(30))
    .responseValidation(true)
    .build();
```

### 테스트 모드

테스트/샌드박스 환경을 위해 구성하세요:

```java theme={null}
DodoPaymentsClient testClient = DodoPaymentsOkHttpClient.builder()
    .fromEnv()
    .testMode()
    .build();
```

## 일반 작업

### 체크아웃 세션 생성

체크아웃 세션을 생성하세요:

```java theme={null}
CheckoutSessionRequest params = CheckoutSessionRequest.builder()
    .addProductCart(ProductItemReq.builder()
        .productId("prod_123")
        .quantity(1)
        .build())
    .returnUrl("https://yourdomain.com/return")
    .build();

CheckoutSessionResponse session = client.checkoutSessions().create(params);
System.out.println("Checkout URL: " + session.checkoutUrl());
```

### 고객 관리

고객 정보를 생성하고 검색하세요:

```java theme={null}
import com.dodopayments.api.models.customers.Customer;
import com.dodopayments.api.models.customers.CustomerCreateParams;

// Create a customer
CustomerCreateParams createParams = CustomerCreateParams.builder()
    .email("customer@example.com")
    .name("John Doe")
    .putMetadata("user_id", "12345")
    .build();

Customer customer = client.customers().create(createParams);

// Retrieve customer
Customer retrieved = client.customers().retrieve("cus_123");
System.out.println("Customer: " + retrieved.name() + " (" + retrieved.email() + ")");
```

### 구독 처리

정기 구독을 생성하고 관리하세요:

```java theme={null}
import com.dodopayments.api.models.payments.AttachExistingCustomer;
import com.dodopayments.api.models.payments.BillingAddress;
import com.dodopayments.api.models.payments.CountryCode;
import com.dodopayments.api.models.subscriptions.SubscriptionChargeParams;
import com.dodopayments.api.models.subscriptions.SubscriptionChargeResponse;
import com.dodopayments.api.models.subscriptions.SubscriptionCreateParams;
import com.dodopayments.api.models.subscriptions.SubscriptionCreateResponse;

// Create a subscription
SubscriptionCreateParams subscriptionParams = SubscriptionCreateParams.builder()
    .billing(BillingAddress.builder()
        .city("San Francisco")
        .country(CountryCode.US)
        .state("CA")
        .street("1 Market St")
        .zipcode("94105")
        .build())
    .customer(AttachExistingCustomer.builder()
        .customerId("cus_123")
        .build())
    .productId("pdt_456")
    .quantity(1)
    .paymentLink(true)
    .returnUrl("https://yourdomain.com/return")
    .build();

SubscriptionCreateResponse subscription = client.subscriptions().create(subscriptionParams);
System.out.println("Subscription ID: " + subscription.subscriptionId());

// Charge an on-demand subscription
// product_price is in the lowest currency denomination (e.g., 2500 = $25.00 USD)
SubscriptionChargeParams chargeParams = SubscriptionChargeParams.builder()
    .subscriptionId(subscription.subscriptionId())
    .productPrice(2500)
    .build();

SubscriptionChargeResponse chargeResponse = client.subscriptions().charge(chargeParams);
System.out.println("Payment ID: " + chargeResponse.paymentId());
```

<Info>
  `productPrice`은(는) 가장 낮은 화폐 단위로 표현됩니다 (예: USD의 경우 센트, INR의 경우 파이사). \$25.00을 청구하려면 `2500`을(를) 입력하세요.
</Info>

<Tip>
  `subscriptions().charge(...)`를 통한 청구는 [온디맨드 구독](/developer-resources/ondemand-subscriptions)을 위한 것입니다. 표준 예약 구독은 제품의 가격 일정에 따라 자동으로 청구됩니다.
</Tip>

## 사용량 기반 청구

### 미터 구성

사용량 추적을 위한 미터 생성 및 관리:

```java theme={null}
import com.dodopayments.api.models.meters.*;

// Create API calls meter
MeterCreateParams apiMeterParams = MeterCreateParams.builder()
    .name("API Requests")
    .eventName("api_request")
    .aggregation("count")
    .putMetadata("category", "api_usage")
    .build();

Meter apiMeter = client.meters().create(apiMeterParams);
System.out.println("Meter created: " + apiMeter.meterId());

// List all meters
client.meters().list()
    .autoPager()
    .forEach(m -> System.out.println("Meter: " + m.name() + " - " + m.aggregation()));
```

### 사용량 이벤트 수집

사용자 정의 이벤트 추적:

```java theme={null}
import com.dodopayments.api.models.usageevents.*;
import java.time.OffsetDateTime;

// Ingest single event
UsageEventIngestParams singleEventParams = UsageEventIngestParams.builder()
    .addEvent(UsageEventIngestParams.Event.builder()
        .eventId("api_call_" + System.currentTimeMillis())
        .customerId("cus_abc123")
        .eventName("api_request")
        .timestamp(OffsetDateTime.now())
        .putMetadata("endpoint", "/api/v1/users")
        .putMetadata("method", "GET")
        .putMetadata("tokens_used", "150")
        .build())
    .build();

UsageEventIngestResponse response = client.usageEvents().ingest(singleEventParams);
System.out.println("Processed: " + response.ingestedCount());
```

### 배치 이벤트 수집

다수의 이벤트를 효율적으로 수집 (요청 당 최대 1000개):

```java theme={null}
UsageEventIngestParams.Builder batchBuilder = UsageEventIngestParams.builder();

for (int i = 0; i < 100; i++) {
    batchBuilder.addEvent(UsageEventIngestParams.Event.builder()
        .eventId("batch_event_" + i + "_" + System.currentTimeMillis())
        .customerId("cus_abc123")
        .eventName("video_transcode")
        .timestamp(OffsetDateTime.now().minusMinutes(i))
        .putMetadata("video_id", "video_" + i)
        .putMetadata("duration_seconds", String.valueOf(120 + i))
        .build());
}

UsageEventIngestResponse batchResponse = client.usageEvents().ingest(batchBuilder.build());
System.out.println("Batch processed: " + batchResponse.ingestedCount() + " events");
```

## 오류 처리

다양한 시나리오에 대한 종합적인 오류 처리:

```java theme={null}
import com.dodopayments.api.errors.*;

try {
    Payment payment = client.payments().retrieve("pay_invalid");
} catch (NotFoundException e) {
    System.err.println("Payment not found: " + e.getMessage());
} catch (UnauthorizedException e) {
    System.err.println("Authentication failed: " + e.getMessage());
} catch (PermissionDeniedException e) {
    System.err.println("Permission denied: " + e.getMessage());
} catch (BadRequestException e) {
    System.err.println("Invalid request: " + e.getMessage());
} catch (UnprocessableEntityException e) {
    System.err.println("Validation error: " + e.getMessage());
} catch (RateLimitException e) {
    System.err.println("Rate limit exceeded: " + e.getMessage());
    // SDK automatically retries with backoff
} catch (InternalServerException e) {
    System.err.println("Server error: " + e.getMessage());
} catch (DodoPaymentsServiceException e) {
    System.err.println("API error: " + e.statusCode() + " - " + e.getMessage());
}
```

<Tip>
  SDK는 연결 오류, 408, 409, 429 및 5xx 오류에 대해 지수 백오프와 함께 자동 재시도를 수행합니다.
</Tip>

## 비동기 작업

비동기 작업을 위한 CompletableFuture 사용:

```java theme={null}
import java.util.concurrent.CompletableFuture;

CompletableFuture<CheckoutSessionResponse> future = client.async()
    .checkoutSessions()
    .create(params);

// Handle response asynchronously
future.thenAccept(response -> {
    System.out.println("Session created: " + response.sessionId());
}).exceptionally(ex -> {
    System.err.println("Error: " + ex.getMessage());
    return null;
});
```

## Spring Boot 통합

### 구성 클래스

```java theme={null}
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DodoPaymentsConfig {
    
    @Value("${dodo.api.key}")
    private String apiKey;
    
    @Value("${dodo.environment:test}")
    private String environment;
    
    @Bean
    public DodoPaymentsClient dodoPayments() {
        return DodoPaymentsOkHttpClient.builder()
            .bearerToken(apiKey)
            .baseUrl(environment.equals("live") 
                ? "https://live.dodopayments.com" 
                : "https://test.dodopayments.com")
            .build();
    }
}
```

### 서비스 레이어

```java theme={null}
import com.dodopayments.api.client.DodoPaymentsClient;
import com.dodopayments.api.models.checkoutsessions.*;
import org.springframework.stereotype.Service;

@Service
public class PaymentService {
    
    private final DodoPaymentsClient client;
    
    public PaymentService(DodoPaymentsClient client) {
        this.client = client;
    }
    
    public CheckoutSessionResponse createCheckout(List<ProductItemReq> items) {
        CheckoutSessionRequest params = CheckoutSessionRequest.builder()
            .productCart(items)
            .returnUrl("https://yourdomain.com/return")
            .build();
            
        return client.checkoutSessions().create(params);
    }
}
```

## 자원

<CardGroup cols={2}>
  <Card title="GitHub Repository" icon="github" href="https://github.com/dodopayments/dodopayments-java">
    소스 코드 보기 및 기여
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/introduction">
    전체 API 문서
  </Card>

  <Card title="Discord Community" icon="discord" href="https://discord.gg/bYqAp4ayYh">
    도움 받기 및 개발자와 연결
  </Card>

  <Card title="Report Issues" icon="bug" href="https://github.com/dodopayments/dodopayments-java/issues">
    버그 신고 또는 기능 요청
  </Card>
</CardGroup>

## 지원

Java SDK에 대한 도움이 필요하십니까?

* **디스코드**: 실시간 지원을 위해 [커뮤니티 서버](https://discord.gg/bYqAp4ayYh)에 참여하세요
* **이메일**: [support@dodopayments.com](mailto:support@dodopayments.com)으로 연락하세요
* **GitHub**: [저장소](https://github.com/dodopayments/dodopayments-java)에 이슈를 등록하세요

## 기여하기

기여를 환영합니다! 시작하려면 [기여 가이드라인](https://github.com/dodopayments/dodopayments-java/blob/main/CONTRIBUTING.md)을 확인하세요.
