@kreiseck/kasseneck-api 1.0.0-rc.3 → 1.0.0-rc.4
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.
- package/CHANGELOG.md +15 -0
- package/README.md +33 -8
- package/dist/cjs/client/errors.d.ts +32 -1
- package/dist/cjs/client/errors.js +77 -4
- package/dist/cjs/payments/hobex.d.ts +7 -4
- package/dist/cjs/payments/hobex.js +7 -4
- package/dist/cjs/payments/stripe.d.ts +3 -1
- package/dist/cjs/payments/stripe.js +3 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client/errors.d.ts +32 -1
- package/dist/esm/client/errors.js +76 -3
- package/dist/esm/payments/hobex.d.ts +7 -4
- package/dist/esm/payments/hobex.js +7 -4
- package/dist/esm/payments/stripe.d.ts +3 -1
- package/dist/esm/payments/stripe.js +3 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/fixtures/hobex-hps-codes.json +1 -1
- package/fixtures/invoice-api.schema.json +1 -1
- package/fixtures/invoice-texts.json +1 -1
- package/fixtures/pos-texts.json +1 -1
- package/fixtures/surface.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -147,6 +147,21 @@ an upgrade as long as `/v1` is served.
|
|
|
147
147
|
again. `setMyRegisterDeviceSettings` takes `shortcuts` only as the whole map
|
|
148
148
|
of known actions (as `posSettingsChanges` produces it): the server checks
|
|
149
149
|
keys bound twice only within the map it receives.
|
|
150
|
+
- **Money calls: an error envelope is not a rejection (1.0.0-rc.4).** On
|
|
151
|
+
`hobexPayApi`, `hobexRefundApi` and `stripeCaptureIntent` an error envelope
|
|
152
|
+
without a code is `outcome: 'unknown'`, and so is every code outside the
|
|
153
|
+
23 rejection codes, all raised before the provider is called: the
|
|
154
|
+
sign-in codes (`errorCodes.auth` without the seven of the partner
|
|
155
|
+
access), the edge codes `validation`, `not_found` and
|
|
156
|
+
`internal_translation_error`, the gates `module_inactive` and
|
|
157
|
+
`not_permitted`, and `route_missing`. `dialect_mismatch` and `response_translation_failed` (also
|
|
158
|
+
with `handled: false`) stay `'unknown'` there. rc.2 and rc.3 read an
|
|
159
|
+
envelope without a code as `'rejected'`, and the README called a retry
|
|
160
|
+
after `'rejected'` safe. Reason: the Hobex and Stripe handlers also answer
|
|
161
|
+
with a plain error message after the provider was called ("Error hobex
|
|
162
|
+
details", "Fehler beim Capturing"), so the card may be charged, the refund
|
|
163
|
+
paid or the payment captured. Same list as in the Dart twin
|
|
164
|
+
`kasseneck_api`.
|
|
150
165
|
- **Strict validation before sending.** The 0.x payment fields
|
|
151
166
|
(`paymentMethod`, `paymentMethodFromServer`, `creditCardProvider`,
|
|
152
167
|
`cardPaymentId`, `cardPaymentData`) throw, also from plain JavaScript.
|
package/README.md
CHANGED
|
@@ -427,10 +427,9 @@ silently. For a layout option of 0.x the message names its English successor.
|
|
|
427
427
|
### `outcome: 'unknown'`: never retry, look it up
|
|
428
428
|
|
|
429
429
|
`KasseneckApiError`, `KasseneckHttpError` and `KasseneckNetworkError` carry
|
|
430
|
-
`outcome`. `'rejected'` means
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
it helps depends on the code). `'unknown'` means the operation **may have been carried out**, for
|
|
430
|
+
`outcome`. `'rejected'` means the server turned the request down; whether
|
|
431
|
+
anything else is safe to do depends on the code, and on the money calls it
|
|
432
|
+
is only set for the codes listed below. `'unknown'` means the operation **may have been carried out**, for
|
|
434
433
|
`createReceipt` a signed receipt in the chain. Then never send it again: read
|
|
435
434
|
the result back (`getReceipt`, `listMyReceipts`, the original of a
|
|
436
435
|
cancellation) and continue from there. `isOutcomeUnknown(error)` covers all
|
|
@@ -448,13 +447,39 @@ three classes. The outcome is unknown for:
|
|
|
448
447
|
5xx, and HTTP 200 with the `Kasseneck-Api-Version: v3` marker but an empty,
|
|
449
448
|
non-JSON (also `text/html`) or status-less body (`KasseneckHttpError`,
|
|
450
449
|
`reason` `empty-body`, `not-json` or `missing-status`). HTML without the
|
|
451
|
-
marker stays `route_missing` with `'rejected'`: no function saw the call
|
|
450
|
+
marker stays `route_missing` with `'rejected'`: no function saw the call;
|
|
451
|
+
- on the money calls: every error envelope **without a code**, and every
|
|
452
|
+
code that is not one of the rejection codes below. The Hobex and Stripe
|
|
453
|
+
handlers also answer with a plain error message after the provider was
|
|
454
|
+
called, so an envelope alone does not prove that nothing happened.
|
|
455
|
+
|
|
456
|
+
On the money calls (`hobexPayApi`, `hobexRefundApi`, `stripeCaptureIntent`)
|
|
457
|
+
`outcome` is `'rejected'` only for codes that are produced before the
|
|
458
|
+
provider is called, taken from the `/v3` contract (`errorCodes`):
|
|
459
|
+
|
|
460
|
+
- the sign-in codes (`errorCodes.auth` without the seven of the partner
|
|
461
|
+
access, which never applies to these calls), raised before the handler
|
|
462
|
+
goes on: `method_not_allowed`, `validation` (a required field is missing
|
|
463
|
+
or has the wrong type), `cashregister_token_missing`,
|
|
464
|
+
`cashregister_token_invalid`, `cashregister_not_found`,
|
|
465
|
+
`account_not_found`, `live_not_enabled`, `unauthorized`, `mfa_required`,
|
|
466
|
+
`user_verification_failed`, `admin_required`, `register_user_not_allowed`,
|
|
467
|
+
`register_user_no_business`, `register_user_not_found`, `user_disabled`,
|
|
468
|
+
`session_expired`, `cashregister_not_assigned`,
|
|
469
|
+
`session_other_cashregister`;
|
|
470
|
+
- the edge codes that stop the call before the handler (`errorCodes.edge`):
|
|
471
|
+
`validation` (unknown fields), `not_found`, `internal_translation_error`;
|
|
472
|
+
- the module and permission gates: `module_inactive`, `not_permitted`;
|
|
473
|
+
- `route_missing` (set by the package: no function saw the call).
|
|
474
|
+
|
|
475
|
+
`dialect_mismatch` and `response_translation_failed` (also with
|
|
476
|
+
`handled: false`) stay `'unknown'` there: the handler may have run.
|
|
452
477
|
|
|
453
478
|
On the money calls an unknown outcome means the card may have been charged,
|
|
454
479
|
the refund may have gone through, the payment may have been captured. A
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
480
|
+
failed `hobexRefund` throws a `KasseneckApiError`; it never returns `false`,
|
|
481
|
+
because a `false` on an unclear outcome invites a second refund. Even a
|
|
482
|
+
`'rejected'` is no invitation to resend blindly: fix the cause first.
|
|
458
483
|
|
|
459
484
|
**Never retry these six calls, and never put a retrying layer under the
|
|
460
485
|
package.** A `fetch` passed in `options.fetch` (or a proxy or service worker in
|
|
@@ -110,6 +110,34 @@ export declare function fehlerDetails(daten: unknown, geheimnisse: readonly stri
|
|
|
110
110
|
* das Ergebnis nachlesen.
|
|
111
111
|
*/
|
|
112
112
|
export type ErrorOutcome = 'unknown' | 'rejected';
|
|
113
|
+
/**
|
|
114
|
+
* Codes, die auf einem Geldweg `outcome: 'rejected'` ergeben; jeder andere
|
|
115
|
+
* Code und eine Huelle ohne Code sind dort `'unknown'`. Aufgenommen ist nur,
|
|
116
|
+
* was entsteht, bevor das Backend den Zahlungsanbieter anspricht (Vertrag
|
|
117
|
+
* v3, `errorCodes`; dieselbe Liste wie `paymentCallRejectedCodes` im
|
|
118
|
+
* Dart-Zwilling):
|
|
119
|
+
*
|
|
120
|
+
* - `errorCodes.auth` ohne die sieben des Partner-Zugangs (18 Codes):
|
|
121
|
+
* Anmeldung und Pruefung in `checkRequest` laufen vor jeder Zeile des
|
|
122
|
+
* Handlers; `validation` heisst dort Pflichtfeld fehlt oder falscher Typ.
|
|
123
|
+
* Der Partner-Zugang trifft diese `api_key`-Aufrufe mit Kassen-Token nie.
|
|
124
|
+
* - aus `errorCodes.edge`: `not_found` (unbekannter Endpunkt, HTTP 404) und
|
|
125
|
+
* `internal_translation_error` (die Anfrage liess sich nicht uebersetzen,
|
|
126
|
+
* es wurde nichts ausgefuehrt); `validation` des Rands (unbekannte Felder,
|
|
127
|
+
* Rumpf ohne Objekt) steht schon oben.
|
|
128
|
+
* - `module_inactive` und `not_permitted`: das Modul- bzw. Rechte-Tor steht
|
|
129
|
+
* ebenfalls vor dem Anbieter.
|
|
130
|
+
* - `route_missing` (vergibt das Paket): HTML ohne `/v3`-Kennzeichen, keine
|
|
131
|
+
* Function hat den Aufruf gesehen.
|
|
132
|
+
*
|
|
133
|
+
* Nicht darin: `dialect_mismatch` (das Paket vergibt ihn auch, wenn ein Rand
|
|
134
|
+
* ohne `/v3` geantwortet hat, dessen Handler gelaufen sein kann) und
|
|
135
|
+
* `response_translation_failed` (der Handler lief; auch `handled: false`
|
|
136
|
+
* heisst nur, dass seine Antwort ein Fehler war, und der kann hinter dem
|
|
137
|
+
* Anbieteraufruf entstanden sein). Der Sammelfang der Handler ("Error hobex
|
|
138
|
+
* details", "Fehler beim Capturing") antwortet ohne Code.
|
|
139
|
+
*/
|
|
140
|
+
export declare const PAYMENT_CALL_REJECTED_CODES: readonly string[];
|
|
113
141
|
/**
|
|
114
142
|
* Codes, die das Paket selbst vergibt, nicht der Server: `route_missing`
|
|
115
143
|
* (HTML statt Backend, der Aufruf kam nie an) und `response_unreadable`
|
|
@@ -146,7 +174,10 @@ export declare class KasseneckApiError extends Error {
|
|
|
146
174
|
* `cancellation_outcome_unknown`, `response_unreadable` (Erfolg gemeldet,
|
|
147
175
|
* Antwort eines Aufrufs mit Wirkung aber unlesbar) und
|
|
148
176
|
* `response_translation_failed` (ausser mit `details.handled === false`);
|
|
149
|
-
* sonst `'rejected'`.
|
|
177
|
+
* sonst `'rejected'`. Auf den Geldwegen (`hobexPayApi`, `hobexRefundApi`,
|
|
178
|
+
* `stripeCaptureIntent`) umgekehrt: `'rejected'` nur mit einem Code aus
|
|
179
|
+
* [PAYMENT_CALL_REJECTED_CODES], ohne Code und mit jedem anderen Code
|
|
180
|
+
* `'unknown'`. Bei `'unknown'` nie wiederholen, sondern nachlesen.
|
|
150
181
|
*/
|
|
151
182
|
readonly outcome: ErrorOutcome;
|
|
152
183
|
constructor(functionName: string, serverMessage: string, details?: Record<string, unknown>, code?: string);
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
* als die Zusage.
|
|
74
74
|
*/
|
|
75
75
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
76
|
-
exports.KasseneckValidationError = exports.KasseneckAuthError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckApiError = exports.CLIENT_ERROR_CODES = void 0;
|
|
76
|
+
exports.KasseneckValidationError = exports.KasseneckAuthError = exports.KasseneckNetworkError = exports.KasseneckHttpError = exports.KasseneckApiError = exports.CLIENT_ERROR_CODES = exports.PAYMENT_CALL_REJECTED_CODES = void 0;
|
|
77
77
|
exports.causeDigest = causeDigest;
|
|
78
78
|
exports.fehlerDetails = fehlerDetails;
|
|
79
79
|
exports.isOutcomeUnknown = isOutcomeUnknown;
|
|
@@ -227,7 +227,77 @@ const AUSGANG_UNKLAR_CODES = new Set([
|
|
|
227
227
|
'cancellation_outcome_unknown',
|
|
228
228
|
'response_unreadable',
|
|
229
229
|
]);
|
|
230
|
-
|
|
230
|
+
/**
|
|
231
|
+
* Aufrufe, die Geld bewegen: `hobexPayApi` belastet eine Karte,
|
|
232
|
+
* `hobexRefundApi` erstattet, `stripeCaptureIntent` zieht eine vorgemerkte
|
|
233
|
+
* Zahlung ein. Ihre Handler antworten auch NACH dem Anbieteraufruf mit einer
|
|
234
|
+
* Fehlerhuelle ohne Code ("Error hobex details", "Fehler beim Capturing");
|
|
235
|
+
* dort gilt darum umgekehrt: Ausgang unklar, ausser der Code belegt, dass der
|
|
236
|
+
* Anbieter nie gerufen wurde.
|
|
237
|
+
*/
|
|
238
|
+
const GELDWEGE = new Set(['hobexPayApi', 'hobexRefundApi', 'stripeCaptureIntent']);
|
|
239
|
+
/**
|
|
240
|
+
* Codes, die auf einem Geldweg `outcome: 'rejected'` ergeben; jeder andere
|
|
241
|
+
* Code und eine Huelle ohne Code sind dort `'unknown'`. Aufgenommen ist nur,
|
|
242
|
+
* was entsteht, bevor das Backend den Zahlungsanbieter anspricht (Vertrag
|
|
243
|
+
* v3, `errorCodes`; dieselbe Liste wie `paymentCallRejectedCodes` im
|
|
244
|
+
* Dart-Zwilling):
|
|
245
|
+
*
|
|
246
|
+
* - `errorCodes.auth` ohne die sieben des Partner-Zugangs (18 Codes):
|
|
247
|
+
* Anmeldung und Pruefung in `checkRequest` laufen vor jeder Zeile des
|
|
248
|
+
* Handlers; `validation` heisst dort Pflichtfeld fehlt oder falscher Typ.
|
|
249
|
+
* Der Partner-Zugang trifft diese `api_key`-Aufrufe mit Kassen-Token nie.
|
|
250
|
+
* - aus `errorCodes.edge`: `not_found` (unbekannter Endpunkt, HTTP 404) und
|
|
251
|
+
* `internal_translation_error` (die Anfrage liess sich nicht uebersetzen,
|
|
252
|
+
* es wurde nichts ausgefuehrt); `validation` des Rands (unbekannte Felder,
|
|
253
|
+
* Rumpf ohne Objekt) steht schon oben.
|
|
254
|
+
* - `module_inactive` und `not_permitted`: das Modul- bzw. Rechte-Tor steht
|
|
255
|
+
* ebenfalls vor dem Anbieter.
|
|
256
|
+
* - `route_missing` (vergibt das Paket): HTML ohne `/v3`-Kennzeichen, keine
|
|
257
|
+
* Function hat den Aufruf gesehen.
|
|
258
|
+
*
|
|
259
|
+
* Nicht darin: `dialect_mismatch` (das Paket vergibt ihn auch, wenn ein Rand
|
|
260
|
+
* ohne `/v3` geantwortet hat, dessen Handler gelaufen sein kann) und
|
|
261
|
+
* `response_translation_failed` (der Handler lief; auch `handled: false`
|
|
262
|
+
* heisst nur, dass seine Antwort ein Fehler war, und der kann hinter dem
|
|
263
|
+
* Anbieteraufruf entstanden sein). Der Sammelfang der Handler ("Error hobex
|
|
264
|
+
* details", "Fehler beim Capturing") antwortet ohne Code.
|
|
265
|
+
*/
|
|
266
|
+
exports.PAYMENT_CALL_REJECTED_CODES = Object.freeze([
|
|
267
|
+
// errorCodes.auth ohne Partner-Zugang
|
|
268
|
+
'method_not_allowed',
|
|
269
|
+
'validation',
|
|
270
|
+
'cashregister_token_missing',
|
|
271
|
+
'cashregister_token_invalid',
|
|
272
|
+
'cashregister_not_found',
|
|
273
|
+
'account_not_found',
|
|
274
|
+
'live_not_enabled',
|
|
275
|
+
'unauthorized',
|
|
276
|
+
'mfa_required',
|
|
277
|
+
'user_verification_failed',
|
|
278
|
+
'admin_required',
|
|
279
|
+
'register_user_not_allowed',
|
|
280
|
+
'register_user_no_business',
|
|
281
|
+
'register_user_not_found',
|
|
282
|
+
'user_disabled',
|
|
283
|
+
'session_expired',
|
|
284
|
+
'cashregister_not_assigned',
|
|
285
|
+
'session_other_cashregister',
|
|
286
|
+
// errorCodes.edge vor dem Handler (validation steht oben)
|
|
287
|
+
'not_found',
|
|
288
|
+
'internal_translation_error',
|
|
289
|
+
// Modul- und Rechte-Tor
|
|
290
|
+
'module_inactive',
|
|
291
|
+
'not_permitted',
|
|
292
|
+
// vom Paket vergeben
|
|
293
|
+
'route_missing',
|
|
294
|
+
]);
|
|
295
|
+
const GELDWEG_ABGELEHNT = new Set(exports.PAYMENT_CALL_REJECTED_CODES);
|
|
296
|
+
function ausgangAusCode(functionName, code, details) {
|
|
297
|
+
// `functionName` kann den Vorgang tragen (`financeWebService/<method>`).
|
|
298
|
+
if (GELDWEGE.has(functionName.split('/')[0])) {
|
|
299
|
+
return code !== undefined && GELDWEG_ABGELEHNT.has(code) ? 'rejected' : 'unknown';
|
|
300
|
+
}
|
|
231
301
|
if (code === undefined)
|
|
232
302
|
return 'rejected';
|
|
233
303
|
if (AUSGANG_UNKLAR_CODES.has(code))
|
|
@@ -271,7 +341,10 @@ class KasseneckApiError extends Error {
|
|
|
271
341
|
* `cancellation_outcome_unknown`, `response_unreadable` (Erfolg gemeldet,
|
|
272
342
|
* Antwort eines Aufrufs mit Wirkung aber unlesbar) und
|
|
273
343
|
* `response_translation_failed` (ausser mit `details.handled === false`);
|
|
274
|
-
* sonst `'rejected'`.
|
|
344
|
+
* sonst `'rejected'`. Auf den Geldwegen (`hobexPayApi`, `hobexRefundApi`,
|
|
345
|
+
* `stripeCaptureIntent`) umgekehrt: `'rejected'` nur mit einem Code aus
|
|
346
|
+
* [PAYMENT_CALL_REJECTED_CODES], ohne Code und mit jedem anderen Code
|
|
347
|
+
* `'unknown'`. Bei `'unknown'` nie wiederholen, sondern nachlesen.
|
|
275
348
|
*/
|
|
276
349
|
outcome;
|
|
277
350
|
constructor(functionName, serverMessage, details = {}, code) {
|
|
@@ -283,7 +356,7 @@ class KasseneckApiError extends Error {
|
|
|
283
356
|
// den Details. So bleibt die Klasse fuer beide Ablageorte dieselbe.
|
|
284
357
|
const kandidat = code !== undefined ? code : details['code'];
|
|
285
358
|
this.code = typeof kandidat === 'string' && BEZEICHNER.test(kandidat) ? kandidat : undefined;
|
|
286
|
-
this.outcome = ausgangAusCode(this.code, details);
|
|
359
|
+
this.outcome = ausgangAusCode(functionName, this.code, details);
|
|
287
360
|
}
|
|
288
361
|
}
|
|
289
362
|
exports.KasseneckApiError = KasseneckApiError;
|
|
@@ -47,8 +47,9 @@ export interface HobexTransactionIdOptions {
|
|
|
47
47
|
* nicht.
|
|
48
48
|
*
|
|
49
49
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
50
|
-
* unlesbare Antwort
|
|
51
|
-
*
|
|
50
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
51
|
+
* der Ablehnungscodes, README `outcome`) kann die Karte belastet sein: den Stand
|
|
52
|
+
* ueber die Transaktionskennung nachlesen, nicht ein zweites Mal belasten.
|
|
52
53
|
*/
|
|
53
54
|
export declare function hobexPay(transport: InternerTransport, options: HobexPayOptions): Promise<HobexReceipt>;
|
|
54
55
|
/**
|
|
@@ -62,8 +63,10 @@ export declare function hobexPay(transport: InternerTransport, options: HobexPay
|
|
|
62
63
|
* Wahrheitswert waere hier also immer `true` — eine Luege ueber den
|
|
63
64
|
* Informationsgehalt, an der ein Aufrufer ein `if` aufhaengt, das nie greift.
|
|
64
65
|
* Misserfolg kommt als geworfener Fehler: eine Fehlerhuelle als
|
|
65
|
-
* [KasseneckApiError]
|
|
66
|
-
*
|
|
66
|
+
* [KasseneckApiError], `'rejected'` nur mit einem der Ablehnungscodes
|
|
67
|
+
* (README `outcome`); ohne Code oder mit anderem Code, bei Netz,
|
|
68
|
+
* Zeitlimit, HTTP 5xx und unlesbarer Erfolgsantwort `outcome: 'unknown'`
|
|
69
|
+
* (die Erstattung kann gelaufen sein).
|
|
67
70
|
* Ein `false` an dieser Stelle luede zum zweiten Versuch ein, also zur
|
|
68
71
|
* doppelten Erstattung. **Nie wiederholen**, sondern den Stand nachlesen.
|
|
69
72
|
*
|
|
@@ -43,8 +43,9 @@ const ENDPUNKT_REFUND = 'hobexRefundApi';
|
|
|
43
43
|
* nicht.
|
|
44
44
|
*
|
|
45
45
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
46
|
-
* unlesbare Antwort
|
|
47
|
-
*
|
|
46
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
47
|
+
* der Ablehnungscodes, README `outcome`) kann die Karte belastet sein: den Stand
|
|
48
|
+
* ueber die Transaktionskennung nachlesen, nicht ein zweites Mal belasten.
|
|
48
49
|
*/
|
|
49
50
|
async function hobexPay(transport, options) {
|
|
50
51
|
const params = zahlungsNutzlast(ENDPUNKT_PAY, options);
|
|
@@ -69,8 +70,10 @@ async function hobexPay(transport, options) {
|
|
|
69
70
|
* Wahrheitswert waere hier also immer `true` — eine Luege ueber den
|
|
70
71
|
* Informationsgehalt, an der ein Aufrufer ein `if` aufhaengt, das nie greift.
|
|
71
72
|
* Misserfolg kommt als geworfener Fehler: eine Fehlerhuelle als
|
|
72
|
-
* [KasseneckApiError]
|
|
73
|
-
*
|
|
73
|
+
* [KasseneckApiError], `'rejected'` nur mit einem der Ablehnungscodes
|
|
74
|
+
* (README `outcome`); ohne Code oder mit anderem Code, bei Netz,
|
|
75
|
+
* Zeitlimit, HTTP 5xx und unlesbarer Erfolgsantwort `outcome: 'unknown'`
|
|
76
|
+
* (die Erstattung kann gelaufen sein).
|
|
74
77
|
* Ein `false` an dieser Stelle luede zum zweiten Versuch ein, also zur
|
|
75
78
|
* doppelten Erstattung. **Nie wiederholen**, sondern den Stand nachlesen.
|
|
76
79
|
*
|
|
@@ -59,6 +59,8 @@ export declare function createStripeLink(transport: InternerTransport, options:
|
|
|
59
59
|
* Pflichtparameter.
|
|
60
60
|
*
|
|
61
61
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
62
|
-
* unlesbare Antwort
|
|
62
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
63
|
+
* der Ablehnungscodes, README `outcome`) kann der Einzug gelaufen sein: den Stand
|
|
64
|
+
* nachlesen.
|
|
63
65
|
*/
|
|
64
66
|
export declare function stripeCaptureIntent(transport: InternerTransport, stripeSessionId: string): Promise<StripeCaptureResult>;
|
|
@@ -74,7 +74,9 @@ async function createStripeLink(transport, options) {
|
|
|
74
74
|
* Pflichtparameter.
|
|
75
75
|
*
|
|
76
76
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
77
|
-
* unlesbare Antwort
|
|
77
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
78
|
+
* der Ablehnungscodes, README `outcome`) kann der Einzug gelaufen sein: den Stand
|
|
79
|
+
* nachlesen.
|
|
78
80
|
*/
|
|
79
81
|
async function stripeCaptureIntent(transport, stripeSessionId) {
|
|
80
82
|
if (typeof stripeSessionId !== 'string' || !stripeSessionId.trim()) {
|
package/dist/cjs/version.d.ts
CHANGED
package/dist/cjs/version.js
CHANGED
|
@@ -110,6 +110,34 @@ export declare function fehlerDetails(daten: unknown, geheimnisse: readonly stri
|
|
|
110
110
|
* das Ergebnis nachlesen.
|
|
111
111
|
*/
|
|
112
112
|
export type ErrorOutcome = 'unknown' | 'rejected';
|
|
113
|
+
/**
|
|
114
|
+
* Codes, die auf einem Geldweg `outcome: 'rejected'` ergeben; jeder andere
|
|
115
|
+
* Code und eine Huelle ohne Code sind dort `'unknown'`. Aufgenommen ist nur,
|
|
116
|
+
* was entsteht, bevor das Backend den Zahlungsanbieter anspricht (Vertrag
|
|
117
|
+
* v3, `errorCodes`; dieselbe Liste wie `paymentCallRejectedCodes` im
|
|
118
|
+
* Dart-Zwilling):
|
|
119
|
+
*
|
|
120
|
+
* - `errorCodes.auth` ohne die sieben des Partner-Zugangs (18 Codes):
|
|
121
|
+
* Anmeldung und Pruefung in `checkRequest` laufen vor jeder Zeile des
|
|
122
|
+
* Handlers; `validation` heisst dort Pflichtfeld fehlt oder falscher Typ.
|
|
123
|
+
* Der Partner-Zugang trifft diese `api_key`-Aufrufe mit Kassen-Token nie.
|
|
124
|
+
* - aus `errorCodes.edge`: `not_found` (unbekannter Endpunkt, HTTP 404) und
|
|
125
|
+
* `internal_translation_error` (die Anfrage liess sich nicht uebersetzen,
|
|
126
|
+
* es wurde nichts ausgefuehrt); `validation` des Rands (unbekannte Felder,
|
|
127
|
+
* Rumpf ohne Objekt) steht schon oben.
|
|
128
|
+
* - `module_inactive` und `not_permitted`: das Modul- bzw. Rechte-Tor steht
|
|
129
|
+
* ebenfalls vor dem Anbieter.
|
|
130
|
+
* - `route_missing` (vergibt das Paket): HTML ohne `/v3`-Kennzeichen, keine
|
|
131
|
+
* Function hat den Aufruf gesehen.
|
|
132
|
+
*
|
|
133
|
+
* Nicht darin: `dialect_mismatch` (das Paket vergibt ihn auch, wenn ein Rand
|
|
134
|
+
* ohne `/v3` geantwortet hat, dessen Handler gelaufen sein kann) und
|
|
135
|
+
* `response_translation_failed` (der Handler lief; auch `handled: false`
|
|
136
|
+
* heisst nur, dass seine Antwort ein Fehler war, und der kann hinter dem
|
|
137
|
+
* Anbieteraufruf entstanden sein). Der Sammelfang der Handler ("Error hobex
|
|
138
|
+
* details", "Fehler beim Capturing") antwortet ohne Code.
|
|
139
|
+
*/
|
|
140
|
+
export declare const PAYMENT_CALL_REJECTED_CODES: readonly string[];
|
|
113
141
|
/**
|
|
114
142
|
* Codes, die das Paket selbst vergibt, nicht der Server: `route_missing`
|
|
115
143
|
* (HTML statt Backend, der Aufruf kam nie an) und `response_unreadable`
|
|
@@ -146,7 +174,10 @@ export declare class KasseneckApiError extends Error {
|
|
|
146
174
|
* `cancellation_outcome_unknown`, `response_unreadable` (Erfolg gemeldet,
|
|
147
175
|
* Antwort eines Aufrufs mit Wirkung aber unlesbar) und
|
|
148
176
|
* `response_translation_failed` (ausser mit `details.handled === false`);
|
|
149
|
-
* sonst `'rejected'`.
|
|
177
|
+
* sonst `'rejected'`. Auf den Geldwegen (`hobexPayApi`, `hobexRefundApi`,
|
|
178
|
+
* `stripeCaptureIntent`) umgekehrt: `'rejected'` nur mit einem Code aus
|
|
179
|
+
* [PAYMENT_CALL_REJECTED_CODES], ohne Code und mit jedem anderen Code
|
|
180
|
+
* `'unknown'`. Bei `'unknown'` nie wiederholen, sondern nachlesen.
|
|
150
181
|
*/
|
|
151
182
|
readonly outcome: ErrorOutcome;
|
|
152
183
|
constructor(functionName: string, serverMessage: string, details?: Record<string, unknown>, code?: string);
|
|
@@ -215,7 +215,77 @@ const AUSGANG_UNKLAR_CODES = new Set([
|
|
|
215
215
|
'cancellation_outcome_unknown',
|
|
216
216
|
'response_unreadable',
|
|
217
217
|
]);
|
|
218
|
-
|
|
218
|
+
/**
|
|
219
|
+
* Aufrufe, die Geld bewegen: `hobexPayApi` belastet eine Karte,
|
|
220
|
+
* `hobexRefundApi` erstattet, `stripeCaptureIntent` zieht eine vorgemerkte
|
|
221
|
+
* Zahlung ein. Ihre Handler antworten auch NACH dem Anbieteraufruf mit einer
|
|
222
|
+
* Fehlerhuelle ohne Code ("Error hobex details", "Fehler beim Capturing");
|
|
223
|
+
* dort gilt darum umgekehrt: Ausgang unklar, ausser der Code belegt, dass der
|
|
224
|
+
* Anbieter nie gerufen wurde.
|
|
225
|
+
*/
|
|
226
|
+
const GELDWEGE = new Set(['hobexPayApi', 'hobexRefundApi', 'stripeCaptureIntent']);
|
|
227
|
+
/**
|
|
228
|
+
* Codes, die auf einem Geldweg `outcome: 'rejected'` ergeben; jeder andere
|
|
229
|
+
* Code und eine Huelle ohne Code sind dort `'unknown'`. Aufgenommen ist nur,
|
|
230
|
+
* was entsteht, bevor das Backend den Zahlungsanbieter anspricht (Vertrag
|
|
231
|
+
* v3, `errorCodes`; dieselbe Liste wie `paymentCallRejectedCodes` im
|
|
232
|
+
* Dart-Zwilling):
|
|
233
|
+
*
|
|
234
|
+
* - `errorCodes.auth` ohne die sieben des Partner-Zugangs (18 Codes):
|
|
235
|
+
* Anmeldung und Pruefung in `checkRequest` laufen vor jeder Zeile des
|
|
236
|
+
* Handlers; `validation` heisst dort Pflichtfeld fehlt oder falscher Typ.
|
|
237
|
+
* Der Partner-Zugang trifft diese `api_key`-Aufrufe mit Kassen-Token nie.
|
|
238
|
+
* - aus `errorCodes.edge`: `not_found` (unbekannter Endpunkt, HTTP 404) und
|
|
239
|
+
* `internal_translation_error` (die Anfrage liess sich nicht uebersetzen,
|
|
240
|
+
* es wurde nichts ausgefuehrt); `validation` des Rands (unbekannte Felder,
|
|
241
|
+
* Rumpf ohne Objekt) steht schon oben.
|
|
242
|
+
* - `module_inactive` und `not_permitted`: das Modul- bzw. Rechte-Tor steht
|
|
243
|
+
* ebenfalls vor dem Anbieter.
|
|
244
|
+
* - `route_missing` (vergibt das Paket): HTML ohne `/v3`-Kennzeichen, keine
|
|
245
|
+
* Function hat den Aufruf gesehen.
|
|
246
|
+
*
|
|
247
|
+
* Nicht darin: `dialect_mismatch` (das Paket vergibt ihn auch, wenn ein Rand
|
|
248
|
+
* ohne `/v3` geantwortet hat, dessen Handler gelaufen sein kann) und
|
|
249
|
+
* `response_translation_failed` (der Handler lief; auch `handled: false`
|
|
250
|
+
* heisst nur, dass seine Antwort ein Fehler war, und der kann hinter dem
|
|
251
|
+
* Anbieteraufruf entstanden sein). Der Sammelfang der Handler ("Error hobex
|
|
252
|
+
* details", "Fehler beim Capturing") antwortet ohne Code.
|
|
253
|
+
*/
|
|
254
|
+
export const PAYMENT_CALL_REJECTED_CODES = Object.freeze([
|
|
255
|
+
// errorCodes.auth ohne Partner-Zugang
|
|
256
|
+
'method_not_allowed',
|
|
257
|
+
'validation',
|
|
258
|
+
'cashregister_token_missing',
|
|
259
|
+
'cashregister_token_invalid',
|
|
260
|
+
'cashregister_not_found',
|
|
261
|
+
'account_not_found',
|
|
262
|
+
'live_not_enabled',
|
|
263
|
+
'unauthorized',
|
|
264
|
+
'mfa_required',
|
|
265
|
+
'user_verification_failed',
|
|
266
|
+
'admin_required',
|
|
267
|
+
'register_user_not_allowed',
|
|
268
|
+
'register_user_no_business',
|
|
269
|
+
'register_user_not_found',
|
|
270
|
+
'user_disabled',
|
|
271
|
+
'session_expired',
|
|
272
|
+
'cashregister_not_assigned',
|
|
273
|
+
'session_other_cashregister',
|
|
274
|
+
// errorCodes.edge vor dem Handler (validation steht oben)
|
|
275
|
+
'not_found',
|
|
276
|
+
'internal_translation_error',
|
|
277
|
+
// Modul- und Rechte-Tor
|
|
278
|
+
'module_inactive',
|
|
279
|
+
'not_permitted',
|
|
280
|
+
// vom Paket vergeben
|
|
281
|
+
'route_missing',
|
|
282
|
+
]);
|
|
283
|
+
const GELDWEG_ABGELEHNT = new Set(PAYMENT_CALL_REJECTED_CODES);
|
|
284
|
+
function ausgangAusCode(functionName, code, details) {
|
|
285
|
+
// `functionName` kann den Vorgang tragen (`financeWebService/<method>`).
|
|
286
|
+
if (GELDWEGE.has(functionName.split('/')[0])) {
|
|
287
|
+
return code !== undefined && GELDWEG_ABGELEHNT.has(code) ? 'rejected' : 'unknown';
|
|
288
|
+
}
|
|
219
289
|
if (code === undefined)
|
|
220
290
|
return 'rejected';
|
|
221
291
|
if (AUSGANG_UNKLAR_CODES.has(code))
|
|
@@ -259,7 +329,10 @@ export class KasseneckApiError extends Error {
|
|
|
259
329
|
* `cancellation_outcome_unknown`, `response_unreadable` (Erfolg gemeldet,
|
|
260
330
|
* Antwort eines Aufrufs mit Wirkung aber unlesbar) und
|
|
261
331
|
* `response_translation_failed` (ausser mit `details.handled === false`);
|
|
262
|
-
* sonst `'rejected'`.
|
|
332
|
+
* sonst `'rejected'`. Auf den Geldwegen (`hobexPayApi`, `hobexRefundApi`,
|
|
333
|
+
* `stripeCaptureIntent`) umgekehrt: `'rejected'` nur mit einem Code aus
|
|
334
|
+
* [PAYMENT_CALL_REJECTED_CODES], ohne Code und mit jedem anderen Code
|
|
335
|
+
* `'unknown'`. Bei `'unknown'` nie wiederholen, sondern nachlesen.
|
|
263
336
|
*/
|
|
264
337
|
outcome;
|
|
265
338
|
constructor(functionName, serverMessage, details = {}, code) {
|
|
@@ -271,7 +344,7 @@ export class KasseneckApiError extends Error {
|
|
|
271
344
|
// den Details. So bleibt die Klasse fuer beide Ablageorte dieselbe.
|
|
272
345
|
const kandidat = code !== undefined ? code : details['code'];
|
|
273
346
|
this.code = typeof kandidat === 'string' && BEZEICHNER.test(kandidat) ? kandidat : undefined;
|
|
274
|
-
this.outcome = ausgangAusCode(this.code, details);
|
|
347
|
+
this.outcome = ausgangAusCode(functionName, this.code, details);
|
|
275
348
|
}
|
|
276
349
|
}
|
|
277
350
|
const GRUND_TEXT = {
|
|
@@ -47,8 +47,9 @@ export interface HobexTransactionIdOptions {
|
|
|
47
47
|
* nicht.
|
|
48
48
|
*
|
|
49
49
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
50
|
-
* unlesbare Antwort
|
|
51
|
-
*
|
|
50
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
51
|
+
* der Ablehnungscodes, README `outcome`) kann die Karte belastet sein: den Stand
|
|
52
|
+
* ueber die Transaktionskennung nachlesen, nicht ein zweites Mal belasten.
|
|
52
53
|
*/
|
|
53
54
|
export declare function hobexPay(transport: InternerTransport, options: HobexPayOptions): Promise<HobexReceipt>;
|
|
54
55
|
/**
|
|
@@ -62,8 +63,10 @@ export declare function hobexPay(transport: InternerTransport, options: HobexPay
|
|
|
62
63
|
* Wahrheitswert waere hier also immer `true` — eine Luege ueber den
|
|
63
64
|
* Informationsgehalt, an der ein Aufrufer ein `if` aufhaengt, das nie greift.
|
|
64
65
|
* Misserfolg kommt als geworfener Fehler: eine Fehlerhuelle als
|
|
65
|
-
* [KasseneckApiError]
|
|
66
|
-
*
|
|
66
|
+
* [KasseneckApiError], `'rejected'` nur mit einem der Ablehnungscodes
|
|
67
|
+
* (README `outcome`); ohne Code oder mit anderem Code, bei Netz,
|
|
68
|
+
* Zeitlimit, HTTP 5xx und unlesbarer Erfolgsantwort `outcome: 'unknown'`
|
|
69
|
+
* (die Erstattung kann gelaufen sein).
|
|
67
70
|
* Ein `false` an dieser Stelle luede zum zweiten Versuch ein, also zur
|
|
68
71
|
* doppelten Erstattung. **Nie wiederholen**, sondern den Stand nachlesen.
|
|
69
72
|
*
|
|
@@ -38,8 +38,9 @@ const ENDPUNKT_REFUND = 'hobexRefundApi';
|
|
|
38
38
|
* nicht.
|
|
39
39
|
*
|
|
40
40
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
41
|
-
* unlesbare Antwort
|
|
42
|
-
*
|
|
41
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
42
|
+
* der Ablehnungscodes, README `outcome`) kann die Karte belastet sein: den Stand
|
|
43
|
+
* ueber die Transaktionskennung nachlesen, nicht ein zweites Mal belasten.
|
|
43
44
|
*/
|
|
44
45
|
export async function hobexPay(transport, options) {
|
|
45
46
|
const params = zahlungsNutzlast(ENDPUNKT_PAY, options);
|
|
@@ -64,8 +65,10 @@ export async function hobexPay(transport, options) {
|
|
|
64
65
|
* Wahrheitswert waere hier also immer `true` — eine Luege ueber den
|
|
65
66
|
* Informationsgehalt, an der ein Aufrufer ein `if` aufhaengt, das nie greift.
|
|
66
67
|
* Misserfolg kommt als geworfener Fehler: eine Fehlerhuelle als
|
|
67
|
-
* [KasseneckApiError]
|
|
68
|
-
*
|
|
68
|
+
* [KasseneckApiError], `'rejected'` nur mit einem der Ablehnungscodes
|
|
69
|
+
* (README `outcome`); ohne Code oder mit anderem Code, bei Netz,
|
|
70
|
+
* Zeitlimit, HTTP 5xx und unlesbarer Erfolgsantwort `outcome: 'unknown'`
|
|
71
|
+
* (die Erstattung kann gelaufen sein).
|
|
69
72
|
* Ein `false` an dieser Stelle luede zum zweiten Versuch ein, also zur
|
|
70
73
|
* doppelten Erstattung. **Nie wiederholen**, sondern den Stand nachlesen.
|
|
71
74
|
*
|
|
@@ -59,6 +59,8 @@ export declare function createStripeLink(transport: InternerTransport, options:
|
|
|
59
59
|
* Pflichtparameter.
|
|
60
60
|
*
|
|
61
61
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
62
|
-
* unlesbare Antwort
|
|
62
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
63
|
+
* der Ablehnungscodes, README `outcome`) kann der Einzug gelaufen sein: den Stand
|
|
64
|
+
* nachlesen.
|
|
63
65
|
*/
|
|
64
66
|
export declare function stripeCaptureIntent(transport: InternerTransport, stripeSessionId: string): Promise<StripeCaptureResult>;
|
|
@@ -70,7 +70,9 @@ export async function createStripeLink(transport, options) {
|
|
|
70
70
|
* Pflichtparameter.
|
|
71
71
|
*
|
|
72
72
|
* **Nie wiederholen.** Bei `isOutcomeUnknown(e)` (Netz, Zeitlimit, HTTP 5xx,
|
|
73
|
-
* unlesbare Antwort
|
|
73
|
+
* unlesbare Antwort, Fehlerhuelle ohne Code oder mit einem Code ausserhalb
|
|
74
|
+
* der Ablehnungscodes, README `outcome`) kann der Einzug gelaufen sein: den Stand
|
|
75
|
+
* nachlesen.
|
|
74
76
|
*/
|
|
75
77
|
export async function stripeCaptureIntent(transport, stripeSessionId) {
|
|
76
78
|
if (typeof stripeSessionId !== 'string' || !stripeSessionId.trim()) {
|
package/dist/esm/version.d.ts
CHANGED
package/dist/esm/version.js
CHANGED
package/fixtures/pos-texts.json
CHANGED
package/fixtures/surface.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kreiseck/kasseneck-api",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.4",
|
|
4
4
|
"description": "Austrian fiscal cash register (RKSV) client for JavaScript and TypeScript: signed receipts, cancellations, card payments, receipt printing (ESC/POS), invoices. RKSV-Registrierkasse für JavaScript und TypeScript.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Kreiseck",
|