Klasyczna integracja z SAP zaczyna się od zdefiniowania interfejsów: dla każdej funkcji powstaje klasa, a do niej struktury i mapowanie pól. Przy kilku funkcjach to działa. Przy kilkudziesięciu każda zmiana parametru w SAP oznacza regenerację kodu i nowe wydanie aplikacji magazynowej.
Studio WMS.net wywołuje funkcje SAP dynamicznie, z kodu w JavaScript albo C#, przy użyciu narzędzia SAP Connector. Programista podaje nazwę funkcji i parametry, a wynik odbiera jako zbiór nazwanych wartości. Poniżej opisano ten model, sposób testowania połączenia, przejście z SOAP oraz zasady, które chronią dynamiczne wywołania przed nadużyciem. Dobór funkcji według procesu, w tym księgowanie i zatwierdzanie, zawiera osobny tekst o odczycie i wykonywaniu funkcji w systemie SAP.
Statyczne mapowanie interfejsu a wywołanie dynamiczne
Wywołanie dynamiczne przenosi opis funkcji z czasu kompilacji do czasu działania. Aplikacja nie zna z góry struktury parametrów, tylko pobiera ją z SAP tuż przed użyciem albo trzyma w pamięci podręcznej. Różnice widać najlepiej przy zmianie funkcji po stronie SAP i przy dodawaniu nowej.
| Cecha | Klasy generowane z interfejsu | Wywołanie dynamiczne |
|---|---|---|
| opis funkcji | zapisany w kodzie w czasie kompilacji | odczytany z SAP w czasie działania |
| nowy parametr w SAP | regeneracja klas i nowe wydanie | dopisanie pola w słowniku parametrów |
| kontrola typów | przez kompilator | przez walidację metadanych przed wysłaniem |
| nowa funkcja w aplikacji | nowa klasa i nowa metoda | nazwa funkcji na liście dozwolonych |
| ryzyko | wolniejsze zmiany | wywołanie niezamierzonej funkcji |
Reguła: elastyczność wywołania dynamicznego wymaga listy dozwolonych funkcji. Aplikacja, która przyjmuje dowolną nazwę funkcji z żądania, pozwala każdemu użytkownikowi uruchomić w SAP wszystko, na co ma uprawnienia konto komunikacyjne.
Odczyt interfejsu funkcji w locie
SAP Connector pozwala odczytać parametry funkcji w locie: programista pobiera listę parametrów, wypełnia je danymi z aplikacji i wywołuje zdalną funkcję bez pisania rozbudowanej konfiguracji. Opis interfejsu zawiera dla każdego parametru cztery informacje, które aplikacja wykorzystuje do walidacji.
- Nazwa i kierunek - wskazanie, czy parametr jest wejściowy, wyjściowy, zmieniany czy tabelą.
- Typ i długość - typ danych ABAP oraz maksymalna długość pola, także dla pól struktur.
- Obowiązkowość - informacja, czy funkcja odrzuci wywołanie bez tego parametru.
- Wartość domyślna - wartość, którą SAP przyjmie po stronie serwera, gdy pole pozostanie puste.

Typy ABAP i typy po stronie klienta
Opis interfejsu podaje typ ABAP każdego pola, a konektor przekłada go na typ używany w aplikacji. Kilka par powtarza się w prawie każdej funkcji magazynowej i każda ma swoją pułapkę.
| Typ ABAP | Zawartość | Typ po stronie C# | Pułapka |
|---|---|---|---|
| CHAR | tekst o stałej długości | string | spacje na końcu pola nie są częścią wartości |
| NUMC | cyfry zapisane jako tekst | string | zera wiodące są istotne, więc nie wolno zamieniać na liczbę |
| DATS | data w postaci RRRRMMDD | DateTime | wartość 00000000 oznacza brak daty |
| QUAN, CURR | liczba dziesiętna z jednostką lub walutą | decimal | typ double wprowadza błędy zaokrągleń przy ilościach ułamkowych |
Wywołanie z kodu w C# i JavaScript
Biblioteka obsługuje różne środowiska programistyczne. Programiści pracujący w C# integrują funkcje SAP z aplikacjami serwerowymi i desktopowymi, a piszący w JavaScript korzystają z nich w aplikacjach webowych. Przeglądarka nigdy nie łączy się z SAP bezpośrednio: żądanie idzie do serwera aplikacji, który trzyma dane logowania konta komunikacyjnego.
C# po stronie serwera
Warstwa serwerowa jest właściwym miejscem na listę dozwolonych funkcji oraz walidację parametrów z limitem czasu. Fragment poniżej pokazuje jej szkielet; interfejs ISapClient jest umowny i nie pochodzi z konkretnej biblioteki.
public sealed class SapGateway
{
private static readonly HashSet<string> Allowed = new(StringComparer.OrdinalIgnoreCase)
{
"BAPI_MATERIAL_AVAILABILITY",
"BAPI_WHSE_STOCK_GET_LIST"
};
private readonly ISapClient _client;
public SapGateway(ISapClient client) => _client = client;
public IReadOnlyDictionary<string, object> Call(
string function, IDictionary<string, object> parameters, TimeSpan timeout)
{
if (!Allowed.Contains(function))
throw new InvalidOperationException("Funkcja spoza listy dozwolonych: " + function);
var meta = _client.DescribeFunction(function); // Import, Export, Changing, Tables
foreach (var name in parameters.Keys)
{
if (!meta.HasParameter(name))
throw new ArgumentException("Nieznany parametr: " + name);
}
using var cts = new CancellationTokenSource(timeout);
return _client.Invoke(function, parameters, cts.Token);
}
}
JavaScript po stronie przeglądarki
Kod w przeglądarce wysyła żądanie asynchroniczne, więc ekran operatora nie blokuje się na czas odpowiedzi SAP. Wywołanie Fetch API zwraca obietnicę, a kod obsługi sprawdza status HTTP i komunikaty typu E oraz A z tabeli RETURN. Adres punktu końcowego w przykładzie jest umowny.
async function readAvailability(material, plant) {
const response = await fetch('/api/sap/call', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
function: 'BAPI_MATERIAL_AVAILABILITY',
parameters: { MATERIAL: material, PLANT: plant }
})
});
if (!response.ok) {
throw new Error('Wywołanie SAP nie powiodło się: ' + response.status);
}
const result = await response.json();
const errors = (result.RETURN || []).filter(m => m.TYPE === 'E' || m.TYPE === 'A');
return { result, errors };
}
Przy operacjach zapisu dodaje się jeszcze identyfikator operacji generowany w przeglądarce, żeby podwójne kliknięcie albo ponowienie po utracie sieci nie wysłało tego samego ruchu dwa razy. Serwer odrzuca powtórzony identyfikator, zanim żądanie dotrze do SAP.
Odpowiedź może zawierać błędy na dwóch poziomach i aplikacja rozróżnia je od razu. Błąd techniczny, na przykład brak połączenia, przekroczenie limitu czasu albo nieistniejąca funkcja, kończy się wyjątkiem i pozwala ponowić wywołanie. Błąd biznesowy, na przykład brak materiału w SAP, przychodzi w tabeli RETURN jako komunikat typu E i wymaga poprawy danych, a ponowienie nic nie da.
Testowanie połączenia i autoryzacji w SAP RFC Connector
Konfiguracja połączenia najczęściej zawodzi już na etapie testowania: od błędnych danych logowania po nieprawidłową trasę sieciową. Wbudowany test w SAP RFC Connector sprawdza adres serwera i port, a także identyfikator użytkownika z hasłem oraz pośrednictwo przez SapRouter; przy błędzie wskazuje przyczynę bez sięgania do zewnętrznych logów. Pełną listę parametrów, wraz z konfiguracją middleware, zawiera strona o połączeniu aplikacji z systemem SAP.
| Test | Co sprawdza | Typowa przyczyna niepowodzenia |
|---|---|---|
| adres serwera i port | osiągalność serwera aplikacyjnego SAP z serwera WMS | zapora lub port z numerem innej instancji (33NN) |
| dane logowania | konto komunikacyjne oraz mandant z językiem sesji | nieprawidłowe hasło albo literówka w numerze mandanta |
| SapRouter | poprawność ciągu trasy przez router | brak wpisu na liście dozwolonych połączeń routera |
| autoryzacja funkcji | prawo do wywołania danej funkcji i struktury | rola bez obiektu S_RFC dla grupy funkcji |
Po nawiązaniu połączenia sprawdza się dostęp do funkcji i struktur. Gdy konto nie ma uprawnień, komunikat pojawia się od razu, a błąd wychodzi na jaw na etapie wdrożenia, a nie po uruchomieniu produkcyjnym. Szczegółowe dane techniczne narzędzia opisuje strona SAP Connector w serwisie produktowym.
Integracja korzysta z osobnego konta z rolą ograniczoną do wywoływanych funkcji. Konto osobiste administratora nie nadaje się do tego celu, bo ślad audytowy w SAP przestaje odróżniać wywołania aplikacji od pracy człowieka.
Konwersja zapytań SOAP na wywołania SAP Connector
Wiele firm nadal komunikuje się z SAP przez SOAP. Protokół ma swoje zalety, ale każda zmiana wywołania wymaga pracy z komunikatem XML i definicją usługi. Wywołanie przez konektor redukuje tę pracę do nazwy funkcji i słownika parametrów.
Co upraszcza się po przejściu z SOAP
Komunikat SOAP ma postać koperty XML z nagłówkiem i treścią, opisanej kontraktem WSDL, zgodnie ze specyfikacją SOAP 1.2 organizacji W3C. Programista buduje ją ręcznie albo generuje klasy z WSDL. Konektor zastępuje to wywołaniem metody z parametrami i zwraca odpowiedź bez pisania kodu obsługującego niskopoziomowe szczegóły protokołu.
| Element | Wywołanie przez SOAP | Wywołanie przez SAP Connector |
|---|---|---|
| komunikat | koperta XML z nagłówkiem i treścią | nazwa funkcji i słownik parametrów |
| kontrakt | plik WSDL wymagający aktualizacji przy zmianie | opis interfejsu funkcji pobierany z SAP |
| typy danych | schemat XML mapowany na typy klienta | typy ABAP mapowane na typy .NET lub JavaScript |
| diagnostyka | odpowiedź typu Fault | tabela RETURN oraz wyjątek biblioteki |
Migracja etapami bez przestoju aplikacji
Przejście nie wymaga jednorazowej przebudowy architektury. Firma przenosi wywołania pojedynczo i porównuje wyniki z dotychczasową ścieżką, aż przestaje znajdować różnice.
- Inwentarz wywołań - lista funkcji wywoływanych dziś przez SOAP wraz z częstością użycia.
- Pierwsza funkcja - przepisanie jednej funkcji odczytowej, bo błąd odczytu nie zmienia danych w SAP.
- Praca równoległa - wysyłanie żądania obiema ścieżkami i porównanie odpowiedzi w dzienniku.
- Wyłączenie SOAP - wycofanie starej ścieżki dla funkcji, dla której wyniki zgadzały się przez ustalony okres.
Reguła: funkcje zapisujące przenosi się dopiero po odczytowych, a każde wywołanie zapisujące dostaje identyfikator operacji, żeby praca równoległa nie utworzyła dwóch dokumentów.
Funkcje z poziomu WMS a funkcje wywoływane bezpośrednio w SAP
Przed wyborem sposobu integracji rozstrzyga się, które czynności wykonuje się w magazynie, a które pozostają w SAP. Zestawienie porządkuje najczęstsze przypadki.
| Obszar działania | Z poziomu WMS | Bezpośrednio w SAP |
|---|---|---|
| aktualizacja stanów magazynowych | automatyczna po każdej operacji na hali | wymaga ręcznego wglądu w moduł MM |
| wywołanie funkcji RFC | dynamiczne, z kodu aplikacji | przez transakcje i raporty ABAP |
| dokumenty magazynowe | generowane w interfejsie WMS | przez odrębne transakcje SAP |
| test połączenia i autoryzacji | wbudowany mechanizm SAP RFC Connector | konfiguracja po stronie administratora SAP |
Wynik operacji na hali trafia do SAP od razu po jej zamknięciu, więc stany magazynowe w obu systemach zgadzają się bez okresowej synchronizacji wsadowej. Dokumenty powstają w miejscu, gdzie pracuje operator, a operacje magazynowe nie wymagają przełączania się na ekrany SAP GUI.
Przykład wywołania funkcji odczytowej w praktyce
Poniższy scenariusz pokazuje przebieg od strony programisty, który pracuje przy wdrożeniu systemu WMS zintegrowanego z SAP. Aplikacja WMS wywołuje funkcję RFC, która zwraca stan magazynowy indeksu materiałowego.
Kod w JavaScript ustawia parametry wejściowe (numer materiału i magazyn), przekazuje je do SAP Connector, a potem odczytuje z odpowiedzi bieżący stan wraz z jednostką miary i lokalizacją składowania. Nie powstaje dodatkowa warstwa pośrednia ani ręczne mapowanie struktur RFC.

Operator na terminalu czeka na odpowiedź, więc odczyt wywołuje się synchronicznie i z krótkim limitem czasu. Zapis, który może potrwać dłużej, warto zakolejkować w bazie WMS i potwierdzać asynchronicznie, a ekran operatora pokazuje wtedy status oczekiwania zamiast blokować pracę. Podział na te dwa tryby ustala się osobno dla każdej funkcji.
Ten sam mechanizm obsługuje wywołanie zwrotne: potwierdzenie wydania towaru w SAP zaraz po zamknięciu zlecenia w zintegrowanym systemie magazynowym. Obie strony pracują na tych samych, aktualnych danych, bez opóźnień wynikających z paczkowej synchronizacji. Warianty pośrednie, na przykład kolejkę IDoc dla dużych wolumenów, porównuje tekst o integracji WMS z SAP, a architekturę z pośrednikami opisuje strona integracja z SAP.
Utrzymanie wywołań dynamicznych po zmianach w SAP
Wywołanie dynamiczne zdejmuje z programisty regenerację klas, ale nie zdejmuje odpowiedzialności za zmiany po stronie SAP. Aktualizacja wersji albo modyfikacja funkcji przez konsultanta zmienia interfejs bez ostrzeżenia dla aplikacji, więc potrzebne są cztery mechanizmy kontrolne, które zestawia poniższa lista.
- Pamięć podręczna metadanych - opis interfejsu odświeżany po zmianie wersji SAP albo według harmonogramu, a nie przy każdym wywołaniu.
- Dziennik wywołań - nazwa funkcji oraz czas odpowiedzi, a także typ komunikatu RETURN, dostępne do analizy po błędzie.
- Limity czasu i sesji - ograniczenie liczby równoległych sesji RFC oraz czasu oczekiwania na odpowiedź.
- Test po aktualizacji - zestaw wywołań kontrolnych uruchamiany na środowisku testowym po każdej zmianie w SAP.
Wraz z dziennikiem warto śledzić rozkład czasów odpowiedzi, bo wolna funkcja odczytowa bywa pierwszym sygnałem, że po stronie SAP pojawiła się blokada albo brakuje indeksu. Przy przejściu na nowszą wersję SAP część funkcji bywa oznaczona jako przestarzała albo zastąpiona inną, dlatego zestaw wywołań kontrolnych obejmuje każdą funkcję z listy dozwolonych. Jeśli aplikacja ma obsługiwać wiele systemów SAP, każde połączenie dostaje własny profil, a środowisko testowe różni się od produkcyjnego numerem mandanta. Szerszy kontekst rozwiązań integracyjnych, także dla aplikacji spoza magazynu, opisuje strona o integracji aplikacji webowych.




