> 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-lt/integracija/api-kliento-sdk/naudojant-sdk/node.js-typescript.md).

# Node.js / TypeScript

Kurti Node.js mokėjimo integracijas naudojant klientus, užklausų DTO, API kvietimus, klaidų valdymą ir webhook'us.

Naudokite šį gidą, jei jau baigėte [Node.js greitasis pradžiamokslis](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/greitos-pradzios/node.js-typescript.md) ir norite sukurti pilną integraciją: sukurti klientą, sudaryti užklausų objektus, kviesti API, valdyti nesėkmes ir apdoroti **Webhook'ą (dar vadinamą atgalinio iškvietimo pranešimais)**. A [pilnas pavyzdys](#complete-example) sujungia žingsnius į visumą.

## 1 žingsnis — Sukurkite klientą

Viskas prasideda nuo `DefaultEgwClientFactory`. Skirtingai nuo „fluent“ Java ir PHP fabrikų, Node.js fabrikas priima vieną konfigūracijos objektą ir nieko neišveda iš bazinio URL — bazinį URL, tokeno galinį tašką ir JWK galinį tašką pateikiate aiškiai:

```ts
import { DefaultEgwClientFactory } from "@tieto/egw-sdk";

const client = new DefaultEgwClientFactory().create({
  baseUri: new URL("https://sandbox.api.ecommerce.sebgroup.com"),
  authentication: {
    tokenEndpoint: new URL("https://api.ecommerce.sebgroup.com/auth/realms/participants-seb/protocol/openid-connect/token"),
    clientId: process.env.EGW_CLIENT_ID!,
    clientSecret: process.env.EGW_CLIENT_SECRET!,
  },
  jwkUri: new URL("https://checkout.ecommerce.sebgroup.com/api/keys/card-encryption.jwk"),
});
```

Importuojant fabriką automatiškai užregistruojami numatytieji adapteriai (HTTP klientas, serializatorius, šifruotojas, tylusis registratorius), todėl aukščiau pateiktas fragmentas yra pilnas. Norėdami pakeisti adapterį — įprastas būdas tvarkyti laikmačius, tarpininkus ar žurnalavimą — iškvieskite `registerProvider({...})` *prieš* `create()`; fabrikas sukūrimo metu padaro užregistruotų tiekėjų momentinę kopiją. Pasiekti `registerProvider` šiuo metu reikia giluminio importo.

Sukurkite klientą vieną kartą paleidimo metu ir naudokite pakartotinai — „OAuth“ prieigos raktas yra talpinamas į spartinančiąją atmintinę ir atnaujinamas automatiškai. Node.js SDK nėra klausytojo, kurį reikėtų atlaisvinti ([5 žingsnyje](#step-5--process-webhooks)); `dispose()` egzistuoja dėl simetrijos, bet dabartinėje versijoje nėra ko sustabdyti.

## 2 žingsnis — Sudarykite užklausos DTO

Užklausos ir atsakymai yra duomenų perdavimo objektai (DTO): nekintamos klasės su `readonly` savybėmis, skaitomomis tiesiogiai (`response.paymentId`). Kiekvienas užklausos DTO turi jam skirtą konstruktoriaus klasę, prieinamą tiek kaip įvardytas eksportas (`AmountBuilder`) ir kaip statinį DTO slapyvardį (`new Amount.Builder()`).

**Klasikinis kūrimo modelis.** Nustatymo metodai yra camelCase formato, pavadinti pagal savybę, ir grąžina konstruktorių; `build()` sukuria DTO:

```ts
import { Amount } from "@tieto/egw-sdk";

const amount = new Amount.Builder()
  .amount("100.00")
  .currency("EUR")
  .build();
```

**Įdėtasis lambda kūrėjas.** Kiekvienai savybei, kuri pati yra DTO, konstruktorius siūlo `<property>Builder(...)` variantą, kuris priima funkciją su įdėtiniu konstruktoriaus objektu — aprašykite įdėtą objektą vietoje, o ne kurkite jį atskirai. Funkcija gauna naują konstruktorių ir turi jį grąžinti:

```ts
import { CitPaymentChannel, InitiateCitPaymentRequest } from "@tieto/egw-sdk";

const request = new InitiateCitPaymentRequest.Builder()
  .channel(CitPaymentChannel.Browser)
  .instructedAmountBuilder((a) => a.amount("100.00").currency("EUR"))
  .orderNumber("ORD-1001")
  .participantId(process.env.EGW_PARTICIPANT_ID!)
  .shopAgreementId(process.env.EGW_SHOP_AGREEMENT_ID!)
  .shopRedirectUrl("https://shop.example.com/return")
  .build();
```

**Vieno elemento pridėjimo metodai.** Masyvo savybės gauna papildomą `<property>Item(...)` metodą, kuris prideda vieną elementą, todėl galite cikle pridėti elementus patys nevaldydami masyvo:

```ts
import { Basket } from "@tieto/egw-sdk";

const basket = new Basket.Builder()
  .itemsItem(rodItem)
  .itemsItem(reelItem)
  .subtotalAmountBuilder((a) => a.amount("100.00").currency("EUR"))
  .build();
```

**Validacija.** Node.js SDK kūrimo metu netikrina privalomų laukų — priešingai nei Java, konstruktorius be rūpesčių sukuria objektą, nors privalomi laukai neapibrėžti, o klaida paaiškėja kaip serverio HTTP 400.

## 3 žingsnis — Kviesti API

Operacijos sugrupuotos pagal sritį ir pasiekiamos per kliento prieigas: `client.payments()`, `client.refunds()`, `client.tokens()`, `client.shop()`, ir atsiskaitymo sesijų grupės `client.cardSessions()`, `client.bankSessions()`, `client.tokenSessions()`, `client.clickToPaySessions()`.

```ts
import { randomUUID } from "node:crypto";

const payments = client.payments();
```

Visos operacijos yra `async` ir kaip pirmąjį argumentą priima užklausos ID eilutę. Kiekvienam kvietimui sugeneruokite po vieną ir saugokite jį kartu su užsakymo įrašu — tai jūsų koreliacijos raktas palaikymui.

Operacijos su užklausos kūno turiniu pateikiamos dviem formomis: `<operation>(...)` priimantis parengtą DTO, ir `<operation>WithBuilder(...)` priimantis funkciją su užklausos konstruktoriaus objektu:

```ts
// Su paruoštu DTO:
const created = await payments.initiateCitPayment(randomUUID(), request);

// Arba su įterpta konstruktoriaus funkcija (CancelReason enum paveiktas
// atviros enum serializavimo ydos, kaip ir visi per tinklą perduodami enum tipai):
const cancelled = await payments.cancelPaymentWithBuilder(
  randomUUID(),
  created.paymentId!,
  (b) => b.reason(CancelReason.SuspectedFraud)
);
```

Būsenos nuskaitymas ir lėšų nuskaičiavimas užbaigus atsiskaitymą:

```ts
const info = await payments.getPaymentInformation(randomUUID(), created.paymentId!);
console.log("Būsena:", info.paymentStatus);

const captured = await payments.capturePaymentWithBuilder(
  randomUUID(),
  created.paymentId!,
  (b) => b.instructedAmountBuilder((a) => a.amount("100.00").currency("EUR"))
);
```

Už kiekvieno kvietimo SDK gauna ir talpina „OAuth 2.0“ prieigos žetoną, nustato `X-Request-ID` antraštę, serializuoja užklausą ir deserializuoja atsakymą į tipizuotą atsakymo DTO.

## 4 žingsnis — apdorokite klaidas

Visos SDK nesėkmės paveldi `ECommException`, kuri paveldi `Error` ir nustato `name` į konkrečios klasės pavadinimą — `"AuthenticationException"`, `"ConnectionException"`, ir t. t. — su pagrindine klaida `cause`. Šioje versijoje išimčių klasės nėra eksportuojamos iš paketo šaknies, todėl šakokite pagal `name` o ne pagal `instanceof`:

```ts
try {
  const created = await payments.initiateCitPayment(randomUUID(), request);
} catch (e) {
  if (e instanceof Error) {
    switch (e.name) {
      case "AuthenticationException":
        // Nepavyko gauti prieigos rakto — patikrinkite kredencialus ir tokeno galinį tašką.
        break;
      case "ConnectionException":
        // Perdavimo klaida. SDK niekada nebando pakartotinai: prieš išsiųsdami būseną keičiančią užklausą, patikrinkite mokėjimo būseną
        // naudodami getPaymentInformation().
        break;
      default:
        // ECommException: API atmetė kvietimą (būsenos kodas yra
        // pranešime, pvz., "Client error during initiateCitPayment: 400") arba
        // atsakymas negalėjo būti apdorotas.
        break;
    }
  }
}
```

API klaidos detalės šioje versijoje nepridedamos prie klaidos — įjunkite registratorių per `registerProvider` ir susiekite pagal `X-Request-ID`; žr. [API klaidų nuskaitymas](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/gaires/klaidu-valdymas.md#reading-api-errors). Visa hierarchija yra [Klaidų tvarkymas](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/gaires/klaidu-valdymas.md).

## 5 žingsnis — apdorokite webhook'us

Platforma praneša jums apie mokėjimo būsenos pokyčius siųsdama POST užklausą į jūsų atskleistą galinį tašką. Skirtingai nuo Java, PHP ir C# SDK, Node.js SDK nepaleidžia klausytojo — HTTP galinį tašką paleidžiate patys (arba pakartotinai naudojate savo esamą Express/Fastify programą) ir naudojate `parseWebhook()` kad deserializuotumėte apkrovą:

```ts
import { createServer } from "node:http";

interface PaymentNotification {
  type: string;
  paymentId: string;
  paymentStatus: string;
}

const notifications = client.notifications();

createServer((req, res) => {
  const chunks: Buffer[] = [];
  req.on("data", (c) => chunks.push(c));
  req.on("end", async () => {
    res.writeHead(200).end(); // pirmiausia patvirtinkite, darbą atlikite vėliau

    const n = notifications.parseWebhook<PaymentNotification>(Buffer.concat(chunks));
    if (n.type === "PAYMENT") {
      const info = await payments.getPaymentInformation(randomUUID(), n.paymentId);
      // Atnaujinkite užsakymą pagal info.paymentStatus — ne vien pagal pranešimą.
    }
  });
}).listen(8080);
```

`parseWebhook<T>()` yra generinis — jūs nurodote apkrovos struktūrą, kaip ir su `PaymentNotification` aukščiau. Pranešimo apkrovos sutartis (kanoninis laukų sąrašas ir įvykių tipai): **\[TBC — nuoroda]**

Visada laikykite pranešimą paleidikliu, o ne tiesa: dabartinė versija nepatikrina įeinančių webhook kvietimų autentiškumo, todėl prieš atnaujindami užsakymą iš naujo užklauskite mokėjimo būsenos per API. Galinį tašką pateikite veikti per TLS. Abu šie punktai aptariami [Saugumo mechanizmuose](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/gaires/saugumo-mechanizmai.md#webhook-notifications).

## Pilnas pavyzdys

Minimali nuo pradžios iki galo eiga — sukurkite klientą, atverkite webhook galinį tašką, inicijuokite mokėjimą ir užfiksuokite jį, kai atsiskaitymas baigiasi:

```ts
import { DefaultEgwClientFactory, CitPaymentChannel } from "@tieto/egw-sdk";
import { createServer } from "node:http";
import { randomUUID } from "node:crypto";

const client = new DefaultEgwClientFactory().create({
  baseUri: new URL("https://sandbox.api.ecommerce.sebgroup.com"),
  authentication: {
    tokenEndpoint: new URL("https://api.ecommerce.sebgroup.com/auth/realms/participants-seb/protocol/openid-connect/token"),
    clientId: process.env.EGW_CLIENT_ID!,
    clientSecret: process.env.EGW_CLIENT_SECRET!,
  },
  jwkUri: new URL("https://checkout.ecommerce.sebgroup.com/api/keys/card-encryption.jwk"),
});

const payments = client.payments();
const notifications = client.notifications();

createServer((req, res) => {
  const chunks: Buffer[] = [];
  req.on("data", (c) => chunks.push(c));
  req.on("end", () => {
    res.writeHead(200).end();
    const n = notifications.parseWebhook<{ paymentId: string; paymentStatus: string }>(
      Buffer.concat(chunks)
    );
    console.log(`Mokėjimas ${n.paymentId} → ${n.paymentStatus}`);
  });
}).listen(8080);

try {
  const created = await payments.initiateCitPaymentWithBuilder(randomUUID(), (b) =>
    b.channel(CitPaymentChannel.Browser) // paveiktas atviros enum ydos
     .instructedAmountBuilder((a) => a.amount("100.00").currency("EUR"))
     .orderNumber("ORD-1001")
     .participantId(process.env.EGW_PARTICIPANT_ID!)
     .shopAgreementId(process.env.EGW_SHOP_AGREEMENT_ID!)
     .shopRedirectUrl("https://shop.example.com/return")
     .description("Fishing rod, 2.7 m")
  );
  console.log("Mokėjimas sukurtas:", created.paymentId);

  // ... pirkėjas užbaigia atsiskaitymą; rezultatą sužinote per
  // aukščiau pateiktu webhook galiniu tašku arba periodiškai tikrinant getPaymentInformation().

  const captured = await payments.capturePaymentWithBuilder(
    randomUUID(),
    created.paymentId!,
    (b) => b.instructedAmountBuilder((a) => a.amount("100.00").currency("EUR"))
  );
  console.log("Nurašyta.");
} catch (e) {
  console.error("Mokėjimo eiga nepavyko:", e instanceof Error ? e.message : e);
}
```

## Kiti žingsniai

* [Klaidų tvarkymas](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/gaires/klaidu-valdymas.md) — visa išimčių hierarchija ir rekomendacijos dėl pakartotinio bandymo.
* [Saugumo mechanizmuose](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/gaires/saugumo-mechanizmai.md) — kortelių šifravimas, webhook saugumas.
* [Node.js greitasis pradžiamokslis](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/greitos-pradzios/node.js-typescript.md) — diegimas, prisijungimo duomenys, žinomi apribojimai.


---

# 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-lt/integracija/api-kliento-sdk/naudojant-sdk/node.js-typescript.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.
