OBS/Kostenpflichtige Module/RESTServer/Beispiel4: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
Keine Bearbeitungszusammenfassung |
Keine Bearbeitungszusammenfassung |
||
| (Eine dazwischenliegende Version desselben Benutzers wird nicht angezeigt) | |||
| Zeile 38: | Zeile 38: | ||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> | ||
// Hilfsfunktion: ein Feld aus dem JSON-Body als String lesen. | |||
// Generics gibt es im Skript nicht - oBody.TryGetValue<string>(...) laesst sich | |||
// nicht uebersetzen. GetValue liefert nil, wenn das Feld fehlt. | |||
function _BodyStr(oBody: TJSONObject; const cFeld: string): string; | |||
var oVal: TJSONValue; | |||
begin | |||
result := ''; | |||
if (oBody = nil) then begin | |||
exit; | |||
end; | |||
oVal := oBody.GetValue(cFeld); | |||
if (Assigned(oVal)) then begin | |||
result := oVal.Value; | |||
end; | |||
end; | |||
// Hilfsfunktion: ein Auftrag als JSON-Objekt | // Hilfsfunktion: ein Auftrag als JSON-Objekt | ||
function _OrderAsJSON(qOrder: TqSQL): TJSONObject; | function _OrderAsJSON(qOrder: TqSQL): TJSONObject; | ||
| Zeile 59: | Zeile 75: | ||
' WHERE au_status <> ' + DB_SQLVal('9') + | ' WHERE au_status <> ' + DB_SQLVal('9') + | ||
' ORDER BY au_nr'; | ' ORDER BY au_nr'; | ||
if (DB_SOpen( | if (DB_SOpen(oDB, cSql, qData)) then begin | ||
while (not qData.EoF) do begin | while (not qData.EoF) do begin | ||
oArr.Add(_OrderAsJSON(qData)); | oArr.Add(_OrderAsJSON(qData)); | ||
| Zeile 73: | Zeile 89: | ||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> | ||
//------------------------------------------------------------------------------ | |||
// Hilfsfunktion: Fehlerantwort im einheitlichen Format aufbauen. | |||
// Fachliche Ablehnungen als 4xx melden, nicht als 200 mit Fehlertext. | |||
//------------------------------------------------------------------------------ | |||
function _Fehler(oParams: TStrings; nStatus: integer; const cCode, cMsg: string): string; | |||
var oRes: TJSONObject; | |||
oErr: TJSONObject; | |||
begin | |||
oErr := TJSONObject.Create(); | |||
oErr.AddPair('code' , cCode); | |||
oErr.AddPair('message', cMsg); | |||
oErr.AddPair('traceId', oParams.Values['_OBS_TRACE_ID']); | |||
oRes := TJSONObject.Create(); | |||
try | |||
oRes.AddPair('_OBS_HTTP_STATUS', nStatus); | |||
oRes.AddPair('error', oErr); | |||
result := oRes.ToJSON(); | |||
finally | |||
MyFreeAndNil(oRes); | |||
end; | |||
end; | |||
function _OrderAsJSON(qOrder: TqSQL): TJSONObject; | function _OrderAsJSON(qOrder: TqSQL): TJSONObject; | ||
begin | begin | ||
| Zeile 91: | Zeile 131: | ||
cUid := oParams.Values['_OBS_PATH_uid']; | cUid := oParams.Values['_OBS_PATH_uid']; | ||
if (cUid = '') then begin | if (cUid = '') then begin | ||
result := ' | result := _Fehler(oParams, 422, 'VALIDATION_FAILED', 'Pfad-Parameter "uid" fehlt'); | ||
exit; | exit; | ||
end; | end; | ||
cSql := 'SELECT * FROM auftraege WHERE sys_uid = ' + DB_SQLVal(cUid); | cSql := 'SELECT * FROM auftraege WHERE sys_uid = ' + DB_SQLVal(cUid); | ||
if (DB_SOpen( | if (DB_SOpen(oDB, cSql, qData)) and (not qData.EoF) then begin | ||
result := _OrderAsJSON(qData).ToJSON(); | result := _OrderAsJSON(qData).ToJSON(); | ||
end else begin | end else begin | ||
result := ' | result := _Fehler(oParams, 404, 'NOT_FOUND', 'Auftrag nicht gefunden'); | ||
end; | end; | ||
end; | end; | ||
| Zeile 107: | Zeile 147: | ||
<syntaxhighlight lang="pascal"> | <syntaxhighlight lang="pascal"> | ||
//------------------------------------------------------------------------------ | |||
// Hilfsfunktion: Fehlerantwort im einheitlichen Format aufbauen. | |||
// Fachliche Ablehnungen als 4xx melden, nicht als 200 mit Fehlertext. | |||
//------------------------------------------------------------------------------ | |||
function _Fehler(oParams: TStrings; nStatus: integer; const cCode, cMsg: string): string; | |||
var oRes: TJSONObject; | |||
oErr: TJSONObject; | |||
begin | |||
oErr := TJSONObject.Create(); | |||
oErr.AddPair('code' , cCode); | |||
oErr.AddPair('message', cMsg); | |||
oErr.AddPair('traceId', oParams.Values['_OBS_TRACE_ID']); | |||
oRes := TJSONObject.Create(); | |||
try | |||
oRes.AddPair('_OBS_HTTP_STATUS', nStatus); | |||
oRes.AddPair('error', oErr); | |||
result := oRes.ToJSON(); | |||
finally | |||
MyFreeAndNil(oRes); | |||
end; | |||
end; | |||
function Put(oParams: TStrings; oBody: TJSONObject): string; | function Put(oParams: TStrings; oBody: TJSONObject): string; | ||
var cUid : string; | var cUid : string; | ||
| Zeile 119: | Zeile 183: | ||
cCode := oParams.Values['_OBS_PATH_code']; | cCode := oParams.Values['_OBS_PATH_code']; | ||
if (cUid = '') or (cCode = '') then begin | if (cUid = '') or (cCode = '') then begin | ||
result := ' | result := _Fehler(oParams, 422, 'VALIDATION_FAILED', 'Pfad-Parameter "uid" oder "code" fehlt'); | ||
exit; | exit; | ||
end; | end; | ||
// Nutzdaten kommen aus dem JSON-Body | // Nutzdaten kommen aus dem JSON-Body | ||
cStatus := | cStatus := _BodyStr(oBody, 'status'); | ||
if (cStatus = '') then begin | if (cStatus = '') then begin | ||
result := ' | result := _Fehler(oParams, 422, 'VALIDATION_FAILED', 'Feld "status" fehlt'); | ||
exit; | exit; | ||
end; | end; | ||
| Zeile 137: | Zeile 198: | ||
' WHERE am_auftrag = ' + DB_SQLVal(cUid) + | ' WHERE am_auftrag = ' + DB_SQLVal(cUid) + | ||
' AND am_code = ' + DB_SQLVal(cCode); | ' AND am_code = ' + DB_SQLVal(cCode); | ||
if (not DB_SOpen( | if (not DB_SOpen(oDB, cSql, qChk)) or (qChk.EoF) then begin | ||
result := ' | result := _Fehler(oParams, 404, 'NOT_FOUND', 'Modul nicht gefunden'); | ||
exit; | exit; | ||
end; | end; | ||
// Update | // Update | ||
xMod := qSqlRead( | xMod := qSqlRead(oDB, 'auftrag_module', | ||
'am_auftrag = ' + DB_SQLVal(cUid) + | 'am_auftrag = ' + DB_SQLVal(cUid) + | ||
' AND am_code = ' + DB_SQLVal(cCode)); | ' AND am_code = ' + DB_SQLVal(cCode)); | ||
Aktuelle Version vom 18. August 2026, 07:03 Uhr
Internet-Shop
Der modified ECommerce Shop
Shop-Menü
- A Preise aktualisieren
- C Personen übertragen
- E Kategorien verwalten
- G Kataloge verwalten
- I Merkliste übertragen
- K Varianten übertragen
- L Artikelvarianten übertragen
- M Referenzarten übertragen
- N Lagerbestände verwalten
- U Bestellungen einlesen
- V leere Passworte füllen
- W Update-Informationen zurücksetzen
- X Konfiguration
- Z Protokoll
Automatische Vorgänge
Preislisten
ZUGFeRD
Factoring
UPS
IMS Professional
SMS
Mehrlager-Verwaltung
Mehrsprachen Modul
Multilanguage Modul
Einfache Produktionsnachverfolgung
DMS - Dokumenten Management System
DMS Dokumente
Tasten und Schaltflächen
F10 Weit.
QR Zeiterfassung
EVA Marketing Tool
Technikersteuerung
Termin-Projekte
Edifact-Schnittstelle
Backup Überwachung Email
Anlagenbuchhaltung
OBS Geo Daten
DeliSprint / DPD
Filialen
Auto-Waagen
Cashback
Moebelschnittstelle
Tourenplanung
Dokumenten Manager
DocuWare-Schnittstelle
OFML-Kalkulation
Pascom
Versicherungsschaden
Gutschriftsanzeigen
OCPP Ladestationen
Kameraverwaltung
DataInOut
REST-Schnittstelle
Sammelverträge
Craftboxx
OpenMasterData / IDS
Sammelpositionen
KI-Mining
Beispiel 4 – Pfad-Parameter (REST-Routing über Templates)
Dieses Beispiel zeigt das Pfad-Template-Routing mit Platzhaltern. Eine Auftrags-Ressource wird über drei Endpunkte abgebildet:
| Methode + Pfad | Zweck |
|---|---|
GET /orders |
Liste aller offenen Aufträge |
GET /orders/{uid} |
Einzelner Auftrag per UID |
PUT /orders/{uid}/modules/{code} |
Status eines Auftrags-Moduls ändern |
Die Platzhalter {uid} und {code} stehen im Skript als
oParams.Values['_OBS_PATH_uid'] bzw.
oParams.Values['_OBS_PATH_code'] zur Verfügung.
Einrichtung in OBS
- Server-Profil: Standard-TLS-Profil Public-API auf
0.0.0.0:443. - Zugang: Orders-Client mit API-Key, Zugriff auf die drei Endpunkte.
- Endpunkte (je ein Eintrag in
RESTSRV_ENDPOINTS, alle Profil Public-API):
| Endpunkt | Pfad-Template | Skript-Methode |
|---|---|---|
orders |
/orders |
Get (Liste)
|
orders |
/orders/{uid} |
Get (Einzel)
|
orders |
/orders/{uid}/modules/{code} |
Put
|
Endpunkt-Skript 1: GET /orders (Liste)
// Hilfsfunktion: ein Feld aus dem JSON-Body als String lesen.
// Generics gibt es im Skript nicht - oBody.TryGetValue<string>(...) laesst sich
// nicht uebersetzen. GetValue liefert nil, wenn das Feld fehlt.
function _BodyStr(oBody: TJSONObject; const cFeld: string): string;
var oVal: TJSONValue;
begin
result := '';
if (oBody = nil) then begin
exit;
end;
oVal := oBody.GetValue(cFeld);
if (Assigned(oVal)) then begin
result := oVal.Value;
end;
end;
// Hilfsfunktion: ein Auftrag als JSON-Objekt
function _OrderAsJSON(qOrder: TqSQL): TJSONObject;
begin
result := TJSONObject.Create();
result.AddPair('uid' , qOrder.A2UID());
result.AddPair('nr' , qOrder.A2C('au_nr'));
result.AddPair('kunde' , qOrder.A2C('au_kunde'));
result.AddPair('status' , qOrder.A2C('au_status'));
result.AddPair('aenderung', DTToSQL(qOrder.A2D('au_aend_dat')));
end;
function Get(oParams: TStrings; oBody: TJSONObject): string;
var cSql : string;
qData: TqSQL;
oArr : TJSONArray;
begin
oArr := TJSONArray.Create();
cSql := 'SELECT * FROM auftraege' +
' WHERE au_status <> ' + DB_SQLVal('9') +
' ORDER BY au_nr';
if (DB_SOpen(oDB, cSql, qData)) then begin
while (not qData.EoF) do begin
oArr.Add(_OrderAsJSON(qData));
qData.Next();
end;
end;
result := oArr.ToJSON();
end;Endpunkt-Skript 2: GET /orders/{uid} (Einzel)
//------------------------------------------------------------------------------
// Hilfsfunktion: Fehlerantwort im einheitlichen Format aufbauen.
// Fachliche Ablehnungen als 4xx melden, nicht als 200 mit Fehlertext.
//------------------------------------------------------------------------------
function _Fehler(oParams: TStrings; nStatus: integer; const cCode, cMsg: string): string;
var oRes: TJSONObject;
oErr: TJSONObject;
begin
oErr := TJSONObject.Create();
oErr.AddPair('code' , cCode);
oErr.AddPair('message', cMsg);
oErr.AddPair('traceId', oParams.Values['_OBS_TRACE_ID']);
oRes := TJSONObject.Create();
try
oRes.AddPair('_OBS_HTTP_STATUS', nStatus);
oRes.AddPair('error', oErr);
result := oRes.ToJSON();
finally
MyFreeAndNil(oRes);
end;
end;
function _OrderAsJSON(qOrder: TqSQL): TJSONObject;
begin
result := TJSONObject.Create();
result.AddPair('uid' , qOrder.A2UID());
result.AddPair('nr' , qOrder.A2C('au_nr'));
result.AddPair('kunde' , qOrder.A2C('au_kunde'));
result.AddPair('status' , qOrder.A2C('au_status'));
result.AddPair('aenderung', DTToSQL(qOrder.A2D('au_aend_dat')));
end;
function Get(oParams: TStrings; oBody: TJSONObject): string;
var cUid : string;
cSql : string;
qData: TqSQL;
begin
// Pfad-Parameter aus /orders/{uid}
cUid := oParams.Values['_OBS_PATH_uid'];
if (cUid = '') then begin
result := _Fehler(oParams, 422, 'VALIDATION_FAILED', 'Pfad-Parameter "uid" fehlt');
exit;
end;
cSql := 'SELECT * FROM auftraege WHERE sys_uid = ' + DB_SQLVal(cUid);
if (DB_SOpen(oDB, cSql, qData)) and (not qData.EoF) then begin
result := _OrderAsJSON(qData).ToJSON();
end else begin
result := _Fehler(oParams, 404, 'NOT_FOUND', 'Auftrag nicht gefunden');
end;
end;Endpunkt-Skript 3: PUT /orders/{uid}/modules/{code}
//------------------------------------------------------------------------------
// Hilfsfunktion: Fehlerantwort im einheitlichen Format aufbauen.
// Fachliche Ablehnungen als 4xx melden, nicht als 200 mit Fehlertext.
//------------------------------------------------------------------------------
function _Fehler(oParams: TStrings; nStatus: integer; const cCode, cMsg: string): string;
var oRes: TJSONObject;
oErr: TJSONObject;
begin
oErr := TJSONObject.Create();
oErr.AddPair('code' , cCode);
oErr.AddPair('message', cMsg);
oErr.AddPair('traceId', oParams.Values['_OBS_TRACE_ID']);
oRes := TJSONObject.Create();
try
oRes.AddPair('_OBS_HTTP_STATUS', nStatus);
oRes.AddPair('error', oErr);
result := oRes.ToJSON();
finally
MyFreeAndNil(oRes);
end;
end;
function Put(oParams: TStrings; oBody: TJSONObject): string;
var cUid : string;
cCode : string;
cStatus: string;
cSql : string;
qChk : TqSQL;
xMod : TqSQL;
begin
// Beide Pfad-Parameter
cUid := oParams.Values['_OBS_PATH_uid'];
cCode := oParams.Values['_OBS_PATH_code'];
if (cUid = '') or (cCode = '') then begin
result := _Fehler(oParams, 422, 'VALIDATION_FAILED', 'Pfad-Parameter "uid" oder "code" fehlt');
exit;
end;
// Nutzdaten kommen aus dem JSON-Body
cStatus := _BodyStr(oBody, 'status');
if (cStatus = '') then begin
result := _Fehler(oParams, 422, 'VALIDATION_FAILED', 'Feld "status" fehlt');
exit;
end;
// Existenzpruefung
cSql := 'SELECT * FROM auftrag_module' +
' WHERE am_auftrag = ' + DB_SQLVal(cUid) +
' AND am_code = ' + DB_SQLVal(cCode);
if (not DB_SOpen(oDB, cSql, qChk)) or (qChk.EoF) then begin
result := _Fehler(oParams, 404, 'NOT_FOUND', 'Modul nicht gefunden');
exit;
end;
// Update
xMod := qSqlRead(oDB, 'auftrag_module',
'am_auftrag = ' + DB_SQLVal(cUid) +
' AND am_code = ' + DB_SQLVal(cCode));
xMod.qSet('am_status', cStatus);
xMod.SaveData(UPDATE_RECORD);
qSqlFree(xMod);
result := '{"status":"ok"}';
end;Test mit curl
# Liste
curl -H "apikey: GEHEIM123" https://api.meinserver.de/orders
# Einzelner Auftrag (uid als Pfad-Parameter)
curl -H "apikey: GEHEIM123" https://api.meinserver.de/orders/4711
# Modul-Status aendern (uid + code als Pfad-Parameter, status im Body)
curl -X PUT \
-H "apikey: GEHEIM123" \
-H "Content-Type: application/json" \
-d '{"status":"21"}' \
https://api.meinserver.de/orders/4711/modules/A1Was dieses Beispiel zeigt
- Eine Ressource, mehrere Pfad-Formen über getrennte Endpunkt-Einträge mit eigenem Skript und eigener Berechtigung.
- Pfad-Parameter werden über
{name}im Template erfasst und im Skript alsoParams.Values['_OBS_PATH_name']gelesen. - Reihenfolge der Skript-Parameter:
oParamszuerst,oBodydanach (umgekehrt zur internen Dispatch-Reihenfolge). - Präzedenz: ein statisches Segment (z. B.
/orders/summary) hätte Vorrang vor/orders/{uid}.