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

# C# / .NET

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

Izmantojiet šo ceļvedi, ja esat pabeidzis [C# ātrais sākums](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/atrie-sakumi/c-.net.md) un vēlaties izveidot pilnvērtīgu integrāciju: izveidot klientu, sastādīt pieprasījuma objektus, izsaukt API, apstrādāt kļūmes un saņemt **Webhook (saukts arī par atpakaļizsaukuma paziņojumiem)**. Pilns [piemērs](#complete-example) saliek soļus kopā.

## 1. solis — izveidojiet klientu

Viss sākas ar `DefaultEgwClientFactory`, ķēdējamu rūpnīcu, kas no jūsu savienojuma iestatījumiem izveido `EgwClient`. Atšķirībā no Java un PHP fabrikām, .NET fabrika neko neizvada no bāzes URL — bāzes URL, tokena galapunktu un (karšu sesijām) JWK galapunktu konfigurējat skaidri, jebkurā secībā:

```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(...)` un `AuthorizingAs(...)` ir obligāti; ja trūkst kaut viena, izsaukums neizdodas pie `CreateEgwClient()` ar `EgwBootstrapException`. `EncryptingWith(...)` ir vajadzīgs tikai karšu apmaksas sesijām, un `ListeningOn(uri)` iespējo Webhook klausītāju, ko izmanto [5. solis](#step-5--listen-for-webhooks).

Fabrikas paraugs ļauj klienta infrastruktūru aizstāt, nemainot lietotnes kodu: adapteri (HTTP klients, serializētājs, šifrētājs, žurnāla rakstītājs) tiek atrasti, izmantojot nodrošinātāja saskarnes (`IApiClientProvider`, `IEgwLoggerProvider`, …), kas tiek atrastas, skenējot komplektāciju, tāpēc vienu no tām varat aizstāt, piegādājot savu nodrošinātāju — ierastais ceļš pielāgotiem starpniekserveriem, TLS materiālam vai taimautiem.

Izveidojiet klientu vienreiz palaišanas laikā un izmantojiet atkārtoti — to ir droši koplietot, un tā OAuth tokens tiek kešots un automātiski atjaunināts. `EgwClient` ir `IDisposable`; `Dispose()` aptur tīmekļa āķa klausītāju, tāpēc, ja to aktivizējāt, turiet klientu aktīvu tik ilgi, cik vēlaties saņemt paziņojumus.

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

Pieprasījumi un atbildes ir datu pārsūtīšanas objekti (DTO) pakotnē `Egw.Sdk.Application.Dto`. Tās ir nemainīgas — tikai lasāmi īpašumi, nav publiska konstruktora — un tiek veidotas, izmantojot ligzdotu `veidotājs` klasi, kurai piekļūst, izmantojot statisko `NewBuilder()` metodi. Viena nosaukšanas īpatnība, ko zināt jau sākumā: `amount` lauka īpašums un iestatītājs tiek saukti `VarAmount` (JSON lauks pārraidē joprojām ir `amount`).

**Klasiskais būvētājs.** Iestatītāji ir nosaukti pēc īpašuma un atgriež veidotāju; `Build()` izveido DTO:

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

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

**Ligzdotais lambda veidotājs.** Katram īpašumam, kas pats ir DTO, veidotājs arī pieņem `Func` virs ligzdotā veidotāja — aprakstiet ligzdoto objektu tieši kodā, nevis veidojiet to atsevišķi. Lambda saņem jaunu veidotāju un tam jāatgriež tas:

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

Abi stili rada identiskus objektus; lambda forma vislabāk lasās ligzdotiem pieprasījumiem, bet klasiskā forma — ja DTO atkārtoti izmantojat vairākos pieprasījumos. Skalārajiem un uzskaitījuma tipa īpašumiem ir tikai klasiskā forma.

**Atsevišķa vienuma pievienotāji.** Kolekciju īpašumiem ir papildu metode viena elementa pievienošanai, lai varētu pievienot vienumus ciklā, pašam nepārvaldot sarakstu:

```csharp
Basket basket = Basket.NewBuilder()
    .Item(BasketItemProduct.NewBuilder()
        .Name("Makšķere")
        .Description("Oglekļa šķiedras makšķerkāts, 2,7 m")
        .Price(a => a.VarAmount("100.00").Currency("EUR"))
        .Quantity(1)
        .Build())
    .SubtotalAmount(a => a.VarAmount("100.00").Currency("EUR"))
    .Build();
```

**Validācija.** .NET SDK būvēšanas laikā nepārbauda obligātos laukus — atšķirībā no Java, trūkstošs `OrderNumber` izpaužas kā HTTP 400 servera pusē, nevis kā lokāls izņēmums.

## 3. solis — izsauciet API

`EgwClient` grupē darbības domēna piekļuves metodēs: `Payments()`, `Refunds()`, `Tokens()`, `Shops()`, checkout-session grupas `CardSessions()`, `BankSessions()`, `TokenSessions()`, `ClickToPaySessions()`, un `Notifications()` tīmekļa āķiem. Visas darbības ir asinhronas un tām ir `Async` piedēklis — sinhronu variantu nav.

Katra darbība kā pirmo argumentu pieņem `Guid` pieprasījuma ID. Ģenerējiet vienu katram izsaukumam un glabājiet to kopā ar pasūtījuma ierakstu — tas ir jūsu korelācijas identifikators atbalstam.

Darbības ar pieprasījuma saturu pieņem vai nu jau izveidotu DTO, vai arī tieši veidotāja lambda:

```csharp
// Ar sagatavotu DTO:
InitiatePaymentResponse created =
    await client.Payments().InitiateCitPaymentAsync(Guid.NewGuid(), request);

// Vai arī ar iekļautu veidotāja lambda:
CancelPaymentResponse cancelled = await client.Payments().CancelPaymentAsync(
    Guid.NewGuid(),
    created.PaymentId!,
    b => b.Reason(CancelReason.SUSPECTEDFRAUD));
```

Stāvokļa nolasīšana un maksājuma ieturēšana pēc norēķinu pabeigšanas:

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

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

Aiz katra izsaukuma SDK iegūst un kešo OAuth 2.0 piekļuves tokenu, iestata `X-Request-ID` galveni, serializē pieprasījumu un deserializē atbildi tipizētā atbildes DTO.

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

Visas SDK kļūmes manto `ECommException`. Vispirms noķeriet konkrētos izņēmumu tipus, uz kuriem varat reaģēt, un `ECommException` kā drošības tīklu:

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

try
{
    InitiatePaymentResponse response =
        await client.Payments().InitiateCitPaymentAsync(Guid.NewGuid(), request);
}
catch (AuthenticationException e)
{
    // Tokena izgūšana vai autorizācija neizdevās — pārbaudiet akreditācijas datus un tokena galapunktu.
}
catch (ConnectionException e)
{
    // Pārsūtīšanas kļūme. SDK nekad neveic atkārtotus mēģinājumus: pārbaudiet maksājuma stāvokli ar
    // GetPaymentInformationAsync(...) pirms atkārtotas stāvokli mainoša izsaukuma nosūtīšanas.
}
catch (ECommException e)
{
    // API noraidīja izsaukumu (statusa kods ir ziņojumā, piemēram,
    // "Klienta kļūda InitiateCitPayment laikā: 400") vai atbildes
    // nevarēja tikt apstrādāta.
}
```

HTTP kļūdu statusi parādās kā bāzes `ECommException` ar statusa kodu ziņojumā; API kļūdas detaļas tiek ierakstītas SDK žurnālā, nevis pievienotas izņēmumam ( `ApiException.StatusCode` un `ResponseBody` piekļuves metodes pastāv, bet šajā būvē nav aizpildītas). Ieslēdziet žurnālu un korelējiet pēc `X-Request-ID` — skatiet [API kļūdu lasīšana](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md#reading-api-errors). Pilnā hierarhija (`SerializationException`, `EncryptionException`, `ApiServerException`, `EgwBootstrapException`, un pārējais) atrodas [Kļūdu apstrāde](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md).

## 5. solis — klausieties Webhook paziņojumus

Platforma jūs informē par maksājuma stāvokļa izmaiņām, nosūtot POST pieprasījumu uz jūsu publicētu galapunktu. SDK šo galapunktu var palaist jūsu vietā: klienta izveides laikā ieslēdziet klausītāju ar `ListeningOn(...)`, pēc tam reģistrējiet apstrādātāju:

```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 =>
{
    // Paziņojums saņemts: maksājums mainījis stāvokli. Pašreizējā būvē
    // paziņojuma slodze vēl neeksponē laukus, tāpēc piegādi uztveriet kā pamošanās
    // signālu: atkārtoti vaicājiet atvērtajiem maksājumiem, izmantojot GetPaymentInformationAsync(...)
    // un atjauniniet pasūtījumus, balstoties uz API atbildi.
});
```

`ReceiveNotifications(...)` pieņem `Action<NotificationRequest>` un atgriež rezultātu uzreiz; klausītājs turpina piegādāt paziņojumus fona pavedienos, līdz klients tiek atbrīvots. Slodzes piekļuves metodes (`type`, `paymentId`, `paymentStatus`, kā tās tiek piegādātas pārraidē), būs pieejamas vēlākā būvē — līdz tam darbojas iepriekš minētais pamošanās signāla modelis.

Vienmēr uztveriet paziņojumu kā trigeri, nevis kā patiesību: pašreizējā būvē ienākošo tīmekļa āķu izsaukumu autentiskums netiek pārbaudīts, tāpēc pirms pasūtījuma atjaunināšanas apstipriniet stāvokli caur API. Pārsūtīšanas prasības (iebūvētais klausītājs runā parastu HTTP — TLS jāpabeidz priekšā tam) ir aplūkotas [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: konfigurējiet `ListeningOn(...)` pirms izsaukšanas `ReceiveNotifications(...)` (bez tā izsaukums neizdodas ar `NullReferenceException` pašreizējā būvē), un reģistrējiet tieši vienu apstrādātāju uz klientu — atcelšanas nav. Ja jūsu apstrādātājs met izņēmumu, SDK atbild ar HTTP 500 un paziņojums SDK netiek piegādāts atkārtoti.

## Pilns piemērs

Minimāls pilna cikla plūsmas piemērs — izveidojiet klientu, klausieties paziņojumus, iniciējiet maksājumu un iekasējiet to, kad apmaksa ir pabeigta:

```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("Saņemts paziņojums — atkārtoti pārbaudu atvērtos maksājumus.");

    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("Makšķere, 2,7 m");

    Console.WriteLine($"Izveidots maksājums: {created.PaymentId}");

    // ... pircējs pabeidz norēķinus; rezultātu uzzināsiet, izmantojot
    // vai, aptaujājot GetPaymentInformationAsync(...).

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

    Console.WriteLine("Iekasēts.");
}
catch (ECommException e)
{
    Console.Error.WriteLine($"Maksājuma plūsma neizdevās: {e.Message}");
}
```

## Nākamie soļi

* [Kļūdu apstrāde](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/kludu-apstrade.md) — pilnu izņēmumu hierarhiju un atkārtotas mēģināšanas norādes.
* [Drošības mehānika](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/celvezi/drosibas-mehanismi.md) — karšu šifrēšanu un webhook drošību.
* [C# ātrais sākums](/seb-docs-draft/seb-docs-public-lv/integracija/api-klienta-sdk/atrie-sakumi/c-.net.md) — instalēšanu, akreditācijas datus un zināmos ierobežojumus.


---

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