@pisell/private-materials 6.6.77 → 6.6.78
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/build/lowcode/assets-daily.json +11 -11
- package/build/lowcode/assets-dev.json +2 -2
- package/build/lowcode/assets-prod.json +11 -11
- package/build/lowcode/index.js +1 -1
- package/build/lowcode/meta.js +1 -1
- package/build/lowcode/preview.js +5 -5
- package/build/lowcode/render/default/view.js +1 -1
- package/build/lowcode/view.js +1 -1
- package/es/components/booking/forms/sendModal/useSendModal.d.ts +1 -1
- package/es/components/checkout/hooks/useWalletPass.d.ts +1 -1
- package/es/components/eftposPay/adyenPos/index.js +9 -5
- package/es/components/eftposPay/adyenPos/receipt.d.ts +21 -0
- package/es/components/eftposPay/adyenPos/receipt.js +185 -0
- package/lib/components/booking/forms/sendModal/useSendModal.d.ts +1 -1
- package/lib/components/checkout/hooks/useWalletPass.d.ts +1 -1
- package/lib/components/eftposPay/adyenPos/index.js +11 -5
- package/lib/components/eftposPay/adyenPos/receipt.d.ts +21 -0
- package/lib/components/eftposPay/adyenPos/receipt.js +193 -0
- package/package.json +3 -3
|
@@ -4,6 +4,6 @@ declare const useSendModal: (bookingId?: number) => {
|
|
|
4
4
|
setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
5
5
|
handleOpen: () => void;
|
|
6
6
|
handleValuesChange: (val: any) => void;
|
|
7
|
-
handleOk: (values: SendModalValues) => Promise<
|
|
7
|
+
handleOk: (values: SendModalValues) => Promise<boolean | undefined>;
|
|
8
8
|
};
|
|
9
9
|
export default useSendModal;
|
|
@@ -17,7 +17,7 @@ export declare const useWalletPass: (props: {
|
|
|
17
17
|
cardData: any;
|
|
18
18
|
handleSelectWallet: (value: number[]) => void;
|
|
19
19
|
selectedWalletIds: any[];
|
|
20
|
-
expiredWalletIds: any
|
|
20
|
+
expiredWalletIds: any;
|
|
21
21
|
expiredWalletData: any;
|
|
22
22
|
disabledWalletData: any[];
|
|
23
23
|
clearAllSelectedWallet: () => void;
|
|
@@ -22,6 +22,7 @@ import { getPayParams } from "../helper";
|
|
|
22
22
|
import { usePayment } from "../aggregatePayment";
|
|
23
23
|
import { EPaymentStatus } from "../aggregatePayment/types";
|
|
24
24
|
import payLog from "../utils/payLog";
|
|
25
|
+
import { buildAdyenReceiptPrintPayload } from "./receipt";
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
* Adyen 常规支付组件
|
|
@@ -128,9 +129,11 @@ var AdyenPos = function AdyenPos(_ref) {
|
|
|
128
129
|
* - 否则直接走成功流程
|
|
129
130
|
*/
|
|
130
131
|
var handleSuccess = function handleSuccess(responseData) {
|
|
131
|
-
var _responseData$data, _response$cvm_result;
|
|
132
|
+
var _responseData$data, _response$cvm_result, _deviceRef$current;
|
|
132
133
|
var _response = (responseData === null || responseData === void 0 || (_responseData$data = responseData.data) === null || _responseData$data === void 0 ? void 0 : _responseData$data.external_unified_response) || {};
|
|
133
134
|
var signatureRequired = _response === null || _response === void 0 || (_response$cvm_result = _response.cvm_result) === null || _response$cvm_result === void 0 ? void 0 : _response$cvm_result.signature_required;
|
|
135
|
+
var deviceSetting = (_deviceRef$current = deviceRef.current) === null || _deviceRef$current === void 0 ? void 0 : _deviceRef$current.setting;
|
|
136
|
+
var receipt = buildAdyenReceiptPrintPayload(_response === null || _response === void 0 ? void 0 : _response.receipts, deviceSetting === null || deviceSetting === void 0 ? void 0 : deviceSetting.print_mode);
|
|
134
137
|
dispatch(updateState({
|
|
135
138
|
status: 'success',
|
|
136
139
|
title: locales.getText('page.eftpos-pay.text.successful')(modeRef.current)
|
|
@@ -138,7 +141,7 @@ var AdyenPos = function AdyenPos(_ref) {
|
|
|
138
141
|
dispatch(updateNextStep());
|
|
139
142
|
dispatch(updateCustom({
|
|
140
143
|
card_reader_surcharge: 0,
|
|
141
|
-
receipt:
|
|
144
|
+
receipt: receipt
|
|
142
145
|
}));
|
|
143
146
|
var params = getPayParams({
|
|
144
147
|
mode: modeRef.current,
|
|
@@ -149,11 +152,12 @@ var AdyenPos = function AdyenPos(_ref) {
|
|
|
149
152
|
pay: payRef.current,
|
|
150
153
|
custom: {
|
|
151
154
|
card_reader_surcharge: 0,
|
|
152
|
-
receipt:
|
|
155
|
+
receipt: receipt
|
|
153
156
|
}
|
|
154
157
|
}, 'success');
|
|
158
|
+
// Adyen 小票只由 print_mode 控制,覆盖 getPayParams 中旧 receipts 设置的结果
|
|
155
159
|
var onChangeParams = _objectSpread(_objectSpread({}, params), {}, {
|
|
156
|
-
receipt:
|
|
160
|
+
receipt: receipt
|
|
157
161
|
});
|
|
158
162
|
if (signatureRequired) {
|
|
159
163
|
// 暂存参数,等待员工完成签名核查后再触发
|
|
@@ -164,7 +168,7 @@ var AdyenPos = function AdyenPos(_ref) {
|
|
|
164
168
|
} else {
|
|
165
169
|
clearRef.current = setTimeout(function () {
|
|
166
170
|
if (unloadRef.current) return;
|
|
167
|
-
onChange('success',
|
|
171
|
+
onChange('success', onChangeParams);
|
|
168
172
|
}, 1000);
|
|
169
173
|
}
|
|
170
174
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** 58mm 热敏纸在标准字体下常用的半角字符列数 */
|
|
2
|
+
export declare const ADYEN_RECEIPT_LINE_WIDTH = 32;
|
|
3
|
+
export interface AdyenReceipt {
|
|
4
|
+
document_qualifier?: string;
|
|
5
|
+
lines?: unknown[];
|
|
6
|
+
}
|
|
7
|
+
/** 获取文本在等宽热敏打印机上的显示列数 */
|
|
8
|
+
export declare const getReceiptTextWidth: (text: string) => number;
|
|
9
|
+
/**
|
|
10
|
+
* 将单份 Adyen PaymentReceipt 转换为可供热敏打印机消费的纯文本。
|
|
11
|
+
*/
|
|
12
|
+
export declare const formatAdyenReceipt: (receipt: AdyenReceipt, width?: number) => string;
|
|
13
|
+
/** 按 Adyen 返回顺序生成商户联、顾客联等独立打印任务 */
|
|
14
|
+
export declare const formatAdyenReceipts: (receipts: unknown, width?: number) => string[];
|
|
15
|
+
/**
|
|
16
|
+
* 是否需要由 POS 打印收据。
|
|
17
|
+
* 兼容历史 boolean 设置以及接口可能返回的 number/string。
|
|
18
|
+
*/
|
|
19
|
+
export declare const shouldPrintReceiptOnPos: (setting?: boolean | number | string) => boolean;
|
|
20
|
+
/** 根据设备设置构建最终传给 POS 的小票数组 */
|
|
21
|
+
export declare const buildAdyenReceiptPrintPayload: (receipts: unknown, printMode?: boolean | number | string, width?: number) => string[];
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
3
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
5
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
6
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
7
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
8
|
+
/** 58mm 热敏纸在标准字体下常用的半角字符列数 */
|
|
9
|
+
export var ADYEN_RECEIPT_LINE_WIDTH = 32;
|
|
10
|
+
var TITLE_KEYS = new Set(['merchantTitle', 'cardholderHeader']);
|
|
11
|
+
var CENTERED_KEYS = new Set(['header1', 'header2', 'approved', 'refused', 'void', 'cvmRes', 'retain', 'thanks', 'sigline', 'merchantSigline']);
|
|
12
|
+
var isCombiningCodePoint = function isCombiningCodePoint(codePoint) {
|
|
13
|
+
return codePoint >= 0x0300 && codePoint <= 0x036f || codePoint >= 0x1ab0 && codePoint <= 0x1aff || codePoint >= 0x1dc0 && codePoint <= 0x1dff || codePoint >= 0x20d0 && codePoint <= 0x20ff || codePoint >= 0xfe20 && codePoint <= 0xfe2f || codePoint === 0xfe0e || codePoint === 0xfe0f;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 判断字符是否需要占用两个等宽打印列。
|
|
18
|
+
* 覆盖 CJK、全角字符和常见 emoji,避免居中及换行时错位。
|
|
19
|
+
*/
|
|
20
|
+
var isWideCodePoint = function isWideCodePoint(codePoint) {
|
|
21
|
+
return codePoint >= 0x1100 && (codePoint <= 0x115f || codePoint === 0x2329 || codePoint === 0x232a || codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f || codePoint >= 0xac00 && codePoint <= 0xd7a3 || codePoint >= 0xf900 && codePoint <= 0xfaff || codePoint >= 0xfe10 && codePoint <= 0xfe19 || codePoint >= 0xfe30 && codePoint <= 0xfe6f || codePoint >= 0xff00 && codePoint <= 0xff60 || codePoint >= 0xffe0 && codePoint <= 0xffe6 || codePoint >= 0x1f300 && codePoint <= 0x1faff || codePoint >= 0x20000 && codePoint <= 0x3fffd);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** 获取文本在等宽热敏打印机上的显示列数 */
|
|
25
|
+
export var getReceiptTextWidth = function getReceiptTextWidth(text) {
|
|
26
|
+
return Array.from(text).reduce(function (width, character) {
|
|
27
|
+
var codePoint = character.codePointAt(0) || 0;
|
|
28
|
+
if (isCombiningCodePoint(codePoint)) {
|
|
29
|
+
return width;
|
|
30
|
+
}
|
|
31
|
+
return width + (isWideCodePoint(codePoint) ? 2 : 1);
|
|
32
|
+
}, 0);
|
|
33
|
+
};
|
|
34
|
+
var normalizeLineWidth = function normalizeLineWidth(width) {
|
|
35
|
+
if (!Number.isFinite(width) || Number(width) < 4) {
|
|
36
|
+
return ADYEN_RECEIPT_LINE_WIDTH;
|
|
37
|
+
}
|
|
38
|
+
return Math.floor(Number(width));
|
|
39
|
+
};
|
|
40
|
+
var wrapText = function wrapText(text, width) {
|
|
41
|
+
var normalizedText = text.trim();
|
|
42
|
+
if (!normalizedText) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
var lines = [];
|
|
46
|
+
var currentLine = '';
|
|
47
|
+
var currentWidth = 0;
|
|
48
|
+
Array.from(normalizedText).forEach(function (character) {
|
|
49
|
+
var characterWidth = getReceiptTextWidth(character);
|
|
50
|
+
if (currentLine && currentWidth + characterWidth > width) {
|
|
51
|
+
lines.push(currentLine);
|
|
52
|
+
currentLine = character;
|
|
53
|
+
currentWidth = characterWidth;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
currentLine += character;
|
|
57
|
+
currentWidth += characterWidth;
|
|
58
|
+
});
|
|
59
|
+
if (currentLine) {
|
|
60
|
+
lines.push(currentLine);
|
|
61
|
+
}
|
|
62
|
+
return lines;
|
|
63
|
+
};
|
|
64
|
+
var centerText = function centerText(text, width) {
|
|
65
|
+
return wrapText(text, width).map(function (line) {
|
|
66
|
+
var padding = Math.max(0, Math.floor((width - getReceiptTextWidth(line)) / 2));
|
|
67
|
+
return "".concat(' '.repeat(padding)).concat(line);
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
var rightAlignText = function rightAlignText(text, width) {
|
|
71
|
+
return wrapText(text, width).map(function (line) {
|
|
72
|
+
var padding = Math.max(0, width - getReceiptTextWidth(line));
|
|
73
|
+
return "".concat(' '.repeat(padding)).concat(line);
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
var frameTitle = function frameTitle(text, width) {
|
|
77
|
+
var innerWidth = width - 2;
|
|
78
|
+
return wrapText(text, innerWidth).map(function (line) {
|
|
79
|
+
var remainingWidth = Math.max(0, innerWidth - getReceiptTextWidth(line));
|
|
80
|
+
var left = Math.floor(remainingWidth / 2);
|
|
81
|
+
var right = remainingWidth - left;
|
|
82
|
+
return "*".concat('-'.repeat(left)).concat(line).concat('-'.repeat(right), "*");
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
var parseReceiptLine = function parseReceiptLine(line) {
|
|
86
|
+
if (typeof line !== 'string' || !line) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
var params = new URLSearchParams(line);
|
|
91
|
+
return {
|
|
92
|
+
key: (params.get('key') || '').trim(),
|
|
93
|
+
name: (params.get('name') || '').trim(),
|
|
94
|
+
value: (params.get('value') || '').trim()
|
|
95
|
+
};
|
|
96
|
+
} catch (_error) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var renderKeyValue = function renderKeyValue(name, value, width) {
|
|
101
|
+
if (!name) {
|
|
102
|
+
return centerText(value, width);
|
|
103
|
+
}
|
|
104
|
+
if (!value) {
|
|
105
|
+
return centerText(name, width);
|
|
106
|
+
}
|
|
107
|
+
var nameWidth = getReceiptTextWidth(name);
|
|
108
|
+
var valueWidth = getReceiptTextWidth(value);
|
|
109
|
+
if (nameWidth + valueWidth + 1 <= width) {
|
|
110
|
+
return ["".concat(name).concat(' '.repeat(width - nameWidth - valueWidth)).concat(value)];
|
|
111
|
+
}
|
|
112
|
+
return [].concat(_toConsumableArray(wrapText(name, width)), _toConsumableArray(rightAlignText(value, width)));
|
|
113
|
+
};
|
|
114
|
+
var renderReceiptLine = function renderReceiptLine(receiptLine, width) {
|
|
115
|
+
var key = receiptLine.key,
|
|
116
|
+
name = receiptLine.name,
|
|
117
|
+
value = receiptLine.value;
|
|
118
|
+
if (key === 'filler') {
|
|
119
|
+
return [''];
|
|
120
|
+
}
|
|
121
|
+
var content = value || name;
|
|
122
|
+
if (TITLE_KEYS.has(key) && content) {
|
|
123
|
+
return frameTitle(content, width);
|
|
124
|
+
}
|
|
125
|
+
if (CENTERED_KEYS.has(key) && content) {
|
|
126
|
+
return centerText(content, width);
|
|
127
|
+
}
|
|
128
|
+
return renderKeyValue(name, value, width);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* 将单份 Adyen PaymentReceipt 转换为可供热敏打印机消费的纯文本。
|
|
133
|
+
*/
|
|
134
|
+
export var formatAdyenReceipt = function formatAdyenReceipt(receipt) {
|
|
135
|
+
var width = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ADYEN_RECEIPT_LINE_WIDTH;
|
|
136
|
+
var lineWidth = normalizeLineWidth(width);
|
|
137
|
+
if (!Array.isArray(receipt === null || receipt === void 0 ? void 0 : receipt.lines)) {
|
|
138
|
+
return '';
|
|
139
|
+
}
|
|
140
|
+
var output = receipt.lines.reduce(function (result, line) {
|
|
141
|
+
var parsedLine = parseReceiptLine(line);
|
|
142
|
+
if (parsedLine) {
|
|
143
|
+
result.push.apply(result, _toConsumableArray(renderReceiptLine(parsedLine, lineWidth)));
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
146
|
+
}, []);
|
|
147
|
+
if (!output.some(Boolean)) {
|
|
148
|
+
return '';
|
|
149
|
+
}
|
|
150
|
+
return "".concat(output.join('\n'), "\n");
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/** 按 Adyen 返回顺序生成商户联、顾客联等独立打印任务 */
|
|
154
|
+
export var formatAdyenReceipts = function formatAdyenReceipts(receipts) {
|
|
155
|
+
var width = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ADYEN_RECEIPT_LINE_WIDTH;
|
|
156
|
+
if (!Array.isArray(receipts)) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
return receipts.map(function (receipt) {
|
|
160
|
+
return receipt && _typeof(receipt) === 'object' ? formatAdyenReceipt(receipt, width) : '';
|
|
161
|
+
}).filter(Boolean);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 是否需要由 POS 打印收据。
|
|
166
|
+
* 兼容历史 boolean 设置以及接口可能返回的 number/string。
|
|
167
|
+
*/
|
|
168
|
+
export var shouldPrintReceiptOnPos = function shouldPrintReceiptOnPos(setting) {
|
|
169
|
+
if (typeof setting === 'boolean') {
|
|
170
|
+
return setting === false;
|
|
171
|
+
}
|
|
172
|
+
if (typeof setting === 'number') {
|
|
173
|
+
return setting === 0;
|
|
174
|
+
}
|
|
175
|
+
if (typeof setting === 'string') {
|
|
176
|
+
return setting === '0';
|
|
177
|
+
}
|
|
178
|
+
return false;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/** 根据设备设置构建最终传给 POS 的小票数组 */
|
|
182
|
+
export var buildAdyenReceiptPrintPayload = function buildAdyenReceiptPrintPayload(receipts, printMode) {
|
|
183
|
+
var width = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ADYEN_RECEIPT_LINE_WIDTH;
|
|
184
|
+
return shouldPrintReceiptOnPos(printMode) ? formatAdyenReceipts(receipts, width) : [];
|
|
185
|
+
};
|
|
@@ -4,6 +4,6 @@ declare const useSendModal: (bookingId?: number) => {
|
|
|
4
4
|
setOpen: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
5
5
|
handleOpen: () => void;
|
|
6
6
|
handleValuesChange: (val: any) => void;
|
|
7
|
-
handleOk: (values: SendModalValues) => Promise<
|
|
7
|
+
handleOk: (values: SendModalValues) => Promise<boolean | undefined>;
|
|
8
8
|
};
|
|
9
9
|
export default useSendModal;
|
|
@@ -17,7 +17,7 @@ export declare const useWalletPass: (props: {
|
|
|
17
17
|
cardData: any;
|
|
18
18
|
handleSelectWallet: (value: number[]) => void;
|
|
19
19
|
selectedWalletIds: any[];
|
|
20
|
-
expiredWalletIds: any
|
|
20
|
+
expiredWalletIds: any;
|
|
21
21
|
expiredWalletData: any;
|
|
22
22
|
disabledWalletData: any[];
|
|
23
23
|
clearAllSelectedWallet: () => void;
|
|
@@ -44,6 +44,7 @@ var import_helper = require("../helper");
|
|
|
44
44
|
var import_aggregatePayment = require("../aggregatePayment");
|
|
45
45
|
var import_types = require("../aggregatePayment/types");
|
|
46
46
|
var import_payLog = __toESM(require("../utils/payLog"));
|
|
47
|
+
var import_receipt = require("./receipt");
|
|
47
48
|
var AdyenPos = ({ onChange, isNativeApp }) => {
|
|
48
49
|
var _a, _b, _c;
|
|
49
50
|
const data = (0, import_store.useContextData)();
|
|
@@ -117,9 +118,14 @@ var AdyenPos = ({ onChange, isNativeApp }) => {
|
|
|
117
118
|
}
|
|
118
119
|
}, []);
|
|
119
120
|
const handleSuccess = (responseData) => {
|
|
120
|
-
var _a2, _b2;
|
|
121
|
+
var _a2, _b2, _c2;
|
|
121
122
|
const _response = ((_a2 = responseData == null ? void 0 : responseData.data) == null ? void 0 : _a2.external_unified_response) || {};
|
|
122
123
|
const signatureRequired = (_b2 = _response == null ? void 0 : _response.cvm_result) == null ? void 0 : _b2.signature_required;
|
|
124
|
+
const deviceSetting = (_c2 = deviceRef.current) == null ? void 0 : _c2.setting;
|
|
125
|
+
const receipt = (0, import_receipt.buildAdyenReceiptPrintPayload)(
|
|
126
|
+
_response == null ? void 0 : _response.receipts,
|
|
127
|
+
deviceSetting == null ? void 0 : deviceSetting.print_mode
|
|
128
|
+
);
|
|
123
129
|
dispatch(
|
|
124
130
|
(0, import_store.updateState)({
|
|
125
131
|
status: "success",
|
|
@@ -129,7 +135,7 @@ var AdyenPos = ({ onChange, isNativeApp }) => {
|
|
|
129
135
|
})
|
|
130
136
|
);
|
|
131
137
|
dispatch((0, import_store.updateNextStep)());
|
|
132
|
-
dispatch((0, import_store.updateCustom)({ card_reader_surcharge: 0, receipt
|
|
138
|
+
dispatch((0, import_store.updateCustom)({ card_reader_surcharge: 0, receipt }));
|
|
133
139
|
const params = (0, import_helper.getPayParams)(
|
|
134
140
|
{
|
|
135
141
|
mode: modeRef.current,
|
|
@@ -138,11 +144,11 @@ var AdyenPos = ({ onChange, isNativeApp }) => {
|
|
|
138
144
|
number: numRef.current,
|
|
139
145
|
device: deviceRef.current,
|
|
140
146
|
pay: payRef.current,
|
|
141
|
-
custom: { card_reader_surcharge: 0, receipt
|
|
147
|
+
custom: { card_reader_surcharge: 0, receipt }
|
|
142
148
|
},
|
|
143
149
|
"success"
|
|
144
150
|
);
|
|
145
|
-
const onChangeParams = { ...params, receipt
|
|
151
|
+
const onChangeParams = { ...params, receipt };
|
|
146
152
|
if (signatureRequired) {
|
|
147
153
|
dispatch(
|
|
148
154
|
(0, import_store.updateCustom)({ successParams: onChangeParams, signatureCheck: true })
|
|
@@ -150,7 +156,7 @@ var AdyenPos = ({ onChange, isNativeApp }) => {
|
|
|
150
156
|
} else {
|
|
151
157
|
clearRef.current = setTimeout(() => {
|
|
152
158
|
if (unloadRef.current) return;
|
|
153
|
-
onChange("success",
|
|
159
|
+
onChange("success", onChangeParams);
|
|
154
160
|
}, 1e3);
|
|
155
161
|
}
|
|
156
162
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** 58mm 热敏纸在标准字体下常用的半角字符列数 */
|
|
2
|
+
export declare const ADYEN_RECEIPT_LINE_WIDTH = 32;
|
|
3
|
+
export interface AdyenReceipt {
|
|
4
|
+
document_qualifier?: string;
|
|
5
|
+
lines?: unknown[];
|
|
6
|
+
}
|
|
7
|
+
/** 获取文本在等宽热敏打印机上的显示列数 */
|
|
8
|
+
export declare const getReceiptTextWidth: (text: string) => number;
|
|
9
|
+
/**
|
|
10
|
+
* 将单份 Adyen PaymentReceipt 转换为可供热敏打印机消费的纯文本。
|
|
11
|
+
*/
|
|
12
|
+
export declare const formatAdyenReceipt: (receipt: AdyenReceipt, width?: number) => string;
|
|
13
|
+
/** 按 Adyen 返回顺序生成商户联、顾客联等独立打印任务 */
|
|
14
|
+
export declare const formatAdyenReceipts: (receipts: unknown, width?: number) => string[];
|
|
15
|
+
/**
|
|
16
|
+
* 是否需要由 POS 打印收据。
|
|
17
|
+
* 兼容历史 boolean 设置以及接口可能返回的 number/string。
|
|
18
|
+
*/
|
|
19
|
+
export declare const shouldPrintReceiptOnPos: (setting?: boolean | number | string) => boolean;
|
|
20
|
+
/** 根据设备设置构建最终传给 POS 的小票数组 */
|
|
21
|
+
export declare const buildAdyenReceiptPrintPayload: (receipts: unknown, printMode?: boolean | number | string, width?: number) => string[];
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
|
|
19
|
+
// src/components/eftposPay/adyenPos/receipt.ts
|
|
20
|
+
var receipt_exports = {};
|
|
21
|
+
__export(receipt_exports, {
|
|
22
|
+
ADYEN_RECEIPT_LINE_WIDTH: () => ADYEN_RECEIPT_LINE_WIDTH,
|
|
23
|
+
buildAdyenReceiptPrintPayload: () => buildAdyenReceiptPrintPayload,
|
|
24
|
+
formatAdyenReceipt: () => formatAdyenReceipt,
|
|
25
|
+
formatAdyenReceipts: () => formatAdyenReceipts,
|
|
26
|
+
getReceiptTextWidth: () => getReceiptTextWidth,
|
|
27
|
+
shouldPrintReceiptOnPos: () => shouldPrintReceiptOnPos
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(receipt_exports);
|
|
30
|
+
var ADYEN_RECEIPT_LINE_WIDTH = 32;
|
|
31
|
+
var TITLE_KEYS = /* @__PURE__ */ new Set(["merchantTitle", "cardholderHeader"]);
|
|
32
|
+
var CENTERED_KEYS = /* @__PURE__ */ new Set([
|
|
33
|
+
"header1",
|
|
34
|
+
"header2",
|
|
35
|
+
"approved",
|
|
36
|
+
"refused",
|
|
37
|
+
"void",
|
|
38
|
+
"cvmRes",
|
|
39
|
+
"retain",
|
|
40
|
+
"thanks",
|
|
41
|
+
"sigline",
|
|
42
|
+
"merchantSigline"
|
|
43
|
+
]);
|
|
44
|
+
var isCombiningCodePoint = (codePoint) => codePoint >= 768 && codePoint <= 879 || codePoint >= 6832 && codePoint <= 6911 || codePoint >= 7616 && codePoint <= 7679 || codePoint >= 8400 && codePoint <= 8447 || codePoint >= 65056 && codePoint <= 65071 || codePoint === 65038 || codePoint === 65039;
|
|
45
|
+
var isWideCodePoint = (codePoint) => codePoint >= 4352 && (codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 42191 && codePoint !== 12351 || codePoint >= 44032 && codePoint <= 55203 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65135 || codePoint >= 65280 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127744 && codePoint <= 129791 || codePoint >= 131072 && codePoint <= 262141);
|
|
46
|
+
var getReceiptTextWidth = (text) => Array.from(text).reduce((width, character) => {
|
|
47
|
+
const codePoint = character.codePointAt(0) || 0;
|
|
48
|
+
if (isCombiningCodePoint(codePoint)) {
|
|
49
|
+
return width;
|
|
50
|
+
}
|
|
51
|
+
return width + (isWideCodePoint(codePoint) ? 2 : 1);
|
|
52
|
+
}, 0);
|
|
53
|
+
var normalizeLineWidth = (width) => {
|
|
54
|
+
if (!Number.isFinite(width) || Number(width) < 4) {
|
|
55
|
+
return ADYEN_RECEIPT_LINE_WIDTH;
|
|
56
|
+
}
|
|
57
|
+
return Math.floor(Number(width));
|
|
58
|
+
};
|
|
59
|
+
var wrapText = (text, width) => {
|
|
60
|
+
const normalizedText = text.trim();
|
|
61
|
+
if (!normalizedText) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const lines = [];
|
|
65
|
+
let currentLine = "";
|
|
66
|
+
let currentWidth = 0;
|
|
67
|
+
Array.from(normalizedText).forEach((character) => {
|
|
68
|
+
const characterWidth = getReceiptTextWidth(character);
|
|
69
|
+
if (currentLine && currentWidth + characterWidth > width) {
|
|
70
|
+
lines.push(currentLine);
|
|
71
|
+
currentLine = character;
|
|
72
|
+
currentWidth = characterWidth;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
currentLine += character;
|
|
76
|
+
currentWidth += characterWidth;
|
|
77
|
+
});
|
|
78
|
+
if (currentLine) {
|
|
79
|
+
lines.push(currentLine);
|
|
80
|
+
}
|
|
81
|
+
return lines;
|
|
82
|
+
};
|
|
83
|
+
var centerText = (text, width) => wrapText(text, width).map((line) => {
|
|
84
|
+
const padding = Math.max(
|
|
85
|
+
0,
|
|
86
|
+
Math.floor((width - getReceiptTextWidth(line)) / 2)
|
|
87
|
+
);
|
|
88
|
+
return `${" ".repeat(padding)}${line}`;
|
|
89
|
+
});
|
|
90
|
+
var rightAlignText = (text, width) => wrapText(text, width).map((line) => {
|
|
91
|
+
const padding = Math.max(0, width - getReceiptTextWidth(line));
|
|
92
|
+
return `${" ".repeat(padding)}${line}`;
|
|
93
|
+
});
|
|
94
|
+
var frameTitle = (text, width) => {
|
|
95
|
+
const innerWidth = width - 2;
|
|
96
|
+
return wrapText(text, innerWidth).map((line) => {
|
|
97
|
+
const remainingWidth = Math.max(0, innerWidth - getReceiptTextWidth(line));
|
|
98
|
+
const left = Math.floor(remainingWidth / 2);
|
|
99
|
+
const right = remainingWidth - left;
|
|
100
|
+
return `*${"-".repeat(left)}${line}${"-".repeat(right)}*`;
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
var parseReceiptLine = (line) => {
|
|
104
|
+
if (typeof line !== "string" || !line) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const params = new URLSearchParams(line);
|
|
109
|
+
return {
|
|
110
|
+
key: (params.get("key") || "").trim(),
|
|
111
|
+
name: (params.get("name") || "").trim(),
|
|
112
|
+
value: (params.get("value") || "").trim()
|
|
113
|
+
};
|
|
114
|
+
} catch (_error) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var renderKeyValue = (name, value, width) => {
|
|
119
|
+
if (!name) {
|
|
120
|
+
return centerText(value, width);
|
|
121
|
+
}
|
|
122
|
+
if (!value) {
|
|
123
|
+
return centerText(name, width);
|
|
124
|
+
}
|
|
125
|
+
const nameWidth = getReceiptTextWidth(name);
|
|
126
|
+
const valueWidth = getReceiptTextWidth(value);
|
|
127
|
+
if (nameWidth + valueWidth + 1 <= width) {
|
|
128
|
+
return [`${name}${" ".repeat(width - nameWidth - valueWidth)}${value}`];
|
|
129
|
+
}
|
|
130
|
+
return [...wrapText(name, width), ...rightAlignText(value, width)];
|
|
131
|
+
};
|
|
132
|
+
var renderReceiptLine = (receiptLine, width) => {
|
|
133
|
+
const { key, name, value } = receiptLine;
|
|
134
|
+
if (key === "filler") {
|
|
135
|
+
return [""];
|
|
136
|
+
}
|
|
137
|
+
const content = value || name;
|
|
138
|
+
if (TITLE_KEYS.has(key) && content) {
|
|
139
|
+
return frameTitle(content, width);
|
|
140
|
+
}
|
|
141
|
+
if (CENTERED_KEYS.has(key) && content) {
|
|
142
|
+
return centerText(content, width);
|
|
143
|
+
}
|
|
144
|
+
return renderKeyValue(name, value, width);
|
|
145
|
+
};
|
|
146
|
+
var formatAdyenReceipt = (receipt, width = ADYEN_RECEIPT_LINE_WIDTH) => {
|
|
147
|
+
const lineWidth = normalizeLineWidth(width);
|
|
148
|
+
if (!Array.isArray(receipt == null ? void 0 : receipt.lines)) {
|
|
149
|
+
return "";
|
|
150
|
+
}
|
|
151
|
+
const output = receipt.lines.reduce((result, line) => {
|
|
152
|
+
const parsedLine = parseReceiptLine(line);
|
|
153
|
+
if (parsedLine) {
|
|
154
|
+
result.push(...renderReceiptLine(parsedLine, lineWidth));
|
|
155
|
+
}
|
|
156
|
+
return result;
|
|
157
|
+
}, []);
|
|
158
|
+
if (!output.some(Boolean)) {
|
|
159
|
+
return "";
|
|
160
|
+
}
|
|
161
|
+
return `${output.join("\n")}
|
|
162
|
+
`;
|
|
163
|
+
};
|
|
164
|
+
var formatAdyenReceipts = (receipts, width = ADYEN_RECEIPT_LINE_WIDTH) => {
|
|
165
|
+
if (!Array.isArray(receipts)) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
return receipts.map(
|
|
169
|
+
(receipt) => receipt && typeof receipt === "object" ? formatAdyenReceipt(receipt, width) : ""
|
|
170
|
+
).filter(Boolean);
|
|
171
|
+
};
|
|
172
|
+
var shouldPrintReceiptOnPos = (setting) => {
|
|
173
|
+
if (typeof setting === "boolean") {
|
|
174
|
+
return setting === false;
|
|
175
|
+
}
|
|
176
|
+
if (typeof setting === "number") {
|
|
177
|
+
return setting === 0;
|
|
178
|
+
}
|
|
179
|
+
if (typeof setting === "string") {
|
|
180
|
+
return setting === "0";
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
};
|
|
184
|
+
var buildAdyenReceiptPrintPayload = (receipts, printMode, width = ADYEN_RECEIPT_LINE_WIDTH) => shouldPrintReceiptOnPos(printMode) ? formatAdyenReceipts(receipts, width) : [];
|
|
185
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
186
|
+
0 && (module.exports = {
|
|
187
|
+
ADYEN_RECEIPT_LINE_WIDTH,
|
|
188
|
+
buildAdyenReceiptPrintPayload,
|
|
189
|
+
formatAdyenReceipt,
|
|
190
|
+
formatAdyenReceipts,
|
|
191
|
+
getReceiptTextWidth,
|
|
192
|
+
shouldPrintReceiptOnPos
|
|
193
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pisell/private-materials",
|
|
3
|
-
"version": "6.6.
|
|
3
|
+
"version": "6.6.78",
|
|
4
4
|
"main": "./lib/index.js",
|
|
5
5
|
"module": "./es/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"@react-spring/web": "^9.6.1",
|
|
65
65
|
"@use-gesture/react": "^10.3.1",
|
|
66
66
|
"@pisell/utils": "3.0.2",
|
|
67
|
+
"@pisell/materials": "6.6.18",
|
|
67
68
|
"@pisell/icon": "0.0.11",
|
|
68
|
-
"@pisell/date-picker": "3.0.7"
|
|
69
|
-
"@pisell/materials": "6.6.18"
|
|
69
|
+
"@pisell/date-picker": "3.0.7"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"react": "^18.0.0",
|