@fire-spark/payments-clisitef-pinpad-rn 0.7.0 → 0.7.1

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/dist/index.d.ts CHANGED
@@ -17,12 +17,17 @@ type ClisitefPinPadOptions = {
17
17
  timeZone?: string;
18
18
  now?: () => Date;
19
19
  confirmationTimeoutMs?: number;
20
+ /**
21
+ * Payment deadline (`policy.timeout_ms`); defaults to 180 s. A
22
+ * `runtime.timeout_ms` in the payment or method config overrides it.
23
+ */
24
+ timeoutMs?: number;
20
25
  };
21
26
  /**
22
27
  * CliSiTef (Software Express) on the kiosk pinpad, Brazil. One adapter per
23
28
  * modality payment (DEBIT / CREDIT / VOUCHER in `payments.config`). The
24
- * pinpad waits on the customer: give the payment a `runtime.timeout_ms`
25
- * well above the 30 s default (e.g. 90 000).
29
+ * pinpad waits on the customer, so the deadline is `timeoutMs` instead of
30
+ * the 30 s library default.
26
31
  */
27
32
  declare const clisitefPinPadPayments: (options?: ClisitefPinPadOptions) => PaymentAdapter;
28
33
  //#endregion
@@ -80,6 +85,11 @@ declare const CLISITEF_CANCEL_CODES: ReadonlySet<number>;
80
85
  declare const CLISITEF_INCONCLUSIVE_CODES: ReadonlySet<number>;
81
86
  /** Approved (`stage 1`) without `stage 2`: undo (legacy `CONFIRMATION_TIMEOUT_MS`). */
82
87
  declare const CLISITEF_CONFIRMATION_TIMEOUT_MS = 60000;
88
+ /**
89
+ * Payment deadline: covers the pinpad table load (`OBTENDO REGISTRO`), which
90
+ * can take minutes, plus card and PIN entry.
91
+ */
92
+ declare const CLISITEF_PAYMENT_TIMEOUT_MS = 180000;
83
93
  /** Legacy operator when the merchant config has none. */
84
94
  declare const CLISITEF_DEFAULT_OPERATOR = "KIOSKO_BR";
85
95
  /** Device-wide record of the last transaction, to undo it after a crash. */
@@ -204,4 +214,4 @@ type ClisitefTransactionInput = {
204
214
  */
205
215
  declare const runClisitefTransaction: (input: ClisitefTransactionInput) => Promise<ClisitefOutcome>;
206
216
  //#endregion
207
- export { CLISITEF_CANCEL_CODES, CLISITEF_CAPTURE_FIELDS, CLISITEF_COMMAND, CLISITEF_CONFIRMATION_TIMEOUT_MS, CLISITEF_DEFAULT_OPERATOR, CLISITEF_FIELD, CLISITEF_INCONCLUSIVE_CODES, CLISITEF_NO, CLISITEF_PINPAD_TYPES, CLISITEF_STORAGE_KEY, CLISITEF_YES, ClisitefFields, ClisitefModality, ClisitefOutcome, ClisitefOutcomeStatus, ClisitefPinPadOptions, ClisitefPinPadSettings, ClisitefTransactionInput, ClisitefTransactionRecord, ClisitefTransactionState, clisitefDetails, clisitefLast4, clisitefMetadata, clisitefPinPadCapabilities, clisitefPinPadDeviceFields, clisitefPinPadErrors, clisitefPinPadPayments, isOpen, readClisitefPinPadSettings, readTransaction, runClisitefTransaction, writeTransaction };
217
+ export { CLISITEF_CANCEL_CODES, CLISITEF_CAPTURE_FIELDS, CLISITEF_COMMAND, CLISITEF_CONFIRMATION_TIMEOUT_MS, CLISITEF_DEFAULT_OPERATOR, CLISITEF_FIELD, CLISITEF_INCONCLUSIVE_CODES, CLISITEF_NO, CLISITEF_PAYMENT_TIMEOUT_MS, CLISITEF_PINPAD_TYPES, CLISITEF_STORAGE_KEY, CLISITEF_YES, ClisitefFields, ClisitefModality, ClisitefOutcome, ClisitefOutcomeStatus, ClisitefPinPadOptions, ClisitefPinPadSettings, ClisitefTransactionInput, ClisitefTransactionRecord, ClisitefTransactionState, clisitefDetails, clisitefLast4, clisitefMetadata, clisitefPinPadCapabilities, clisitefPinPadDeviceFields, clisitefPinPadErrors, clisitefPinPadPayments, isOpen, readClisitefPinPadSettings, readTransaction, runClisitefTransaction, writeTransaction };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PaymentError, createPaymentError, definePaymentErrors, toPaymentError } from "@fire-spark/payments";
2
- import { CLISITEF_ABORT_FLAG, CLISITEF_CONFIRM, CLISITEF_MODALITY, CLISITEF_RESULT, CLISITEF_TIMEOUT_CODE, clisitef, clisitefAdditionalParams, clisitefFiscalDateTime, formatClisitefAmount, parseClisitefMenu } from "@fire-spark/payments-clisitef-client";
2
+ import { CLISITEF_ABORT_FLAG, CLISITEF_CONFIRM, CLISITEF_MODALITY, CLISITEF_RESULT, CLISITEF_TIMEOUT_CODE, clisitef, clisitefAdditionalParams, clisitefDebug, clisitefDebugCall, clisitefFiscalDateTime, formatClisitefAmount, parseClisitefMenu } from "@fire-spark/payments-clisitef-client";
3
3
  //#region src/constants.ts
4
4
  /**
5
5
  * `onData` commands handled by the adapter (Fiserv "Tabela de códigos de
@@ -71,6 +71,11 @@ const CLISITEF_INCONCLUSIVE_CODES = /* @__PURE__ */ new Set([
71
71
  ]);
72
72
  /** Approved (`stage 1`) without `stage 2`: undo (legacy `CONFIRMATION_TIMEOUT_MS`). */
73
73
  const CLISITEF_CONFIRMATION_TIMEOUT_MS = 6e4;
74
+ /**
75
+ * Payment deadline: covers the pinpad table load (`OBTENDO REGISTRO`), which
76
+ * can take minutes, plus card and PIN entry.
77
+ */
78
+ const CLISITEF_PAYMENT_TIMEOUT_MS = 18e4;
74
79
  /** Legacy operator when the merchant config has none. */
75
80
  const CLISITEF_DEFAULT_OPERATOR = "KIOSKO_BR";
76
81
  /** Device-wide record of the last transaction, to undo it after a crash. */
@@ -296,6 +301,11 @@ const readClisitefPinPadSettings = (config, device) => {
296
301
  };
297
302
  Object.assign(values, more);
298
303
  const missing = Object.keys(values).filter((key) => !values[key]);
304
+ clisitefDebug("pinpad.settings", "read", {
305
+ config,
306
+ device,
307
+ missing
308
+ });
299
309
  if (missing.length) throw notConfigured(missing);
300
310
  if (!isModality(modality)) throw notConfigured(["a valid modality"]);
301
311
  return {
@@ -324,6 +334,7 @@ const isRecord = (value) => {
324
334
  };
325
335
  const readTransaction = async (storage) => {
326
336
  const raw = await storage.get(CLISITEF_STORAGE_KEY);
337
+ clisitefDebug("pinpad.store", "read", { raw });
327
338
  if (!raw) return null;
328
339
  try {
329
340
  const parsed = JSON.parse(raw);
@@ -333,6 +344,7 @@ const readTransaction = async (storage) => {
333
344
  }
334
345
  };
335
346
  const writeTransaction = async (storage, record) => {
347
+ clisitefDebug("pinpad.store", `write ${record.state}`, record);
336
348
  await storage.set(CLISITEF_STORAGE_KEY, JSON.stringify(record));
337
349
  };
338
350
  const isOpen = (record) => {
@@ -391,7 +403,23 @@ const runClisitefTransaction = (input) => {
391
403
  let queue = Promise.resolve();
392
404
  let resolve = () => void 0;
393
405
  const done = new Promise((r) => resolve = r);
406
+ const log = (event, data) => {
407
+ const flags = {
408
+ captured,
409
+ approved,
410
+ closing,
411
+ aborted
412
+ };
413
+ clisitefDebug("pinpad.transaction", event, {
414
+ ...data && typeof data === "object" ? data : { value: data },
415
+ flags
416
+ });
417
+ };
394
418
  const settle = (status, reason) => {
419
+ log(`settle ${status}`, {
420
+ ...reason,
421
+ fields: Object.fromEntries(fields)
422
+ });
395
423
  clearTimeout(watchdog);
396
424
  for (const subscription of subscriptions) subscription.remove();
397
425
  signal.removeEventListener("abort", onAbort);
@@ -403,6 +431,7 @@ const runClisitefTransaction = (input) => {
403
431
  });
404
432
  };
405
433
  const undo = async (reason) => {
434
+ log("undo (finishTransaction 0)", reason);
406
435
  try {
407
436
  const p1 = {
408
437
  confirm: CLISITEF_CONFIRM.UNDO,
@@ -418,6 +447,7 @@ const runClisitefTransaction = (input) => {
418
447
  }
419
448
  };
420
449
  const close = async (reason) => {
450
+ log("close", reason);
421
451
  if (closing) return;
422
452
  closing = true;
423
453
  if (!approved) await client.abortTransaction(CLISITEF_ABORT_FLAG).catch(() => 0);
@@ -425,6 +455,7 @@ const runClisitefTransaction = (input) => {
425
455
  settle("declined", reason);
426
456
  };
427
457
  function onAbort() {
458
+ log("signal aborted (payment deadline)");
428
459
  aborted = true;
429
460
  close({
430
461
  code: null,
@@ -432,10 +463,18 @@ const runClisitefTransaction = (input) => {
432
463
  });
433
464
  }
434
465
  const reply = async (data) => {
466
+ log("reply", {
467
+ data,
468
+ skipped: closing
469
+ });
435
470
  if (closing) return;
436
471
  await client.continueTransaction(data);
437
472
  };
438
473
  const onData = async (event) => {
474
+ log("onData", {
475
+ ...event,
476
+ title
477
+ });
439
478
  const { command, input: text } = event;
440
479
  if (command === CLISITEF_COMMAND.STORE_FIELD) {
441
480
  fields.set(event.fieldId, text);
@@ -459,16 +498,24 @@ const runClisitefTransaction = (input) => {
459
498
  }
460
499
  if (SILENT.has(command)) return reply("");
461
500
  if (command === CLISITEF_COMMAND.CONFIRM) {
501
+ log("ui.confirm → in", { text: text.trim() || title });
462
502
  const yes = await ui.confirm({ text: text.trim() || title });
503
+ log("ui.confirm ← out", { yes });
463
504
  return reply(yes ? "0" : "1");
464
505
  }
465
506
  if (command === CLISITEF_COMMAND.MENU) {
466
507
  const options = parseClisitefMenu(text);
467
508
  const label = title || "Selecione uma opção";
468
- return reply(await ui.select({
509
+ log("ui.select → in", {
469
510
  title: label,
470
511
  options
471
- }));
512
+ });
513
+ const picked = await ui.select({
514
+ title: label,
515
+ options
516
+ });
517
+ log("ui.select ← out", { picked });
518
+ return reply(picked);
472
519
  }
473
520
  if (READS.has(command)) {
474
521
  const label = text.trim() || title || "Informe o dado";
@@ -478,7 +525,10 @@ const runClisitefTransaction = (input) => {
478
525
  type: inputType(command),
479
526
  maxLength: max
480
527
  };
481
- return reply(await ui.input(p1));
528
+ log("ui.input → in", p1);
529
+ const value = await ui.input(p1);
530
+ log("ui.input ← out", { value });
531
+ return reply(value);
482
532
  }
483
533
  const message = `Unsupported CliSiTef command ${command}`;
484
534
  return close({
@@ -489,6 +539,7 @@ const runClisitefTransaction = (input) => {
489
539
  const confirm = () => {
490
540
  const message = "CliSiTef did not close the confirmation";
491
541
  const expire = () => {
542
+ log("confirmation watchdog expired", { skipped: closing });
492
543
  if (closing) return;
493
544
  closing = true;
494
545
  undo({
@@ -501,6 +552,10 @@ const runClisitefTransaction = (input) => {
501
552
  confirm: CLISITEF_CONFIRM.CONFIRM,
502
553
  ...input.finish
503
554
  };
555
+ log("confirm (finishTransaction 1)", {
556
+ ...p1,
557
+ watchdogMs: input.confirmationTimeoutMs
558
+ });
504
559
  client.finishTransaction(p1).catch((error) => {
505
560
  if (closing) return;
506
561
  closing = true;
@@ -513,6 +568,11 @@ const runClisitefTransaction = (input) => {
513
568
  };
514
569
  const onResult = async (event) => {
515
570
  const { stage, resultCode: code } = event;
571
+ log("onTransactionResult", {
572
+ stage,
573
+ code,
574
+ skipped: closing
575
+ });
516
576
  if (closing) return;
517
577
  if (stage === 1 && code === CLISITEF_RESULT.OK) {
518
578
  approved = true;
@@ -552,6 +612,10 @@ const runClisitefTransaction = (input) => {
552
612
  code: errorCode(error),
553
613
  message: errorMessage(error)
554
614
  };
615
+ log("handler threw", {
616
+ ...reason,
617
+ error
618
+ });
555
619
  if (closing) return;
556
620
  await close({
557
621
  ...reason,
@@ -560,6 +624,10 @@ const runClisitefTransaction = (input) => {
560
624
  });
561
625
  };
562
626
  const begin = async () => {
627
+ log("begin", {
628
+ start: input.start,
629
+ finish: input.finish
630
+ });
563
631
  if (signal.aborted) {
564
632
  aborted = true;
565
633
  return settle("declined", {
@@ -665,6 +733,16 @@ const outcomeError = (outcome, attempt) => {
665
733
  fallback
666
734
  });
667
735
  };
736
+ const debugContext = (ctx) => {
737
+ const { attemptReference, attempt, amount, config, deviceSettings } = ctx;
738
+ return {
739
+ attemptReference,
740
+ attempt,
741
+ amount,
742
+ config,
743
+ deviceSettings
744
+ };
745
+ };
668
746
  const terminalError = (error) => {
669
747
  const message = error instanceof Error ? error.message : String(error);
670
748
  return {
@@ -676,19 +754,24 @@ const terminalError = (error) => {
676
754
  /**
677
755
  * CliSiTef (Software Express) on the kiosk pinpad, Brazil. One adapter per
678
756
  * modality payment (DEBIT / CREDIT / VOUCHER in `payments.config`). The
679
- * pinpad waits on the customer: give the payment a `runtime.timeout_ms`
680
- * well above the 30 s default (e.g. 90 000).
757
+ * pinpad waits on the customer, so the deadline is `timeoutMs` instead of
758
+ * the 30 s library default.
681
759
  */
682
760
  const clisitefPinPadPayments = (options = {}) => {
683
761
  const client = options.client ?? clisitef;
684
762
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
685
763
  const confirmationMs = options.confirmationTimeoutMs ?? 6e4;
764
+ const timeoutMs = options.timeoutMs ?? 18e4;
686
765
  const lock = createLock();
687
766
  const storageOf = (ctx) => {
688
767
  return options.storage ?? ctx.storage;
689
768
  };
690
769
  const configure = async (settings) => {
691
770
  const code = await client.configure(settings.configure);
771
+ clisitefDebug("pinpad.adapter.configure", "result", {
772
+ code,
773
+ settings
774
+ });
692
775
  if (code === 0) return null;
693
776
  client.invalidate();
694
777
  return toPaymentError(clisitefPinPadErrors, {
@@ -701,6 +784,10 @@ const clisitefPinPadPayments = (options = {}) => {
701
784
  const { fiscalCoupon, fiscalDate, time } = record;
702
785
  const count = client.getQttPendingTransactions;
703
786
  const pending = await count(fiscalDate, fiscalCoupon).catch(() => null);
787
+ clisitefDebug("pinpad.adapter.recover", "pending", {
788
+ pending,
789
+ record
790
+ });
704
791
  if (pending === null) return record;
705
792
  let next;
706
793
  if (pending > 0) {
@@ -740,6 +827,7 @@ const clisitefPinPadPayments = (options = {}) => {
740
827
  error
741
828
  };
742
829
  }
830
+ clisitefDebug("pinpad.adapter.recover", `→ ${next.state}`, next);
743
831
  await writeTransaction(storage, next);
744
832
  return next;
745
833
  };
@@ -750,6 +838,10 @@ const clisitefPinPadPayments = (options = {}) => {
750
838
  const storage = storageOf(ctx);
751
839
  let record = await readTransaction(storage);
752
840
  if (!error && record && isOpen(record)) record = await recover(storage, record);
841
+ clisitefDebug("pinpad.adapter.prepare", "done", {
842
+ error,
843
+ record
844
+ });
753
845
  return {
754
846
  settings,
755
847
  error,
@@ -855,6 +947,11 @@ const clisitefPinPadPayments = (options = {}) => {
855
947
  ...t1,
856
948
  ...t2
857
949
  });
950
+ const fields = Object.fromEntries(outcome.fields);
951
+ clisitefDebug("pinpad.adapter.charge", "outcome", {
952
+ ...outcome,
953
+ fields
954
+ });
858
955
  const metadata = metadataOf(outcome.fields);
859
956
  if (outcome.status === "confirmed") {
860
957
  const details = clisitefDetails(metadata);
@@ -916,8 +1013,14 @@ const clisitefPinPadPayments = (options = {}) => {
916
1013
  error: void 0
917
1014
  };
918
1015
  };
919
- const operation = (run) => {
1016
+ const operation = (run, name = "terminal") => {
920
1017
  return (ctx) => {
1018
+ const scope = `pinpad.terminal.${name}`;
1019
+ const input = {
1020
+ config: ctx.config,
1021
+ deviceSettings: ctx.deviceSettings
1022
+ };
1023
+ const traced = () => clisitefDebugCall(scope, input, task);
921
1024
  const task = async () => {
922
1025
  try {
923
1026
  const data = await run(ctx);
@@ -930,7 +1033,7 @@ const clisitefPinPadPayments = (options = {}) => {
930
1033
  return terminalError(error);
931
1034
  }
932
1035
  };
933
- return lock(task);
1036
+ return lock(traced);
934
1037
  };
935
1038
  };
936
1039
  const terminal = {
@@ -940,15 +1043,17 @@ const clisitefPinPadPayments = (options = {}) => {
940
1043
  const error = await configure(s1);
941
1044
  if (error) throw new Error(error.message);
942
1045
  return "CliSiTef configured";
943
- }),
944
- test: operation(async () => `CliSiTef ${await client.getVersion()}`),
945
- status: operation(async () => client.getHealth() ?? {}),
1046
+ }, "init"),
1047
+ test: operation(async () => {
1048
+ return `CliSiTef ${await client.getVersion()}`;
1049
+ }, "test"),
1050
+ status: operation(async () => client.getHealth() ?? {}, "status"),
946
1051
  extra: [{
947
1052
  key: "submit_pending_messages",
948
1053
  label: "Send pending messages",
949
1054
  run: operation(async () => {
950
1055
  return `Pending messages sent (${await client.submitPendingMessages()})`;
951
- })
1056
+ }, "submit_pending_messages")
952
1057
  }, {
953
1058
  key: "release_pinpad",
954
1059
  label: "Release pinpad",
@@ -957,7 +1062,7 @@ const clisitefPinPadPayments = (options = {}) => {
957
1062
  await client.disconnectSitef();
958
1063
  client.invalidate();
959
1064
  return "Pinpad released";
960
- })
1065
+ }, "release_pinpad")
961
1066
  }]
962
1067
  };
963
1068
  return {
@@ -966,12 +1071,31 @@ const clisitefPinPadPayments = (options = {}) => {
966
1071
  deviceFields: clisitefPinPadDeviceFields,
967
1072
  errors: clisitefPinPadErrors,
968
1073
  capabilities: clisitefPinPadCapabilities,
969
- start: (ctx) => lock(() => charge(ctx)),
970
- query: (ctx, result) => lock(() => query(ctx, result)),
971
- cancel: (ctx, result) => lock(() => cancel(ctx, result)),
1074
+ policy: { timeout_ms: timeoutMs },
1075
+ start: (ctx) => {
1076
+ const run = () => charge(ctx);
1077
+ const traced = () => clisitefDebugCall("pinpad.start", debugContext(ctx), run);
1078
+ return lock(traced);
1079
+ },
1080
+ query: (ctx, result) => {
1081
+ const input = {
1082
+ ctx: debugContext(ctx),
1083
+ result
1084
+ };
1085
+ const run = () => query(ctx, result);
1086
+ return lock(() => clisitefDebugCall("pinpad.query", input, run));
1087
+ },
1088
+ cancel: (ctx, result) => {
1089
+ const input = {
1090
+ ctx: debugContext(ctx),
1091
+ result
1092
+ };
1093
+ const run = () => cancel(ctx, result);
1094
+ return lock(() => clisitefDebugCall("pinpad.cancel", input, run));
1095
+ },
972
1096
  reversalFor: (result) => result.status === "PAID" ? "manual" : "cancel",
973
1097
  terminal
974
1098
  };
975
1099
  };
976
1100
  //#endregion
977
- export { CLISITEF_CANCEL_CODES, CLISITEF_CAPTURE_FIELDS, CLISITEF_COMMAND, CLISITEF_CONFIRMATION_TIMEOUT_MS, CLISITEF_DEFAULT_OPERATOR, CLISITEF_FIELD, CLISITEF_INCONCLUSIVE_CODES, CLISITEF_NO, CLISITEF_PINPAD_TYPES, CLISITEF_STORAGE_KEY, CLISITEF_YES, clisitefDetails, clisitefLast4, clisitefMetadata, clisitefPinPadCapabilities, clisitefPinPadDeviceFields, clisitefPinPadErrors, clisitefPinPadPayments, isOpen, readClisitefPinPadSettings, readTransaction, runClisitefTransaction, writeTransaction };
1101
+ export { CLISITEF_CANCEL_CODES, CLISITEF_CAPTURE_FIELDS, CLISITEF_COMMAND, CLISITEF_CONFIRMATION_TIMEOUT_MS, CLISITEF_DEFAULT_OPERATOR, CLISITEF_FIELD, CLISITEF_INCONCLUSIVE_CODES, CLISITEF_NO, CLISITEF_PAYMENT_TIMEOUT_MS, CLISITEF_PINPAD_TYPES, CLISITEF_STORAGE_KEY, CLISITEF_YES, clisitefDetails, clisitefLast4, clisitefMetadata, clisitefPinPadCapabilities, clisitefPinPadDeviceFields, clisitefPinPadErrors, clisitefPinPadPayments, isOpen, readClisitefPinPadSettings, readTransaction, runClisitefTransaction, writeTransaction };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fire-spark/payments-clisitef-pinpad-rn",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Fire Spark CliSiTef (Software Express) pinpad adapter for Brazil: debit, credit and voucher on Android kiosks",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -17,9 +17,9 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@fire-spark/payments": "^0.7.0",
21
- "@fire-spark/payments-clisitef-client": "^0.7.0",
22
- "@fire-spark/types": "^0.7.0"
20
+ "@fire-spark/payments": "^0.7.1",
21
+ "@fire-spark/payments-clisitef-client": "^0.7.1",
22
+ "@fire-spark/types": "^0.7.1"
23
23
  },
24
24
  "devDependencies": {
25
25
  "tsdown": "^0.22.14",