rufen method
Einen Endpunkt rufen. null-Werte in params fallen weg, damit das
Backend "nicht gesetzt" nicht als ausdrueckliche Angabe missversteht.
Implementation
Future<Map<String, dynamic>> rufen(
String name, {
Map<String, dynamic> params = const <String, dynamic>{},
}) async {
final nutzlast = <String, dynamic>{};
params.forEach((schluessel, wert) {
if (wert != null) nutzlast[schluessel] = wert;
});
// Ausserhalb des try: ein nicht serialisierbarer Parameter ist ein
// Programmierfehler und keine Netzstoerung.
final String rumpf = jsonEncode(<String, dynamic>{'params': nutzlast});
final http.Response antwort;
try {
antwort = await _http
.post(
Uri.parse('$baseUrl/$name'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'Bearer $_schluessel',
},
body: rumpf,
)
.timeout(_frist);
} on TimeoutException catch (e) {
// Getrennt vom Netzfehler: die Anfrage war draussen, der Ausgang ist
// unbekannt. Ueber `createPartnerCustomer` kann der Betrieb laengst
// angelegt sein -- mit `idempotencyKey` ist die Wiederholung dann
// folgenlos, ohne ihn nicht.
throw KasseneckHttpError(name, 0, KasseneckHttpError.zeitablauf, causeType: '${e.runtimeType}');
} on Object catch (e) {
// Nur der Typ, nie die Meldung: die kann eine Adresse tragen. Der
// Schluessel faehrt in der Kopfzeile und ist davon nicht betroffen.
throw KasseneckHttpError(name, 0, KasseneckHttpError.netz, causeType: '${e.runtimeType}');
}
Object? roh;
try {
roh = jsonDecode(antwort.body);
} on FormatException {
// Typischer Fall: der Aufruf landete mangels Weiterleitung auf der
// HTML-Seite -- HTTP 200, aber kein JSON.
throw KasseneckHttpError(name, antwort.statusCode, 'not-json');
}
if (roh is! Map) throw KasseneckHttpError(name, antwort.statusCode, 'missing-status');
final huelle = Map<String, dynamic>.from(roh);
if (huelle['status'] == 'success') {
final daten = huelle['data'];
if (daten == null) return <String, dynamic>{};
if (daten is! Map) throw KasseneckHttpError(name, antwort.statusCode, 'data-not-object');
return Map<String, dynamic>.from(daten);
}
final meldung = huelle['message'];
// Die Beilage wird gesiebt und nicht durchgereicht -- flach, klein,
// bezeichner-foermig benannt, und kein Wert, der mit dem gesendeten
// Schluessel ueberlappt (siehe fehlerDetails).
final details = fehlerDetails(huelle['data'], <String>[_schluessel]);
final code = details['code'];
throw KasseneckApiError(
name,
meldung is String && meldung.isNotEmpty ? meldung : 'Der Aufruf ist fehlgeschlagen.',
code: code is String && RegExp(r'^[A-Za-z][A-Za-z0-9_./-]{0,63}$').hasMatch(code) ? code : null,
details: details,
);
}