@cimplify/sdk 0.16.3 → 0.18.0
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/advanced.d.mts +2 -2
- package/dist/advanced.d.ts +2 -2
- package/dist/advanced.js +90 -2913
- package/dist/advanced.mjs +3 -2893
- package/dist/chunk-2JI47EYJ.mjs +2786 -0
- package/dist/chunk-DYKFSV77.js +2837 -0
- package/dist/chunk-FLPI2VVJ.js +72 -0
- package/dist/chunk-FTL2SXCG.mjs +674 -0
- package/dist/chunk-KTTQC5HG.mjs +687 -0
- package/dist/chunk-LM3CJ4L7.mjs +69 -0
- package/dist/chunk-MJECWMOY.js +692 -0
- package/dist/chunk-RYQ5IPWX.js +714 -0
- package/dist/chunk-S6TU55KP.js +170 -0
- package/dist/chunk-WDIMISRC.mjs +166 -0
- package/dist/{client-BaolRdB4.d.mts → client-B1UtuyOg.d.ts} +21 -12
- package/dist/{client-C59R79gx.d.ts → client-BFFfuzJr.d.mts} +21 -12
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +401 -4420
- package/dist/index.mjs +5 -4325
- package/dist/{payment-C6ULw3K-.d.mts → payment-D9FTaOse.d.mts} +66 -1
- package/dist/{payment-C6ULw3K-.d.ts → payment-D9FTaOse.d.ts} +66 -1
- package/dist/{price-CbR6DCt0.d.mts → price-9JsPuknm.d.mts} +1 -1
- package/dist/{price-Bd6JBV8W.d.ts → price-BD1iioLh.d.ts} +1 -1
- package/dist/react.d.mts +43 -11
- package/dist/react.d.ts +43 -11
- package/dist/react.js +540 -3981
- package/dist/react.mjs +489 -3933
- package/dist/styles.css +1 -1
- package/dist/utils.d.mts +5 -5
- package/dist/utils.d.ts +5 -5
- package/dist/utils.js +122 -721
- package/dist/utils.mjs +2 -695
- package/package.json +1 -1
- package/registry/add-on-selector.json +1 -1
- package/registry/catalogue-page.json +1 -1
- package/registry/checkout-page.json +1 -1
- package/registry/composite-selector.json +1 -1
- package/registry/product-grid.json +1 -1
package/dist/utils.mjs
CHANGED
|
@@ -1,695 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// src/utils/price.ts
|
|
4
|
-
var CURRENCY_SYMBOLS = {
|
|
5
|
-
USD: "$",
|
|
6
|
-
EUR: "\u20AC",
|
|
7
|
-
GBP: "\xA3",
|
|
8
|
-
JPY: "\xA5",
|
|
9
|
-
CNY: "\xA5",
|
|
10
|
-
CHF: "CHF",
|
|
11
|
-
CAD: "C$",
|
|
12
|
-
AUD: "A$",
|
|
13
|
-
NZD: "NZ$",
|
|
14
|
-
HKD: "HK$",
|
|
15
|
-
SGD: "S$",
|
|
16
|
-
INR: "\u20B9",
|
|
17
|
-
BRL: "R$",
|
|
18
|
-
MXN: "MX$",
|
|
19
|
-
KRW: "\u20A9",
|
|
20
|
-
RUB: "\u20BD",
|
|
21
|
-
TRY: "\u20BA",
|
|
22
|
-
THB: "\u0E3F",
|
|
23
|
-
PLN: "z\u0142",
|
|
24
|
-
SEK: "kr",
|
|
25
|
-
NOK: "kr",
|
|
26
|
-
DKK: "kr",
|
|
27
|
-
CZK: "K\u010D",
|
|
28
|
-
HUF: "Ft",
|
|
29
|
-
ILS: "\u20AA",
|
|
30
|
-
AED: "\u062F.\u0625",
|
|
31
|
-
SAR: "\uFDFC",
|
|
32
|
-
MYR: "RM",
|
|
33
|
-
PHP: "\u20B1",
|
|
34
|
-
IDR: "Rp",
|
|
35
|
-
VND: "\u20AB",
|
|
36
|
-
TWD: "NT$",
|
|
37
|
-
GHS: "GH\u20B5",
|
|
38
|
-
NGN: "\u20A6",
|
|
39
|
-
KES: "KSh",
|
|
40
|
-
ZAR: "R",
|
|
41
|
-
XOF: "CFA",
|
|
42
|
-
XAF: "FCFA",
|
|
43
|
-
EGP: "E\xA3",
|
|
44
|
-
MAD: "MAD",
|
|
45
|
-
TZS: "TSh",
|
|
46
|
-
UGX: "USh",
|
|
47
|
-
RWF: "FRw",
|
|
48
|
-
ETB: "Br",
|
|
49
|
-
ZMW: "ZK",
|
|
50
|
-
BWP: "P",
|
|
51
|
-
MUR: "\u20A8",
|
|
52
|
-
SCR: "\u20A8",
|
|
53
|
-
NAD: "N$",
|
|
54
|
-
SZL: "E",
|
|
55
|
-
LSL: "L",
|
|
56
|
-
MWK: "MK",
|
|
57
|
-
AOA: "Kz",
|
|
58
|
-
CDF: "FC",
|
|
59
|
-
GMD: "D",
|
|
60
|
-
GNF: "FG",
|
|
61
|
-
LRD: "L$",
|
|
62
|
-
SLL: "Le",
|
|
63
|
-
MZN: "MT",
|
|
64
|
-
SDG: "SDG",
|
|
65
|
-
SSP: "SSP",
|
|
66
|
-
SOS: "Sh.So.",
|
|
67
|
-
DJF: "Fdj",
|
|
68
|
-
ERN: "Nfk",
|
|
69
|
-
CVE: "$",
|
|
70
|
-
STN: "Db",
|
|
71
|
-
KMF: "CF",
|
|
72
|
-
BIF: "FBu"
|
|
73
|
-
};
|
|
74
|
-
function getCurrencySymbol(currencyCode2) {
|
|
75
|
-
return CURRENCY_SYMBOLS[currencyCode2.toUpperCase()] || currencyCode2;
|
|
76
|
-
}
|
|
77
|
-
function formatNumberCompact(value, decimals = 1) {
|
|
78
|
-
const absValue = Math.abs(value);
|
|
79
|
-
const sign = value < 0 ? "-" : "";
|
|
80
|
-
if (absValue >= 1e9) {
|
|
81
|
-
return `${sign}${(absValue / 1e9).toFixed(decimals)}B`;
|
|
82
|
-
}
|
|
83
|
-
if (absValue >= 1e6) {
|
|
84
|
-
return `${sign}${(absValue / 1e6).toFixed(decimals)}M`;
|
|
85
|
-
}
|
|
86
|
-
if (absValue >= 1e3) {
|
|
87
|
-
return `${sign}${(absValue / 1e3).toFixed(decimals)}K`;
|
|
88
|
-
}
|
|
89
|
-
return `${sign}${absValue.toFixed(decimals)}`;
|
|
90
|
-
}
|
|
91
|
-
function formatPrice(amount, currency = "GHS", locale = "en-US") {
|
|
92
|
-
const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
93
|
-
if (isNaN(numAmount)) {
|
|
94
|
-
return `${getCurrencySymbol(currency)}0.00`;
|
|
95
|
-
}
|
|
96
|
-
try {
|
|
97
|
-
return new Intl.NumberFormat(locale, {
|
|
98
|
-
style: "currency",
|
|
99
|
-
currency: currency.toUpperCase(),
|
|
100
|
-
minimumFractionDigits: 2,
|
|
101
|
-
maximumFractionDigits: 2
|
|
102
|
-
}).format(numAmount);
|
|
103
|
-
} catch {
|
|
104
|
-
return `${getCurrencySymbol(currency)}${numAmount.toFixed(2)}`;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
function formatPriceAdjustment(amount, currency = "GHS", locale = "en-US") {
|
|
108
|
-
const formatted = formatPrice(Math.abs(amount), currency, locale);
|
|
109
|
-
if (amount > 0) {
|
|
110
|
-
return `+${formatted}`;
|
|
111
|
-
} else if (amount < 0) {
|
|
112
|
-
return `-${formatted}`;
|
|
113
|
-
}
|
|
114
|
-
return formatted;
|
|
115
|
-
}
|
|
116
|
-
function formatPriceCompact(amount, currency = "GHS", decimals = 1) {
|
|
117
|
-
const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
118
|
-
if (isNaN(numAmount)) {
|
|
119
|
-
return `${getCurrencySymbol(currency)}0`;
|
|
120
|
-
}
|
|
121
|
-
const symbol = getCurrencySymbol(currency);
|
|
122
|
-
if (Math.abs(numAmount) < 1e3) {
|
|
123
|
-
return `${symbol}${numAmount.toFixed(2)}`;
|
|
124
|
-
}
|
|
125
|
-
return `${symbol}${formatNumberCompact(numAmount, decimals)}`;
|
|
126
|
-
}
|
|
127
|
-
function formatMoney(amount, currency = "GHS") {
|
|
128
|
-
const symbol = getCurrencySymbol(currency);
|
|
129
|
-
const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
130
|
-
if (isNaN(numAmount)) {
|
|
131
|
-
return `${symbol}0.00`;
|
|
132
|
-
}
|
|
133
|
-
return `${symbol}${numAmount.toFixed(2)}`;
|
|
134
|
-
}
|
|
135
|
-
function parsePrice(value) {
|
|
136
|
-
if (value === void 0 || value === null) {
|
|
137
|
-
return 0;
|
|
138
|
-
}
|
|
139
|
-
if (typeof value === "number") {
|
|
140
|
-
return isNaN(value) ? 0 : value;
|
|
141
|
-
}
|
|
142
|
-
const cleaned = value.replace(/[^\d.-]/g, "");
|
|
143
|
-
const parsed = parseFloat(cleaned);
|
|
144
|
-
return isNaN(parsed) ? 0 : parsed;
|
|
145
|
-
}
|
|
146
|
-
function hasTaxInfo(priceInfo) {
|
|
147
|
-
return priceInfo.tax_info !== void 0 && priceInfo.tax_info !== null;
|
|
148
|
-
}
|
|
149
|
-
function getTaxAmount(priceInfo) {
|
|
150
|
-
return parsePrice(priceInfo.tax_info?.tax_amount);
|
|
151
|
-
}
|
|
152
|
-
function isTaxInclusive(priceInfo) {
|
|
153
|
-
return priceInfo.tax_info?.is_inclusive === true;
|
|
154
|
-
}
|
|
155
|
-
function formatPriceWithTax(priceInfo, currency = "GHS") {
|
|
156
|
-
const finalPrice = formatPrice(priceInfo.final_price, currency);
|
|
157
|
-
if (!hasTaxInfo(priceInfo)) {
|
|
158
|
-
return finalPrice;
|
|
159
|
-
}
|
|
160
|
-
if (isTaxInclusive(priceInfo)) {
|
|
161
|
-
return `${finalPrice} (incl. tax)`;
|
|
162
|
-
}
|
|
163
|
-
return `${finalPrice} + ${formatPrice(getTaxAmount(priceInfo), currency)} tax`;
|
|
164
|
-
}
|
|
165
|
-
function getDisplayPrice(product) {
|
|
166
|
-
if (product.price_info) {
|
|
167
|
-
return parsePrice(product.price_info.final_price);
|
|
168
|
-
}
|
|
169
|
-
if (product.final_price !== void 0 && product.final_price !== null) {
|
|
170
|
-
return parsePrice(product.final_price);
|
|
171
|
-
}
|
|
172
|
-
if (product.default_price !== void 0 && product.default_price !== null) {
|
|
173
|
-
return parsePrice(product.default_price);
|
|
174
|
-
}
|
|
175
|
-
return 0;
|
|
176
|
-
}
|
|
177
|
-
function getBasePrice(product) {
|
|
178
|
-
if (product.price_info) {
|
|
179
|
-
return parsePrice(product.price_info.base_price);
|
|
180
|
-
}
|
|
181
|
-
if (product.base_price !== void 0 && product.base_price !== null) {
|
|
182
|
-
return parsePrice(product.base_price);
|
|
183
|
-
}
|
|
184
|
-
if (product.default_price !== void 0 && product.default_price !== null) {
|
|
185
|
-
return parsePrice(product.default_price);
|
|
186
|
-
}
|
|
187
|
-
return 0;
|
|
188
|
-
}
|
|
189
|
-
function isOnSale(product) {
|
|
190
|
-
const basePrice = getBasePrice(product);
|
|
191
|
-
const finalPrice = getDisplayPrice(product);
|
|
192
|
-
return basePrice > finalPrice && basePrice > 0;
|
|
193
|
-
}
|
|
194
|
-
function getDiscountPercentage(product) {
|
|
195
|
-
const basePrice = getBasePrice(product);
|
|
196
|
-
const finalPrice = getDisplayPrice(product);
|
|
197
|
-
if (basePrice > finalPrice && basePrice > 0) {
|
|
198
|
-
return Math.round((basePrice - finalPrice) / basePrice * 100);
|
|
199
|
-
}
|
|
200
|
-
return 0;
|
|
201
|
-
}
|
|
202
|
-
function getMarkupPercentage(product) {
|
|
203
|
-
const basePrice = getBasePrice(product);
|
|
204
|
-
const finalPrice = getDisplayPrice(product);
|
|
205
|
-
if (finalPrice > basePrice && basePrice > 0) {
|
|
206
|
-
return Math.round((finalPrice - basePrice) / basePrice * 100);
|
|
207
|
-
}
|
|
208
|
-
return 0;
|
|
209
|
-
}
|
|
210
|
-
function getProductCurrency(product) {
|
|
211
|
-
if (product.price_info?.currency) {
|
|
212
|
-
return product.price_info.currency;
|
|
213
|
-
}
|
|
214
|
-
if (product.currency) {
|
|
215
|
-
return product.currency;
|
|
216
|
-
}
|
|
217
|
-
return "GHS";
|
|
218
|
-
}
|
|
219
|
-
function formatProductPrice(product, locale = "en-US") {
|
|
220
|
-
const price = getDisplayPrice(product);
|
|
221
|
-
const currency = getProductCurrency(product);
|
|
222
|
-
return formatPrice(price, currency, locale);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// src/types/common.ts
|
|
226
|
-
function money(value) {
|
|
227
|
-
return typeof value === "string" ? parseFloat(value) || 0 : value;
|
|
228
|
-
}
|
|
229
|
-
function moneyFromNumber(value) {
|
|
230
|
-
return value;
|
|
231
|
-
}
|
|
232
|
-
var DOCS_ERROR_BASE_URL = "https://docs.cimplify.io/reference/error-codes";
|
|
233
|
-
function docsUrlForCode(code) {
|
|
234
|
-
return `${DOCS_ERROR_BASE_URL}#${code.toLowerCase().replace(/_/g, "-")}`;
|
|
235
|
-
}
|
|
236
|
-
var ERROR_SUGGESTIONS = {
|
|
237
|
-
UNKNOWN_ERROR: "An unexpected error occurred. Capture the request/response payload and retry with exponential backoff.",
|
|
238
|
-
NETWORK_ERROR: "Check the shopper's connection and retry. If this persists, inspect CORS, DNS, and API reachability.",
|
|
239
|
-
TIMEOUT: "The request exceeded the timeout. Retry once, then poll order status before charging again.",
|
|
240
|
-
UNAUTHORIZED: "Authentication is missing or expired. Ensure a valid access token is set and refresh the session if needed.",
|
|
241
|
-
FORBIDDEN: "The key/session lacks permission for this resource. Verify business ownership and API key scope.",
|
|
242
|
-
NOT_FOUND: "The requested resource does not exist or is not visible in this environment.",
|
|
243
|
-
VALIDATION_ERROR: "One or more fields are invalid. Validate required fields and enum values before retrying.",
|
|
244
|
-
CART_EMPTY: "The cart has no items. Redirect back to menu/catalogue and require at least one line item.",
|
|
245
|
-
CART_EXPIRED: "This cart is no longer active. Recreate a new cart and re-add shopper selections.",
|
|
246
|
-
CART_NOT_FOUND: "Cart could not be located. It may have expired or belongs to a different key/location.",
|
|
247
|
-
ITEM_UNAVAILABLE: "The selected item is unavailable at this location/time. Prompt the shopper to pick an alternative.",
|
|
248
|
-
VARIANT_NOT_FOUND: "The requested variant no longer exists. Refresh product data and require re-selection.",
|
|
249
|
-
VARIANT_OUT_OF_STOCK: "The selected variant is out of stock. Show in-stock variants and block checkout for this line.",
|
|
250
|
-
ADDON_REQUIRED: "A required add-on is missing. Ensure required modifier groups are completed before add-to-cart.",
|
|
251
|
-
ADDON_MAX_EXCEEDED: "Too many add-ons were selected. Enforce max selections client-side before submission.",
|
|
252
|
-
CHECKOUT_VALIDATION_FAILED: "Checkout payload failed validation. Verify customer, order type, and address fields are complete.",
|
|
253
|
-
DELIVERY_ADDRESS_REQUIRED: "Delivery orders require an address. Collect and pass address info before processing checkout.",
|
|
254
|
-
CUSTOMER_INFO_REQUIRED: "Customer details are required. Ensure name/email/phone are available before checkout.",
|
|
255
|
-
QUOTE_NOT_FOUND: "Quote could not be found. Refresh pricing and create a new quote before checkout.",
|
|
256
|
-
QUOTE_EXPIRED: "Quote has expired. Re-fetch pricing to generate a new quote with a valid expiry window.",
|
|
257
|
-
QUOTE_CONSUMED: "Quote has already been used. Request a fresh quote to prevent duplicate checkout attempts.",
|
|
258
|
-
QUOTE_STORAGE_UNAVAILABLE: "Quote storage is temporarily unavailable. Retry shortly and avoid charging until quote fetch succeeds.",
|
|
259
|
-
PAYMENT_FAILED: "Payment provider rejected or failed processing. Show retry/change-method options to the shopper.",
|
|
260
|
-
PAYMENT_CANCELLED: "Payment was cancelled by the shopper or provider flow. Allow a safe retry path.",
|
|
261
|
-
INSUFFICIENT_FUNDS: "Payment method has insufficient funds. Prompt shopper to use another method.",
|
|
262
|
-
CARD_DECLINED: "Card was declined. Ask shopper to retry or switch payment method.",
|
|
263
|
-
INVALID_OTP: "Authorization code is invalid. Let shopper re-enter OTP/PIN and retry.",
|
|
264
|
-
OTP_EXPIRED: "Authorization code expired. Request a new OTP and re-submit authorization.",
|
|
265
|
-
AUTHORIZATION_FAILED: "Additional payment authorization failed. Retry authorization or change payment method.",
|
|
266
|
-
PAYMENT_ACTION_NOT_COMPLETED: "Required payment action was not completed. Resume provider flow and poll for status.",
|
|
267
|
-
SLOT_UNAVAILABLE: "Selected schedule slot is unavailable. Refresh available slots and ask shopper to reselect.",
|
|
268
|
-
BOOKING_CONFLICT: "The requested booking conflicts with an existing reservation. Pick another slot/resource.",
|
|
269
|
-
SERVICE_NOT_FOUND: "Requested service no longer exists. Refresh service catalogue and retry selection.",
|
|
270
|
-
OUT_OF_STOCK: "Inventory is depleted for this item. Remove it or reduce quantity before checkout.",
|
|
271
|
-
INSUFFICIENT_QUANTITY: "Requested quantity exceeds available inventory. Reduce quantity and retry.",
|
|
272
|
-
BUSINESS_ID_REQUIRED: "Business context could not be resolved. Verify the public key and business bootstrap call.",
|
|
273
|
-
INVALID_CART: "Cart is invalid for checkout. Sync cart state, ensure items exist, then retry.",
|
|
274
|
-
ORDER_TYPE_REQUIRED: "Order type is required. Provide one of delivery, pickup, or dine_in before checkout.",
|
|
275
|
-
NO_PAYMENT_ELEMENT: "PaymentElement is required for processCheckout(). Mount it before triggering checkout.",
|
|
276
|
-
PAYMENT_NOT_MOUNTED: "PaymentElement iframe is not mounted. Mount it in the DOM before processCheckout().",
|
|
277
|
-
AUTH_INCOMPLETE: "AuthElement has not completed authentication. Wait for AUTHENTICATED before checkout.",
|
|
278
|
-
AUTH_LOST: "Session was cleared during checkout. Re-authenticate and restart checkout safely.",
|
|
279
|
-
ALREADY_PROCESSING: "Checkout is already in progress. Disable duplicate submits until completion.",
|
|
280
|
-
CHECKOUT_NOT_READY: "Checkout elements are still initializing. Wait for readiness before submit.",
|
|
281
|
-
CANCELLED: "Checkout was cancelled. Preserve cart state and allow shopper to retry.",
|
|
282
|
-
REQUEST_TIMEOUT: "Provider call timed out. Poll payment/order status before issuing another charge attempt.",
|
|
283
|
-
POPUP_BLOCKED: "Browser blocked provider popup. Ask shopper to enable popups and retry.",
|
|
284
|
-
FX_QUOTE_FAILED: "Failed to lock FX quote. Retry currency quote or fallback to base currency."
|
|
285
|
-
};
|
|
286
|
-
Object.fromEntries(
|
|
287
|
-
Object.entries(ERROR_SUGGESTIONS).map(([code, suggestion]) => [
|
|
288
|
-
code,
|
|
289
|
-
{
|
|
290
|
-
docs_url: docsUrlForCode(code),
|
|
291
|
-
suggestion
|
|
292
|
-
}
|
|
293
|
-
])
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
// src/utils/payment.ts
|
|
297
|
-
function categorizePaymentError(error, errorCode) {
|
|
298
|
-
let message = "An unexpected error occurred during payment processing. Please try again or contact support.";
|
|
299
|
-
let recoverable = true;
|
|
300
|
-
let code = errorCode || "PAYMENT_ERROR";
|
|
301
|
-
const technical = error.stack;
|
|
302
|
-
const errorMessage = error.message?.toLowerCase() || "";
|
|
303
|
-
if (errorCode === "INSUFFICIENT_FUNDS" || errorMessage.includes("insufficient") || errorMessage.includes("funds")) {
|
|
304
|
-
code = "INSUFFICIENT_FUNDS";
|
|
305
|
-
message = "Your payment method has insufficient funds. Please try another payment method.";
|
|
306
|
-
} else if (errorCode === "CARD_DECLINED" || errorMessage.includes("declined")) {
|
|
307
|
-
code = "CARD_DECLINED";
|
|
308
|
-
message = "Your card was declined. Please try another card or payment method.";
|
|
309
|
-
} else if (errorMessage.includes("cancelled") || errorMessage.includes("canceled") || errorCode === "PAYMENT_CANCELLED") {
|
|
310
|
-
code = "PAYMENT_CANCELLED";
|
|
311
|
-
message = "Payment was cancelled. You can try again when ready.";
|
|
312
|
-
} else if (errorMessage.includes("network") || errorMessage.includes("connection") || errorCode === "NETWORK_ERROR") {
|
|
313
|
-
code = "NETWORK_ERROR";
|
|
314
|
-
message = "Network connection issue. Please check your internet connection and try again.";
|
|
315
|
-
} else if (errorMessage.includes("timeout") || errorCode === "TIMEOUT") {
|
|
316
|
-
code = "TIMEOUT";
|
|
317
|
-
message = "Payment processing timed out. Please try again.";
|
|
318
|
-
} else if (errorCode === "PAYMENT_ACTION_NOT_COMPLETED") {
|
|
319
|
-
code = "PAYMENT_ACTION_NOT_COMPLETED";
|
|
320
|
-
message = "Payment action was not completed. Please try again.";
|
|
321
|
-
} else if (errorCode === "AUTHORIZATION_FAILED") {
|
|
322
|
-
code = "AUTHORIZATION_FAILED";
|
|
323
|
-
message = "Authorization failed. Please check your code and try again.";
|
|
324
|
-
} else if (errorCode === "INVALID_OTP") {
|
|
325
|
-
code = "INVALID_OTP";
|
|
326
|
-
message = "Invalid verification code. Please check and try again.";
|
|
327
|
-
}
|
|
328
|
-
return { code, message, recoverable, technical };
|
|
329
|
-
}
|
|
330
|
-
function isQuickPaymentResponse(response) {
|
|
331
|
-
return response !== null && typeof response === "object" && "payment" in response && typeof response.payment === "object";
|
|
332
|
-
}
|
|
333
|
-
function isWebPaymentResponse(response) {
|
|
334
|
-
return response !== null && typeof response === "object" && "transaction" in response && typeof response.transaction === "object";
|
|
335
|
-
}
|
|
336
|
-
function normalizePaymentResponse(response) {
|
|
337
|
-
if (!response) {
|
|
338
|
-
return {
|
|
339
|
-
method: "unknown",
|
|
340
|
-
provider: "unknown",
|
|
341
|
-
requires_action: false,
|
|
342
|
-
metadata: {}
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
if (isQuickPaymentResponse(response)) {
|
|
346
|
-
return {
|
|
347
|
-
method: response.payment.type?.toLowerCase() || "unknown",
|
|
348
|
-
provider: response.payment.provider?.toLowerCase() || "unknown",
|
|
349
|
-
requires_action: !!response.payment.redirect_url || !!response.payment.access_code,
|
|
350
|
-
public_key: response.payment.public_key,
|
|
351
|
-
client_secret: response.payment.access_code,
|
|
352
|
-
access_code: response.payment.access_code,
|
|
353
|
-
redirect_url: response.payment.redirect_url,
|
|
354
|
-
transaction_id: response.payment.reference,
|
|
355
|
-
order_id: response.order_id,
|
|
356
|
-
reference: response.payment.reference,
|
|
357
|
-
instructions: response.payment.instructions,
|
|
358
|
-
metadata: response.payment.metadata
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
if (isWebPaymentResponse(response)) {
|
|
362
|
-
const objectAuthType = response.authorization_type && typeof response.authorization_type === "object" && "address" in response.authorization_type ? "address" : void 0;
|
|
363
|
-
const authType = typeof response.authorization_type === "string" ? response.authorization_type.trim().toLowerCase().replace(/[\s-]+/g, "_") : void 0;
|
|
364
|
-
const validStringAuthTypes = ["otp", "pin", "phone", "birthday", "address"];
|
|
365
|
-
const safeAuthType = objectAuthType || (authType && validStringAuthTypes.includes(authType) ? authType : void 0);
|
|
366
|
-
return {
|
|
367
|
-
provider: response.transaction.provider_type?.toLowerCase() || "unknown",
|
|
368
|
-
requires_action: response.requires_action || false,
|
|
369
|
-
public_key: response.public_key,
|
|
370
|
-
client_secret: response.client_secret,
|
|
371
|
-
redirect_url: response.authorization_url,
|
|
372
|
-
transaction_id: response.transaction.id,
|
|
373
|
-
order_id: response.transaction.order_id,
|
|
374
|
-
reference: response.transaction.provider_reference,
|
|
375
|
-
metadata: response.transaction.metadata,
|
|
376
|
-
method: response.transaction.payment_method?.toLowerCase() || "unknown",
|
|
377
|
-
instructions: response.display_text,
|
|
378
|
-
display_text: response.display_text,
|
|
379
|
-
requires_authorization: response.requires_authorization,
|
|
380
|
-
authorization_type: safeAuthType,
|
|
381
|
-
provider_payment_id: response.provider_payment_id || response.transaction.provider_reference
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
return {
|
|
385
|
-
method: "unknown",
|
|
386
|
-
provider: "unknown",
|
|
387
|
-
requires_action: false,
|
|
388
|
-
metadata: {}
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
var PAYMENT_SUCCESS_STATUSES = /* @__PURE__ */ new Set([
|
|
392
|
-
"success",
|
|
393
|
-
"succeeded",
|
|
394
|
-
"paid",
|
|
395
|
-
"captured",
|
|
396
|
-
"completed",
|
|
397
|
-
"authorized"
|
|
398
|
-
]);
|
|
399
|
-
var PAYMENT_FAILURE_STATUSES = /* @__PURE__ */ new Set([
|
|
400
|
-
"failed",
|
|
401
|
-
"declined",
|
|
402
|
-
"cancelled",
|
|
403
|
-
"voided",
|
|
404
|
-
"error",
|
|
405
|
-
"abandoned"
|
|
406
|
-
]);
|
|
407
|
-
var PAYMENT_REQUIRES_ACTION_STATUSES = /* @__PURE__ */ new Set([
|
|
408
|
-
"requires_action",
|
|
409
|
-
"requires_payment_method",
|
|
410
|
-
"requires_capture"
|
|
411
|
-
]);
|
|
412
|
-
var PAYMENT_STATUS_ALIAS_MAP = {
|
|
413
|
-
ok: "success",
|
|
414
|
-
done: "success",
|
|
415
|
-
paid: "paid",
|
|
416
|
-
paid_in_full: "paid",
|
|
417
|
-
paid_successfully: "paid",
|
|
418
|
-
succeeded: "success",
|
|
419
|
-
captured: "captured",
|
|
420
|
-
completed: "completed",
|
|
421
|
-
pending_confirmation: "pending_confirmation",
|
|
422
|
-
requires_authorization: "requires_action",
|
|
423
|
-
requires_action: "requires_action",
|
|
424
|
-
requires_payment_method: "requires_payment_method",
|
|
425
|
-
requires_capture: "requires_capture",
|
|
426
|
-
partially_paid: "partially_paid",
|
|
427
|
-
partially_refunded: "partially_refunded",
|
|
428
|
-
card_declined: "declined",
|
|
429
|
-
canceled: "cancelled",
|
|
430
|
-
authorized: "authorized",
|
|
431
|
-
cancelled: "cancelled",
|
|
432
|
-
unresolved: "pending"
|
|
433
|
-
};
|
|
434
|
-
var KNOWN_PAYMENT_STATUSES = /* @__PURE__ */ new Set([
|
|
435
|
-
"initialized",
|
|
436
|
-
"pending",
|
|
437
|
-
"processing",
|
|
438
|
-
"authorized",
|
|
439
|
-
"captured",
|
|
440
|
-
"failed",
|
|
441
|
-
"cancelled",
|
|
442
|
-
"refunded",
|
|
443
|
-
"unknown",
|
|
444
|
-
"voided",
|
|
445
|
-
"requires_action",
|
|
446
|
-
"abandoned",
|
|
447
|
-
"reversed",
|
|
448
|
-
"disputed",
|
|
449
|
-
"refund_pending",
|
|
450
|
-
"created",
|
|
451
|
-
"pending_confirmation",
|
|
452
|
-
"success",
|
|
453
|
-
"succeeded",
|
|
454
|
-
"declined",
|
|
455
|
-
"partially_refunded",
|
|
456
|
-
"partially_paid",
|
|
457
|
-
"paid",
|
|
458
|
-
"unpaid",
|
|
459
|
-
"requires_payment_method",
|
|
460
|
-
"requires_capture",
|
|
461
|
-
"completed",
|
|
462
|
-
"error"
|
|
463
|
-
]);
|
|
464
|
-
function normalizeStatusToken(status) {
|
|
465
|
-
return status?.trim().toLowerCase().replace(/[\s-]+/g, "_") ?? "";
|
|
466
|
-
}
|
|
467
|
-
function normalizePaymentStatusValue(status) {
|
|
468
|
-
const normalized = normalizeStatusToken(status);
|
|
469
|
-
if (Object.prototype.hasOwnProperty.call(PAYMENT_STATUS_ALIAS_MAP, normalized)) {
|
|
470
|
-
return PAYMENT_STATUS_ALIAS_MAP[normalized];
|
|
471
|
-
}
|
|
472
|
-
return KNOWN_PAYMENT_STATUSES.has(normalized) ? normalized : "unknown";
|
|
473
|
-
}
|
|
474
|
-
function isPaymentStatusSuccess(status) {
|
|
475
|
-
const normalizedStatus = normalizePaymentStatusValue(status);
|
|
476
|
-
return PAYMENT_SUCCESS_STATUSES.has(normalizedStatus);
|
|
477
|
-
}
|
|
478
|
-
function isPaymentStatusFailure(status) {
|
|
479
|
-
const normalizedStatus = normalizePaymentStatusValue(status);
|
|
480
|
-
return PAYMENT_FAILURE_STATUSES.has(normalizedStatus);
|
|
481
|
-
}
|
|
482
|
-
function isPaymentStatusRequiresAction(status) {
|
|
483
|
-
const normalizedStatus = normalizePaymentStatusValue(status);
|
|
484
|
-
return PAYMENT_REQUIRES_ACTION_STATUSES.has(normalizedStatus);
|
|
485
|
-
}
|
|
486
|
-
function normalizeStatusResponse(response) {
|
|
487
|
-
if (!response || typeof response !== "object") {
|
|
488
|
-
return {
|
|
489
|
-
status: "pending",
|
|
490
|
-
paid: false,
|
|
491
|
-
amount: moneyFromNumber(0),
|
|
492
|
-
currency: "",
|
|
493
|
-
message: "No status available"
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
const res = response;
|
|
497
|
-
const normalizedStatus = normalizePaymentStatusValue(res.status ?? void 0);
|
|
498
|
-
const normalizedAmount = typeof res.amount === "string" ? money(res.amount) : typeof res.amount === "number" && Number.isFinite(res.amount) ? moneyFromNumber(res.amount) : moneyFromNumber(0);
|
|
499
|
-
const normalizedCurrency = typeof res.currency === "string" && res.currency.trim().length > 0 ? res.currency : "";
|
|
500
|
-
const paidValue = res.paid === true;
|
|
501
|
-
const derivedPaid = paidValue || [
|
|
502
|
-
"success",
|
|
503
|
-
"succeeded",
|
|
504
|
-
"paid",
|
|
505
|
-
"captured",
|
|
506
|
-
"authorized",
|
|
507
|
-
"completed"
|
|
508
|
-
].includes(normalizedStatus);
|
|
509
|
-
return {
|
|
510
|
-
status: normalizedStatus,
|
|
511
|
-
paid: derivedPaid,
|
|
512
|
-
amount: normalizedAmount,
|
|
513
|
-
currency: normalizedCurrency,
|
|
514
|
-
reference: res.reference,
|
|
515
|
-
message: res.message || ""
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
var MOBILE_MONEY_PROVIDERS = {
|
|
519
|
-
mtn: { name: "MTN Mobile Money", prefix: ["024", "054", "055", "059"] },
|
|
520
|
-
vodafone: { name: "Vodafone Cash", prefix: ["020", "050"] },
|
|
521
|
-
airtel: { name: "AirtelTigo Money", prefix: ["027", "057", "026", "056"] }
|
|
522
|
-
};
|
|
523
|
-
function detectMobileMoneyProvider(phoneNumber) {
|
|
524
|
-
const cleaned = phoneNumber.replace(/\D/g, "");
|
|
525
|
-
const prefix = cleaned.slice(-9, -6);
|
|
526
|
-
for (const [provider, info] of Object.entries(MOBILE_MONEY_PROVIDERS)) {
|
|
527
|
-
if (info.prefix.some((p) => prefix.startsWith(p.slice(1)))) {
|
|
528
|
-
return provider;
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
return null;
|
|
532
|
-
}
|
|
533
|
-
var ISO3_TO_COUNTRY_CODE = {
|
|
534
|
-
AGO: "AO",
|
|
535
|
-
ARE: "AE",
|
|
536
|
-
AUS: "AU",
|
|
537
|
-
BDI: "BI",
|
|
538
|
-
BRA: "BR",
|
|
539
|
-
BWA: "BW",
|
|
540
|
-
CAN: "CA",
|
|
541
|
-
CHE: "CH",
|
|
542
|
-
CHN: "CN",
|
|
543
|
-
COD: "CD",
|
|
544
|
-
EGY: "EG",
|
|
545
|
-
ETH: "ET",
|
|
546
|
-
GHA: "GH",
|
|
547
|
-
GIN: "GN",
|
|
548
|
-
GMB: "GM",
|
|
549
|
-
GBR: "GB",
|
|
550
|
-
HKG: "HK",
|
|
551
|
-
IDN: "ID",
|
|
552
|
-
IND: "IN",
|
|
553
|
-
ISR: "IL",
|
|
554
|
-
JPN: "JP",
|
|
555
|
-
KEN: "KE",
|
|
556
|
-
KOR: "KR",
|
|
557
|
-
LBR: "LR",
|
|
558
|
-
MUS: "MU",
|
|
559
|
-
MEX: "MX",
|
|
560
|
-
MOZ: "MZ",
|
|
561
|
-
MWI: "MW",
|
|
562
|
-
MYS: "MY",
|
|
563
|
-
NAM: "NA",
|
|
564
|
-
NGA: "NG",
|
|
565
|
-
PHL: "PH",
|
|
566
|
-
RWA: "RW",
|
|
567
|
-
SAU: "SA",
|
|
568
|
-
SGP: "SG",
|
|
569
|
-
SLE: "SL",
|
|
570
|
-
THA: "TH",
|
|
571
|
-
TUR: "TR",
|
|
572
|
-
TWN: "TW",
|
|
573
|
-
TZA: "TZ",
|
|
574
|
-
UGA: "UG",
|
|
575
|
-
USA: "US",
|
|
576
|
-
VNM: "VN",
|
|
577
|
-
ZAF: "ZA",
|
|
578
|
-
ZMB: "ZM"
|
|
579
|
-
};
|
|
580
|
-
var CURRENCY_TO_COUNTRY_CODE = {
|
|
581
|
-
AED: "AE",
|
|
582
|
-
AOA: "AO",
|
|
583
|
-
AUD: "AU",
|
|
584
|
-
BIF: "BI",
|
|
585
|
-
BWP: "BW",
|
|
586
|
-
BRL: "BR",
|
|
587
|
-
CAD: "CA",
|
|
588
|
-
CDF: "CD",
|
|
589
|
-
CHF: "CH",
|
|
590
|
-
CNY: "CN",
|
|
591
|
-
EGP: "EG",
|
|
592
|
-
ETB: "ET",
|
|
593
|
-
GHS: "GH",
|
|
594
|
-
GMD: "GM",
|
|
595
|
-
GNF: "GN",
|
|
596
|
-
GBP: "GB",
|
|
597
|
-
HKD: "HK",
|
|
598
|
-
IDR: "ID",
|
|
599
|
-
ILS: "IL",
|
|
600
|
-
INR: "IN",
|
|
601
|
-
JPY: "JP",
|
|
602
|
-
KES: "KE",
|
|
603
|
-
KRW: "KR",
|
|
604
|
-
LRD: "LR",
|
|
605
|
-
MUR: "MU",
|
|
606
|
-
MWK: "MW",
|
|
607
|
-
MXN: "MX",
|
|
608
|
-
MYR: "MY",
|
|
609
|
-
MZN: "MZ",
|
|
610
|
-
NAD: "NA",
|
|
611
|
-
NGN: "NG",
|
|
612
|
-
PHP: "PH",
|
|
613
|
-
RWF: "RW",
|
|
614
|
-
SAR: "SA",
|
|
615
|
-
SGD: "SG",
|
|
616
|
-
SLL: "SL",
|
|
617
|
-
THB: "TH",
|
|
618
|
-
TRY: "TR",
|
|
619
|
-
TWD: "TW",
|
|
620
|
-
TZS: "TZ",
|
|
621
|
-
UGX: "UG",
|
|
622
|
-
USD: "US",
|
|
623
|
-
VND: "VN",
|
|
624
|
-
ZAR: "ZA",
|
|
625
|
-
ZMW: "ZM"
|
|
626
|
-
};
|
|
627
|
-
function normalizeCountryCode(value) {
|
|
628
|
-
const normalized = value?.trim().toUpperCase();
|
|
629
|
-
if (!normalized) {
|
|
630
|
-
return void 0;
|
|
631
|
-
}
|
|
632
|
-
if (normalized.length === 2) {
|
|
633
|
-
return normalized;
|
|
634
|
-
}
|
|
635
|
-
return ISO3_TO_COUNTRY_CODE[normalized];
|
|
636
|
-
}
|
|
637
|
-
function parsePhoneCandidate(value, country) {
|
|
638
|
-
try {
|
|
639
|
-
return country ? parsePhoneNumberFromString(value, country) : parsePhoneNumberFromString(value);
|
|
640
|
-
} catch {
|
|
641
|
-
return void 0;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
function resolvePhoneCountryCode(options = {}) {
|
|
645
|
-
const explicitCountry = normalizeCountryCode(options.country);
|
|
646
|
-
if (explicitCountry) {
|
|
647
|
-
return explicitCountry;
|
|
648
|
-
}
|
|
649
|
-
const currency = options.currency?.trim().toUpperCase();
|
|
650
|
-
if (!currency) {
|
|
651
|
-
return void 0;
|
|
652
|
-
}
|
|
653
|
-
return CURRENCY_TO_COUNTRY_CODE[currency];
|
|
654
|
-
}
|
|
655
|
-
function normalizePhoneToE164(raw, options = {}) {
|
|
656
|
-
const trimmed = raw.trim();
|
|
657
|
-
if (!trimmed) {
|
|
658
|
-
return null;
|
|
659
|
-
}
|
|
660
|
-
const country = resolvePhoneCountryCode(options);
|
|
661
|
-
const digits = trimmed.replace(/\D/g, "");
|
|
662
|
-
const internationalDigits = digits.startsWith("00") ? digits.slice(2) : digits;
|
|
663
|
-
const attempts = [];
|
|
664
|
-
const seen = /* @__PURE__ */ new Set();
|
|
665
|
-
function addAttempt(value, nextCountry) {
|
|
666
|
-
const key = `${nextCountry || ""}:${value}`;
|
|
667
|
-
if (seen.has(key)) {
|
|
668
|
-
return;
|
|
669
|
-
}
|
|
670
|
-
seen.add(key);
|
|
671
|
-
attempts.push({ value, country: nextCountry });
|
|
672
|
-
}
|
|
673
|
-
if (country) {
|
|
674
|
-
addAttempt(trimmed, country);
|
|
675
|
-
}
|
|
676
|
-
addAttempt(trimmed);
|
|
677
|
-
if (country && digits) {
|
|
678
|
-
addAttempt(digits, country);
|
|
679
|
-
}
|
|
680
|
-
if (internationalDigits) {
|
|
681
|
-
addAttempt(`+${internationalDigits}`);
|
|
682
|
-
}
|
|
683
|
-
for (const attempt of attempts) {
|
|
684
|
-
const parsed = parsePhoneCandidate(attempt.value, attempt.country);
|
|
685
|
-
if (parsed?.isValid()) {
|
|
686
|
-
return parsed.format("E.164");
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
return null;
|
|
690
|
-
}
|
|
691
|
-
function isValidPhoneForContext(raw, options = {}) {
|
|
692
|
-
return normalizePhoneToE164(raw, options) !== null;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
export { CURRENCY_SYMBOLS, MOBILE_MONEY_PROVIDERS, categorizePaymentError, detectMobileMoneyProvider, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatPriceWithTax, formatProductPrice, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getProductCurrency, getTaxAmount, hasTaxInfo, isOnSale, isPaymentStatusFailure, isPaymentStatusRequiresAction, isPaymentStatusSuccess, isTaxInclusive, isValidPhoneForContext, normalizePaymentResponse, normalizePhoneToE164, normalizeStatusResponse, parsePrice, resolvePhoneCountryCode };
|
|
1
|
+
export { isValidPhoneForContext, normalizePhoneToE164, resolvePhoneCountryCode } from './chunk-WDIMISRC.mjs';
|
|
2
|
+
export { CURRENCY_SYMBOLS, MOBILE_MONEY_PROVIDERS, categorizePaymentError, detectMobileMoneyProvider, formatMoney, formatNumberCompact, formatPrice, formatPriceAdjustment, formatPriceCompact, formatPriceWithTax, formatProductPrice, getBasePrice, getCurrencySymbol, getDiscountPercentage, getDisplayPrice, getMarkupPercentage, getProductCurrency, getTaxAmount, hasTaxInfo, isOnSale, isPaymentStatusFailure, isPaymentStatusRequiresAction, isPaymentStatusSuccess, isTaxInclusive, normalizePaymentResponse, normalizeStatusResponse, parsePrice } from './chunk-FTL2SXCG.mjs';
|