> ## 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.

# Java

> Integrasikan Dodo Payments ke dalam aplikasi Java Anda dengan SDK yang kuat dan aman tipe

SDK Java menyediakan akses yang nyaman dan ergonomis ke Dodo Payments REST API untuk aplikasi yang ditulis dalam Java. Ini memanfaatkan fitur spesifik Java seperti Optional, Stream, dan CompletableFuture untuk pengembangan Java modern.

## Instalasi

### Maven

Tambahkan dependensi ke `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

Tambahkan dependensi ke `build.gradle`:

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

<Tip>
  Selalu gunakan versi SDK terbaru untuk mengakses fitur Dodo Payments terkini. Periksa [Maven Central](https://central.sonatype.com/artifact/com.dodopayments.api/dodo-payments-java) untuk versi terbaru.
</Tip>

<Info>
  SDK ini mendukung Java 8 dan semua versi selanjutnya, termasuk Java 11, 17, dan 21.
</Info>

## Memulai Cepat

Inisialisasi klien dan buat sesi checkout:

```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>
  Selalu simpan kunci API Anda secara aman menggunakan variabel lingkungan, properti sistem, atau sistem manajemen konfigurasi yang aman. Jangan pernah menyimpannya secara langsung di kode sumber Anda.
</Warning>

## Fitur Utama

<CardGroup cols={2}>
  <Card title="Type Safety" icon="shield-check">
    API dengan tipe kuat yang memiliki keamanan waktu kompilasi
  </Card>

  <Card title="Thread-Safe" icon="bolt">
    Aman untuk digunakan secara bersamaan dalam aplikasi multi-threaded
  </Card>

  <Card title="Builder Pattern" icon="layer-group">
    Pola builder intuitif untuk menyusun permintaan
  </Card>

  <Card title="Async Support" icon="arrows-rotate">
    Dukungan CompletableFuture untuk operasi asinkron
  </Card>
</CardGroup>

## Konfigurasi

### Variabel Lingkungan

Konfigurasi menggunakan variabel lingkungan atau properti sistem:

```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();
```

### Konfigurasi Manual

Konfigurasi secara manual dengan semua opsi:

```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();
```

### Mode Uji

Konfigurasi untuk lingkungan uji/sandbox:

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

## Operasi Umum

### Buat Sesi Checkout

Hasilkan sesi checkout:

```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());
```

### Kelola Pelanggan

Buat dan ambil informasi pelanggan:

```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() + ")");
```

### Tangani Langganan

Buat dan kelola langganan berulang:

```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` dinyatakan dalam denominasi mata uang terendah (misalnya, sen untuk USD, paise untuk INR). Untuk menagih \$25,00, kirimkan `2500`.
</Info>

<Tip>
  Penagihan melalui `subscriptions().charge(...)` dimaksudkan untuk [langganan sesuai permintaan](/developer-resources/ondemand-subscriptions). Langganan terjadwal standar ditagih secara otomatis berdasarkan jadwal harga produk.
</Tip>

## Penagihan Berbasis Penggunaan

### Mengonfigurasi Meter

Buat dan kelola meteran untuk melacak penggunaan:

```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()));
```

### Memasukkan Acara Penggunaan

Lacak acara khusus:

```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());
```

### Memasukkan Acara Secara Batch

Masukkan beberapa acara secara efisien (maksimal 1000 per permintaan):

```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");
```

## Penanganan Kesalahan

Penanganan kesalahan yang komprehensif untuk berbagai skenario:

```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 secara otomatis mengulangi permintaan pada kesalahan koneksi, 408, 409, 429, dan kesalahan 5xx dengan backoff eksponensial.
</Tip>

## Operasi Async

Gunakan CompletableFuture untuk operasi asinkron:

```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;
});
```

## Integrasi Spring Boot

### Kelas Konfigurasi

```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();
    }
}
```

### Lapisan Layanan

```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);
    }
}
```

## Sumber Daya

<CardGroup cols={2}>
  <Card title="GitHub Repository" icon="github" href="https://github.com/dodopayments/dodopayments-java">
    Lihat kode sumber dan berkontribusi
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/introduction">
    Dokumentasi API lengkap
  </Card>

  <Card title="Discord Community" icon="discord" href="https://discord.gg/bYqAp4ayYh">
    Dapatkan bantuan dan terhubung dengan pengembang
  </Card>

  <Card title="Report Issues" icon="bug" href="https://github.com/dodopayments/dodopayments-java/issues">
    Laporkan bug atau minta fitur
  </Card>
</CardGroup>

## Dukungan

Perlu bantuan dengan Java SDK?

* **Discord**: Bergabunglah dengan [server komunitas](https://discord.gg/bYqAp4ayYh) kami untuk dukungan waktu nyata
* **Email**: Hubungi kami di [support@dodopayments.com](mailto:support@dodopayments.com)
* **GitHub**: Buka isu di [repository](https://github.com/dodopayments/dodopayments-java)

## Kontribusi

Kami menyambut kontribusi! Lihat [panduan kontribusi](https://github.com/dodopayments/dodopayments-java/blob/main/CONTRIBUTING.md) untuk memulai.
