@pisell/private-materials 6.11.803 → 6.11.804

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.
@@ -542,7 +542,8 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
542
542
  }
543
543
  }, [isActive]);
544
544
  const handleReturnToAdvertisement = (replace = true, reason) => {
545
- if (replace && (paymentPageSessionRef.current || getHasScanRequest() || renderCatalog && (getIsProcessing() || getIsPaymentProcessing()))) return;
545
+ if (paymentPageSessionRef.current) return;
546
+ if (replace && (getHasScanRequest() || renderCatalog && (getIsProcessing() || getIsPaymentProcessing()))) return;
546
547
  if (returningToAdvertisementRef.current) return;
547
548
  returningToAdvertisementRef.current = true;
548
549
  setIsReturningToAdvertisement(true);
@@ -670,6 +671,7 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
670
671
  businessCode,
671
672
  checkoutSnapshot: preparation.runtimeSnapshot
672
673
  }));
674
+ const paymentStatus = payload.orderSnapshot.payment_status === "partially_paid" ? "partially_paid" : "paid";
673
675
  persistKioskSessionView(context.sales.bookingTicket, "catalog");
674
676
  try {
675
677
  yield context.sales.clearCartAndReset();
@@ -678,7 +680,7 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
678
680
  }
679
681
  try {
680
682
  if (!isActiveRef.current || paymentPageSessionRef.current !== session) return;
681
- if (!(yield handOffPaidCheckout(payload))) {
683
+ if (!(paymentStatus === "paid" && (yield handOffPaidCheckout(payload)))) {
682
684
  var _payload$paymentResul;
683
685
  setPaymentResult((_payload$paymentResul = payload.paymentResult) !== null && _payload$paymentResul !== void 0 ? _payload$paymentResul : null);
684
686
  setView("success");
@@ -686,7 +688,7 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
686
688
  onOrderComplete === null || onOrderComplete === void 0 || onOrderComplete({
687
689
  type: "checkout",
688
690
  data: _objectSpread2(_objectSpread2({}, payload), {}, {
689
- status: "paid",
691
+ status: paymentStatus,
690
692
  reason: "paid"
691
693
  }),
692
694
  order_id: payload.orderId,
@@ -87,17 +87,17 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
87
87
  const acceptOutcome = useMemoizedFn(function() {
88
88
  var _ref = _asyncToGenerator(function* (outcome, external) {
89
89
  if (!mountedRef.current || stateRef.current === "complete") return;
90
- if (outcome.kind === "paid") {
90
+ if (outcome.kind === "paid" || outcome.kind === "partial" && external) {
91
91
  var _external$orderSnapsh, _baseSales$getTempOrd2, _utils$getData;
92
92
  transition("complete");
93
93
  retryRef.current = void 0;
94
94
  const orderSnapshot = cloneDeep((external === null || external === void 0 || (_external$orderSnapsh = external.orderSnapshot) === null || _external$orderSnapsh === void 0 ? void 0 : _external$orderSnapsh.tempOrder) || (external === null || external === void 0 ? void 0 : external.orderSnapshot) || ((_baseSales$getTempOrd2 = baseSales.getTempOrder) === null || _baseSales$getTempOrd2 === void 0 ? void 0 : _baseSales$getTempOrd2.call(baseSales)) || {});
95
95
  if (external === null || external === void 0 ? void 0 : external.payments) orderSnapshot.payments = cloneDeep(external.payments);
96
96
  orderSnapshot.order_id = outcome.orderId;
97
- orderSnapshot.payment_status = "paid";
97
+ orderSnapshot.payment_status = outcome.kind === "partial" ? "partially_paid" : "paid";
98
98
  const paymentResult = presentBaseSalesPaymentResult({
99
99
  baseSales,
100
- status: "success",
100
+ status: outcome.kind === "partial" ? "partially-paid" : "success",
101
101
  displayMode: "page",
102
102
  currencySymbol,
103
103
  payments: external === null || external === void 0 ? void 0 : external.payments,
@@ -196,7 +196,7 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
196
196
  }
197
197
  }));
198
198
  const beginAuthorization = useMemoizedFn((_source) => {
199
- var _readPaymentAmount;
199
+ var _globalThis$crypto, _globalThis$crypto$ra;
200
200
  if (stateRef.current !== "idle") return null;
201
201
  if (!authorizationAvailableRef.current) {
202
202
  toast.fail(locales.getText("pisell2.checkout.self-service.empty"));
@@ -208,11 +208,10 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
208
208
  toast.fail(error instanceof Error ? error.message : String(error));
209
209
  return null;
210
210
  }
211
- const token = Symbol("authorization");
211
+ const token = ((_globalThis$crypto = globalThis.crypto) === null || _globalThis$crypto === void 0 || (_globalThis$crypto$ra = _globalThis$crypto.randomUUID) === null || _globalThis$crypto$ra === void 0 ? void 0 : _globalThis$crypto$ra.call(_globalThis$crypto)) || `kiosk-payment-${Date.now()}-${Math.random().toString(36).slice(2)}`;
212
212
  authorizationRef.current = {
213
213
  token,
214
- settling: false,
215
- amount: (_readPaymentAmount = readPaymentAmount(baseSales)) !== null && _readPaymentAmount !== void 0 ? _readPaymentAmount : 0
214
+ settling: false
216
215
  };
217
216
  transition("authorizing");
218
217
  const release = (() => {
@@ -221,6 +220,7 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
221
220
  authorizationRef.current = void 0;
222
221
  transition("idle");
223
222
  });
223
+ release.paymentRequestId = token;
224
224
  release.isActive = () => {
225
225
  var _authorizationRef$cur;
226
226
  return mountedRef.current && ((_authorizationRef$cur = authorizationRef.current) === null || _authorizationRef$cur === void 0 ? void 0 : _authorizationRef$cur.token) === token;
@@ -242,30 +242,15 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
242
242
  const authorization = authorizationRef.current;
243
243
  if (!authorization || authorization.settling) return;
244
244
  if (command !== "payment_result") return;
245
+ if (params.requestId !== authorization.token) return;
245
246
  authorization.settling = true;
246
247
  try {
247
248
  if (params.status === "cancelled") {
248
249
  yield acceptOutcome({ kind: "cancelled" });
249
250
  return;
250
251
  }
251
- if (params.ok === true) try {
252
- const outcome = inspectPaymentCompletion(baseSales, params.syncResult);
253
- if (outcome.kind === "partial") {
254
- var _baseSales$getTempOrd3, _baseSales$getTempOrd4;
255
- const currentOrderId = String((_baseSales$getTempOrd3 = (_baseSales$getTempOrd4 = baseSales.getTempOrder) === null || _baseSales$getTempOrd4 === void 0 || (_baseSales$getTempOrd4 = _baseSales$getTempOrd4.call(baseSales)) === null || _baseSales$getTempOrd4 === void 0 ? void 0 : _baseSales$getTempOrd4.order_id) !== null && _baseSales$getTempOrd3 !== void 0 ? _baseSales$getTempOrd3 : "").trim();
256
- if (currentOrderId === String(outcome.orderId)) yield context.sales.refreshSalesDetail({ forceRemote: true });
257
- else if (!currentOrderId || /^local[_-]/i.test(currentOrderId)) {
258
- const remoteOrderId = Number(outcome.orderId);
259
- if (!Number.isFinite(remoteOrderId) || remoteOrderId <= 0) throw new Error("The paid order cannot be refreshed.");
260
- yield context.sales.loadDetailByRemote(remoteOrderId);
261
- } else throw new Error("The current order changed before payment synchronization.");
262
- const nextAmount = readPaymentAmount(baseSales);
263
- if (nextAmount === void 0 || nextAmount >= authorization.amount) yield acceptOutcome({ kind: "uncertain" });
264
- else {
265
- preparationRef.current = yield context.sales.prepareCheckout();
266
- yield acceptOutcome(outcome);
267
- }
268
- } else yield acceptOutcome(outcome, params);
252
+ if (params.ok === true && (params.status === void 0 || params.status === "success")) try {
253
+ yield acceptOutcome(inspectPaymentCompletion(baseSales, params.syncResult, "main-screen"), params);
269
254
  } catch (error) {
270
255
  yield acceptOutcome({
271
256
  kind: "uncertain",
@@ -25,28 +25,45 @@ function submitData(submitResult) {
25
25
  var _submitResult$data;
26
26
  return (submitResult === null || submitResult === void 0 || (_submitResult$data = submitResult.data) === null || _submitResult$data === void 0 ? void 0 : _submitResult$data.data) || (submitResult === null || submitResult === void 0 ? void 0 : submitResult.data) || submitResult;
27
27
  }
28
- /** An approved terminal response is insufficient: require the submitted order too. */
29
- function inspectPaymentCompletion(baseSales, result) {
30
- var _sync$isOrderFullyPai, _ref3, _data$order_id, _baseSales$getTempOrd2;
28
+ /** Sale numbers survive local-to-remote id changes; never settle onto another cart. */
29
+ function capturePaymentOrder(baseSales) {
30
+ var _baseSales$getTempOrd2, _order$order_id;
31
+ const order = (_baseSales$getTempOrd2 = baseSales.getTempOrder) === null || _baseSales$getTempOrd2 === void 0 ? void 0 : _baseSales$getTempOrd2.call(baseSales);
32
+ const saleNumber = String((order === null || order === void 0 ? void 0 : order.external_sale_number) || "").trim();
33
+ const orderId = String((_order$order_id = order === null || order === void 0 ? void 0 : order.order_id) !== null && _order$order_id !== void 0 ? _order$order_id : "").trim();
34
+ return () => {
35
+ var _baseSales$getTempOrd3, _current$order_id;
36
+ const current = (_baseSales$getTempOrd3 = baseSales.getTempOrder) === null || _baseSales$getTempOrd3 === void 0 ? void 0 : _baseSales$getTempOrd3.call(baseSales);
37
+ return saleNumber ? String((current === null || current === void 0 ? void 0 : current.external_sale_number) || "").trim() === saleNumber : orderId ? String((_current$order_id = current === null || current === void 0 ? void 0 : current.order_id) !== null && _current$order_id !== void 0 ? _current$order_id : "").trim() === orderId : Boolean(order) && current === order;
38
+ };
39
+ }
40
+ /**
41
+ * Require a successful order submission as well as payment completion.
42
+ * Main-screen POS checkout persists paid orders locally before background sync;
43
+ * device payments still require a cloud-confirmed order before fulfillment.
44
+ */
45
+ function inspectPaymentCompletion(baseSales, result, submissionSource = "kiosk") {
46
+ var _sync$isOrderFullyPai, _ref3, _ref4, _data$order_id, _baseSales$getTempOrd4;
47
+ const isMainScreen = submissionSource === "main-screen";
31
48
  const sync = (result === null || result === void 0 ? void 0 : result.syncResult) || result;
32
49
  const submitted = sync === null || sync === void 0 ? void 0 : sync.submitResult;
33
50
  const data = submitData(submitted);
34
- const amount = readPaymentAmount(baseSales);
51
+ const amount = isMainScreen ? void 0 : readPaymentAmount(baseSales);
35
52
  const fullyPaid = (_sync$isOrderFullyPai = sync === null || sync === void 0 ? void 0 : sync.isOrderFullyPaid) !== null && _sync$isOrderFullyPai !== void 0 ? _sync$isOrderFullyPai : sync === null || sync === void 0 ? void 0 : sync.isFullyPaid;
36
- if ([
53
+ if (!isMainScreen && [
37
54
  data === null || data === void 0 ? void 0 : data.need_sync,
38
55
  submitted === null || submitted === void 0 ? void 0 : submitted.need_sync,
39
56
  sync === null || sync === void 0 ? void 0 : sync.need_sync
40
57
  ].some((value) => Number(value) === 1)) throw new Error("Order sync is not complete.");
41
58
  if (!isSalesOrderSubmitSuccess(submitted)) throw new Error((data === null || data === void 0 ? void 0 : data.message) || (submitted === null || submitted === void 0 ? void 0 : submitted.message) || "Order sync is not complete.");
42
- const orderId = (_ref3 = (_data$order_id = data === null || data === void 0 ? void 0 : data.order_id) !== null && _data$order_id !== void 0 ? _data$order_id : data === null || data === void 0 ? void 0 : data.orderId) !== null && _ref3 !== void 0 ? _ref3 : baseSales === null || baseSales === void 0 || (_baseSales$getTempOrd2 = baseSales.getTempOrder) === null || _baseSales$getTempOrd2 === void 0 || (_baseSales$getTempOrd2 = _baseSales$getTempOrd2.call(baseSales)) === null || _baseSales$getTempOrd2 === void 0 ? void 0 : _baseSales$getTempOrd2.order_id;
59
+ const orderId = (_ref3 = (_ref4 = (_data$order_id = data === null || data === void 0 ? void 0 : data.order_id) !== null && _data$order_id !== void 0 ? _data$order_id : data === null || data === void 0 ? void 0 : data.orderId) !== null && _ref4 !== void 0 ? _ref4 : isMainScreen ? data === null || data === void 0 ? void 0 : data.external_sale_number : void 0) !== null && _ref3 !== void 0 ? _ref3 : baseSales === null || baseSales === void 0 || (_baseSales$getTempOrd4 = baseSales.getTempOrder) === null || _baseSales$getTempOrd4 === void 0 || (_baseSales$getTempOrd4 = _baseSales$getTempOrd4.call(baseSales)) === null || _baseSales$getTempOrd4 === void 0 ? void 0 : _baseSales$getTempOrd4.order_id;
43
60
  const orderStatus = String((data === null || data === void 0 ? void 0 : data.payment_status) || "").toLowerCase();
44
- if (orderId === void 0 || orderId === null || String(orderId).trim() === "" || /^local[_-]/i.test(String(orderId))) throw new Error("The submitted order has no remote order id.");
45
- if (fullyPaid === false && amount !== void 0 && amount > 0) return {
61
+ if (orderId === void 0 || orderId === null || String(orderId).trim() === "" || !isMainScreen && /^local[_-]/i.test(String(orderId))) throw new Error("The submitted order has no valid order id.");
62
+ if (fullyPaid === false && (isMainScreen || amount !== void 0 && amount > 0)) return {
46
63
  kind: "partial",
47
64
  orderId
48
65
  };
49
- if (orderStatus && orderStatus !== "paid" || (data === null || data === void 0 ? void 0 : data.order_wait_pay_amount) !== void 0 && Number(data.order_wait_pay_amount) !== 0 || fullyPaid === false || fullyPaid !== true && amount !== 0) throw new Error("The submitted order has not been confirmed as fully paid.");
66
+ if (orderStatus && orderStatus !== "paid" || (data === null || data === void 0 ? void 0 : data.order_wait_pay_amount) !== void 0 && Number(data.order_wait_pay_amount) !== 0 || fullyPaid === false || fullyPaid !== true && (isMainScreen ? orderStatus !== "paid" : amount !== 0)) throw new Error("The submitted order has not been confirmed as fully paid.");
50
67
  return {
51
68
  kind: "paid",
52
69
  orderId,
@@ -57,18 +74,21 @@ function syncConfirmedPayments(_x) {
57
74
  return _syncConfirmedPayments.apply(this, arguments);
58
75
  }
59
76
  function _syncConfirmedPayments() {
60
- _syncConfirmedPayments = _asyncToGenerator(function* (baseSales) {
61
- const retry = () => syncConfirmedPayments(baseSales);
77
+ _syncConfirmedPayments = _asyncToGenerator(function* (baseSales, isCurrentOrder = capturePaymentOrder(baseSales)) {
78
+ const retry = () => syncConfirmedPayments(baseSales, isCurrentOrder);
79
+ if (!isCurrentOrder()) return { kind: "uncertain" };
62
80
  try {
63
81
  var _baseSales$getOrderPa3;
64
82
  if (!(baseSales === null || baseSales === void 0 ? void 0 : baseSales.syncPaymentsToOrder)) throw new Error("Order sync is unavailable.");
65
- return inspectPaymentCompletion(baseSales, yield baseSales.syncPaymentsToOrder({
83
+ const result = yield baseSales.syncPaymentsToOrder({
66
84
  payments: ((_baseSales$getOrderPa3 = baseSales.getOrderPayments) === null || _baseSales$getOrderPa3 === void 0 ? void 0 : _baseSales$getOrderPa3.call(baseSales)) || [],
67
85
  paymentStatus: "paid",
68
86
  submitWhenPaid: true,
69
87
  smallTicketDataFlag: 1,
70
88
  confirmPendingVoucherPayments: true
71
- }));
89
+ });
90
+ if (!isCurrentOrder()) return { kind: "uncertain" };
91
+ return inspectPaymentCompletion(baseSales, result);
72
92
  } catch (error) {
73
93
  return {
74
94
  kind: "sync-failed",
@@ -86,14 +106,15 @@ function messageOf(error) {
86
106
  * A retry resumes this same confirmed payment; it never invokes a provider again.
87
107
  * Pending insertion avoids addOrderPayment's fire-and-forget paid synchronization.
88
108
  */
89
- function createFinalizer({ baseSales, method, confirmed, preparedPaymentNumber }) {
109
+ function createFinalizer({ baseSales, method, confirmed, preparedPaymentNumber, isCurrentOrder }) {
90
110
  var _confirmed$metadata;
91
111
  let paymentNumber = preparedPaymentNumber;
92
112
  const transactionNumber = (_confirmed$metadata = confirmed.metadata) === null || _confirmed$metadata === void 0 ? void 0 : _confirmed$metadata.unique_payment_number;
93
113
  const attemptId = `kiosk-${Date.now()}-${Math.random().toString(36).slice(2)}`;
94
114
  const metadata = _objectSpread2(_objectSpread2({}, confirmed.metadata), {}, { unique_payment_number: transactionNumber || attemptId });
95
115
  return function() {
96
- var _ref4 = _asyncToGenerator(function* () {
116
+ var _ref5 = _asyncToGenerator(function* () {
117
+ if (!isCurrentOrder()) return { kind: "uncertain" };
97
118
  try {
98
119
  var _baseSales$getOrderPa4;
99
120
  let payments = ((_baseSales$getOrderPa4 = baseSales.getOrderPayments) === null || _baseSales$getOrderPa4 === void 0 ? void 0 : _baseSales$getOrderPa4.call(baseSales)) || [];
@@ -123,10 +144,11 @@ function createFinalizer({ baseSales, method, confirmed, preparedPaymentNumber }
123
144
  return ((_item$metadata2 = item.metadata) === null || _item$metadata2 === void 0 ? void 0 : _item$metadata2.unique_payment_number) === metadata.unique_payment_number;
124
145
  });
125
146
  }
147
+ if (!isCurrentOrder()) return { kind: "uncertain" };
126
148
  paymentNumber = String((payment === null || payment === void 0 ? void 0 : payment.payment_number) || "").trim();
127
149
  if (!paymentNumber) throw new Error("The recorded payment has no payment number.");
128
- if (payment.status === "paid") return syncConfirmedPayments(baseSales);
129
- return inspectPaymentCompletion(baseSales, preparedPaymentNumber ? yield completePendingEftposPayment({
150
+ if (payment.status === "paid") return syncConfirmedPayments(baseSales, isCurrentOrder);
151
+ const result = preparedPaymentNumber ? yield completePendingEftposPayment({
130
152
  baseSales,
131
153
  paymentNumber,
132
154
  amount: confirmed.amount,
@@ -142,7 +164,9 @@ function createFinalizer({ baseSales, method, confirmed, preparedPaymentNumber }
142
164
  }, {
143
165
  persistDraft: true,
144
166
  submitWhenPaid: true
145
- }));
167
+ });
168
+ if (!isCurrentOrder()) return { kind: "uncertain" };
169
+ return inspectPaymentCompletion(baseSales, result);
146
170
  } catch (error) {
147
171
  return {
148
172
  kind: "sync-failed",
@@ -152,7 +176,7 @@ function createFinalizer({ baseSales, method, confirmed, preparedPaymentNumber }
152
176
  }
153
177
  });
154
178
  return function finalize() {
155
- return _ref4.apply(this, arguments);
179
+ return _ref5.apply(this, arguments);
156
180
  };
157
181
  }();
158
182
  }
@@ -165,6 +189,7 @@ function _executeKioskPayment() {
165
189
  const terminal = CHECKOUT_VISIBLE_PAYMENT_CODES.includes(code);
166
190
  let prepared;
167
191
  let dispatched = false;
192
+ const isCurrentOrder = capturePaymentOrder(baseSales);
168
193
  try {
169
194
  var _confirmed$metadata2;
170
195
  assertCurrent();
@@ -176,6 +201,7 @@ function _executeKioskPayment() {
176
201
  method,
177
202
  amount
178
203
  });
204
+ if (!isCurrentOrder()) return { kind: "uncertain" };
179
205
  assertCurrent();
180
206
  dispatched = terminal;
181
207
  const confirmed = terminal ? yield runtime.execute({
@@ -195,6 +221,7 @@ function _executeKioskPayment() {
195
221
  percentage: method.percentage
196
222
  } : null
197
223
  };
224
+ if (!isCurrentOrder()) return { kind: "uncertain" };
198
225
  if (confirmed.status !== "success") {
199
226
  if (confirmed.preservePendingPayment) return {
200
227
  kind: "uncertain",
@@ -219,20 +246,24 @@ function _executeKioskPayment() {
219
246
  baseSales,
220
247
  method,
221
248
  confirmed,
222
- preparedPaymentNumber: prepared === null || prepared === void 0 ? void 0 : prepared.paymentNumber
249
+ preparedPaymentNumber: prepared === null || prepared === void 0 ? void 0 : prepared.paymentNumber,
250
+ isCurrentOrder
223
251
  })();
224
252
  } catch (error) {
225
253
  if (dispatched) return {
226
254
  kind: "uncertain",
227
255
  message: messageOf(error)
228
256
  };
229
- if (prepared) try {
230
- yield discardPendingEftposPayment(baseSales, prepared.paymentNumber);
231
- } catch (rollbackError) {
232
- return {
233
- kind: "uncertain",
234
- message: messageOf(rollbackError)
235
- };
257
+ if (prepared) {
258
+ if (!isCurrentOrder()) return { kind: "uncertain" };
259
+ try {
260
+ yield discardPendingEftposPayment(baseSales, prepared.paymentNumber);
261
+ } catch (rollbackError) {
262
+ return {
263
+ kind: "uncertain",
264
+ message: messageOf(rollbackError)
265
+ };
266
+ }
236
267
  }
237
268
  return {
238
269
  kind: "failed",
@@ -13,7 +13,7 @@ import locales_default from "./locales.js";
13
13
  import { clearAllPaymentResultToastsV2, closePaymentResultToastV2, setTillButtonV2 } from "./components/PaymentResultToastV2/PaymentResultToastV2Provider.js";
14
14
  import { mapPaymentStatusToV2Status } from "./components/PaymentResultToastV2/resolve.js";
15
15
  import { createStartNewOrderPaymentModalEvent } from "./payment-modal-utils.js";
16
- import { CHECKOUT_VISIBLE_PAYMENT_CODES, SCI_PAYMENT_CODES, SPI_PAYMENT_CODES, WALLET_PASS_CODE_ARRAY, WALLET_PASS_CODE_MAP, resolvePiPaymentProvider } from "./constants.js";
16
+ import { CHECKOUT_VISIBLE_PAYMENT_CODES, MERCHANT_CHANNELS, SCI_PAYMENT_CODES, SPI_PAYMENT_CODES, WALLET_PASS_CODE_ARRAY, WALLET_PASS_CODE_MAP, resolvePiPaymentProvider } from "./constants.js";
17
17
  import PaymentMethodRuntime_default from "./paymentRuntime/PaymentMethodRuntime.js";
18
18
  import { presentBaseSalesPaymentResult } from "./paymentRuntime/presentBaseSalesPaymentResult.js";
19
19
  import { buildSciEftposSurchargeDisplayMap, getCardReadersWithSurcharge, getCurrentDeviceNumber, getShopWalletPassId, isPaidPaymentItem, isPendingVoucherPaymentItem, reorderPaymentMethodList } from "./utils.js";
@@ -469,7 +469,7 @@ const PaymentContent = forwardRef(({ cartData, orderInfo, isModalOpen, onPayment
469
469
  const [showCashPayment, setShowCashPayment] = useState(false);
470
470
  const [paymentOptionsTitle, setPaymentOptionsTitle] = useState(locales.getText("cards.and.digitals") || "Cards & Digitals");
471
471
  useOsKey();
472
- const paymentChannel = useMemo(() => String((getData === null || getData === void 0 ? void 0 : getData("channel")) || "pos").trim().toLowerCase(), [getData]);
472
+ const paymentChannel = useMemo(() => String((getData === null || getData === void 0 ? void 0 : getData("channel")) || "").trim().toLowerCase(), [getData]);
473
473
  const paymentScanActivity = useCheckoutPaymentScanActivity(paymentChannel === "kiosk");
474
474
  const activeKioskPaymentActivityRef = useRef();
475
475
  const paymentOptionList = useMemo(() => {
@@ -1736,7 +1736,7 @@ const PaymentContent = forwardRef(({ cartData, orderInfo, isModalOpen, onPayment
1736
1736
  style: { marginTop: "10px" }
1737
1737
  }, locales.getText("order.start-new-order")) } } : {}), {}, {
1738
1738
  platform: paymentChannel || "pos",
1739
- usageScene: paymentChannel === "kiosk" ? "user" : "merchant",
1739
+ usageScene: MERCHANT_CHANNELS.includes(paymentChannel) ? "merchant" : "user",
1740
1740
  onChange: function() {
1741
1741
  var _ref29 = _asyncToGenerator(function* (event) {
1742
1742
  const isTerminalEvent = event.type === "success" || event.type === "closed" || event.type === "printOnTimeout";
@@ -105,13 +105,13 @@ const PaymentMethodItem = ({ appearance = "default", method, amountSymbol, custo
105
105
  if (finishPaymentActivity && !finishPaymentActivity.isActive()) return;
106
106
  const authorizationResult = yield Promise.resolve((_window = window) === null || _window === void 0 || (_window = _window.app) === null || _window === void 0 ? void 0 : _window.applicationManager.get("global").runFunction("authorizeAction", {
107
107
  onClose: finishPaymentActivity,
108
- params: {
108
+ params: _objectSpread2({
109
109
  action: "pay",
110
110
  business_code: otherParams.businessCode || otherParams.business_code,
111
111
  paymentMethodCode: method.code,
112
112
  paymentMethodType: method.type,
113
113
  amount: customAmount
114
- }
114
+ }, (finishPaymentActivity === null || finishPaymentActivity === void 0 ? void 0 : finishPaymentActivity.paymentRequestId) ? { paymentRequestId: finishPaymentActivity.paymentRequestId } : {})
115
115
  }));
116
116
  if (String((authorizationResult === null || authorizationResult === void 0 ? void 0 : authorizationResult.status) || "").toLowerCase() !== "success") finishPaymentActivity === null || finishPaymentActivity === void 0 || finishPaymentActivity();
117
117
  } catch (error) {
@@ -9,6 +9,8 @@ const WALLET_PASS_CODE_MAP = {
9
9
  "gift_card": "GIFTCARD",
10
10
  "point_card": "POINTCARD"
11
11
  };
12
+ /** 仅明确的商户渠道可使用人工确认等商户支付操作。 */
13
+ const MERCHANT_CHANNELS = ["pos"];
12
14
  const SCI_PAYMENT_CODES = [
13
15
  "EFTPOS_LINKLY",
14
16
  "EFTPOS_TYRO",
@@ -47,4 +49,4 @@ const PI_PAYMENT_PROVIDER_MAP = {
47
49
  /** 灰度开关开启时才把 Checkout 支付方式路由到 PiPayment。 */
48
50
  const resolvePiPaymentProvider = (code, enabled) => enabled ? PI_PAYMENT_PROVIDER_MAP[code] : void 0;
49
51
  //#endregion
50
- export { CHECKOUT_VISIBLE_PAYMENT_CODES, SCI_PAYMENT_CODES, SCI_PAYMENT_CODE_TO_READER_TYPE, SPI_PAYMENT_CODES, WALLET_PASS_CODE_ARRAY, WALLET_PASS_CODE_MAP, resolvePiPaymentProvider };
52
+ export { CHECKOUT_VISIBLE_PAYMENT_CODES, MERCHANT_CHANNELS, SCI_PAYMENT_CODES, SCI_PAYMENT_CODE_TO_READER_TYPE, SPI_PAYMENT_CODES, WALLET_PASS_CODE_ARRAY, WALLET_PASS_CODE_MAP, resolvePiPaymentProvider };
@@ -3,7 +3,7 @@ import { _asyncToGenerator } from "../../../_virtual/_@oxc-project_runtime@0.122
3
3
  import { PiPaymentType } from "../../../plus/piPaymentUI/contracts/index.js";
4
4
  import PiPayment from "../../../plus/piPaymentUI/PiPayment.js";
5
5
  import paymentMethods_default from "../../pay/toB/paymentMethods/index.js";
6
- import { SCI_PAYMENT_CODES, SPI_PAYMENT_CODES, resolvePiPaymentProvider } from "../constants.js";
6
+ import { MERCHANT_CHANNELS, SCI_PAYMENT_CODES, SPI_PAYMENT_CODES, resolvePiPaymentProvider } from "../constants.js";
7
7
  import React, { forwardRef, memo, useImperativeHandle, useMemo, useRef } from "react";
8
8
  import { formatAmount } from "@pisell/utils";
9
9
  //#region src/components/checkout/paymentRuntime/PaymentMethodRuntime.tsx
@@ -60,7 +60,7 @@ var PaymentMethodRuntime_default = memo(forwardRef(function PaymentMethodRuntime
60
60
  const paymentMethodsRef = useRef(null);
61
61
  const piPaymentRef = useRef(null);
62
62
  const { getData } = context.appHelper.utils || {};
63
- const paymentChannel = useMemo(() => String((getData === null || getData === void 0 ? void 0 : getData("channel")) || "pos").trim().toLowerCase(), [getData]);
63
+ const paymentChannel = useMemo(() => String((getData === null || getData === void 0 ? void 0 : getData("channel")) || "").trim().toLowerCase(), [getData]);
64
64
  const calculateSurcharge = (surchargeConfig, amount) => {
65
65
  if (!(surchargeConfig === null || surchargeConfig === void 0 ? void 0 : surchargeConfig.is_surcharge)) return 0;
66
66
  const baseAmount = Number(amount) || 0;
@@ -242,7 +242,7 @@ var PaymentMethodRuntime_default = memo(forwardRef(function PaymentMethodRuntime
242
242
  type: "shop"
243
243
  },
244
244
  platform: paymentChannel || "pos",
245
- usageScene: paymentChannel === "kiosk" ? "user" : "merchant",
245
+ usageScene: MERCHANT_CHANNELS.includes(paymentChannel) ? "merchant" : "user",
246
246
  onChange: (event) => {
247
247
  var _compatibleEvent$para, _compatibleEvent$para2;
248
248
  if (settled) return;
@@ -543,7 +543,8 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
543
543
  }
544
544
  }, [isActive]);
545
545
  const handleReturnToAdvertisement = (replace = true, reason) => {
546
- if (replace && (paymentPageSessionRef.current || getHasScanRequest() || renderCatalog && (getIsProcessing() || getIsPaymentProcessing()))) return;
546
+ if (paymentPageSessionRef.current) return;
547
+ if (replace && (getHasScanRequest() || renderCatalog && (getIsProcessing() || getIsPaymentProcessing()))) return;
547
548
  if (returningToAdvertisementRef.current) return;
548
549
  returningToAdvertisementRef.current = true;
549
550
  setIsReturningToAdvertisement(true);
@@ -671,6 +672,7 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
671
672
  businessCode,
672
673
  checkoutSnapshot: preparation.runtimeSnapshot
673
674
  }));
675
+ const paymentStatus = payload.orderSnapshot.payment_status === "partially_paid" ? "partially_paid" : "paid";
674
676
  persistKioskSessionView(context.sales.bookingTicket, "catalog");
675
677
  try {
676
678
  yield context.sales.clearCartAndReset();
@@ -679,7 +681,7 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
679
681
  }
680
682
  try {
681
683
  if (!isActiveRef.current || paymentPageSessionRef.current !== session) return;
682
- if (!(yield handOffPaidCheckout(payload))) {
684
+ if (!(paymentStatus === "paid" && (yield handOffPaidCheckout(payload)))) {
683
685
  var _payload$paymentResul;
684
686
  setPaymentResult((_payload$paymentResul = payload.paymentResult) !== null && _payload$paymentResul !== void 0 ? _payload$paymentResul : null);
685
687
  setView("success");
@@ -687,7 +689,7 @@ function KioskBigSaleTemplate({ isActive = true, osKey, productListPreferencesCh
687
689
  onOrderComplete === null || onOrderComplete === void 0 || onOrderComplete({
688
690
  type: "checkout",
689
691
  data: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, payload), {}, {
690
- status: "paid",
692
+ status: paymentStatus,
691
693
  reason: "paid"
692
694
  }),
693
695
  order_id: payload.orderId,
@@ -89,17 +89,17 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
89
89
  const acceptOutcome = (0, ahooks.useMemoizedFn)(function() {
90
90
  var _ref = require_asyncToGenerator._asyncToGenerator(function* (outcome, external) {
91
91
  if (!mountedRef.current || stateRef.current === "complete") return;
92
- if (outcome.kind === "paid") {
92
+ if (outcome.kind === "paid" || outcome.kind === "partial" && external) {
93
93
  var _external$orderSnapsh, _baseSales$getTempOrd2, _utils$getData;
94
94
  transition("complete");
95
95
  retryRef.current = void 0;
96
96
  const orderSnapshot = (0, lodash.cloneDeep)((external === null || external === void 0 || (_external$orderSnapsh = external.orderSnapshot) === null || _external$orderSnapsh === void 0 ? void 0 : _external$orderSnapsh.tempOrder) || (external === null || external === void 0 ? void 0 : external.orderSnapshot) || ((_baseSales$getTempOrd2 = baseSales.getTempOrder) === null || _baseSales$getTempOrd2 === void 0 ? void 0 : _baseSales$getTempOrd2.call(baseSales)) || {});
97
97
  if (external === null || external === void 0 ? void 0 : external.payments) orderSnapshot.payments = (0, lodash.cloneDeep)(external.payments);
98
98
  orderSnapshot.order_id = outcome.orderId;
99
- orderSnapshot.payment_status = "paid";
99
+ orderSnapshot.payment_status = outcome.kind === "partial" ? "partially_paid" : "paid";
100
100
  const paymentResult = require_presentBaseSalesPaymentResult.presentBaseSalesPaymentResult({
101
101
  baseSales,
102
- status: "success",
102
+ status: outcome.kind === "partial" ? "partially-paid" : "success",
103
103
  displayMode: "page",
104
104
  currencySymbol,
105
105
  payments: external === null || external === void 0 ? void 0 : external.payments,
@@ -198,7 +198,7 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
198
198
  }
199
199
  }));
200
200
  const beginAuthorization = (0, ahooks.useMemoizedFn)((_source) => {
201
- var _readPaymentAmount;
201
+ var _globalThis$crypto, _globalThis$crypto$ra;
202
202
  if (stateRef.current !== "idle") return null;
203
203
  if (!authorizationAvailableRef.current) {
204
204
  toast.fail(_pisell_utils.locales.getText("pisell2.checkout.self-service.empty"));
@@ -210,11 +210,10 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
210
210
  toast.fail(error instanceof Error ? error.message : String(error));
211
211
  return null;
212
212
  }
213
- const token = Symbol("authorization");
213
+ const token = ((_globalThis$crypto = globalThis.crypto) === null || _globalThis$crypto === void 0 || (_globalThis$crypto$ra = _globalThis$crypto.randomUUID) === null || _globalThis$crypto$ra === void 0 ? void 0 : _globalThis$crypto$ra.call(_globalThis$crypto)) || `kiosk-payment-${Date.now()}-${Math.random().toString(36).slice(2)}`;
214
214
  authorizationRef.current = {
215
215
  token,
216
- settling: false,
217
- amount: (_readPaymentAmount = require_transaction.readPaymentAmount(baseSales)) !== null && _readPaymentAmount !== void 0 ? _readPaymentAmount : 0
216
+ settling: false
218
217
  };
219
218
  transition("authorizing");
220
219
  const release = (() => {
@@ -223,6 +222,7 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
223
222
  authorizationRef.current = void 0;
224
223
  transition("idle");
225
224
  });
225
+ release.paymentRequestId = token;
226
226
  release.isActive = () => {
227
227
  var _authorizationRef$cur;
228
228
  return mountedRef.current && ((_authorizationRef$cur = authorizationRef.current) === null || _authorizationRef$cur === void 0 ? void 0 : _authorizationRef$cur.token) === token;
@@ -244,30 +244,15 @@ function KioskPaymentPage({ context, checkoutPreparation, channel, onBack, onPai
244
244
  const authorization = authorizationRef.current;
245
245
  if (!authorization || authorization.settling) return;
246
246
  if (command !== "payment_result") return;
247
+ if (params.requestId !== authorization.token) return;
247
248
  authorization.settling = true;
248
249
  try {
249
250
  if (params.status === "cancelled") {
250
251
  yield acceptOutcome({ kind: "cancelled" });
251
252
  return;
252
253
  }
253
- if (params.ok === true) try {
254
- const outcome = require_transaction.inspectPaymentCompletion(baseSales, params.syncResult);
255
- if (outcome.kind === "partial") {
256
- var _baseSales$getTempOrd3, _baseSales$getTempOrd4;
257
- const currentOrderId = String((_baseSales$getTempOrd3 = (_baseSales$getTempOrd4 = baseSales.getTempOrder) === null || _baseSales$getTempOrd4 === void 0 || (_baseSales$getTempOrd4 = _baseSales$getTempOrd4.call(baseSales)) === null || _baseSales$getTempOrd4 === void 0 ? void 0 : _baseSales$getTempOrd4.order_id) !== null && _baseSales$getTempOrd3 !== void 0 ? _baseSales$getTempOrd3 : "").trim();
258
- if (currentOrderId === String(outcome.orderId)) yield context.sales.refreshSalesDetail({ forceRemote: true });
259
- else if (!currentOrderId || /^local[_-]/i.test(currentOrderId)) {
260
- const remoteOrderId = Number(outcome.orderId);
261
- if (!Number.isFinite(remoteOrderId) || remoteOrderId <= 0) throw new Error("The paid order cannot be refreshed.");
262
- yield context.sales.loadDetailByRemote(remoteOrderId);
263
- } else throw new Error("The current order changed before payment synchronization.");
264
- const nextAmount = require_transaction.readPaymentAmount(baseSales);
265
- if (nextAmount === void 0 || nextAmount >= authorization.amount) yield acceptOutcome({ kind: "uncertain" });
266
- else {
267
- preparationRef.current = yield context.sales.prepareCheckout();
268
- yield acceptOutcome(outcome);
269
- }
270
- } else yield acceptOutcome(outcome, params);
254
+ if (params.ok === true && (params.status === void 0 || params.status === "success")) try {
255
+ yield acceptOutcome(require_transaction.inspectPaymentCompletion(baseSales, params.syncResult, "main-screen"), params);
271
256
  } catch (error) {
272
257
  yield acceptOutcome({
273
258
  kind: "uncertain",