> For the complete documentation index, see [llms.txt](https://docs.ecommerce.seb.ee/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ecommerce.seb.ee/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/sdk-izmantosana/java.md).

# Java

Izveidojiet Java maksājumu integrācijas ar klientiem, pieprasījuma DTO, API izsaukumiem, kļūdu apstrādi un webhook.

Izmantojiet šo rokasgrāmatu, ja esat pabeidzis [Java ātrais sākums](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/atrie-sakumi/java.md) un vēlaties izveidot pilnu integrāciju: izveidot klientu, sastādīt pieprasījuma objektus, izsaukt API, apstrādāt kļūmes un saņemt **Webhook (arī saukts par atpakaļsaukuma paziņojumiem)**. Katrs solis balstās uz iepriekšējo. A [pilns piemērs](#complete-example) apvieno tos kopā.

## 1. solis — izveidojiet klientu

Viss sākas ar `DefaultEgwClientFactory`— plūstošu fabriku, kas izveido `EgwClient` no jūsu savienojuma iestatījumiem. Katra metode atgriež rūpnīcu, tāpēc jūs ķēdējat konfigurāciju un pabeidzat ar `createEgwClient()`:

```java
import com.tieto.banking.egw.merchantapi.sdk.application.EgwClient;
import com.tieto.banking.egw.merchantapi.sdk.application.bootstrap.DefaultEgwClientFactory;
import java.net.URI;

EgwClient client = new DefaultEgwClientFactory()
        .connectingTo(URI.create("https://sandbox.api.ecommerce.sebgroup.com"))
        .authorizingAs(System.getenv("EGW_CLIENT_ID"), System.getenv("EGW_CLIENT_SECRET"))
        .createEgwClient();
```

Rūpnīcas modelis pastāv, lai klienta infrastruktūru varētu aizstāt, nemainot jūsu lietotnes kodu: `connectingWith(ApiClient)` aizstāj HTTP klientu (starpniekserveri, TLS, taimautus), `loggingWith(EgwLogger)` pieslēdz diagnostiku, un `listeningAt(URI)` iespējo Webhook klausītāju, ko izmanto [5. solis](#step-5--listen-for-webhooks). Konfigurējiet un veidojiet no viena pavediena — rūpnīca nav droša darbam vairākos pavedienos — bet iegūtais `EgwClient` ir nemainīgs un droši koplietojams visā jūsu lietotnē. Izveidojiet to vienreiz palaišanas laikā un izmantojiet atkārtoti; tā OAuth marķieru kešatmiņa ir droša darbam vairākos pavedienos un automātiski atjaunojas.

Rūpnīca atvasina OAuth marķiera galapunktu un kartes šifrēšanas JWK galapunktu no pamata URL. Ja jūsu izvietojums kādu no tiem apkalpo no cita resursdatora, pārrakstiet tikai to ar `.tokenEndpoint(URI)` vai `.jwkEndpoint(URI)` jebkurā ķēdes vietā — tas, ko atstājat nenorādītu, joprojām tiks atvasināts.

`EgwClient` ir `AutoCloseable`. `close()` aptur tīmekļa āķa klausītāju; ja to iespējojāt, turiet klientu atvērtu tik ilgi, cik vēlaties saņemt paziņojumus, un dodiet priekšroku try-with-resources vai izslēgšanas āķim, lai klausītājs tiktu korekti atbrīvots.

## 2. solis — sastādiet pieprasījuma DTO

Pieprasījumi un atbildes ir vienkārši datu pārsūtīšanas objekti (DTO) paketē `...sdk.application.dto`: `InitiateCitPaymentRequest`, `Amount`, `Basket`, un tā tālāk. Atbildes piedāvā standarta getterus (`response.getPaymentId()`). Pieprasījumi tiek veidoti ar būvētājiem, un būvētāji atbalsta trīs savstarpēji papildinošus modeļus.

**Klasiskais konstruktors.** Katram DTO ir statisks `builder()` metodi; seteri ir nosaukti pēc lauka un atgriež būvētāju, un `build()` izveido DTO:

```java
Amount amount = Amount.builder()
        .amount("100.00")
        .currency("EUR")
        .build();
```

**Iekļauta lambda būvētāja.** Katram īpašumam, kas pats ir DTO, būvētājs pieņem arī `UnaryOperator` uz ligzdoto būvētāju. Tā vietā, lai veidotu `Amount` atsevišķi, aprakstiet to iekšēji — lambda saņem jaunu ligzdotu būvētāju un tam tas jāatgriež:

```java
InitiateCitPaymentRequest request = InitiateCitPaymentRequest.builder()
        .channel(CitPaymentChannel.BROWSER)
        .instructedAmount(a -> a.amount("100.00").currency("EUR"))
        .orderNumber("ORD-1001")
        .participantId(System.getenv("EGW_PARTICIPANT_ID"))
        .shopAgreementId(System.getenv("EGW_SHOP_AGREEMENT_ID"))
        .shopRedirectUrl("https://shop.example.com/return")
        .build();
```

Abas formas rada identiskus objektus; lambda forma vislabāk lasās dziļi ligzdotiem pieprasījumiem, bet klasiskā forma — kad atkārtoti izmantojat DTO vairākos pieprasījumos. Skalāriem un uzskaitījuma tipa īpašumiem (`orderNumber`, `channel`) ir tikai klasiskā forma.

**Pievienotāji atsevišķiem vienumiem.** Saraksta īpašumiem tiek pievienota papildu `<property>Item(...)` metode, kas pievieno vienu elementu, lai jūs varētu pievienot vienumus ciklā, pašam nepārvaldot sarakstu:

```java
Basket basket = Basket.builder()
        .itemsItem(BasketItemProduct.builder()
                .name("Fishing rod")
                .description("Carbon fiber rod, 2.7 m")
                .price(Amount.builder().amount("100.00").currency("EUR").build())
                .quantity(1)
                .build())
        .subtotalAmount(a -> a.amount("100.00").currency("EUR"))
        .build();
```

Vienumu pievienotāji pieņem pilnībā izveidotu elementu — polimorfos sarakstos, piemēram, groza vienumos, izvēlieties konkrēto tipu (`BasketItemProduct`, `BasketItemShipping`, `BasketItemDiscount`, `BasketItemTax`).

**Validācija.** `build()` pārbauda obligātos laukus un nekavējoties izmet `InvalidRequestException` nekavējoties — trūkstošs `orderNumber` neizdodas būvēšanas laikā jūsu kodā, nevis kā HTTP 400 atbildes cikls. Tāpēc pieprasījumus vienmēr vajadzētu veidot caur būvētājiem: DTO ir arī publiski konstruktori bez argumentiem un seteri, taču šis ceļš pilnībā izlaiž validāciju.

## 3. solis — izsauciet API

`EgwClient` grupē operācijas domēna piekļuvēs: `payments()`, `refunds()`, `tokens()`, `shops()`, kā arī checkout-session grupas `cardSessions()`, `bankSessions()`, `tokenSessions()`, `clickToPaySessions()`, un `notifications()` tīmekļa āķiem. Katrs piekļuves punkts atgriež vieglu API objektu — izsauciet to uz vietas, nevis kešojiet.

Katra operācija, kas pieņem pieprasījuma ķermeni, tieši pieņem vai nu gatavu DTO, vai arī būvētāja lambda, tāpēc īsiem izsaukumiem nav vajadzīga atsevišķa pieprasījuma mainīgā:

```java
// Ar sagatavotu DTO:
InitiatePaymentResponse created = client.payments().initiateCitPayment(request);

// Vai arī ar būvētāja lambda tieši vietā:
CancelPaymentResponse cancelled = client.payments().cancelPayment(
        created.getPaymentId(),
        b -> b.reason(CancelReason.SUSPECTED_FRAUD));
```

Operācijas bez ķermeņa pieņem vienkāršus argumentus:

```java
PaymentInformationResponse info =
        client.payments().getPaymentInformation(created.getPaymentId(), null);
System.out.println("Status: " + info.getPaymentStatus());
```

Tipiska norēķinu norakstīšanas plūsma pēc tam, kad pircējs pabeidz checkout:

```java
CapturePaymentResponse captured = client.payments().capturePayment(
        created.getPaymentId(),
        b -> b.instructedAmount(a -> a.amount("100.00").currency("EUR")));
```

Un atmaksa, kas atrodas savā piekļuves punktā, jo tā ir atsevišķs resurss ar savu ID:

```java
RefundPaymentResponse refund = client.refunds().refundPayment(b -> b
        .paymentId(created.getPaymentId())
        .instructedAmount(a -> a.amount("100.00").currency("EUR")));
```

Aiz katra izsaukuma SDK iegūst un kešo OAuth 2.0 piekļuves marķieri, iestata unikālu `X-Request-ID` galveni, serializē pieprasījumu un deserializē atbildi tipizētā atbildes DTO. Ieslēdziet žurnālu rakstītāju ar `loggingWith(...)` un reģistrējiet `X-Request-ID` lai sasaistītu neveiksmīgos izsaukumus ar atbalstu — skatiet [Kļūdu apstrāde](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md#reading-api-errors).

## 4. solis — apstrādājiet izņēmumus

Visas SDK kļūmes ir nepārbaudīti izņēmumi, kas paplašina `ECommException`. Vispirms ķeriet konkrētos tipus, uz kuriem varat rīkoties, un `ECommException` lietojiet kā drošības tīklu:

```java
try {
    InitiatePaymentResponse response = client.payments().initiateCitPayment(request);
} catch (InvalidRequestException e) {
    // Būvēšanas laikā trūka obligāts lauks — izlabojiet pieprasījumu kodā.
} catch (AuthenticationException e) {
    // Neizdevās iegūt marķieri vai autorizēties — pārbaudiet klienta ID un slepeno atslēgu Merchant Portal.
} catch (ConnectionException e) {
    // Transporta kļūme (DNS, noraidīts savienojums, tīkla kļūda).
} catch (ECommException e) {
    // API noraidīja izsaukumu, vai arī atbildi nevarēja apstrādāt.
}
```

Ko praksē nozīmē katrs catch bloks:

* `InvalidRequestException` — izmet `build()` pirms jebkādas tīkla trafika. Tā ir koda kļūda, nevis izpildlaika nosacījums; nav ko atkārtot.
* `AuthenticationException` — OAuth marķieri neizdevās iegūt. Pārbaudiet klienta ID un slepeno atslēgu Merchant Portal.
* `ConnectionException` — pieprasījums var būt vai nebūt sasniedzis platformu. SDK nekad neatkārto pieprasījumu; pēc savienojuma kļūmes izsaukumā, kas maina stāvokli, pārbaudiet maksājuma stāvokli ar `getPaymentInformation(...)` pirms atkārtotas nosūtīšanas. Skatiet [Atkārtoti mēģinājumi, idempotence, taimauti](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md#retries-idempotency-timeouts).
* `ECommException` (pamata tips) — HTTP kļūdas statuss vai nederīga atbilde. Statusa kods parādās izņēmuma ziņojumā (piemēram `Klienta kļūda izsaucot initiateCitPayment: 404`; atbildes kļūdu detaļas tiek ierakstītas SDK žurnālā, nevis pievienotas izņēmumam, tāpēc turiet ieslēgtu žurnālu rakstītāju, lai šos diagnosticētu — skatiet [API kļūdu lasīšana](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md#reading-api-errors).

Nepašauriniet savu pēdējo catch līdz `ApiException`: HTTP kļūdas statusi parādās kā pamata `ECommException`, un `AuthenticationException`/`ConnectionException` ir līdzvērtīgi `ApiException`, nevis apakšklases. `SerializationException`, `EncryptionException`, `ApiServerException` un `EgwBootstrapException`, ir atrodama [Kļūdu apstrāde](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md).

## 5. solis — klausieties Webhookus

Platforma paziņo par maksājumu stāvokļa izmaiņām, veicot POST uz galapunktu, ko jūs atklājat. SDK var šo galapunktu palaist jūsu vietā: iespējojiet klausītāju klienta izveides brīdī ar `listeningAt(...)`, pēc tam reģistrējiet apstrādātāju caur `notifications()`:

```java
EgwClient client = new DefaultEgwClientFactory()
        .connectingTo(URI.create("https://sandbox.api.ecommerce.sebgroup.com"))
        .authorizingAs(System.getenv("EGW_CLIENT_ID"), System.getenv("EGW_CLIENT_SECRET"))
        .listeningAt(URI.create("http://0.0.0.0:8080/egw/notifications"))
        .createEgwClient();

client.notifications().receiveNotifications(notification -> {
    if ("PAYMENT".equals(notification.getType())) {
        PaymentInformationResponse info =
                client.payments().getPaymentInformation(notification.getPaymentId(), null);
        // Atjauniniet pasūtījumu, izmantojot info.getPaymentStatus() — nevis tikai no paziņojuma.
    }
});
```

`receiveNotifications(...)` pieņem `Consumer<NotificationRequest>` un atgriežas nekavējoties; klausītājs turpina piegādāt paziņojumus fona pavedienā līdz `client.close()`. Paziņojums satur `type`, `paymentId` un `paymentStatus` kā virknes.

Vienmēr uztveriet paziņojumu kā ierosinātāju, nevis patiesību: pašreizējā versija nepārbauda ienākošo tīmekļa āķu izsaukumu autentiskumu, tāpēc pirms pasūtījuma atjaunināšanas atkārtoti iegūstiet maksājuma stāvokli caur API. Tas un transporta prasības (iebūvētais klausītājs runā vienkāršā HTTP — TLS jābeidz tā priekšā) ir aprakstītas [Drošības mehānika](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/drosibas-mehanismi.md#webhook-notifications).

Divi lietošanas noteikumi palīdz uzturēt klausītāju veselīgu: konfigurējiet `listeningAt(...)` pirms izsaukšanas `receiveNotifications(...)` (bez tā izsaukums neizdodas ar `NullPointerException` pašreizējā versijā), un reģistrējiet tieši vienu apstrādātāju uz klientu — nav atcelšanas iespējas, un izsaukt `receiveNotifications(...)` divreiz uz tā paša klienta nav atbalstīts. Ja jūsu apstrādātājs izmet izņēmumu, SDK atbild platformai ar HTTP 500, un SDK paziņojumu nepiegādā atkārtoti, tāpēc turiet apstrādātājus īsus un ātri apstiprināmus.

## Pilns piemērs

Minimāla pilna procesa plūsma — izveidojiet klientu, klausieties paziņojumus, uzsāciet maksājumu un nofiksējiet to, kad checkout ir pabeigts:

```java
import com.tieto.banking.egw.merchantapi.sdk.application.EgwClient;
import com.tieto.banking.egw.merchantapi.sdk.application.bootstrap.DefaultEgwClientFactory;
import com.tieto.banking.egw.merchantapi.sdk.application.dto.*;
import com.tieto.banking.egw.merchantapi.sdk.core.ECommException;
import java.net.URI;

public class EgwIntegration {
    public static void main(String[] args) {
        try (EgwClient client = new DefaultEgwClientFactory()
                .connectingTo(URI.create("https://sandbox.api.ecommerce.sebgroup.com"))
                .authorizingAs(System.getenv("EGW_CLIENT_ID"), System.getenv("EGW_CLIENT_SECRET"))
                .listeningAt(URI.create("http://0.0.0.0:8080/egw/notifications"))
                .createEgwClient()) {

            client.notifications().receiveNotifications(n ->
                    System.out.println("Maksājums " + n.getPaymentId() + " → " + n.getPaymentStatus());

            InitiatePaymentResponse created = client.payments().initiateCitPayment(b -> b
                    .channel(CitPaymentChannel.BROWSER)
                    .instructedAmount(a -> a.amount("100.00").currency("EUR"))
                    .orderNumber("ORD-1001")
                    .participantId(System.getenv("EGW_PARTICIPANT_ID"))
                    .shopAgreementId(System.getenv("EGW_SHOP_AGREEMENT_ID"))
                    .shopRedirectUrl("https://shop.example.com/return")
                    .description("Fishing rod, 2.7 m"));

            System.out.println("Maksājums izveidots: " + created.getPaymentId());

            // ... pircējs pabeidz norēķinu; rezultātu uzzināsiet caur iepriekš minēto
            // paziņojumu apstrādātājs augstāk vai aptaujājot getPaymentInformation(...).

            CapturePaymentResponse captured = client.payments().capturePayment(
                    created.getPaymentId(),
                    b -> b.instructedAmount(a -> a.amount("100.00").currency("EUR")));

            System.out.println("Nofiksēts, statuss: " + captured.getPaymentStatus());

        } catch (ECommException e) {
            System.err.println("Maksājuma plūsma neizdevās: " + e.getMessage());
        }
    }
}
```

## Nākamie soļi

* [Kļūdu apstrāde](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md) — pilnā izņēmumu hierarhija un ieteikumi atkārtotiem mēģinājumiem.
* [Drošības mehānika](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/drosibas-mehanismi.md) — kartes šifrēšana kartes checkout sesijām, tīmekļa āķu drošība.
* [Java ātrais sākums](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/atrie-sakumi/java.md) — instalēšana, akreditācijas dati, zināmie ierobežojumi.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.ecommerce.seb.ee/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/sdk-izmantosana/java.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
