Punkty dostępowe API¶
Konektor udostępnia w sieci lokalnej jeden, wspólny dla wszystkich programów ERP interfejs HTTP/JSON pod ścieżkami /api/v1/*. Ta strona opisuje go dla integratora budującego własnego klienta.
Kontrakt jest celowo identyczny dla wszystkich trzech konektorów. To jedyny powód, dla którego terminal i panel MobiSkan nie wymagają żadnych zmian przy przełączeniu klienta na inny program ERP. Konektor tłumaczy schemat swojego ERP na te struktury, a klient nie wie, z jakim programem rozmawia.
Transport¶
| Element | Wartość |
|---|---|
| Protokół | wyłącznie HTTPS, bez nasłuchu HTTP |
| Port domyślny | 5443 dla Subiekta GT, 5444 dla Subiekta nexo, 5445 dla PC-Marketu |
| Certyfikat | samopodpisany, klient nie weryfikuje łańcucha ani nazwy hosta, tylko przypina odcisk certyfikatu przy pierwszym połączeniu |
| Format | JSON, nazwy pól w notacji camelCase |
| Wartości wyliczeniowe | przesyłane jako liczby, nie jako tekst |
| Zasięg | sieć lokalna, interfejs nie jest przeznaczony do wystawiania w internecie |
Konektor jest osiągany po adresie IP, dlatego nazwa hosta w certyfikacie nie jest weryfikowana. Tożsamości dowodzi przypięty odcisk. Wymiana certyfikatu na maszynie z konektorem wymaga ponownego zaufania po stronie klienta.
Uwierzytelnianie¶
Każde żądanie poza sondą stanu musi nieść nagłówek:
Authorization: Bearer <token parowania>
Token parowania jest współdzielonym sekretem ustalanym przy instalacji konektora. Nie jest tokenem sesji: nie wygasa i nie podlega odnawianiu. Konektor porównuje go w stałym czasie, żeby czas odpowiedzi nie zdradzał kolejnych znaków tokenu.
Dwa świadome wyjątki od tej reguły:
- Sonda stanu nie wymaga tokenu. Terminal musi móc sprawdzić konektor, zanim się z nim sparuje.
- Pusty token w konfiguracji wyłącza uwierzytelnianie w całości. To ułatwienie na czas prac deweloperskich. Instalacja produkcyjna musi mieć token ustawiony, inaczej cały katalog i wszystkie dokumenty są dostępne dla dowolnego hosta w sieci lokalnej bez żadnego uwierzytelnienia.
Nieprawidłowy token skutkuje odpowiedzią 401.
Zestawienie punktów dostępowych¶
Kolumny mówią, który konektor ma daną operację zaimplementowaną.
| Metoda i ścieżka | Do czego | Subiekt GT | Subiekt nexo | PC-Market |
|---|---|---|---|---|
GET /api/v1/health |
sondowanie i parowanie, zwraca rodzaj konektora, identyfikator instalacji, wersję i stan połączenia z bazą ERP | tak | tak | tak |
GET /api/v1/catalog?since=<token> |
katalog towarów, pusty parametr oznacza pełny zrzut, podany token oznacza zmiany od tego punktu | tak | tak | tak |
GET /api/v1/catalog/products/{id}/photo |
zdjęcie główne towaru jako bajty JPEG | tak | nie | nie |
GET /api/v1/business-partners |
kontrahenci, zawsze pełny stan | tak | tak | tak |
GET /api/v1/warehouses |
magazyny, zawsze pełny stan | tak | tak | tak |
GET /api/v1/stock |
stany magazynowe, zawsze pełny stan | tak | tak | tak |
GET /api/v1/documents?type=PZ\|WZ\|MM\|PW\|RW |
dokumenty magazynowe wskazanego typu wraz z pozycjami | tak | tak, bez MM | tak |
GET /api/v1/documents/mm/{id}/warehouses |
para magazynów dokumentu MM | tak | nie | nie |
POST /api/v1/catalog/products |
utworzenie lub aktualizacja towaru w ERP | tak | tak | tak, zawsze niedostępne |
POST /api/v1/documents/complete |
zapis wyniku kompletacji dokumentu | tak | tak | tak, zawsze niedostępne |
Operacja, której dany ERP nie obsługuje, ma swoją ścieżkę i odpowiada kodem 503 z informacją, że jest niedostępna. Nie jest to 404 ani brak ścieżki, ponieważ klient nie odróżniłby tego od zepsutego albo starszego wdrożenia i ponawiałby żądanie bez sensu.
Parametr type jest wymagany przy pobieraniu dokumentów i nie rozróżnia wielkości liter. Inna wartość skutkuje odpowiedzią 400.
Zapytania o kontrahentów, magazyny i stany nie przyjmują żadnych parametrów i zwracają komplet danych. Przyrostowość jest dostępna wyłącznie dla katalogu towarów i tylko wtedy, gdy dany ERP ma czym ją obsłużyć.
Kształt odpowiedzi odczytu¶
Poniżej pola najwyższego poziomu w kolejności, w jakiej występują w kontrakcie.
HealthResult : connectorType, instanceId, version, erpConnected, znacznik czasu UTC
CatalogResult : token, full, products[], deactivated[]
ProductDto : externalId, symbol, name, unitShortName, priceNet, currencyCode,
active, barcodes[], rowVersion, vatExempt, vatRatePercent, attributes{}
BusinessPartnerDto : externalId, nip, companyName, country, address, city, postcode, phone, email
WarehouseDto : externalId, symbol, name, isMain
StockLevelsResult : items[] -> externalProductId, externalWarehouseId, quantity
DocumentsResult : documents[]
DocumentDto : externalId, type, isAutoGenerated, fullNumber, issueDate,
warehouseExternalId, payerPartnerExternalId,
recipientPartnerExternalId, rawStatus, rawStatusBlock, positions[]
DocumentPositionDto : externalId, productExternalId, quantity, unit, warehouseExternalId,
destinationWarehouseExternalId
Dwie zasady utrzymujące ten kontrakt niezależnym od konkretnego ERP:
externalIdjest identyfikatorem w programie ERP, nie w MobiSkan. Klient dopasowuje dane po parze złożonej ze źródła i tego identyfikatora i nigdy nie zakłada jego formatu. W jednym programie to liczba, w innym symbol tekstowy.rowVersionitokenniosą przyrostowość i są dla klienta nieprzezroczyste. Konektor decyduje, co w nich umieści, a klient jedynie zapamiętuje wartość i odsyła ją bez zmian w kolejnym zapytaniu o katalog.
Pola rawStatus i rawStatusBlock niosą surowe kody statusu z programu ERP, celowo nieprzetłumaczone na własną enumerację. Ich znaczenie jest specyficzne dla konkretnego programu i klient nie powinien na nich polegać poza diagnostyką.
Wartości pola type dokumentu: 0 dla PZ, 1 dla WZ, 2 dla MM, 3 dla PW, 4 dla RW.
Zapis: odróżnienie braku możliwości od nieudanej próby¶
To jest najważniejszy element kontraktu dla integratora.
Operacje zapisu nie zgłaszają błędów wyjątkiem ani samym kodem HTTP. Zwracają rekord z trzema polami rozstrzygającymi, co się stało:
| Pole | Znaczenie |
|---|---|
available |
czy ten konektor w ogóle potrafi wykonać tę operację, gdzie false oznacza brak dodatku producenta, brak licencji albo brak mechanizmu zapisu w danym programie ERP |
success |
czy próba zapisu się powiodła |
error |
powód, gdy available albo success ma wartość false |
Odwzorowanie na kody HTTP:
| Sytuacja | Kod | Ciało odpowiedzi |
|---|---|---|
| Zapisano | 200 | available: true, success: true |
| Konektor tego nie potrafi | 503 | available: false wraz z powodem |
| Zapis odrzucony przez ERP | 502 | available: true, success: false wraz z komunikatem |
| Brak wymaganych pól w żądaniu | 400 | komunikat o błędnym żądaniu |
Rozdzielenie sytuacji "ten konektor tego nie potrafi" od "próbowałem i się nie udało" jest częścią kontraktu, a nie szczegółem implementacji. Klient powinien reagować na nie inaczej:
- Przy
503funkcja jest niedostępna trwale dla tej instalacji. Właściwą reakcją jest ukrycie albo wyszarzenie jej w interfejsie, a nie ponawianie próby. Taką odpowiedź daje między innymi konektor PC-Marketu na każdą próbę zapisu towaru oraz konektory Subiekt bez aktywnego dodatku producenta. - Przy
502operacja jest wspierana, ale konkretna próba się nie powiodła. Właściwą reakcją jest pokazanie komunikatu z polaerrori umożliwienie ponowienia.
Gdyby oba przypadki zwracały jeden kod, klient musiałby zgadywać po treści komunikatu.
Ta sama trójstanowa odpowiedź obowiązuje dla zapytania o parę magazynów dokumentu MM.
Żądania zapisu¶
| Operacja | Pola żądania |
|---|---|
| Zapis towaru | symbol, name, opcjonalnie priceLevelName wraz z netPrice (podawane razem albo wcale). Konektor Subiekt nexo nie obsługuje ceny i dodatkowo przyjmuje opcjonalne supplierNip |
| Zapis wyniku kompletacji | type, documentExternalId oraz positions[] z polami positionExternalId i completedQuantity, a dodatkowo opcjonalne requestId |
Odpowiedź na zapis towaru niesie poza polami rozstrzygającymi także created, mówiące czy towar powstał, czy został zaktualizowany, oraz externalId rekordu w ERP.
Odpowiedź na zapis kompletacji niesie fullyCompleted oraz differentialDocumentExternalId. Przy pełnej zgodności ilości nic nie jest zapisywane, fullyCompleted ma wartość true, a identyfikator dokumentu różnicowego pozostaje pusty. Przy kompletacji częściowej powstaje nowy dokument różnicowy, a jego identyfikator wraca w tym polu.
Pole requestId jest kluczem powtórzenia. Klient, który ponawia wysyłkę po przekroczeniu limitu oczekiwania, wysyła przy każdej próbie tę samą wartość, a konektor odsyła wtedy wynik pierwszego zapisu zamiast tworzyć w programie ERP kolejny dokument różnicowy. Odpowiedź na powtórzenie jest nieodróżnialna od pierwszej. Pole pozostaje opcjonalne ze względu na starsze wersje aplikacji, ale każdy klient, który ponawia żądania, powinien je wysyłać.
Pozycja, której positionExternalId nie ma odpowiednika w dokumencie źródłowym, jest błędem 502 i nic nie zostaje zapisane w programie ERP. Taka rozbieżność oznacza, że dokument zmieniono w programie ERP już po pobraniu go przez klienta, więc ciche pominięcie takiej pozycji gubiłoby skompletowany towar.
Wysyłanie danych z konektora do panelu¶
Poza opisanym wyżej odpytywaniem konektor sam wysyła katalog i dokumenty magazynowe do panelu MobiSkan WMS. Jest to jednak powierzchnia serwera panelu, a nie konektora, i nie należy do interfejsu opisanego na tej stronie.
Wymagania wobec nowego klienta¶
Minimum, żeby własny klient działał z konektorem:
- Obsłuż sondę stanu bez tokenu oraz pobranie katalogu z tokenem. To wystarcza do sparowania i pierwszej synchronizacji.
- Zachowaj wielkość liter w nazwach pól - JSON jest w notacji camelCase.
- Traktuj
tokenkatalogu jako ciąg nieprzezroczysty i odsyłaj go bez zmian. - Rozróżniaj
503od502przy operacjach zapisu. - Przypnij odcisk certyfikatu przy pierwszym połączeniu i odrzucaj inny certyfikat pod tym samym adresem.