> 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-et/integratsioon/api-kliendi-sdk/juhendid/sdk-adapterite-asendamine.md).

# SDK adapterite asendamine

Asendage SDK taristuadapterid natiivsete HTTP, logimise, serialiseerimise, krüptimise ja webhooki rakendustega.

Kasuta seda juhendit, kui soovid asendada ühe SDK sisseehitatud adapteritest — suuna HTTP omaenda kliendi kaudu, saada SDK diagnostika oma logiraamistikku, vaheta JSON-seriaalija või asenda testides port stub'iga.

See [SDK arhitektuur](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/juhendid/arhitektuur-ja-laiendatavus.md) see leht selgitab pordi‑ja‑adapterite disaini ning loetleb viis porti ja nende vaikimisi adapterid. See leht on praktiline järelteema: millist hooba tõmmata ja täpne süntaks iga keele jaoks.

## Kuidas ülekirjutamine toimib

Iga keel pakub samu kolme hooba, samas eelistusjärjekorras:

1. **Anna tehasele (või `EgwClienti` konstruktorile) valmis eksemplar.** Selgesõnaliselt antud adapter võidab alati — tehas langeb varuga tagasi avastamisele nende portide puhul, mille sa jätsid määramata. See on kõige otsem ja deterministlikum tee ning õige valik ühekordsete asenduste jaoks.
2. **Registreeri pakkuja SDK teenusepakkuja liidese (SPI) mehhanismi kaudu.** A *pakkuja* on väike tehaseobjekt, mis teab, kuidas sinu adapterit ehitada; SDK alglaadimine avastab selle ja kasutab seda igal pool, kus klient luuakse. Mõiste SPI pärineb Java maailmast, kuid SDK rakendab seda kontseptsiooni kõigis neljas keeles — iga SDK hoiab oma pakkujalepinguid spetsiaalses `spi` nimeruumis, mille avastab sellele platvormile omane viis. Kui tead klassikalist .NET pakkujamudelit, Laraveli teenusepakkujaid või Angulari/NestJSi sõltuvussüstimise pakkujaid, siis on see sama idee. See on õige tee siis, kui ülekirjutus on üle kogu virna kehtiv poliitika ("kõik selle teenuse EGW kliendid logivad Serilogi kaudu") mitte eksemplaripõhine valik.
3. **Laienda klienditehast.** Tehased järgivad template-method mustrit: üks ülekirjutatav `newXxx()` loomismeetod iga pordi kohta (Java/PHP). Alamklassimine annab sulle täieliku kontrolli konstruktsiooni üle, puudutamata SPI-d üldse.

See *mehhanism* taga on see koht, kus keeled erinevad, kasutades kumbki oma platvormile omast idiomi. Mine otse oma keele juurde:

* [**Java**](#java) — `ServiceLoader` avastamine, registreeritud läbi `META-INF/services` faili
* [**PHP**](#php) — liidese ja klassi kaart failis `providers.php` mille annad tehasele
* [**C#**](#c) — assamblaaži skannimine; klassi deklareerimine *on* registreerimine
* [**Node.js / TypeScript**](#nodejs) — selgesõnaline `registerProvider()` kutsung

Üks asümmeetria, mida Java ja PHP puhul teada: tehas pakub API kliendi, API serveri ja logija jaoks selgesõnalisi settereid, kuid seriaalija ja andmekrüpteerija luuakse alati SPI kaudu — nende kahe asendamiseks kasuta 2. hooba või 3. hooba.

## Java

* **Avastus** — `java.util.ServiceLoader`
* **Registreerimine** — `META-INF/services/<provider FQN>` faili või JPMS `provides` lausel
* **Kui mitu pakkujat vastavad** — esimene classpath'il võidab

Alglaadimine on `DefaultEgwClientFactory`, mis lahendab iga pordi kaudu `java.util.ServiceLoader` vastandades pakkujaliidestega failis `...sdk.application.bootstrap.spi`: `ApiClientProvider`, `ApiServerProvider`, `DataEncrypterProvider`, `SerializerProvider`, ja `EgwLoggerProvider`.

**1. hoob — tehase settereid.** `connectingWith(ApiClient)`, `listeningWith(ApiServer)`, ja `loggingWith(EgwLogger)` aktsepteerivad valmis eksemplare:

```java
var client = new DefaultEgwClientFactory()
        .connectingTo(baseApiUri)
        .authorizingAs(System.getenv("EGW_CLIENT_ID"), System.getenv("EGW_CLIENT_SECRET"))
        .loggingWith(new Slf4jEgwLogger(LoggerFactory.getLogger("egw-sdk")))
        .createEgwClient();
```

**2. hoob — ServiceLoaderi pakkuja.** Rakenda pakkujaliidest avaliku ilmaargumendilise konstruktoriga, seejärel registreeri see `META-INF/services`Logija on kõige puhtam SPI sihtmärk — SDK-ga ei tule kaasa ühtegi `EgwLoggerProvider` oma registreeringut, nii et sinu oma leitakse ilma konkurentsita:

```java
public final class Slf4jEgwLoggerProvider implements EgwLoggerProvider {
    @Override
    public EgwLogger create() {
        return new Slf4jEgwLogger(LoggerFactory.getLogger("egw-sdk"));
    }
}
```

```
# src/main/resources/META-INF/services/com.tieto.banking.egw.merchantapi.sdk.application.bootstrap.spi.EgwLoggerProvider
com.example.shop.egw.Slf4jEgwLoggerProvider
```

Ülejäänud nelja pordi puhul registreerib SDK oma pakkujad core JAR-is, nii et sinu oma konkureerib classpathil esikoha nimel, mitte ei asenda midagi — SPI registreering ei ole seal garanteeritud ülekirjutus. Nende puhul eelista 1. või 3. hooba.

**3. hoob — tehase alamklass.** `DefaultEgwClientFactory` on laiendatav; ülekirjuta `newXxx()` meetod pordi jaoks, mida soovid asendada. See on usaldusväärne viis seriaalija või krüpteerija asendamiseks:

```java
public class ShopEgwClientFactory extends DefaultEgwClientFactory {
    @Override
    protected Serializer newSerializer() {
        return new ShopJsonbSerializer();
    }
}
```

## PHP

* **Avastus** — pakkujate konfiguratsioonifail
* **Registreerimine** — liidese → klassi kaart failis `providers.php` mille annad tehasele
* **Kui mitu pakkujat vastavad** — ei saa juhtuda; kaart sisaldab ühe kirje iga pordi kohta

Alglaadimine loeb liidese ja klassi kaardi tavalisest PHP konfiguratsioonifailist. Pakkujaliidesed asuvad `...\Application\Bootstrap\Spi`: `ApiClientProviderInterface`, `ApiServerProviderInterface`, `DataEncrypterProviderInterface`, `SerializerProviderInterface`, `EgwLoggerProviderInterface`.

**1. hoob — tehase settereid.** Sama kuju nagu Java-s (`connectingWith()`, `listeningWith()`, `loggingWith()`):

```php
$client = (new DefaultEgwClientFactory())
    ->connectingTo($baseApiUri)
    ->authorizingAs(getenv('EGW_CLIENT_ID'), getenv('EGW_CLIENT_SECRET'))
    ->loggingWith(new Psr3EgwLogger($psrLogger))
    ->createEgwClient();
```

**2. hoob — sinu enda providers'i fail.** Kopeeri SDK `config/providers.php`, asenda kirjed, mida soovid muuta, ja anna faili tee tehase konstruktorile. Ära muuda faili sees `vendor/` — vaikimisi tee lahendab sinna, ja Composer kirjutab selle üle:

```php
<?php // config/egw-providers.php
// SPI-liideste, pakendatud pakkujate ja sinu pakkujate use-laused on välja jäetud

return [
    ApiClientProviderInterface::class => GuzzleHttpClientProvider::class,
    ApiServerProviderInterface::class => ReactPhpHttpServerProvider::class,
    DataEncrypterProviderInterface::class => WebTokenDataEncrypterProvider::class,
    SerializerProviderInterface::class => ShopJsonSerializerProvider::class,   // sinu ülekirjutus
    EgwLoggerProviderInterface::class => Psr3EgwLoggerProvider::class,         // sinu ülekirjutus
];
```

```php
$factory = new DefaultEgwClientFactory(__DIR__ . '/config/egw-providers.php');
```

Pakkuja on klass avaliku ilmaargumendilise konstruktoriga, mis rakendab liidest:

```php
final class ShopJsonSerializerProvider implements SerializerProviderInterface
{
    public function create(EgwLoggerInterface $logger): SerializerInterface
    {
        return new ShopJsonSerializer();
    }
}
```

**3. hoob — tehase alamklass.** Laienda `DefaultEgwClientFactory` (või `AbstractEgwClientFactory`) ja ülekirjuta asjakohane `newXxx()` meetod, täpselt nagu Java-s.

## C\#

* **Avastus** — assambleede skannimine (reflektsiooni abil laaditud assambleede üle)
* **Registreerimine** — mitte midagi; lihtsalt deklareeri avalik klass, mis rakendab pakkujaliidest
* **Kui mitu pakkujat vastavad** — esimene assamblee laadimisjärjekorras võidab

Alglaadimine skannib praeguse `AppDomaini` laaditud assambleesid konkreetsete klasside jaoks, mis rakendavad pakkujaliideseid nimeruumis `Egw.Sdk.Application.Bootstrap.Spi`: `IApiClientProvider`, `IApiServerProvider`, `IDataEncrypterProvider`, `ISerializerProvider`, `IEgwLoggerProvider`. Ei ole midagi registreerida — klassi deklareerimine on registreerimine. Pakkujad instantseeritakse reflektsiooni kaudu, seega vajavad nad avalikku ilma parameetriteta konstruktorit.

Logija on taas kõige puhtam SPI sihtmärk, sest SDK-ga ei tule kaasa ühtegi vaikimisi `IEgwLoggerProvider`:

```csharp
public sealed class SerilogEgwLoggerProvider : IEgwLoggerProvider
{
    public IEgwLogger Create() => new SerilogEgwLogger(Log.Logger);
}
```

Kaks praktilist märget. Skannimine näeb ainult assambleesid, mis on juba AppDomaini laaditud — kui sinu pakkuja asub assamblees, mida veel miski ei ole puudutanud, siis laadi see enne kliendi loomist jõuga (viita mõnele selle tüübile). Ja nende portide puhul, mille jaoks SDK tarnib vaikimisi pakkuja, konkureerib sinu oma assamblee laadimise järjekorras esimese koha nimel, mitte ei asenda midagi — see ei ole garanteeritud ülekirjutus.

Garanteeritud ülekirjutus C#-is on otsene konstrueerimine — `EgwClienti`'i konstruktor võtab kõik viis porti:

```csharp
var apiClient = new HttpApiClient(myHttpClient, authentication, logger); // sinu enda HttpClient eksemplar
using var client = new EgwClient(
    baseUri, apiClient, apiServer: null,
    new JoseDataEncrypter(apiClient, jwkEndpoint, logger),
    new JsonSerializer(logger),
    logger);
```

Pane tähele esimest rida: `HttpApiClient` võtab vastu süstitud `HttpClient`, nii et saad rakendada oma käsitlejaid, aegumisi ja puhverserveri seadeid ilma porti üldse rakendamata.

## Node.js

Kehtib nii JavaScripti kui TypeScripti puhul.

* **Avastus** — mitte ühtegi; selgesõnaline register
* **Registreerimine** — kutsu `registerProvider({...})` enne kliendi loomist
* **Kui mitu pakkujat vastavad** — viimane registreering võidab

JS SDK-s puudub kaudne avastus — registreerimine on selgesõnaline kutse, mis sobib platvormi moodulipõhise idiomiga. Registris on ühe pordi kohta üks pakkuja, ja `registerProvider()` võtab osalise objekti vastu ja liidab selle, nii et ülekirjutad ainult selle, mida nimetad:

```ts
// Alpha märkus: süvaimport seni, kuni registerProvider eksporditakse paketi juurtest — vt allpool
import { registerProvider } from "@tieto/egw-sdk/dist/application/bootstrap/spi/ProviderRegistry.js";

registerProvider({
  loggerProvider: { create: () => new PinoEgwLogger(pino()) }
});

const client = new DefaultEgwClientFactory().create({
  baseUri: new URL("https://sandbox-api.example.com/merchant"),
  authentication: {
    tokenEndpoint: new URL(process.env.EGW_TOKEN_ENDPOINT!),
    clientId: process.env.EGW_CLIENT_ID!,
    clientSecret: process.env.EGW_CLIENT_SECRET!
  },
  jwkUri: new URL(process.env.EGW_JWK_URI!)
});
```

Pakkujad on tavalised objektliteraalid, millel on `create()` meetod — sulud, mitte klassid — seega ei vaja konfiguratsiooni andmine adapterisse mingit tseremooniat. Kutsu `registerProvider()` enne tehase loomist; SDK registreerib oma vaikimisi väärtused siis, kui tehase moodul laaditakse, ja sinu hilisem registreering asendab need võtme kaupa.

Praeguses alfaversioonis, `registerProvider` ei ekspordita veel paketi juurkohast, seega vajab see süvaimporti SDK `ProviderRegistry` moodulist — vt [Node.js-i kiirjuhendi teadaolevad piirangud](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/kiirstardid/node.js-typescript.md).

Otsene konstrueerimine toimib samuti — `EgwClienti`'i konstruktor võtab kõik viis porti, ja `AxiosApiClient` võtab vastu süstitud `AxiosInstance` (kolmas konstruktoriparameeter) sinu interceptoreid, aegumisi ja puhverserveri konfiguratsiooni jaoks.

## Seotud lehed

* [SDK arhitektuur](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/juhendid/arhitektuur-ja-laiendatavus.md) — pordi‑ja‑adapterite disain, viis porti ja nende vaikimisi adapterid
* [Ülevaade](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/ulevaade.md) — keelte maatriks, paketid, alfaolek
* [Vigade käsitlemine](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/juhendid/vigade-kasitlemine.md) — `ECommException` hierarhia, milles teie adapterid osalevad
* [Turvamehhanismid](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/juhendid/turvamehhanismid.md) — mida adapter peab järgima (märgikäsitlus, JWE, logide maskeerimine)
* Keelepõhised kiirkäivitused: [Java](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/kiirstardid/java.md) · [PHP](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/kiirstardid/php.md) · [C#](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/kiirstardid/c-.net.md) · [Node.js](/seb-docs-draft/seb-docs-public-et/integratsioon/api-kliendi-sdk/kiirstardid/node.js-typescript.md)


---

# 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-et/integratsioon/api-kliendi-sdk/juhendid/sdk-adapterite-asendamine.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.
