> 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/c-.net.md).

# C# / .NET

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

Naudokite šį gidą, jei jau baigėte [C# greito paleidimo vadovas](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/greitos-pradzios/c-.net.md) ir norite sukurti pilną integraciją: sukurti klientą, sudaryti užklausos objektus, kviesti API, apdoroti nesėkmes ir gauti **Webhook'ą (dar vadinamą atgalinio iškvietimo pranešimais)**. A [pilnas pavyzdys](#complete-example) sujungia žingsnius į visumą.

## 1 žingsnis — Sukurkite klientą

Viskas prasideda nuo `DefaultEgwClientFactory`, sklandaus stiliaus gamyklos, kuri sukuria `EgwClient`. Skirtingai nuo Java ir PHP gamyklų, .NET gamykla nieko nepaveldi iš bazinio URL — bazinį URL, prieigos rakto galinį tašką ir (kortelių sesijoms) JWK galinį tašką konfigūruojate aiškiai, bet kuria tvarka:

```csharp
using Egw.Sdk.Application;
using Egw.Sdk.Application.Bootstrap;

using EgwClient client = new DefaultEgwClientFactory()
    .ConnectingTo("https://sandbox.api.ecommerce.sebgroup.com")
    .TokenEndpoint("https://api.ecommerce.sebgroup.com/auth/realms/participants-seb/protocol/openid-connect/token")
    .AuthorizingAs(
        Environment.GetEnvironmentVariable("EGW_CLIENT_ID")!,
        Environment.GetEnvironmentVariable("EGW_CLIENT_SECRET")!)
    .EncryptingWith("https://checkout.ecommerce.sebgroup.com/api/keys/card-encryption.jwk")
    .CreateEgwClient();
```

`ConnectingTo(...)`, `TokenEndpoint(...)` ir `AuthorizingAs(...)` yra būtini; jei trūksta bent vieno, viskas nepavyksta ties `CreateEgwClient()` su `EgwBootstrapException`. `EncryptingWith(...)` reikalingas tik kortelių atsiskaitymo sesijoms, ir `ListeningOn(uri)` įjungia Webhook klausyklą, naudojamą [5 žingsnyje](#step-5--listen-for-webhooks).

Gamyklos modelis leidžia kliento infrastruktūrą pakeisti nekeičiant jūsų programos kodo: adapteriai (HTTP klientas, serializatorius, šifruotojas, registratorius) parenkami per tiekėjų sąsajas (`IApiClientProvider`, `IEgwLoggerProvider`, …), aptinkamas atliekant surinkinio skenavimą, todėl vieną jų pakeičiate pristatydami savo tiekėją — įprastas kelias naudoti pasirinktinius tarpinius serverius, TLS medžiagą arba skirtuosius laikus.

Sukurkite klientą vieną kartą paleidimo metu ir naudokite pakartotinai — juo saugu dalintis, o jo OAuth prieigos raktas yra talpinamas į talpyklą ir automatiškai atnaujinamas. `EgwClient` yra `IDisposable`; `Dispose()` sustabdo webhook klausyklę, todėl jei ją įjungėte, laikykite klientą aktyvų tiek laiko, kiek norite gauti pranešimus.

## 2 žingsnis — Sudarykite užklausos DTO

Užklausos ir atsakymai yra duomenų perdavimo objektai (DTO)  `Egw.Sdk.Application.Dto`. Jos yra nekintamos — tik skaitymui skirtos savybės, jokio viešo konstruktoriaus — ir sudaromos per įdėtą `Builder` klasę, pasiekiamą per statinį `NewBuilder()` metodą. Vienas vardijimo niuansas, kurį verta žinoti iš anksto: `amount` laukelio savybė ir nustatymo metodas vadinami `VarAmount` (JSON laukas perduodant vis dar yra `amount`).

**Klasikinis kūrimo modelis.** Nustatymo metodai pavadinami pagal savybę ir grąžina kūrėją; `Build()` sukuria DTO:

```csharp
using Egw.Sdk.Application.Dto;

Amount amount = Amount.NewBuilder()
    .VarAmount("100.00")
    .Currency("EUR")
    .Build();
```

**Įdėtasis lambda kūrėjas.** Kiekvienai savybei, kuri pati yra DTO, kūrėjas taip pat priima `Func` per įdėtą kūrėją — įdėtą objektą aprašykite tiesiogiai vietoje, užuot kūrę jį atskirai. Lambda gauna naują kūrėją ir turi jį grąžinti:

```csharp
InitiateCitPaymentRequest request = InitiateCitPaymentRequest.NewBuilder()
    .Channel(CitPaymentChannel.BROWSER)
    .InstructedAmount(a => a.VarAmount("100.00").Currency("EUR"))
    .OrderNumber("ORD-1001")
    .ParticipantId(Environment.GetEnvironmentVariable("EGW_PARTICIPANT_ID")!)
    .ShopAgreementId(Environment.GetEnvironmentVariable("EGW_SHOP_AGREEMENT_ID")!)
    .ShopRedirectUrl("https://shop.example.com/return")
    .Build();
```

Abu būdai sukuria identiškus objektus; lambda forma geriausiai skaitosi įdėtoms užklausoms, o klasikinė forma — kai DTO pakartotinai naudojate keliose užklausose. Skaliarinės ir enum savybės turi tik klasikinę formą.

**Vieno elemento pridėjimo metodai.** Kolekcijų savybėms suteikiamas papildomas vieno elemento metodas, kuris prideda vieną įrašą, todėl galite pridėti elementus cikle nevaldydami sąrašo patys:

```csharp
Basket basket = Basket.NewBuilder()
    .Item(BasketItemProduct.NewBuilder()
        .Name("Fishing rod")
        .Description("Carbon fiber rod, 2.7 m")
        .Price(a => a.VarAmount("100.00").Currency("EUR"))
        .Quantity(1)
        .Build())
    .SubtotalAmount(a => a.VarAmount("100.00").Currency("EUR"))
    .Build();
```

**Validacija.** .NET SDK tikrinimo laiku nepatikrina privalomų laukų — skirtingai nuo Java, trūkstamas `OrderNumber` pasireiškia kaip serverio HTTP 400, o ne kaip vietinė išimtis.

## 3 žingsnis — Kviesti API

`EgwClient` sugrupuoja operacijas į srities prieigos metodus: `Payments()`, `Refunds()`, `Tokens()`, `Shops()`, atsiskaitymo sesijų grupėje `CardSessions()`, `BankSessions()`, `TokenSessions()`, `ClickToPaySessions()`, ir `Notifications()` skirta webhookams. Visos operacijos yra asinchroninės ir turi `Async` priesagą — sinchroninių variantų nėra.

Kiekviena operacija kaip pirmąjį argumentą priima `Guid` užklausos ID. Sugeneruokite po vieną kiekvienam kvietimui ir laikykite jį kartu su užsakymo įrašu — tai jūsų sąsajos identifikatorius palaikymui.

Operacijos su užklausos kūnu priima arba jau sukurtą DTO, arba tiesiog lambda kūrėją:

```csharp
// Su paruoštu DTO:
InitiatePaymentResponse created =
    await client.Payments().InitiateCitPaymentAsync(Guid.NewGuid(), request);

// Arba su lambda kūrėju vietoje:
CancelPaymentResponse cancelled = await client.Payments().CancelPaymentAsync(
    Guid.NewGuid(),
    created.PaymentId!,
    b => b.Reason(CancelReason.SUSPECTEDFRAUD));
```

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

```csharp
PaymentInformationResponse info = await client.Payments()
    .GetPaymentInformationAsync(Guid.NewGuid(), created.PaymentId!, false);
Console.WriteLine($"Būsena: {info.PaymentStatus}");

CapturePaymentResponse captured = await client.Payments().CapturePaymentAsync(
    Guid.NewGuid(),
    created.PaymentId!,
    b => b.InstructedAmount(a => a.VarAmount("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 išimtis

Visos SDK nesėkmės paveldi `ECommException`. Pirmiausia gaudykite konkrečius tipus, su kuriais galite veikti, o kaip apsaugos tinklą naudokite: `ECommException` kaip apsaugos tinklą:

```csharp
using Egw.Sdk.Core;
using Egw.Sdk.Application.Ports.ApiClient;

try
{
    InitiatePaymentResponse response =
        await client.Payments().InitiateCitPaymentAsync(Guid.NewGuid(), request);
}
catch (AuthenticationException e)
{
    // Prieigos rakto gavimas arba autorizacija nepavyko — patikrinkite prisijungimo duomenis ir prieigos rakto galinį tašką.
}
catch (ConnectionException e)
{
    // Perdavimo klaida. SDK niekada nebandys pakartotinai: prieš siųsdami iš naujo būseną keičiančią užklausą patikrinkite mokėjimo būseną su
    // GetPaymentInformationAsync(...).
}
catch (ECommException e)
{
    // API atmetė kvietimą (būsenos kodas yra pranešime, pvz.
    // "Client error during InitiateCitPayment: 400") arba atsakymo
    // negalėjo būti apdorotas.
}
```

HTTP klaidų būsenos pateikiamos kaip bazinė `ECommException` su būsenos kodu pranešime; API klaidos detalės įrašomos į SDK registratorių, o ne pridedamos prie išimties ( `ApiException.StatusCode` ir `ResponseBody` prieigos metodai egzistuoja, bet šiame leidime nėra užpildomi). Įjunkite registratorių ir sulyginkite 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 (`SerializationException`, `EncryptionException`, `ApiServerException`, `EgwBootstrapException`, ir visa kita) yra skiltyje [Klaidų tvarkymas](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/gaires/klaidu-valdymas.md).

## 5 žingsnis — Klausykitės webhook'ų

Platforma jus informuoja apie mokėjimo būsenos pokyčius siųsdama POST į jūsų pateiktą galinį tašką. SDK gali paleisti tą galinį tašką už jus: įjunkite klausyklą kliento kūrimo metu su `ListeningOn(...)`, tada užregistruokite tvarkyklę:

```csharp
using EgwClient client = new DefaultEgwClientFactory()
    .ConnectingTo("https://sandbox.api.ecommerce.sebgroup.com")
    .TokenEndpoint("https://api.ecommerce.sebgroup.com/auth/realms/participants-seb/protocol/openid-connect/token")
    .AuthorizingAs(clientId, clientSecret)
    .ListeningOn("http://0.0.0.0:8080/egw/notifications")
    .CreateEgwClient();

client.Notifications().ReceiveNotifications(notification =>
{
    // Atėjo pranešimas: mokėjimas pakeitė būseną. Dabartiniame leidime
    // pranešimo apkrova dar neturi jokių laukų, todėl pristatymą laikykite pabudimo
    // signalu: iš naujo užklauskite savo atvirus mokėjimus naudodami GetPaymentInformationAsync(...)
    // ir atnaujinkite užsakymus pagal API atsakymą.
});
```

`ReceiveNotifications(...)` priima `Action<NotificationRequest>` ir iš karto grąžina; klausyklė toliau siunčia pranešimus foninėse gijose, kol klientas nebus išmestas. Apkrovos prieigos metodai (`tipas`, `paymentId`, `paymentStatus`, kaip perduodama tinkle) bus pateikti vėlesniame leidime — iki tol pirmiau aprašytas pabudimo signalo modelis yra veikiantis kelias.

Visada laikykite pranešimą kaip paleidiklį, o ne kaip tiesą: dabartinis leidimas netikrina įeinančių webhook kvietimų autentiškumo, todėl prieš atnaujindami užsakymą būseną patvirtinkite per API. Perdavimo reikalavimai (įmontuota klausyklė kalba paprastu HTTP — prieš ją užbaikite TLS) aprašyti [Saugumo mechanizmuose](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/gaires/saugumo-mechanizmai.md#webhook-notifications). Du naudojimo taisyklės: sukonfigūruokite `ListeningOn(...)` prieš kviesdami `ReceiveNotifications(...)` (be to kvietimas dabartiniame leidime nepavyks su `NullReferenceException` ), ir kiekvienam klientui užregistruokite tik vieną tvarkytuvę — anuliavimo nėra. Jei jūsų tvarkytuvas išmeta klaidą, SDK atsako HTTP 500 ir SDK pranešimo neperduoda pakartotinai.

## Pilnas pavyzdys

Minimalus visos eigos pavyzdys — sukurkite klientą, klausykitės pranešimų, inicijuokite mokėjimą ir užfiksuokite jį, kai atsiskaitymas baigiasi:

```csharp
using Egw.Sdk.Application;
using Egw.Sdk.Application.Bootstrap;
using Egw.Sdk.Application.Dto;
using Egw.Sdk.Core;

using EgwClient client = new DefaultEgwClientFactory()
    .ConnectingTo("https://sandbox.api.ecommerce.sebgroup.com")
    .TokenEndpoint("https://api.ecommerce.sebgroup.com/auth/realms/participants-seb/protocol/openid-connect/token")
    .AuthorizingAs(
        Environment.GetEnvironmentVariable("EGW_CLIENT_ID")!,
        Environment.GetEnvironmentVariable("EGW_CLIENT_SECRET")!)
    .ListeningOn("http://0.0.0.0:8080/egw/notifications")
    .CreateEgwClient();

try
{
    client.Notifications().ReceiveNotifications(_ =>
        Console.WriteLine("Pranešimas gautas — iš naujo tikrinami atviri mokėjimai."));

    InitiatePaymentResponse created = await client.Payments().InitiateCitPaymentAsync(
        Guid.NewGuid(),
        b => b.Channel(CitPaymentChannel.BROWSER)
              .InstructedAmount(a => a.VarAmount("100.00").Currency("EUR"))
              .OrderNumber("ORD-1001")
              .ParticipantId(Environment.GetEnvironmentVariable("EGW_PARTICIPANT_ID")!)
              .ShopAgreementId(Environment.GetEnvironmentVariable("EGW_SHOP_AGREEMENT_ID")!)
              .ShopRedirectUrl("https://shop.example.com/return")
              .Description("Žvejybos meškerė, 2,7 m"));

    Console.WriteLine($"Mokėjimas sukurtas: {created.PaymentId}");

    // ... pirkėjas užbaigia atsiskaitymą; rezultatą sužinote per
    // pranešimų tvarkytuvą aukščiau arba apklausiant GetPaymentInformationAsync(...).

    CapturePaymentResponse captured = await client.Payments().CapturePaymentAsync(
        Guid.NewGuid(),
        created.PaymentId!,
        b => b.InstructedAmount(a => a.VarAmount("100.00").Currency("EUR")));

    Console.WriteLine("Užfiksuota.");
}
catch (ECommException e)
{
    Console.Error.WriteLine($"Mokėjimo eiga nepavyko: {e.Message}");
}
```

## 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.
* [C# greito paleidimo vadovas](/seb-docs-draft/seb-docs-public-lt/integracija/api-kliento-sdk/greitos-pradzios/c-.net.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/c-.net.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.
