@kreiseck/kasseneck-api 0.9.3 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/cjs/kasse/settings.d.ts +10 -2
  3. package/dist/cjs/kasse/settings.js +10 -2
  4. package/dist/cjs/payments/hobex-hps/index.d.ts +2 -2
  5. package/dist/cjs/payments/hobex-hps/index.js +36 -1
  6. package/dist/cjs/payments/hobex-hps/outcome.d.ts +20 -1
  7. package/dist/cjs/payments/hobex-hps/outcome.js +11 -0
  8. package/dist/cjs/payments/hobex-hps/payments.d.ts +19 -0
  9. package/dist/cjs/payments/hobex-hps/payments.js +160 -33
  10. package/dist/cjs/payments/hobex-hps/transaction-response.d.ts +180 -31
  11. package/dist/cjs/payments/hobex-hps/transaction-response.js +308 -88
  12. package/dist/cjs/payments/index.d.ts +1 -1
  13. package/dist/cjs/payments/index.js +8 -1
  14. package/dist/esm/kasse/settings.d.ts +10 -2
  15. package/dist/esm/kasse/settings.js +10 -2
  16. package/dist/esm/payments/hobex-hps/index.d.ts +2 -2
  17. package/dist/esm/payments/hobex-hps/index.js +2 -2
  18. package/dist/esm/payments/hobex-hps/outcome.d.ts +20 -1
  19. package/dist/esm/payments/hobex-hps/outcome.js +10 -0
  20. package/dist/esm/payments/hobex-hps/payments.d.ts +19 -0
  21. package/dist/esm/payments/hobex-hps/payments.js +161 -34
  22. package/dist/esm/payments/hobex-hps/transaction-response.d.ts +180 -31
  23. package/dist/esm/payments/hobex-hps/transaction-response.js +302 -87
  24. package/dist/esm/payments/index.d.ts +1 -1
  25. package/dist/esm/payments/index.js +1 -1
  26. package/fixtures/hobex-hps-codes.json +365 -15
  27. package/fixtures/kasse-settings-standard.json +1 -1
  28. package/fixtures/kasse-texte.json +1 -1
  29. package/fixtures/oberflaeche.json +2 -1
  30. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,68 @@ Was vor 0.7.0 geschah, steht in der Commit-Historie (`git log`); ab hier wird
4
4
  es hier geführt. Ein Eintrag nennt die Änderung **und ihren Grund** —
5
5
  nur der Grund überlebt den nächsten Umbau.
6
6
 
7
+ ## 0.10.0
8
+
9
+ ### Die Antwortcodeliste von hobex — jeder Code eingeordnet, jeder Ausgang mit Grund
10
+
11
+ **Anlass:** hobex hat am 11.09.2026 die Antwortcodeliste der HPS-Anwendung
12
+ geschickt. Drei der Codes kamen seit dem 28.08.2026 im Betrieb vor (`100004`,
13
+ `100005`, `100015`) und waren bis jetzt ungedeutet. Jede Zahlung damit lief in
14
+ die Klaerung und endete erst ueber die Zwei-9027-Regel. Zwilling:
15
+ `kasseneck_api` 6.9.0, Begruendungen dort in `doc/kartenzahlung.md`.
16
+
17
+ - **`HPS_CODES`** fuehrt alle 31 Codes der Liste zusammen mit den gemessenen:
18
+ Code, hobex-Titel, Bedeutung, Wirkung (`effect`), Grund (`reason`) und
19
+ Quelle (`source`). `isConclusive` liest seine Positivliste daraus.
20
+ `HPS_MEASURED_CODES` bleibt als abgekuendigter Name fuer dieselbe Tabelle.
21
+ - **Was vor dem Host scheitert, ist eine Ablehnung** (Kartenlesen, EMV-Kernel,
22
+ Eingaben am Geraet, Geraetezustand, fehlerhafte Anfrage) -- `declined`, ohne
23
+ Abbruch und ohne Statusabfrage. Dazu `100029`: das Terminal storniert laut
24
+ hobex selbst.
25
+ - **Neu: `effect: 'hostUncertain'`** (`isHostUncertain`) fuer `100006`,
26
+ `100007`, `100023`, `100024`, `100026`, `100027`, `100999`. Der Host war
27
+ beteiligt, das Terminal storniert nicht selbst. Die Zwei-9027-Regel greift
28
+ hier **nicht**; die Klaerung endet nach zwei Abfragen ohne Neues als
29
+ `unresolved`, nur ein `'0'` entscheidet danach noch, und ein Abbruchversuch
30
+ entfaellt. Bei einer Aufhebung entscheidet ein unveraendertes `'0'` auf die
31
+ Originalzahlung dann ebenfalls nichts.
32
+ - **`rejectsRequest` / `isConclusiveAsStatus`:** zehn Codes weisen die Anfrage
33
+ selbst ab (`9002`, `100001`, `100008`, `100108`, `100009`, `100010`,
34
+ `100013`, `100018`, `100022`, `100998`). Auf eine Zahlung sind sie deren
35
+ Ablehnung, auf eine Statusabfrage sagen sie nichts ueber den gesuchten
36
+ Vorgang (gemessen fuer `100108`). Die Klaerung liest den Status deshalb
37
+ ueber `isConclusiveAsStatus` -- sonst haette ein gesperrtes Terminal eine
38
+ verlorene Zahlung als "nicht belastet" ausgewiesen.
39
+ - **`HpsPaymentResult.reason`** traegt fuer jeden Ausgang den Grund, den Satz
40
+ fuer den Bediener gibt `HPS_REASON_HINTS`. Gesetzt, wo entschieden wurde:
41
+ bestaetigter Abbruch `aborted`, HTTP 409 `terminalBusy`, eine ueber die
42
+ Zwei-9027-Regel geklaerte Zahlung mit dem Grund ihres eigenen Codes.
43
+ `isHostUncertainResult` sagt einer spaeteren Nachfrage, dass ein `9027` dort
44
+ nicht "nicht belastet" heisst.
45
+ - `hpsCodeInfo`, `hpsCodeReason` und die Namen aller neuen Codes
46
+ (`CARD_READ_FAILED_CODE` usw.) sind exportiert.
47
+ - Der Nachweis nennt bei einer Ablehnung den hobex-Titel mit
48
+ (`Terminal: abgelehnt (100015 "Card declined")`).
49
+ - `fixtures/hobex-hps-codes.json` fuehrt je Code zusaetzlich `title`,
50
+ `effect`, `reason`, `source` und die Saetze je Grund (`gruende`).
51
+
52
+ ## 0.9.4
53
+
54
+ ### `qrModus` faengt bei `auto` an — sonst stellte die Vorgabe den Altbestand um
55
+
56
+ **Anlass:** 0.9.3 gab `qrModus` die harte Vorgabe `raster`. Die Browser-Kasse
57
+ druckt den Signatur-QR aber seit jeher ueber den nativen ESC/POS-Befehl; jedes
58
+ Geraet, das nie durch den Drucker-Wizard laeuft, haette damit ploetzlich ein
59
+ Rasterbild gedruckt — ueber BLE mehrere Sekunden je Bon, und niemand haette
60
+ etwas umgestellt.
61
+
62
+ - **`QR_MODUS` fuehrt jetzt `auto` als ersten Wert**, und
63
+ `KASSE_GERAET_STANDARD.qrModus` steht darauf. `auto` heisst *unbestimmt*: an
64
+ diesem Geraet hat noch niemand am Papier entschieden, jede Kasse bleibt bei
65
+ ihrer bisherigen Praxis (Browser-Kasse ESC/POS, App Rasterbild). Nur ein
66
+ ausdruecklich gesetzter Wert aendert etwas.
67
+ - Wer `KasseQrModus` erschoepfend auswertet, bekommt einen dritten Fall.
68
+
7
69
  ## 0.9.3
8
70
 
9
71
  ### `qrModus` am Geraet: mit welchem Befehl der Signatur-QR auf den Bon kommt
@@ -58,12 +58,20 @@ export type KasseLadeAuto = typeof LADE_AUTO[number];
58
58
  * und schneller, aber aeltere Geraete drucken dann gar keinen QR oder
59
59
  * Zeichensalat.
60
60
  *
61
+ * `auto` ist die Vorgabe und heisst **unbestimmt**: an diesem Geraet hat noch
62
+ * niemand am Papier entschieden. Jede Kasse bleibt dann bei ihrer bisherigen
63
+ * Praxis — die Browser-Kasse beim ESC/POS-Befehl, die App beim Rasterbild.
64
+ * Eine harte Vorgabe waere hier eine stille Umstellung des Altbestands
65
+ * gewesen: jedes Geraet, das nie durch den Drucker-Wizard lief, druckte
66
+ * ploetzlich anders, und ueber BLE kostet ein Rasterbild mehrere Sekunden je
67
+ * Bon. Nur ein ausdruecklich gesetzter Wert aendert etwas.
68
+ *
61
69
  * **Eine Geraete-Einstellung, keine des Betriebs:** derselbe Bon kommt an einer
62
70
  * Kasse sauber heraus und an der Nebenkasse nicht. Und sie ist nicht
63
71
  * kosmetisch — nach § 132a BAO ist der QR Teil des Belegs; wer den falschen
64
72
  * Modus stehen laesst, erteilt Belege ohne lesbare Signatur.
65
73
  */
66
- export declare const QR_MODUS: readonly ["raster", "escpos"];
74
+ export declare const QR_MODUS: readonly ["auto", "raster", "escpos"];
67
75
  export type KasseQrModus = typeof QR_MODUS[number];
68
76
  /** Groesse des Kuerzel-Logos in der Kopfzeile der Kasse. */
69
77
  export declare const LOGO_GROESSE: readonly ["S", "M", "L"];
@@ -191,7 +199,7 @@ export interface KasseSettingsGeraet {
191
199
  papier: KassePapier;
192
200
  zeichensatz: KasseZeichensatz;
193
201
  schnitt: KasseSchnitt;
194
- /** Befehl fuer den Signatur-QR auf dem Bon; der Drucker-Wizard probiert beide aus. */
202
+ /** Befehl fuer den Signatur-QR auf dem Bon; 'auto' = unbestimmt, der Drucker-Wizard probiert beide aus. */
195
203
  qrModus: KasseQrModus;
196
204
  ladeAn: boolean;
197
205
  ladeAuto: KasseLadeAuto;
@@ -50,12 +50,20 @@ exports.LADE_AUTO = ['bar', 'immer', 'nie'];
50
50
  * und schneller, aber aeltere Geraete drucken dann gar keinen QR oder
51
51
  * Zeichensalat.
52
52
  *
53
+ * `auto` ist die Vorgabe und heisst **unbestimmt**: an diesem Geraet hat noch
54
+ * niemand am Papier entschieden. Jede Kasse bleibt dann bei ihrer bisherigen
55
+ * Praxis — die Browser-Kasse beim ESC/POS-Befehl, die App beim Rasterbild.
56
+ * Eine harte Vorgabe waere hier eine stille Umstellung des Altbestands
57
+ * gewesen: jedes Geraet, das nie durch den Drucker-Wizard lief, druckte
58
+ * ploetzlich anders, und ueber BLE kostet ein Rasterbild mehrere Sekunden je
59
+ * Bon. Nur ein ausdruecklich gesetzter Wert aendert etwas.
60
+ *
53
61
  * **Eine Geraete-Einstellung, keine des Betriebs:** derselbe Bon kommt an einer
54
62
  * Kasse sauber heraus und an der Nebenkasse nicht. Und sie ist nicht
55
63
  * kosmetisch — nach § 132a BAO ist der QR Teil des Belegs; wer den falschen
56
64
  * Modus stehen laesst, erteilt Belege ohne lesbare Signatur.
57
65
  */
58
- exports.QR_MODUS = ['raster', 'escpos'];
66
+ exports.QR_MODUS = ['auto', 'raster', 'escpos'];
59
67
  /*
60
68
  * Auch die uebrigen Wertemengen der Einstellungen stehen jetzt als Liste da —
61
69
  * vorher waren sie nur als Union am Feld ausgeschrieben. Ein Zwilling konnte
@@ -129,7 +137,7 @@ exports.KASSE_GERAET_STANDARD = Object.freeze({
129
137
  tasten: { ...exports.KASSE_TASTEN_STANDARD },
130
138
  druckerAn: false, druckerArt: 'sdp', druckerIp: '', druckerPort: 9100, druckerBt: '', druckerName: '', druckerId: '', druckerDevid: 'local_printer',
131
139
  connectDruckerId: '',
132
- papier: 'mm80', zeichensatz: 'CP1252', schnitt: 'partial', qrModus: 'raster',
140
+ papier: 'mm80', zeichensatz: 'CP1252', schnitt: 'partial', qrModus: 'auto',
133
141
  ladeAn: false, ladeAuto: 'bar',
134
142
  terminalIp: '', terminalPort: 8080, terminalVia: 'direkt',
135
143
  terminalArt: 'keins', terminalTid: '', tastenMarken: true,
@@ -20,8 +20,8 @@
20
20
  export { type HpsConnectCancelOptions, type HpsConnectClient, type HpsConnectClientOptions, type HpsConnectFetch, type HpsConnectFetchResponse, type HpsConnectPaymentOptions, type HpsConnectRefundOptions, type HpsConnectTarget, type HpsConnectTransactionOptions, createHpsConnectClient, } from './connect-client.js';
21
21
  export { HpsClarifyTimeoutError, HpsConnectException, HpsConnectTerminalError, HpsConnectTransportError, HpsPreflightError, HpsTransactionIdError, PREFLIGHT_CONNECT_CODES, } from './errors.js';
22
22
  export { type HpsPaymentEvent, type HpsPaymentEventKind, type HpsPaymentObserver, } from './events.js';
23
- export { type CardPaymentOutcome, type HpsPaymentResult, mayRetrySafely, } from './outcome.js';
23
+ export { type CardPaymentOutcome, type HpsPaymentResult, isHostUncertainResult, mayRetrySafely, } from './outcome.js';
24
24
  export { type HpsCancelOptions, type HpsPaymentOptions, type HpsPayments, type HpsPaymentsOptions, type HpsRefundOptions, createHpsPayments, } from './payments.js';
25
25
  export { MAX_TRANSACTION_ID_LENGTH, createHpsTransactionIdGenerator, isValidHpsTransactionId, newHpsTransactionId, type HpsTransactionIdGeneratorOptions, } from './transaction-id.js';
26
- export { ABORTED_CODE, APPROVED_CODE, CARD_NOT_PRESENT_CODE, HPS_MEASURED_CODES, INVALID_TRANSACTION_CODE, NOT_ABORTABLE_CODE, INVALID_AMOUNT_CODE, AMOUNT_OUT_OF_RANGE_CODE, INVALID_TID_CODE, WRONG_PIN_CODE, NO_STATEMENT_CODE, TECHNICAL_ERROR_CODE, TERMINAL_BUSY_HTTP_STATUS, TRANSACTION_CANCELED_CODE, isApproved, isCanceled, isConclusive, isInProgress, isNoStatement, isNotAbortable, isTechnicalError, isUnknownCode, parseHpsTransactionResponse, type HpsMeasuredCode, type HpsTransactionResponse, } from './transaction-response.js';
26
+ export { ABORTED_CODE, APP_SELECT_FAILED_CODE, APPROVED_CODE, BAD_REQUEST_CODE, CARD_DECLINED_CODE, CARD_INFO_NOT_ENTERED_CODE, CARD_NOT_PRESENT_CODE, CARD_NOT_SUPPORTED_CODE, CARD_READ_FAILED_CODE, CHIP_DATA_MISMATCH_CODE, COMPLETION_FAILED_CODE, DIAGNOSIS_FAILED_CODE, HOST_COMMUNICATION_FAILED_CODE, HOST_STEP_FAILED_CODE, HOST_TIMEOUT_REVERSED_CODE, HPS_CODES, HPS_MEASURED_CODES, HPS_REASON_HINTS, INTERNAL_ERROR_CODE, INVALID_MESSAGE_TYPE_CODE, INVALID_TID_DOCUMENTED_CODE, INVALID_TX_TYPE_CODE, MAX_RETRIES_EXCEEDED_CODE, NOT_FOUND_CODE, PASSWORD_NOT_ENTERED_CODE, REFUND_DISABLED_CODE, REFUND_PASSWORD_INVALID_CODE, SCEP_ENROLLMENT_FAILED_CODE, TERMINAL_BLOCKED_CODE, TERMINAL_BUSY_CODE, TIP_SELECTION_FAILED_CODE, UNSUPPORTED_USER_DATA_CODE, hpsCodeInfo, hpsCodeReason, isHostUncertain, isHostUncertainReason, INVALID_TRANSACTION_CODE, NOT_ABORTABLE_CODE, INVALID_AMOUNT_CODE, AMOUNT_OUT_OF_RANGE_CODE, INVALID_TID_CODE, WRONG_PIN_CODE, NO_STATEMENT_CODE, TECHNICAL_ERROR_CODE, TERMINAL_BUSY_HTTP_STATUS, TRANSACTION_CANCELED_CODE, isApproved, isCanceled, isConclusive, isConclusiveAsStatus, isInProgress, isNoStatement, isNotAbortable, isTechnicalError, isUnknownCode, parseHpsTransactionResponse, type HpsCode, type HpsCodeEffect, type HpsCodeReason, type HpsCodeSource, type HpsMeasuredCode, type HpsTransactionResponse, } from './transaction-response.js';
27
27
  export { hobexReceiptFromHps } from './receipt.js';
@@ -19,7 +19,8 @@
19
19
  * des Aufrufers.
20
20
  */
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.hobexReceiptFromHps = exports.parseHpsTransactionResponse = exports.isUnknownCode = exports.isTechnicalError = exports.isNotAbortable = exports.isNoStatement = exports.isInProgress = exports.isConclusive = exports.isCanceled = exports.isApproved = exports.TRANSACTION_CANCELED_CODE = exports.TERMINAL_BUSY_HTTP_STATUS = exports.TECHNICAL_ERROR_CODE = exports.NO_STATEMENT_CODE = exports.WRONG_PIN_CODE = exports.INVALID_TID_CODE = exports.AMOUNT_OUT_OF_RANGE_CODE = exports.INVALID_AMOUNT_CODE = exports.NOT_ABORTABLE_CODE = exports.INVALID_TRANSACTION_CODE = exports.HPS_MEASURED_CODES = exports.CARD_NOT_PRESENT_CODE = exports.APPROVED_CODE = exports.ABORTED_CODE = exports.newHpsTransactionId = exports.isValidHpsTransactionId = exports.createHpsTransactionIdGenerator = exports.MAX_TRANSACTION_ID_LENGTH = exports.createHpsPayments = exports.mayRetrySafely = exports.PREFLIGHT_CONNECT_CODES = exports.HpsTransactionIdError = exports.HpsPreflightError = exports.HpsConnectTransportError = exports.HpsConnectTerminalError = exports.HpsConnectException = exports.HpsClarifyTimeoutError = exports.createHpsConnectClient = void 0;
22
+ exports.isHostUncertain = exports.hpsCodeReason = exports.hpsCodeInfo = exports.UNSUPPORTED_USER_DATA_CODE = exports.TIP_SELECTION_FAILED_CODE = exports.TERMINAL_BUSY_CODE = exports.TERMINAL_BLOCKED_CODE = exports.SCEP_ENROLLMENT_FAILED_CODE = exports.REFUND_PASSWORD_INVALID_CODE = exports.REFUND_DISABLED_CODE = exports.PASSWORD_NOT_ENTERED_CODE = exports.NOT_FOUND_CODE = exports.MAX_RETRIES_EXCEEDED_CODE = exports.INVALID_TX_TYPE_CODE = exports.INVALID_TID_DOCUMENTED_CODE = exports.INVALID_MESSAGE_TYPE_CODE = exports.INTERNAL_ERROR_CODE = exports.HPS_REASON_HINTS = exports.HPS_MEASURED_CODES = exports.HPS_CODES = exports.HOST_TIMEOUT_REVERSED_CODE = exports.HOST_STEP_FAILED_CODE = exports.HOST_COMMUNICATION_FAILED_CODE = exports.DIAGNOSIS_FAILED_CODE = exports.COMPLETION_FAILED_CODE = exports.CHIP_DATA_MISMATCH_CODE = exports.CARD_READ_FAILED_CODE = exports.CARD_NOT_SUPPORTED_CODE = exports.CARD_NOT_PRESENT_CODE = exports.CARD_INFO_NOT_ENTERED_CODE = exports.CARD_DECLINED_CODE = exports.BAD_REQUEST_CODE = exports.APPROVED_CODE = exports.APP_SELECT_FAILED_CODE = exports.ABORTED_CODE = exports.newHpsTransactionId = exports.isValidHpsTransactionId = exports.createHpsTransactionIdGenerator = exports.MAX_TRANSACTION_ID_LENGTH = exports.createHpsPayments = exports.mayRetrySafely = exports.isHostUncertainResult = exports.PREFLIGHT_CONNECT_CODES = exports.HpsTransactionIdError = exports.HpsPreflightError = exports.HpsConnectTransportError = exports.HpsConnectTerminalError = exports.HpsConnectException = exports.HpsClarifyTimeoutError = exports.createHpsConnectClient = void 0;
23
+ exports.hobexReceiptFromHps = exports.parseHpsTransactionResponse = exports.isUnknownCode = exports.isTechnicalError = exports.isNotAbortable = exports.isNoStatement = exports.isInProgress = exports.isConclusiveAsStatus = exports.isConclusive = exports.isCanceled = exports.isApproved = exports.TRANSACTION_CANCELED_CODE = exports.TERMINAL_BUSY_HTTP_STATUS = exports.TECHNICAL_ERROR_CODE = exports.NO_STATEMENT_CODE = exports.WRONG_PIN_CODE = exports.INVALID_TID_CODE = exports.AMOUNT_OUT_OF_RANGE_CODE = exports.INVALID_AMOUNT_CODE = exports.NOT_ABORTABLE_CODE = exports.INVALID_TRANSACTION_CODE = exports.isHostUncertainReason = void 0;
23
24
  var connect_client_js_1 = require("./connect-client.js");
24
25
  Object.defineProperty(exports, "createHpsConnectClient", { enumerable: true, get: function () { return connect_client_js_1.createHpsConnectClient; } });
25
26
  var errors_js_1 = require("./errors.js");
@@ -31,6 +32,7 @@ Object.defineProperty(exports, "HpsPreflightError", { enumerable: true, get: fun
31
32
  Object.defineProperty(exports, "HpsTransactionIdError", { enumerable: true, get: function () { return errors_js_1.HpsTransactionIdError; } });
32
33
  Object.defineProperty(exports, "PREFLIGHT_CONNECT_CODES", { enumerable: true, get: function () { return errors_js_1.PREFLIGHT_CONNECT_CODES; } });
33
34
  var outcome_js_1 = require("./outcome.js");
35
+ Object.defineProperty(exports, "isHostUncertainResult", { enumerable: true, get: function () { return outcome_js_1.isHostUncertainResult; } });
34
36
  Object.defineProperty(exports, "mayRetrySafely", { enumerable: true, get: function () { return outcome_js_1.mayRetrySafely; } });
35
37
  var payments_js_1 = require("./payments.js");
36
38
  Object.defineProperty(exports, "createHpsPayments", { enumerable: true, get: function () { return payments_js_1.createHpsPayments; } });
@@ -41,9 +43,41 @@ Object.defineProperty(exports, "isValidHpsTransactionId", { enumerable: true, ge
41
43
  Object.defineProperty(exports, "newHpsTransactionId", { enumerable: true, get: function () { return transaction_id_js_1.newHpsTransactionId; } });
42
44
  var transaction_response_js_1 = require("./transaction-response.js");
43
45
  Object.defineProperty(exports, "ABORTED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.ABORTED_CODE; } });
46
+ Object.defineProperty(exports, "APP_SELECT_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.APP_SELECT_FAILED_CODE; } });
44
47
  Object.defineProperty(exports, "APPROVED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.APPROVED_CODE; } });
48
+ Object.defineProperty(exports, "BAD_REQUEST_CODE", { enumerable: true, get: function () { return transaction_response_js_1.BAD_REQUEST_CODE; } });
49
+ Object.defineProperty(exports, "CARD_DECLINED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.CARD_DECLINED_CODE; } });
50
+ Object.defineProperty(exports, "CARD_INFO_NOT_ENTERED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.CARD_INFO_NOT_ENTERED_CODE; } });
45
51
  Object.defineProperty(exports, "CARD_NOT_PRESENT_CODE", { enumerable: true, get: function () { return transaction_response_js_1.CARD_NOT_PRESENT_CODE; } });
52
+ Object.defineProperty(exports, "CARD_NOT_SUPPORTED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.CARD_NOT_SUPPORTED_CODE; } });
53
+ Object.defineProperty(exports, "CARD_READ_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.CARD_READ_FAILED_CODE; } });
54
+ Object.defineProperty(exports, "CHIP_DATA_MISMATCH_CODE", { enumerable: true, get: function () { return transaction_response_js_1.CHIP_DATA_MISMATCH_CODE; } });
55
+ Object.defineProperty(exports, "COMPLETION_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.COMPLETION_FAILED_CODE; } });
56
+ Object.defineProperty(exports, "DIAGNOSIS_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.DIAGNOSIS_FAILED_CODE; } });
57
+ Object.defineProperty(exports, "HOST_COMMUNICATION_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.HOST_COMMUNICATION_FAILED_CODE; } });
58
+ Object.defineProperty(exports, "HOST_STEP_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.HOST_STEP_FAILED_CODE; } });
59
+ Object.defineProperty(exports, "HOST_TIMEOUT_REVERSED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.HOST_TIMEOUT_REVERSED_CODE; } });
60
+ Object.defineProperty(exports, "HPS_CODES", { enumerable: true, get: function () { return transaction_response_js_1.HPS_CODES; } });
46
61
  Object.defineProperty(exports, "HPS_MEASURED_CODES", { enumerable: true, get: function () { return transaction_response_js_1.HPS_MEASURED_CODES; } });
62
+ Object.defineProperty(exports, "HPS_REASON_HINTS", { enumerable: true, get: function () { return transaction_response_js_1.HPS_REASON_HINTS; } });
63
+ Object.defineProperty(exports, "INTERNAL_ERROR_CODE", { enumerable: true, get: function () { return transaction_response_js_1.INTERNAL_ERROR_CODE; } });
64
+ Object.defineProperty(exports, "INVALID_MESSAGE_TYPE_CODE", { enumerable: true, get: function () { return transaction_response_js_1.INVALID_MESSAGE_TYPE_CODE; } });
65
+ Object.defineProperty(exports, "INVALID_TID_DOCUMENTED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.INVALID_TID_DOCUMENTED_CODE; } });
66
+ Object.defineProperty(exports, "INVALID_TX_TYPE_CODE", { enumerable: true, get: function () { return transaction_response_js_1.INVALID_TX_TYPE_CODE; } });
67
+ Object.defineProperty(exports, "MAX_RETRIES_EXCEEDED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.MAX_RETRIES_EXCEEDED_CODE; } });
68
+ Object.defineProperty(exports, "NOT_FOUND_CODE", { enumerable: true, get: function () { return transaction_response_js_1.NOT_FOUND_CODE; } });
69
+ Object.defineProperty(exports, "PASSWORD_NOT_ENTERED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.PASSWORD_NOT_ENTERED_CODE; } });
70
+ Object.defineProperty(exports, "REFUND_DISABLED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.REFUND_DISABLED_CODE; } });
71
+ Object.defineProperty(exports, "REFUND_PASSWORD_INVALID_CODE", { enumerable: true, get: function () { return transaction_response_js_1.REFUND_PASSWORD_INVALID_CODE; } });
72
+ Object.defineProperty(exports, "SCEP_ENROLLMENT_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.SCEP_ENROLLMENT_FAILED_CODE; } });
73
+ Object.defineProperty(exports, "TERMINAL_BLOCKED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.TERMINAL_BLOCKED_CODE; } });
74
+ Object.defineProperty(exports, "TERMINAL_BUSY_CODE", { enumerable: true, get: function () { return transaction_response_js_1.TERMINAL_BUSY_CODE; } });
75
+ Object.defineProperty(exports, "TIP_SELECTION_FAILED_CODE", { enumerable: true, get: function () { return transaction_response_js_1.TIP_SELECTION_FAILED_CODE; } });
76
+ Object.defineProperty(exports, "UNSUPPORTED_USER_DATA_CODE", { enumerable: true, get: function () { return transaction_response_js_1.UNSUPPORTED_USER_DATA_CODE; } });
77
+ Object.defineProperty(exports, "hpsCodeInfo", { enumerable: true, get: function () { return transaction_response_js_1.hpsCodeInfo; } });
78
+ Object.defineProperty(exports, "hpsCodeReason", { enumerable: true, get: function () { return transaction_response_js_1.hpsCodeReason; } });
79
+ Object.defineProperty(exports, "isHostUncertain", { enumerable: true, get: function () { return transaction_response_js_1.isHostUncertain; } });
80
+ Object.defineProperty(exports, "isHostUncertainReason", { enumerable: true, get: function () { return transaction_response_js_1.isHostUncertainReason; } });
47
81
  Object.defineProperty(exports, "INVALID_TRANSACTION_CODE", { enumerable: true, get: function () { return transaction_response_js_1.INVALID_TRANSACTION_CODE; } });
48
82
  Object.defineProperty(exports, "NOT_ABORTABLE_CODE", { enumerable: true, get: function () { return transaction_response_js_1.NOT_ABORTABLE_CODE; } });
49
83
  Object.defineProperty(exports, "INVALID_AMOUNT_CODE", { enumerable: true, get: function () { return transaction_response_js_1.INVALID_AMOUNT_CODE; } });
@@ -57,6 +91,7 @@ Object.defineProperty(exports, "TRANSACTION_CANCELED_CODE", { enumerable: true,
57
91
  Object.defineProperty(exports, "isApproved", { enumerable: true, get: function () { return transaction_response_js_1.isApproved; } });
58
92
  Object.defineProperty(exports, "isCanceled", { enumerable: true, get: function () { return transaction_response_js_1.isCanceled; } });
59
93
  Object.defineProperty(exports, "isConclusive", { enumerable: true, get: function () { return transaction_response_js_1.isConclusive; } });
94
+ Object.defineProperty(exports, "isConclusiveAsStatus", { enumerable: true, get: function () { return transaction_response_js_1.isConclusiveAsStatus; } });
60
95
  Object.defineProperty(exports, "isInProgress", { enumerable: true, get: function () { return transaction_response_js_1.isInProgress; } });
61
96
  Object.defineProperty(exports, "isNoStatement", { enumerable: true, get: function () { return transaction_response_js_1.isNoStatement; } });
62
97
  Object.defineProperty(exports, "isNotAbortable", { enumerable: true, get: function () { return transaction_response_js_1.isNotAbortable; } });
@@ -1,4 +1,4 @@
1
- import type { HpsTransactionResponse } from './transaction-response.js';
1
+ import { type HpsCodeReason, type HpsTransactionResponse } from './transaction-response.js';
2
2
  /**
3
3
  * Ausgang eines Kartenzahlvorgangs — die einzige Frage, die ein Aufrufer
4
4
  * wirklich hat: darf ich es nochmal versuchen?
@@ -35,6 +35,18 @@ export interface HpsPaymentResult {
35
35
  * Entscheidung getragen. Bei schluessigem Ausgang nicht gesetzt.
36
36
  */
37
37
  readonly lastResponse?: HpsTransactionResponse;
38
+ /**
39
+ * Worauf die Kasse reagiert -- der Grund hinter dem Ausgang, mit dem Satz
40
+ * fuer den Bediener in `HPS_REASON_HINTS`.
41
+ *
42
+ * Gesetzt an der Stelle, die den Ausgang entschieden hat, nicht aus
43
+ * [response] abgeleitet: ein bestaetigter Abbruch antwortet `'0'` und ist
44
+ * trotzdem `'aborted'`, und wenn die Zwei-9027-Regel eine Zahlung als
45
+ * abgelehnt klaert, zaehlt der Code der ZAHLUNG, nicht das `9027` danach.
46
+ * Fehlt, wenn kein Code etwas erklaert (die Leitung riss ab, bevor das
47
+ * Terminal etwas sagte) und bei einer Aufhebung, die nicht gegriffen hat.
48
+ */
49
+ readonly reason?: HpsCodeReason;
38
50
  /**
39
51
  * Verlauf der Klaerung, in Reihenfolge — der Nachweis, der im
40
52
  * Belastungsstreit gelesen wird. Behauptet nie eine Ursache, die nicht
@@ -44,3 +56,10 @@ export interface HpsPaymentResult {
44
56
  }
45
57
  /** Nur bei `'declined'` steht fest, dass nichts belastet wurde. */
46
58
  export declare function mayRetrySafely(result: Pick<HpsPaymentResult, 'outcome'>): boolean;
59
+ /**
60
+ * `true`, wenn der Ausgang offen ist, weil das Terminal eine Stoerung beim
61
+ * oder nach dem hobex-Host meldete (`effect: 'hostUncertain'`). Wichtig fuer
62
+ * jede SPAETERE Nachfrage: antwortet die Statusabfrage dann `9027`, heisst das
63
+ * hier NICHT "nichts belastet".
64
+ */
65
+ export declare function isHostUncertainResult(result: Pick<HpsPaymentResult, 'outcome' | 'reason'>): boolean;
@@ -1,7 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.mayRetrySafely = mayRetrySafely;
4
+ exports.isHostUncertainResult = isHostUncertainResult;
5
+ const transaction_response_js_1 = require("./transaction-response.js");
4
6
  /** Nur bei `'declined'` steht fest, dass nichts belastet wurde. */
5
7
  function mayRetrySafely(result) {
6
8
  return result.outcome === 'declined';
7
9
  }
10
+ /**
11
+ * `true`, wenn der Ausgang offen ist, weil das Terminal eine Stoerung beim
12
+ * oder nach dem hobex-Host meldete (`effect: 'hostUncertain'`). Wichtig fuer
13
+ * jede SPAETERE Nachfrage: antwortet die Statusabfrage dann `9027`, heisst das
14
+ * hier NICHT "nichts belastet".
15
+ */
16
+ function isHostUncertainResult(result) {
17
+ return result.outcome === 'unresolved' && (0, transaction_response_js_1.isHostUncertainReason)(result.reason);
18
+ }
@@ -89,6 +89,25 @@ import type { HpsPaymentResult } from './outcome.js';
89
89
  * Kein [tryAbort]-Versuch bei [cancel]: die Originalzahlung ist laengst
90
90
  * abgeschlossen und antwortet gemessen mit `100010` -- ein Abbruch darauf
91
91
  * waere sinnlos.
92
+ *
93
+ * ## Stoerung beim Host: die Klaerung darf nichts schliessen (11.09.2026)
94
+ *
95
+ * Die Antwortcodeliste von hobex benennt Codes, bei denen der Host beteiligt
96
+ * war und das Terminal NICHT selbst storniert (`effect: 'hostUncertain'`,
97
+ * etwa `100007`). Fuer sie gilt zweierlei:
98
+ *
99
+ * 1. Die Zwei-9027-Regel ([ausGeschlossenerAntwort]) greift nicht. Sie
100
+ * schliesst aus "das Terminal hat geantwortet und nichts gespeichert" auf
101
+ * "nichts belastet" -- das stimmt fuer einen Vorgang, der am Terminal
102
+ * endete, aber nicht fuer einen, dessen Ausgang beim Host liegt. Dasselbe
103
+ * gilt sinngemaess fuer [cancel]: ein unveraendertes `'0'` auf die
104
+ * Originalzahlung beweist dann nicht, dass die Aufhebung beim Host nicht
105
+ * ankam.
106
+ * 2. Die Klaerung wartet trotzdem nicht das ganze Budget ab. Sagt die
107
+ * Statusabfrage zweimal in Folge nichts Neues (`9027` oder erneut ein
108
+ * solcher Code), endet sie sofort als `unresolved` -- das Terminal wird es
109
+ * auch in 90 Sekunden nicht wissen. Meldet sie dagegen `'0'`, ist die
110
+ * Zahlung genehmigt, ganz normal.
92
111
  */
93
112
  export interface HpsPaymentsOptions {
94
113
  /** Wie lange insgesamt geklaert wird, bevor der Ausgang offen bleibt. Vorgabe 90 s. */