설치
Maven
의존성을pom.xml에 추가하세요:
pom.xml
<dependency>
<groupId>com.dodopayments.api</groupId>
<artifactId>dodo-payments-java</artifactId>
<version>1.97.1</version>
</dependency>
Gradle
의존성을build.gradle에 추가하세요:
build.gradle.kts
implementation("com.dodopayments.api:dodo-payments-java:1.97.1")
가장 최신 Dodo Payments 기능에 액세스하려면 항상 최신 SDK 버전을 사용하세요. 최신 버전은 Maven Central에서 확인할 수 있습니다.
이 SDK는 Java 8과 그 이후 버전(예: Java 11, 17, 21)을 모두 지원합니다.
빠른 시작
클라이언트를 초기화하고 체크아웃 세션을 생성하세요: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());
API 키는 환경 변수, 시스템 속성 또는 보안 구성 관리 시스템을 사용하여 항상 안전하게 보관하세요. 절대 소스 코드에 하드코딩하지 마세요.
주요 기능
Type Safety
컴파일 시점 안전성을 제공하는 강한 타입의 API
Thread-Safe
멀티스레드 애플리케이션에서 안전한 동시 사용 가능
Builder Pattern
요청을 구성하기 위한 직관적인 빌더 패턴
Async Support
비동기 작업을 위한 CompletableFuture 지원
구성
환경 변수
환경 변수 또는 시스템 속성을 사용하여 구성하세요:.env
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_BASE_URL=https://live.dodopayments.com
// Automatically reads from environment variables
DodoPaymentsClient client = DodoPaymentsOkHttpClient.fromEnv();
수동 구성
모든 옵션으로 수동으로 구성하세요: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();
테스트 모드
Test Mode 환경을 구성하세요:DodoPaymentsClient testClient = DodoPaymentsOkHttpClient.builder()
.fromEnv()
.testMode()
.build();
일반 작업
체크아웃 세션 생성
체크아웃 세션을 생성하세요:CheckoutSessionRequest params = CheckoutSessionRequest.builder()
.addProductCart(ProductItemReq.builder()
.productId("pdt_123")
.quantity(1)
.build())
.returnUrl("https://yourdomain.com/return")
.build();
CheckoutSessionResponse session = client.checkoutSessions().create(params);
System.out.println("Checkout URL: " + session.checkoutUrl());
고객 관리
고객 정보를 생성하고 검색하세요: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() + ")");
구독 처리
정기 구독을 생성하고 관리하세요:POST /subscriptions (SDK의 subscriptions.create 메서드)는 deprecated 상태입니다. 기존 integration에서는 여전히 작동하지만, 새로운 integration에서는 Checkout Session을 통해 subscription을 생성해야 합니다.import com.dodopayments.api.models.payments.AttachExistingCustomer;
import com.dodopayments.api.models.payments.BillingAddress;
import com.dodopayments.api.models.misc.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());
productPrice은 가장 낮은 통화 단위(예: USD의 cents, INR의 paise)로 표현됩니다. $25.00을 청구하려면 2500을 전달하세요.subscriptions().charge(...)을 통한 청구는 on-demand subscriptions을 위한 것입니다. 표준 scheduled subscriptions은 product의 pricing schedule에 따라 자동으로 청구됩니다.Usage-Based Billing
Meters 구성
사용량을 추적하기 위한 meters를 생성하고 관리하세요:import com.dodopayments.api.models.meters.*;
// Create API calls meter
MeterCreateParams apiMeterParams = MeterCreateParams.builder()
.name("API Requests")
.eventName("api_request")
.aggregation(MeterAggregation.builder()
.type(MeterAggregation.Type.COUNT)
.build())
.measurementUnit("calls")
.build();
Meter apiMeter = client.meters().create(apiMeterParams);
System.out.println("Meter created: " + apiMeter.id());
// List all meters
client.meters().list()
.autoPager()
.forEach(m -> System.out.println("Meter: " + m.name() + " - " + m.aggregation()));
Usage Events 수집
custom events를 추적하세요:import com.dodopayments.api.models.usageevents.EventInput;
import com.dodopayments.api.models.usageevents.*;
import java.time.OffsetDateTime;
// Ingest single event
UsageEventIngestParams singleEventParams = UsageEventIngestParams.builder()
.addEvent(EventInput.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());
Events 일괄 수집
여러 events를 효율적으로 수집합니다(요청당 최대 1000개):UsageEventIngestParams.Builder batchBuilder = UsageEventIngestParams.builder();
for (int i = 0; i < 100; i++) {
batchBuilder.addEvent(EventInput.builder()
.eventId("batch_event_" + i + "_" + System.currentTimeMillis())
.customerId("cus_abc123")
.eventName("video_transcode")
.timestamp(OffsetDateTime.now().minusSeconds(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");
Error Handling
다양한 시나리오에 대한 포괄적인 error handling: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());
}
SDK는 connection errors, 408, 409, 429 및 5xx errors가 발생하면 exponential backoff를 사용하여 요청을 자동으로 재시도합니다.
Async Operations
비동기 operations에는 CompletableFuture를 사용하세요: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 Integration
Configuration Class
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();
}
}
Service Layer
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);
}
}
Resources
GitHub Repository
소스 코드를 확인하고 contribute하세요
API Reference
전체 API documentation
Discord Community
도움을 받고 developers와 연결하세요
Report Issues
bugs를 신고하거나 features를 요청하세요
Support
Java SDK에 대한 도움이 필요하신가요?- Discord: 실시간 지원을 받으려면 community server에 참여하세요
- Email: support@dodopayments.com으로 문의하세요
- GitHub: repository에 issue를 등록하세요