@pisell/pisellos 0.0.230 → 0.0.232
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/modules/Order/index.d.ts +13 -2
- package/dist/modules/Order/index.js +93 -1
- package/dist/modules/Order/types.d.ts +45 -0
- package/dist/modules/Order/types.js +8 -0
- package/dist/modules/Payment/cash.d.ts +8 -0
- package/dist/modules/Payment/cash.js +20 -1
- package/dist/modules/Payment/cashRecommendationAlgorithm.d.ts +22 -0
- package/dist/modules/Payment/cashRecommendationAlgorithm.js +423 -0
- package/dist/modules/Payment/eftpos.js +1 -1
- package/dist/modules/Payment/index.d.ts +34 -124
- package/dist/modules/Payment/index.js +662 -1280
- package/dist/modules/Payment/mx51.d.ts +0 -0
- package/dist/modules/Payment/mx51.js +0 -0
- package/dist/modules/Payment/types.d.ts +323 -45
- package/dist/modules/Payment/types.js +101 -2
- package/dist/modules/Payment/utils.d.ts +17 -0
- package/dist/modules/Payment/utils.js +62 -0
- package/dist/modules/Payment/walletpass.d.ts +96 -0
- package/dist/modules/Payment/walletpass.js +492 -0
- package/dist/modules/Schedule/index.d.ts +9 -0
- package/dist/modules/Schedule/index.js +60 -0
- package/dist/solution/Checkout/index.d.ts +254 -2
- package/dist/solution/Checkout/index.js +2472 -320
- package/dist/solution/Checkout/types.d.ts +207 -6
- package/dist/solution/Checkout/types.js +5 -0
- package/lib/modules/Order/index.d.ts +13 -2
- package/lib/modules/Order/index.js +65 -1
- package/lib/modules/Order/types.d.ts +45 -0
- package/lib/modules/Payment/cash.d.ts +8 -0
- package/lib/modules/Payment/cash.js +14 -1
- package/lib/modules/Payment/cashRecommendationAlgorithm.d.ts +22 -0
- package/lib/modules/Payment/cashRecommendationAlgorithm.js +342 -0
- package/lib/modules/Payment/eftpos.js +1 -1
- package/lib/modules/Payment/index.d.ts +34 -124
- package/lib/modules/Payment/index.js +232 -533
- package/lib/modules/Payment/mx51.d.ts +0 -0
- package/lib/modules/Payment/mx51.js +0 -0
- package/lib/modules/Payment/types.d.ts +323 -45
- package/lib/modules/Payment/types.js +37 -2
- package/lib/modules/Payment/utils.d.ts +17 -0
- package/lib/modules/Payment/utils.js +67 -0
- package/lib/modules/Payment/walletpass.d.ts +96 -0
- package/lib/modules/Payment/walletpass.js +304 -0
- package/lib/modules/Schedule/index.d.ts +9 -0
- package/lib/modules/Schedule/index.js +36 -0
- package/lib/solution/Checkout/index.d.ts +254 -2
- package/lib/solution/Checkout/index.js +1361 -39
- package/lib/solution/Checkout/types.d.ts +207 -6
- package/lib/solution/Checkout/types.js +5 -0
- package/package.json +1 -1
- package/dist/modules/Payment/wallet.d.ts +0 -11
- package/dist/modules/Payment/wallet.js +0 -78
- package/lib/modules/Payment/wallet.d.ts +0 -11
- package/lib/modules/Payment/wallet.js +0 -51
|
@@ -0,0 +1,342 @@
|
|
|
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/modules/Payment/cashRecommendationAlgorithm.ts
|
|
20
|
+
var cashRecommendationAlgorithm_exports = {};
|
|
21
|
+
__export(cashRecommendationAlgorithm_exports, {
|
|
22
|
+
CURRENCY_DENOMINATIONS: () => CURRENCY_DENOMINATIONS,
|
|
23
|
+
recommendOptimalPayments: () => recommendOptimalPayments
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(cashRecommendationAlgorithm_exports);
|
|
26
|
+
var CURRENCY_DENOMINATIONS = {
|
|
27
|
+
// 美元
|
|
28
|
+
"USD": [100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05, 0.01],
|
|
29
|
+
// 人民币
|
|
30
|
+
"CNY": [100, 50, 20, 10, 5, 1, 0.5, 0.1, 0.05, 0.01],
|
|
31
|
+
"RMB": [100, 50, 20, 10, 5, 1, 0.5, 0.1, 0.05, 0.01],
|
|
32
|
+
// 欧元
|
|
33
|
+
"EUR": [500, 200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01],
|
|
34
|
+
// 日元
|
|
35
|
+
"JPY": [1e4, 5e3, 2e3, 1e3, 500, 100, 50, 10, 5, 1],
|
|
36
|
+
// 英镑
|
|
37
|
+
"GBP": [50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01],
|
|
38
|
+
// 澳元
|
|
39
|
+
"AUD": [100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1],
|
|
40
|
+
// 加元
|
|
41
|
+
"CAD": [100, 50, 20, 10, 5, 2, 1, 0.25, 0.1, 0.05],
|
|
42
|
+
// 港元
|
|
43
|
+
"HKD": [1e3, 500, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1],
|
|
44
|
+
// 新台币
|
|
45
|
+
"TWD": [2e3, 1e3, 500, 200, 100, 50, 10, 5, 1],
|
|
46
|
+
// 韩元
|
|
47
|
+
"KRW": [5e4, 1e4, 5e3, 1e3, 500, 100, 50, 10, 5, 1],
|
|
48
|
+
// 新加坡元
|
|
49
|
+
"SGD": [1e4, 1e3, 100, 50, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.01],
|
|
50
|
+
// 瑞士法郎
|
|
51
|
+
"CHF": [1e3, 200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05],
|
|
52
|
+
// 默认通用面额(如果币种不在列表中)
|
|
53
|
+
"DEFAULT": [100, 50, 20, 10, 5, 1, 0.5, 0.25, 0.1, 0.05, 0.01]
|
|
54
|
+
};
|
|
55
|
+
function recommendOptimalPayments(targetAmount, denominations) {
|
|
56
|
+
if (targetAmount <= 0 || !isFinite(targetAmount) || isNaN(targetAmount)) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
if (!denominations || !Array.isArray(denominations) || denominations.length === 0) {
|
|
60
|
+
return [Math.ceil(targetAmount)];
|
|
61
|
+
}
|
|
62
|
+
const maxReasonableDenom = targetAmount * 5;
|
|
63
|
+
const validDenoms = denominations.filter((denom) => denom > 0 && isFinite(denom) && !isNaN(denom) && denom <= maxReasonableDenom).slice(0, 8);
|
|
64
|
+
if (validDenoms.length === 0) {
|
|
65
|
+
return [Math.ceil(targetAmount)];
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const precision = 100;
|
|
69
|
+
const target = Math.round(targetAmount * precision);
|
|
70
|
+
const denoms = validDenoms.map((d) => Math.round(d * precision)).sort((a, b) => b - a);
|
|
71
|
+
const paymentOptions = [];
|
|
72
|
+
const exactCombination = findExactCombination(target, denoms, precision);
|
|
73
|
+
if (exactCombination) {
|
|
74
|
+
paymentOptions.push(exactCombination);
|
|
75
|
+
}
|
|
76
|
+
for (let i = 0; i < Math.min(denoms.length, 6); i++) {
|
|
77
|
+
const denom = denoms[i];
|
|
78
|
+
const count = Math.ceil(target / denom);
|
|
79
|
+
const sum = count * denom;
|
|
80
|
+
if (sum >= target && count <= 12) {
|
|
81
|
+
paymentOptions.push({
|
|
82
|
+
combination: Array(count).fill(denom / precision),
|
|
83
|
+
sum: sum / precision,
|
|
84
|
+
coinCount: count,
|
|
85
|
+
denomTypes: 1
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (let i = 0; i < Math.min(denoms.length - 1, 5); i++) {
|
|
90
|
+
for (let j = i + 1; j < Math.min(denoms.length, 6); j++) {
|
|
91
|
+
const denom1 = denoms[i];
|
|
92
|
+
const denom2 = denoms[j];
|
|
93
|
+
const maxCount1 = Math.min(Math.ceil(target / denom1) + 1, 8);
|
|
94
|
+
const maxCount2 = Math.min(Math.ceil(target / denom2) + 1, 10);
|
|
95
|
+
for (let count1 = 1; count1 <= maxCount1; count1++) {
|
|
96
|
+
for (let count2 = 1; count2 <= maxCount2; count2++) {
|
|
97
|
+
const sum = count1 * denom1 + count2 * denom2;
|
|
98
|
+
if (sum >= target) {
|
|
99
|
+
const combination = [
|
|
100
|
+
...Array(count1).fill(denom1 / precision),
|
|
101
|
+
...Array(count2).fill(denom2 / precision)
|
|
102
|
+
];
|
|
103
|
+
paymentOptions.push({
|
|
104
|
+
combination,
|
|
105
|
+
sum: sum / precision,
|
|
106
|
+
coinCount: count1 + count2,
|
|
107
|
+
denomTypes: 2
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
for (let i = 0; i < Math.min(denoms.length - 2, 3); i++) {
|
|
115
|
+
for (let j = i + 1; j < Math.min(denoms.length - 1, 4); j++) {
|
|
116
|
+
for (let k = j + 1; k < Math.min(denoms.length, 5); k++) {
|
|
117
|
+
const denom1 = denoms[i];
|
|
118
|
+
const denom2 = denoms[j];
|
|
119
|
+
const denom3 = denoms[k];
|
|
120
|
+
const maxCount1 = Math.min(Math.ceil(target / denom1) + 1, 5);
|
|
121
|
+
const maxCount2 = Math.min(Math.ceil(target / denom2) + 1, 6);
|
|
122
|
+
const maxCount3 = Math.min(Math.ceil(target / denom3) + 1, 8);
|
|
123
|
+
for (let count1 = 1; count1 <= maxCount1; count1++) {
|
|
124
|
+
for (let count2 = 1; count2 <= maxCount2; count2++) {
|
|
125
|
+
for (let count3 = 1; count3 <= maxCount3; count3++) {
|
|
126
|
+
const sum = count1 * denom1 + count2 * denom2 + count3 * denom3;
|
|
127
|
+
if (sum >= target) {
|
|
128
|
+
const combination = [
|
|
129
|
+
...Array(count1).fill(denom1 / precision),
|
|
130
|
+
...Array(count2).fill(denom2 / precision),
|
|
131
|
+
...Array(count3).fill(denom3 / precision)
|
|
132
|
+
];
|
|
133
|
+
paymentOptions.push({
|
|
134
|
+
combination,
|
|
135
|
+
sum: sum / precision,
|
|
136
|
+
coinCount: count1 + count2 + count3,
|
|
137
|
+
denomTypes: 3
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
for (let i = 0; i < Math.min(denoms.length - 3, 2); i++) {
|
|
147
|
+
for (let j = i + 1; j < Math.min(denoms.length - 2, 3); j++) {
|
|
148
|
+
for (let k = j + 1; k < Math.min(denoms.length - 1, 4); k++) {
|
|
149
|
+
for (let l = k + 1; l < Math.min(denoms.length, 5); l++) {
|
|
150
|
+
const denom1 = denoms[i];
|
|
151
|
+
const denom2 = denoms[j];
|
|
152
|
+
const denom3 = denoms[k];
|
|
153
|
+
const denom4 = denoms[l];
|
|
154
|
+
const maxCount1 = Math.min(Math.ceil(target / denom1) + 1, 3);
|
|
155
|
+
const maxCount2 = Math.min(Math.ceil(target / denom2) + 1, 4);
|
|
156
|
+
const maxCount3 = Math.min(Math.ceil(target / denom3) + 1, 5);
|
|
157
|
+
const maxCount4 = Math.min(Math.ceil(target / denom4) + 1, 6);
|
|
158
|
+
for (let count1 = 1; count1 <= maxCount1; count1++) {
|
|
159
|
+
for (let count2 = 1; count2 <= maxCount2; count2++) {
|
|
160
|
+
for (let count3 = 1; count3 <= maxCount3; count3++) {
|
|
161
|
+
for (let count4 = 1; count4 <= maxCount4; count4++) {
|
|
162
|
+
const sum = count1 * denom1 + count2 * denom2 + count3 * denom3 + count4 * denom4;
|
|
163
|
+
if (sum >= target) {
|
|
164
|
+
const combination = [
|
|
165
|
+
...Array(count1).fill(denom1 / precision),
|
|
166
|
+
...Array(count2).fill(denom2 / precision),
|
|
167
|
+
...Array(count3).fill(denom3 / precision),
|
|
168
|
+
...Array(count4).fill(denom4 / precision)
|
|
169
|
+
];
|
|
170
|
+
paymentOptions.push({
|
|
171
|
+
combination,
|
|
172
|
+
sum: sum / precision,
|
|
173
|
+
coinCount: count1 + count2 + count3 + count4,
|
|
174
|
+
denomTypes: 4
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (paymentOptions.length === 0) {
|
|
186
|
+
const minValidDenom = validDenoms.find((denom) => denom >= targetAmount);
|
|
187
|
+
if (minValidDenom) {
|
|
188
|
+
return [minValidDenom];
|
|
189
|
+
} else {
|
|
190
|
+
const maxDenom = Math.max(...validDenoms);
|
|
191
|
+
const count = Math.ceil(targetAmount / maxDenom);
|
|
192
|
+
return [count * maxDenom];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const uniqueCombinations = removeDuplicateAndExtendedCombinations(paymentOptions, targetAmount);
|
|
196
|
+
uniqueCombinations.sort((a, b) => {
|
|
197
|
+
if (a.denomTypes !== b.denomTypes) {
|
|
198
|
+
return a.denomTypes - b.denomTypes;
|
|
199
|
+
}
|
|
200
|
+
if (a.coinCount !== b.coinCount) {
|
|
201
|
+
return a.coinCount - b.coinCount;
|
|
202
|
+
}
|
|
203
|
+
return a.sum - b.sum;
|
|
204
|
+
});
|
|
205
|
+
const uniqueAmounts = /* @__PURE__ */ new Set();
|
|
206
|
+
const finalResults = [];
|
|
207
|
+
for (const item of uniqueCombinations) {
|
|
208
|
+
const roundedAmount = Math.round(item.sum * 100) / 100;
|
|
209
|
+
if (!uniqueAmounts.has(roundedAmount) && finalResults.length < 10) {
|
|
210
|
+
uniqueAmounts.add(roundedAmount);
|
|
211
|
+
finalResults.push(roundedAmount);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return finalResults.sort((a, b) => a - b);
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.warn("推荐支付金额计算出错:", error);
|
|
217
|
+
const safeAmount = Math.ceil(targetAmount);
|
|
218
|
+
return [targetAmount, safeAmount];
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function findExactCombination(target, denoms, precision) {
|
|
222
|
+
function dfs(remaining, denomIndex, currentCombination) {
|
|
223
|
+
if (remaining === 0) {
|
|
224
|
+
return currentCombination;
|
|
225
|
+
}
|
|
226
|
+
if (remaining < 0 || denomIndex >= denoms.length || currentCombination.length > 10) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
const denom = denoms[denomIndex];
|
|
230
|
+
const maxCount = Math.min(Math.floor(remaining / denom), 8);
|
|
231
|
+
for (let count = maxCount; count >= 0; count--) {
|
|
232
|
+
const newCombination = [...currentCombination, ...Array(count).fill(denom)];
|
|
233
|
+
const result = dfs(remaining - count * denom, denomIndex + 1, newCombination);
|
|
234
|
+
if (result) {
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
const exactMatch = dfs(target, 0, []);
|
|
241
|
+
if (exactMatch && exactMatch.length > 0) {
|
|
242
|
+
const denomTypes = new Set(exactMatch).size;
|
|
243
|
+
return {
|
|
244
|
+
combination: exactMatch.map((d) => d / precision),
|
|
245
|
+
sum: target / precision,
|
|
246
|
+
coinCount: exactMatch.length,
|
|
247
|
+
denomTypes
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
function removeDuplicateAndExtendedCombinations(combinations, targetAmount) {
|
|
253
|
+
const result = [];
|
|
254
|
+
combinations.sort((a, b) => {
|
|
255
|
+
if (a.denomTypes !== b.denomTypes) {
|
|
256
|
+
return a.denomTypes - b.denomTypes;
|
|
257
|
+
}
|
|
258
|
+
if (a.coinCount !== b.coinCount) {
|
|
259
|
+
return a.coinCount - b.coinCount;
|
|
260
|
+
}
|
|
261
|
+
return a.sum - b.sum;
|
|
262
|
+
});
|
|
263
|
+
for (let i = 0; i < combinations.length; i++) {
|
|
264
|
+
const current = combinations[i];
|
|
265
|
+
let shouldSkip = false;
|
|
266
|
+
for (let j = 0; j < result.length; j++) {
|
|
267
|
+
const existing = result[j];
|
|
268
|
+
if (isSameCombination(current.combination, existing.combination)) {
|
|
269
|
+
shouldSkip = true;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
if (isExtensionOf(current.combination, existing.combination)) {
|
|
273
|
+
shouldSkip = true;
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (!shouldSkip) {
|
|
278
|
+
for (let j = result.length - 1; j >= 0; j--) {
|
|
279
|
+
if (isExtensionOf(result[j].combination, current.combination)) {
|
|
280
|
+
result.splice(j, 1);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
result.push(current);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return result;
|
|
287
|
+
}
|
|
288
|
+
function isExtensionOf(combinationA, combinationB) {
|
|
289
|
+
if (combinationA.length <= combinationB.length) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
const countA = {};
|
|
293
|
+
const countB = {};
|
|
294
|
+
combinationA.forEach((coin) => {
|
|
295
|
+
countA[coin] = (countA[coin] || 0) + 1;
|
|
296
|
+
});
|
|
297
|
+
combinationB.forEach((coin) => {
|
|
298
|
+
countB[coin] = (countB[coin] || 0) + 1;
|
|
299
|
+
});
|
|
300
|
+
for (const coin in countB) {
|
|
301
|
+
if (!countA[coin] || countA[coin] < countB[coin]) {
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
let hasExtra = false;
|
|
306
|
+
for (const coin in countA) {
|
|
307
|
+
if (countA[coin] > (countB[coin] || 0)) {
|
|
308
|
+
hasExtra = true;
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return hasExtra;
|
|
313
|
+
}
|
|
314
|
+
function isSameCombination(combinationA, combinationB) {
|
|
315
|
+
if (combinationA.length !== combinationB.length) {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
const countA = {};
|
|
319
|
+
const countB = {};
|
|
320
|
+
combinationA.forEach((coin) => {
|
|
321
|
+
countA[coin] = (countA[coin] || 0) + 1;
|
|
322
|
+
});
|
|
323
|
+
combinationB.forEach((coin) => {
|
|
324
|
+
countB[coin] = (countB[coin] || 0) + 1;
|
|
325
|
+
});
|
|
326
|
+
for (const coin in countA) {
|
|
327
|
+
if (countA[coin] !== (countB[coin] || 0)) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
for (const coin in countB) {
|
|
332
|
+
if (countB[coin] !== (countA[coin] || 0)) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
339
|
+
0 && (module.exports = {
|
|
340
|
+
CURRENCY_DENOMINATIONS,
|
|
341
|
+
recommendOptimalPayments
|
|
342
|
+
});
|
|
@@ -39,7 +39,7 @@ var EftposPaymentImpl = class {
|
|
|
39
39
|
type: eftposMethod.type,
|
|
40
40
|
voucher_id: ""
|
|
41
41
|
};
|
|
42
|
-
await this.paymentModule.
|
|
42
|
+
await this.paymentModule.addPaymentItemAsync(orderUuid, paymentItem);
|
|
43
43
|
}
|
|
44
44
|
async checkDeviceStatus() {
|
|
45
45
|
return true;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Module, PisellCore, ModuleOptions } from '../../types';
|
|
2
|
+
import { RequestPlugin } from '../../plugins';
|
|
2
3
|
import { BaseModule } from '../BaseModule';
|
|
3
|
-
import { PaymentModuleAPI, PaymentMethod, PaymentOrder, PaymentItem, PaymentItemInput, PaymentUpdateFields, PushOrderParams, CashPayment, EftposPayment,
|
|
4
|
+
import { PaymentModuleAPI, PaymentMethod, PaymentOrder, PaymentItem, PaymentItemInput, PaymentUpdateFields, PushOrderParams, CashPayment, EftposPayment, WalletPassPayment, RoundingRule, RoundingInterval } from './types';
|
|
4
5
|
export * from './types';
|
|
5
6
|
export { generateRequestUniqueId };
|
|
6
7
|
/**
|
|
@@ -12,40 +13,19 @@ declare function generateRequestUniqueId(): string;
|
|
|
12
13
|
/**
|
|
13
14
|
* 支付模块实现
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
-
* 1. 用户操作 → 调用支付API (pushPaymentAsync, submitPayAsync等)
|
|
17
|
-
* 2. 数据处理 → 更新本地IndexDB中的订单和支付项数据
|
|
18
|
-
* 3. 立即完成 → 本地订单状态立即更新为PaymentStatus.Finished(isSynced保持false)
|
|
19
|
-
* 4. 后台同步 → 网络请求推送到TasksManager异步同步到服务器
|
|
20
|
-
* 5. 同步成功 → 网络请求成功后,isSynced设为true
|
|
21
|
-
* 6. 自动重试 → TasksManager自动重试失败的网络请求,直到isSynced为true
|
|
22
|
-
*
|
|
23
|
-
* 数据状态说明:
|
|
24
|
-
* - PaymentStatus.Processing: 订单正在进行支付操作
|
|
25
|
-
* - PaymentStatus.PartiallyPaid + isSynced=false: 部分支付完成,等待服务器同步
|
|
26
|
-
* - PaymentStatus.PartiallyPaid + isSynced=true: 部分支付且已同步到服务器
|
|
27
|
-
* - PaymentStatus.Finished + isSynced=false: 本地支付完成,等待服务器同步
|
|
28
|
-
* - PaymentStatus.Finished + isSynced=true: 支付完成且已同步到服务器
|
|
29
|
-
*
|
|
30
|
-
* 这种设计的优势:
|
|
31
|
-
* - 即时反馈:支付操作后立即显示完成状态,用户体验更佳
|
|
32
|
-
* - 离线支持:即使网络断开也能正常操作,数据保存在本地
|
|
33
|
-
* - 同步追踪:通过isSynced清楚知道哪些数据还未同步到服务器
|
|
34
|
-
* - 自动重试:TasksManager会自动重试失败的网络请求
|
|
35
|
-
* - 异步处理:不阻塞用户界面,网络同步在后台进行
|
|
36
|
-
* - 数据一致性:通过事件系统确保数据状态同步
|
|
16
|
+
* 负责处理支付相关的数据管理和本地存储
|
|
37
17
|
*/
|
|
38
18
|
export declare class PaymentModule extends BaseModule implements Module, PaymentModuleAPI {
|
|
39
19
|
protected defaultName: string;
|
|
40
20
|
protected defaultVersion: string;
|
|
41
|
-
|
|
21
|
+
request: RequestPlugin;
|
|
42
22
|
private app;
|
|
43
23
|
private store;
|
|
44
24
|
private dbManager;
|
|
45
25
|
private logger;
|
|
46
26
|
cash: CashPayment;
|
|
47
27
|
eftpos: EftposPayment;
|
|
48
|
-
wallet:
|
|
28
|
+
wallet: WalletPassPayment;
|
|
49
29
|
constructor(name?: string, version?: string);
|
|
50
30
|
initialize(core: PisellCore, options: ModuleOptions): Promise<void>;
|
|
51
31
|
/**
|
|
@@ -93,20 +73,10 @@ export declare class PaymentModule extends BaseModule implements Module, Payment
|
|
|
93
73
|
* 创建支付订单(新方法,专注支付数据)
|
|
94
74
|
*/
|
|
95
75
|
createPaymentOrderAsync(params: PushOrderParams): Promise<PaymentOrder>;
|
|
96
|
-
/**
|
|
97
|
-
* 往交易组中添加订单(兼容性方法)
|
|
98
|
-
* @deprecated 使用 createPaymentOrderAsync 替代
|
|
99
|
-
*/
|
|
100
|
-
pushOrderAsync(params: PushOrderParams): Promise<PaymentOrder>;
|
|
101
76
|
/**
|
|
102
77
|
* 删除支付订单(新方法)
|
|
103
78
|
*/
|
|
104
79
|
deletePaymentOrderAsync(orderUuid: string): Promise<void>;
|
|
105
|
-
/**
|
|
106
|
-
* 删除订单(兼容性方法)
|
|
107
|
-
* @deprecated 使用 deletePaymentOrderAsync 替代
|
|
108
|
-
*/
|
|
109
|
-
deleteOrderAsync(orderUuid: string): Promise<void>;
|
|
110
80
|
/**
|
|
111
81
|
* 更新订单
|
|
112
82
|
*/
|
|
@@ -124,26 +94,34 @@ export declare class PaymentModule extends BaseModule implements Module, Payment
|
|
|
124
94
|
replaceOrderIdByUuidAsync(orderUuid: string, newOrderId: string): Promise<PaymentOrder | null>;
|
|
125
95
|
/**
|
|
126
96
|
* 获取支付项(新方法)
|
|
97
|
+
*
|
|
98
|
+
* @param orderUuid 订单UUID
|
|
99
|
+
* @param includeVoided 是否包含已撤销的支付项,默认为false
|
|
100
|
+
* @returns 支付项数组
|
|
127
101
|
*/
|
|
128
|
-
getPaymentItemsAsync(orderUuid: string): Promise<PaymentItem[]>;
|
|
102
|
+
getPaymentItemsAsync(orderUuid: string, includeVoided?: boolean): Promise<PaymentItem[]>;
|
|
129
103
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
104
|
+
* 获取所有支付项(包括已撤销的)
|
|
105
|
+
*
|
|
106
|
+
* @param orderUuid 订单UUID
|
|
107
|
+
* @returns 所有支付项数组(包括撤销的)
|
|
132
108
|
*/
|
|
133
|
-
|
|
109
|
+
getAllPaymentItemsAsync(orderUuid: string): Promise<PaymentItem[]>;
|
|
134
110
|
/**
|
|
135
111
|
* 为某个订单添加支付项(新方法)
|
|
136
112
|
*/
|
|
137
113
|
addPaymentItemAsync(orderUuid: string, paymentItem: PaymentItemInput): Promise<void>;
|
|
138
114
|
/**
|
|
139
|
-
*
|
|
140
|
-
* @deprecated 使用 addPaymentItemAsync 替代
|
|
115
|
+
* 删除一个支付项 - 标记删除而非物理删除
|
|
141
116
|
*/
|
|
142
|
-
|
|
117
|
+
deletePaymentAsync(orderUuid: string, paymentUuid: string): Promise<void>;
|
|
143
118
|
/**
|
|
144
|
-
*
|
|
119
|
+
* 批量更新代金券类支付项(覆盖更新)
|
|
120
|
+
*
|
|
121
|
+
* 删除所有现有的带 voucher_id 的支付项,然后添加新的代金券支付项
|
|
122
|
+
* 这是一个覆盖式更新,确保代金券支付项的一致性
|
|
145
123
|
*/
|
|
146
|
-
|
|
124
|
+
updateVoucherPaymentItemsAsync(orderUuid: string, voucherPaymentItems: PaymentItemInput[]): Promise<void>;
|
|
147
125
|
/**
|
|
148
126
|
* 更新一个支付项
|
|
149
127
|
*/
|
|
@@ -158,10 +136,6 @@ export declare class PaymentModule extends BaseModule implements Module, Payment
|
|
|
158
136
|
* 提交单个订单的支付(推送到任务队列)
|
|
159
137
|
*/
|
|
160
138
|
private submitSingleOrderPayment;
|
|
161
|
-
/**
|
|
162
|
-
* 添加到同步任务队列
|
|
163
|
-
*/
|
|
164
|
-
private addToSyncQueue;
|
|
165
139
|
/**
|
|
166
140
|
* 获取订单剩余待付金额
|
|
167
141
|
*/
|
|
@@ -186,15 +160,6 @@ export declare class PaymentModule extends BaseModule implements Module, Payment
|
|
|
186
160
|
* 获取钱包支付方式
|
|
187
161
|
*/
|
|
188
162
|
getWalletPaymentMethod(): Promise<PaymentMethod | null>;
|
|
189
|
-
/**
|
|
190
|
-
* 注册任务处理函数
|
|
191
|
-
*/
|
|
192
|
-
private registerTaskHandlers;
|
|
193
|
-
/**
|
|
194
|
-
* 静态方法:处理支付同步任务(后台网络同步)
|
|
195
|
-
* 这个方法里不允许用 this,因为需要作为静态方法注入到任务队列里
|
|
196
|
-
*/
|
|
197
|
-
static syncPaymentTask(payload: any): Promise<any>;
|
|
198
163
|
/**
|
|
199
164
|
* 确保支付模块所需的数据库表已创建
|
|
200
165
|
*/
|
|
@@ -204,77 +169,22 @@ export declare class PaymentModule extends BaseModule implements Module, Payment
|
|
|
204
169
|
*/
|
|
205
170
|
getPartiallyPaidOrdersAsync(): Promise<PaymentOrder[]>;
|
|
206
171
|
/**
|
|
207
|
-
*
|
|
208
|
-
*/
|
|
209
|
-
getUnsyncedOrdersAsync(): Promise<PaymentOrder[]>;
|
|
210
|
-
/**
|
|
211
|
-
* 清理已完成且已同步的订单
|
|
212
|
-
* 注意:只清理完全支付的订单,部分支付的订单保留以便继续支付
|
|
213
|
-
*/
|
|
214
|
-
cleanupFinishedOrders(): Promise<void>;
|
|
215
|
-
/**
|
|
216
|
-
* 检测未同步的订单并重新加入任务队列
|
|
217
|
-
*
|
|
218
|
-
* 此方法专门用于处理因网络问题导致任务队列执行失败但队列被清空的情况。
|
|
219
|
-
* 它会检查本地 IndexDB 中所有未同步的订单(isSynced: false),
|
|
220
|
-
* 并将这些订单重新添加到任务队列中。
|
|
221
|
-
*
|
|
222
|
-
* 使用场景:
|
|
223
|
-
* - 网络恢复后重新检查未同步的订单
|
|
224
|
-
* - 应用启动时检查并重新排队未完成的支付
|
|
225
|
-
* - 用户手动重试前的预检查
|
|
226
|
-
*
|
|
227
|
-
* @returns Promise<number> 返回重新加入队列的订单数量
|
|
228
|
-
*/
|
|
229
|
-
recheckAndRequeueUnsyncedOrders(): Promise<number>;
|
|
230
|
-
/**
|
|
231
|
-
* 手动执行支付同步队列
|
|
232
|
-
* 外部可以调用此方法来触发支付同步任务的执行
|
|
233
|
-
*
|
|
234
|
-
* 注意:此方法只执行现有队列中的任务,不会检查未同步的订单。
|
|
235
|
-
* 如果需要检查未同步订单,请先调用 recheckAndRequeueUnsyncedOrders()
|
|
172
|
+
* 智能金额舍入
|
|
236
173
|
*
|
|
237
|
-
*
|
|
238
|
-
* ```typescript
|
|
239
|
-
* // 1. 先检查并重新排队未同步订单,然后执行队列
|
|
240
|
-
* const requeuedCount = await paymentModule.recheckAndRequeueUnsyncedOrders();
|
|
241
|
-
* if (requeuedCount > 0) {
|
|
242
|
-
* await paymentModule.runPaymentSyncQueue();
|
|
243
|
-
* }
|
|
174
|
+
* 根据指定的舍入间隔和规则对金额进行舍入处理
|
|
244
175
|
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
176
|
+
* @param originalAmount 原始金额
|
|
177
|
+
* @param interval 舍入间隔 (0.05, 0.1, 0.5, 1)
|
|
178
|
+
* @param rule 舍入规则 (standard, standard_down, always_up, always_down)
|
|
179
|
+
* @returns 舍入后的金额(保留两位小数的字符串)
|
|
248
180
|
*/
|
|
249
|
-
|
|
181
|
+
roundAmountAsync(originalAmount: number | string, interval: RoundingInterval | number, rule: RoundingRule | string): Promise<string>;
|
|
250
182
|
/**
|
|
251
|
-
*
|
|
252
|
-
* 用于处理因网络问题导致任务队列清空但订单未同步的情况
|
|
183
|
+
* 标准舍入处理(处理中点情况)
|
|
253
184
|
*
|
|
254
|
-
* @param
|
|
255
|
-
* @
|
|
185
|
+
* @param value 要舍入的值
|
|
186
|
+
* @param midpointUp 中点是否向上舍入
|
|
187
|
+
* @returns 舍入后的值
|
|
256
188
|
*/
|
|
257
|
-
private
|
|
258
|
-
/**
|
|
259
|
-
* 删除支付项(新方法)
|
|
260
|
-
*/
|
|
261
|
-
deletePaymentItemAsync(orderUuid: string, paymentUuid: string): Promise<void>;
|
|
262
|
-
/**
|
|
263
|
-
* 更新支付项(新方法)
|
|
264
|
-
*/
|
|
265
|
-
updatePaymentItemAsync(orderUuid: string, paymentUuid: string, params: PaymentUpdateFields): Promise<void>;
|
|
266
|
-
/**
|
|
267
|
-
* 获取订单剩余待付金额(新方法)
|
|
268
|
-
*/
|
|
269
|
-
getRemainingAmountAsync(orderUuid: string): Promise<number>;
|
|
270
|
-
/**
|
|
271
|
-
* 获取订单剩余待付金额(基于用户输入的金额)(新方法)
|
|
272
|
-
*/
|
|
273
|
-
getRemainingAmountWithInputAsync(inputAmount: string | number, orderUuid: string): Promise<number>;
|
|
274
|
-
/**
|
|
275
|
-
* 提交支付(新方法)
|
|
276
|
-
*/
|
|
277
|
-
submitPaymentAsync(orderUuid: string): Promise<{
|
|
278
|
-
status: 'success' | 'failed';
|
|
279
|
-
}>;
|
|
189
|
+
private standardRound;
|
|
280
190
|
}
|