@funnelfox/billing 0.7.1 → 0.8.0-add-release-docs.8
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/chunk-index.cjs.js +262 -21
- package/dist/chunk-index.es.js +262 -21
- package/dist/funnelfox-billing.js +262 -21
- package/dist/funnelfox-billing.min.js +1 -1
- package/package.json +6 -2
- package/src/types.d.ts +1 -0
|
@@ -374,6 +374,9 @@
|
|
|
374
374
|
return v.toString(16);
|
|
375
375
|
});
|
|
376
376
|
}
|
|
377
|
+
function isBrowser() {
|
|
378
|
+
return typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
379
|
+
}
|
|
377
380
|
function sleep(ms) {
|
|
378
381
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
379
382
|
}
|
|
@@ -492,7 +495,7 @@
|
|
|
492
495
|
/**
|
|
493
496
|
* @fileoverview Constants for Funnefox SDK
|
|
494
497
|
*/
|
|
495
|
-
const SDK_VERSION = '0.
|
|
498
|
+
const SDK_VERSION = '0.8.0-add-release-docs.8';
|
|
496
499
|
const DEFAULTS = {
|
|
497
500
|
BASE_URL: 'https://billing.funnelfox.com',
|
|
498
501
|
REGION: 'default',
|
|
@@ -726,7 +729,7 @@
|
|
|
726
729
|
}
|
|
727
730
|
catch (error) {
|
|
728
731
|
onMethodRenderError(allowedPaymentMethod);
|
|
729
|
-
throw new PrimerError(
|
|
732
|
+
throw new PrimerError(`Failed to initialize Primer checkout method ${allowedPaymentMethod}`, error);
|
|
730
733
|
}
|
|
731
734
|
}
|
|
732
735
|
async initMethod(method, htmlNode, options) {
|
|
@@ -760,7 +763,7 @@
|
|
|
760
763
|
}
|
|
761
764
|
}
|
|
762
765
|
catch (error) {
|
|
763
|
-
throw new PrimerError(
|
|
766
|
+
throw new PrimerError(`Failed to initialize Primer checkout method ${method}`, error);
|
|
764
767
|
}
|
|
765
768
|
}
|
|
766
769
|
async renderCardCheckoutWithElements(elements, { onSubmit, onInputChange, onCardInputValueChange, isCardholderNameRequired, isPostalCodeRequired, onMethodRenderError, onMethodRender, }) {
|
|
@@ -920,7 +923,7 @@
|
|
|
920
923
|
}
|
|
921
924
|
catch (error) {
|
|
922
925
|
onMethodRenderError(exports.PaymentMethod.PAYMENT_CARD);
|
|
923
|
-
throw new PrimerError('Failed to initialize Primer checkout', error);
|
|
926
|
+
throw new PrimerError('Failed to initialize Primer checkout method PAYMENT_CARD', error);
|
|
924
927
|
}
|
|
925
928
|
}
|
|
926
929
|
async initializeHeadlessCheckout(clientToken, primerOptions, method) {
|
|
@@ -1060,6 +1063,9 @@
|
|
|
1060
1063
|
}
|
|
1061
1064
|
return element;
|
|
1062
1065
|
}
|
|
1066
|
+
refreshClientSession() {
|
|
1067
|
+
return this.currentHeadless?.then(headless => headless.refreshClientSession());
|
|
1068
|
+
}
|
|
1063
1069
|
}
|
|
1064
1070
|
PrimerWrapper.headlessManager = new HeadlessManager();
|
|
1065
1071
|
|
|
@@ -1499,6 +1505,216 @@
|
|
|
1499
1505
|
});
|
|
1500
1506
|
}
|
|
1501
1507
|
|
|
1508
|
+
const MAX_QUERY_LENGTH = 1800;
|
|
1509
|
+
function getErrorImage(orgId, options) {
|
|
1510
|
+
if (typeof document === 'undefined') {
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
const params = new URLSearchParams({
|
|
1514
|
+
message: truncate(options.message, 500),
|
|
1515
|
+
code: options.code || 'SDK_ERROR',
|
|
1516
|
+
timestamp: Date.now().toString(),
|
|
1517
|
+
sdk_version: SDK_VERSION,
|
|
1518
|
+
});
|
|
1519
|
+
if (options.req_id) {
|
|
1520
|
+
appendIfFits(params, 'req_id', options.req_id, MAX_QUERY_LENGTH);
|
|
1521
|
+
}
|
|
1522
|
+
if (options.context) {
|
|
1523
|
+
Object.entries(options.context).forEach(([key, value]) => {
|
|
1524
|
+
if (value !== undefined && value !== null) {
|
|
1525
|
+
appendIfFits(params, key, truncate(String(value), 1000), MAX_QUERY_LENGTH);
|
|
1526
|
+
}
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
const origin = (options.baseUrl || DEFAULTS.BASE_URL).replace(/\/$/, '');
|
|
1530
|
+
const url = `${origin}/sdk_report/${encodeURIComponent(orgId)}/crash?${params.toString()}`;
|
|
1531
|
+
const img = new Image();
|
|
1532
|
+
img.src = url;
|
|
1533
|
+
img.style.display = 'none';
|
|
1534
|
+
img.onload = () => {
|
|
1535
|
+
img.remove();
|
|
1536
|
+
};
|
|
1537
|
+
img.onerror = () => {
|
|
1538
|
+
img.remove();
|
|
1539
|
+
};
|
|
1540
|
+
(document.body || document.documentElement)?.appendChild(img);
|
|
1541
|
+
}
|
|
1542
|
+
function truncate(value, maxLength) {
|
|
1543
|
+
return value.length > maxLength ? value.slice(0, maxLength) : value;
|
|
1544
|
+
}
|
|
1545
|
+
function appendIfFits(params, key, value, maxLength) {
|
|
1546
|
+
const nextParams = new URLSearchParams(params);
|
|
1547
|
+
nextParams.append(key, value);
|
|
1548
|
+
if (nextParams.toString().length > maxLength) {
|
|
1549
|
+
return false;
|
|
1550
|
+
}
|
|
1551
|
+
params.append(key, value);
|
|
1552
|
+
return true;
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
let activeScope = null;
|
|
1556
|
+
const recentSignatures = new Map();
|
|
1557
|
+
const DEDUPE_WINDOW_MS = 3000;
|
|
1558
|
+
let isListening = false;
|
|
1559
|
+
function startUnhandledErrorTelemetry(scope) {
|
|
1560
|
+
if (!scope.enabled || !isBrowser()) {
|
|
1561
|
+
return () => { };
|
|
1562
|
+
}
|
|
1563
|
+
activeScope = scope;
|
|
1564
|
+
attachListeners();
|
|
1565
|
+
return () => {
|
|
1566
|
+
stopUnhandledErrorTelemetry(scope.id);
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
function stopUnhandledErrorTelemetry(scopeId) {
|
|
1570
|
+
if (activeScope?.id === scopeId) {
|
|
1571
|
+
activeScope = null;
|
|
1572
|
+
recentSignatures.clear();
|
|
1573
|
+
detachListeners();
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
function attachListeners() {
|
|
1577
|
+
if (isListening || typeof window === 'undefined') {
|
|
1578
|
+
return;
|
|
1579
|
+
}
|
|
1580
|
+
window.addEventListener('error', handleWindowError);
|
|
1581
|
+
window.addEventListener('unhandledrejection', handleUnhandledRejection);
|
|
1582
|
+
isListening = true;
|
|
1583
|
+
}
|
|
1584
|
+
function detachListeners() {
|
|
1585
|
+
if (!isListening || typeof window === 'undefined') {
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
window.removeEventListener('error', handleWindowError);
|
|
1589
|
+
window.removeEventListener('unhandledrejection', handleUnhandledRejection);
|
|
1590
|
+
isListening = false;
|
|
1591
|
+
}
|
|
1592
|
+
function handleWindowError(event) {
|
|
1593
|
+
const normalized = normalizeError(event.error || event.message || 'Unhandled browser error', 'UNHANDLED_ERROR');
|
|
1594
|
+
reportToActiveScopes(normalized, {
|
|
1595
|
+
event_type: 'error',
|
|
1596
|
+
filename: event.filename,
|
|
1597
|
+
lineno: event.lineno,
|
|
1598
|
+
colno: event.colno,
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
function handleUnhandledRejection(event) {
|
|
1602
|
+
const normalized = normalizeError(event.reason || 'Unhandled promise rejection', 'UNHANDLED_REJECTION');
|
|
1603
|
+
reportToActiveScopes(normalized, {
|
|
1604
|
+
event_type: 'unhandledrejection',
|
|
1605
|
+
});
|
|
1606
|
+
}
|
|
1607
|
+
function reportToActiveScopes(error, eventContext) {
|
|
1608
|
+
if (!activeScope) {
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
if (!canReport(error, eventContext.event_type)) {
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
try {
|
|
1615
|
+
const context = activeScope.getContext();
|
|
1616
|
+
getErrorImage(activeScope.orgId, {
|
|
1617
|
+
baseUrl: activeScope.baseUrl,
|
|
1618
|
+
message: `${error.name}: ${error.message}`,
|
|
1619
|
+
code: error.code,
|
|
1620
|
+
context: {
|
|
1621
|
+
...eventContext,
|
|
1622
|
+
order_id: context.orderId,
|
|
1623
|
+
price_id: context.priceId,
|
|
1624
|
+
page_url: getPageUrl(),
|
|
1625
|
+
},
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
catch {
|
|
1629
|
+
// Telemetry must never affect checkout behavior.
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
function canReport(error, eventType) {
|
|
1633
|
+
const now = Date.now();
|
|
1634
|
+
pruneExpiredSignatures(now);
|
|
1635
|
+
const signature = buildSignature(error, eventType);
|
|
1636
|
+
const previousReportTime = recentSignatures.get(signature);
|
|
1637
|
+
if (typeof previousReportTime === 'number' &&
|
|
1638
|
+
now - previousReportTime < DEDUPE_WINDOW_MS) {
|
|
1639
|
+
return false;
|
|
1640
|
+
}
|
|
1641
|
+
recentSignatures.set(signature, now);
|
|
1642
|
+
return true;
|
|
1643
|
+
}
|
|
1644
|
+
function pruneExpiredSignatures(now) {
|
|
1645
|
+
recentSignatures.forEach((timestamp, signature) => {
|
|
1646
|
+
if (now - timestamp >= DEDUPE_WINDOW_MS) {
|
|
1647
|
+
recentSignatures.delete(signature);
|
|
1648
|
+
}
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
1651
|
+
function buildSignature(error, eventType) {
|
|
1652
|
+
const firstStackLine = error.stack?.split('\n')[0] || '';
|
|
1653
|
+
return [
|
|
1654
|
+
eventType || '',
|
|
1655
|
+
error.code || '',
|
|
1656
|
+
error.message || '',
|
|
1657
|
+
firstStackLine,
|
|
1658
|
+
].join('|');
|
|
1659
|
+
}
|
|
1660
|
+
function normalizeError(reason, fallbackCode) {
|
|
1661
|
+
if (reason instanceof Error) {
|
|
1662
|
+
return {
|
|
1663
|
+
name: reason.name || 'Error',
|
|
1664
|
+
message: reason.message || 'Unknown error',
|
|
1665
|
+
code: getErrorCode(reason, fallbackCode),
|
|
1666
|
+
stack: reason.stack,
|
|
1667
|
+
};
|
|
1668
|
+
}
|
|
1669
|
+
if (typeof reason === 'object' && reason !== null) {
|
|
1670
|
+
const record = reason;
|
|
1671
|
+
return {
|
|
1672
|
+
name: toSafeString(record.name) || 'Error',
|
|
1673
|
+
message: toSafeString(record.message) || safeStringify(reason),
|
|
1674
|
+
code: toSafeString(record.code) || fallbackCode,
|
|
1675
|
+
stack: toSafeString(record.stack),
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
return {
|
|
1679
|
+
name: 'Error',
|
|
1680
|
+
message: toSafeString(reason) || 'Unknown error',
|
|
1681
|
+
code: fallbackCode,
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
function getErrorCode(error, fallbackCode) {
|
|
1685
|
+
const record = error;
|
|
1686
|
+
return typeof record.code === 'string' && record.code
|
|
1687
|
+
? record.code
|
|
1688
|
+
: fallbackCode;
|
|
1689
|
+
}
|
|
1690
|
+
function toSafeString(value) {
|
|
1691
|
+
if (typeof value === 'string') {
|
|
1692
|
+
return value;
|
|
1693
|
+
}
|
|
1694
|
+
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
1695
|
+
return String(value);
|
|
1696
|
+
}
|
|
1697
|
+
return '';
|
|
1698
|
+
}
|
|
1699
|
+
function safeStringify(value) {
|
|
1700
|
+
try {
|
|
1701
|
+
return JSON.stringify(value);
|
|
1702
|
+
}
|
|
1703
|
+
catch {
|
|
1704
|
+
return 'Unserializable error';
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
function getPageUrl() {
|
|
1708
|
+
if (typeof window === 'undefined' || !window.location) {
|
|
1709
|
+
return '';
|
|
1710
|
+
}
|
|
1711
|
+
const location = window.location;
|
|
1712
|
+
if (location.origin && location.pathname) {
|
|
1713
|
+
return `${location.origin}${location.pathname}`;
|
|
1714
|
+
}
|
|
1715
|
+
return (location.href || '').split(/[?#]/)[0];
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1502
1718
|
/**
|
|
1503
1719
|
* @fileoverview Checkout instance manager for Funnefox SDK
|
|
1504
1720
|
*/
|
|
@@ -1508,6 +1724,8 @@
|
|
|
1508
1724
|
this.counter = 0;
|
|
1509
1725
|
this.cachedSessionResponse = null;
|
|
1510
1726
|
this.cardSessionFieldConfig = {};
|
|
1727
|
+
this.isTelemetryEnabled = false;
|
|
1728
|
+
this.telemetryCleanup = null;
|
|
1511
1729
|
this.handleInputChange = (inputName, error) => {
|
|
1512
1730
|
this.emit(EVENTS.INPUT_ERROR, { name: inputName, error });
|
|
1513
1731
|
};
|
|
@@ -1670,6 +1888,7 @@
|
|
|
1670
1888
|
await this.createSession();
|
|
1671
1889
|
await this._initializePrimerCheckout();
|
|
1672
1890
|
this._setState('ready');
|
|
1891
|
+
this.startUnhandledTelemetry();
|
|
1673
1892
|
this.checkoutConfig?.onInitialized?.();
|
|
1674
1893
|
return this;
|
|
1675
1894
|
}
|
|
@@ -1744,6 +1963,7 @@
|
|
|
1744
1963
|
sessionResponse = await sessionRequest;
|
|
1745
1964
|
}
|
|
1746
1965
|
this.cachedSessionResponse = sessionResponse;
|
|
1966
|
+
this.isTelemetryEnabled = !!sessionResponse.data?.sdk_telemetry_enabled;
|
|
1747
1967
|
this.isCollectingApplePayEmail =
|
|
1748
1968
|
!!sessionResponse.data?.collect_apple_pay_email;
|
|
1749
1969
|
this.applySessionCardFieldConfig(sessionResponse);
|
|
@@ -1997,6 +2217,7 @@
|
|
|
1997
2217
|
throw new CheckoutError('Cannot update price while payment is processing');
|
|
1998
2218
|
}
|
|
1999
2219
|
try {
|
|
2220
|
+
this.onLoaderChangeWithRace(true);
|
|
2000
2221
|
this._setState('updating');
|
|
2001
2222
|
// Invalidate session cache
|
|
2002
2223
|
CheckoutInstance.sessionCache.clear();
|
|
@@ -2007,9 +2228,12 @@
|
|
|
2007
2228
|
clientMetadata,
|
|
2008
2229
|
});
|
|
2009
2230
|
this.checkoutConfig.priceId = newPriceId;
|
|
2231
|
+
await this.primerWrapper.refreshClientSession();
|
|
2232
|
+
this.onLoaderChangeWithRace(false);
|
|
2010
2233
|
this._setState('ready');
|
|
2011
2234
|
}
|
|
2012
2235
|
catch (error) {
|
|
2236
|
+
this.onLoaderChangeWithRace(false);
|
|
2013
2237
|
this._setState('error');
|
|
2014
2238
|
this.emit(EVENTS.ERROR, error);
|
|
2015
2239
|
throw error;
|
|
@@ -2028,6 +2252,7 @@
|
|
|
2028
2252
|
if (this.isDestroyed)
|
|
2029
2253
|
return;
|
|
2030
2254
|
try {
|
|
2255
|
+
this.stopUnhandledTelemetry();
|
|
2031
2256
|
CheckoutInstance.sessionCache.clear();
|
|
2032
2257
|
await this.primerWrapper.destroy();
|
|
2033
2258
|
this._setState('destroyed');
|
|
@@ -2202,6 +2427,7 @@
|
|
|
2202
2427
|
}
|
|
2203
2428
|
await this.primerWrapper.initializeHeadlessCheckout(this.clientToken, checkoutOptions, method);
|
|
2204
2429
|
const methodInterface = await this.primerWrapper.initMethod(method, element, methodOptions);
|
|
2430
|
+
this.startUnhandledTelemetry(method);
|
|
2205
2431
|
return {
|
|
2206
2432
|
...methodInterface,
|
|
2207
2433
|
destroy: async () => {
|
|
@@ -2210,25 +2436,35 @@
|
|
|
2210
2436
|
},
|
|
2211
2437
|
};
|
|
2212
2438
|
}
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2439
|
+
startUnhandledTelemetry(paymentMethod) {
|
|
2440
|
+
if (paymentMethod) {
|
|
2441
|
+
this.telemetryPaymentMethod = paymentMethod;
|
|
2442
|
+
}
|
|
2443
|
+
if (!this.isTelemetryEnabled || this.telemetryCleanup) {
|
|
2444
|
+
return;
|
|
2445
|
+
}
|
|
2446
|
+
this.telemetryCleanup = startUnhandledErrorTelemetry({
|
|
2447
|
+
id: this.id,
|
|
2448
|
+
orgId: this.orgId,
|
|
2449
|
+
baseUrl: this.baseUrl,
|
|
2450
|
+
enabled: this.isTelemetryEnabled,
|
|
2451
|
+
getContext: () => ({
|
|
2452
|
+
checkoutId: this.id,
|
|
2453
|
+
orderId: this.orderId,
|
|
2454
|
+
priceId: this.checkoutConfig.priceId,
|
|
2455
|
+
state: this.state,
|
|
2456
|
+
paymentMethod: this.telemetryPaymentMethod,
|
|
2457
|
+
reqId: this.cachedSessionResponse?.req_id,
|
|
2458
|
+
}),
|
|
2459
|
+
});
|
|
2460
|
+
}
|
|
2461
|
+
stopUnhandledTelemetry() {
|
|
2462
|
+
this.telemetryCleanup?.();
|
|
2463
|
+
this.telemetryCleanup = null;
|
|
2464
|
+
this.telemetryPaymentMethod = undefined;
|
|
2225
2465
|
}
|
|
2226
|
-
const url = `https://billing.funnelfox.com/sdk_report/${encodeURIComponent(orgId)}/crash?${params.toString()}`;
|
|
2227
|
-
const img = new Image();
|
|
2228
|
-
img.src = url;
|
|
2229
|
-
img.style.display = 'none';
|
|
2230
|
-
document.body.appendChild(img);
|
|
2231
2466
|
}
|
|
2467
|
+
CheckoutInstance.sessionCache = new Map();
|
|
2232
2468
|
|
|
2233
2469
|
/**
|
|
2234
2470
|
* @fileoverview Public API with configuration and orchestration logic
|
|
@@ -2269,6 +2505,7 @@
|
|
|
2269
2505
|
}
|
|
2270
2506
|
catch (error) {
|
|
2271
2507
|
getErrorImage(options.orgId, {
|
|
2508
|
+
baseUrl: options.apiConfig?.baseUrl,
|
|
2272
2509
|
message: error.message,
|
|
2273
2510
|
code: error.code,
|
|
2274
2511
|
req_id: error?.response?.req_id,
|
|
@@ -2320,6 +2557,7 @@
|
|
|
2320
2557
|
}
|
|
2321
2558
|
catch (error) {
|
|
2322
2559
|
getErrorImage(orgId, {
|
|
2560
|
+
baseUrl,
|
|
2323
2561
|
message: error.message,
|
|
2324
2562
|
code: error.code,
|
|
2325
2563
|
req_id: error?.response?.req_id,
|
|
@@ -2370,6 +2608,7 @@
|
|
|
2370
2608
|
}
|
|
2371
2609
|
catch (error) {
|
|
2372
2610
|
getErrorImage(options.orgId, {
|
|
2611
|
+
baseUrl: options.baseUrl,
|
|
2373
2612
|
message: error.message,
|
|
2374
2613
|
code: error.code,
|
|
2375
2614
|
req_id: error?.response?.req_id,
|
|
@@ -2408,6 +2647,7 @@
|
|
|
2408
2647
|
}
|
|
2409
2648
|
catch (error) {
|
|
2410
2649
|
getErrorImage(params.orgId, {
|
|
2650
|
+
baseUrl: params.baseUrl,
|
|
2411
2651
|
message: error.message,
|
|
2412
2652
|
code: error.code,
|
|
2413
2653
|
req_id: error?.response?.req_id,
|
|
@@ -2430,6 +2670,7 @@
|
|
|
2430
2670
|
if (typeof window !== 'undefined') {
|
|
2431
2671
|
window.Billing = Billing;
|
|
2432
2672
|
}
|
|
2673
|
+
console.debug('Billing SDK inited');
|
|
2433
2674
|
|
|
2434
2675
|
var template$1 = "<div class=\"ff-skin-default\" id=\"ff-payment-method-containers\">\n <div id=\"success-screen\" style=\"display: none\">\n <div class=\"success\">\n <img alt=\"Loading\" src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIHZpZXdCb3g9IjAgMCA1MCA1MCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTI1IDAuMTExMzI4QzIwLjA3NzQgMC4xMTEzMjggMTUuMjY1NCAxLjU3MTA0IDExLjE3MjUgNC4zMDU4NkM3LjA3OTUyIDcuMDQwNjkgMy44ODk0NSAxMC45Mjc4IDIuMDA1NjYgMTUuNDc1N0MwLjEyMTg4MyAyMC4wMjM1IC0wLjM3MSAyNS4wMjc4IDAuNTg5MzQzIDI5Ljg1NThDMS41NDk2OSAzNC42ODM4IDMuOTIwMTIgMzkuMTE4NSA3LjQwMDkgNDIuNTk5M0MxMC44ODE3IDQ2LjA4MDEgMTUuMzE2NCA0OC40NTA1IDIwLjE0NDQgNDkuNDEwOUMyNC45NzI0IDUwLjM3MTIgMjkuOTc2NyA0OS44NzgzIDM0LjUyNDYgNDcuOTk0NkMzOS4wNzI0IDQ2LjExMDggNDIuOTU5NSA0Mi45MjA3IDQ1LjY5NDQgMzguODI3N0M0OC40MjkyIDM0LjczNDggNDkuODg4OSAyOS45MjI4IDQ5Ljg4ODkgMjUuMDAwMkM0OS44ODg5IDE4LjM5OTMgNDcuMjY2NyAxMi4wNjg3IDQyLjU5OTEgNy40MDExMkMzNy45MzE1IDIuNzMzNTQgMzEuNjAwOSAwLjExMTMyOCAyNSAwLjExMTMyOFpNNDEuMjU1NiAxNi42NDY5TDIwLjgxNTYgMzcuMDcxM0w4Ljc0NDQ0IDI1LjAwMDJDOC4zMzE4OCAyNC41ODc3IDguMTAwMTEgMjQuMDI4MSA4LjEwMDExIDIzLjQ0NDdDOC4xMDAxMSAyMi44NjEyIDguMzMxODggMjIuMzAxNyA4Ljc0NDQ0IDIxLjg4OTFDOS4xNTcgMjEuNDc2NSA5LjcxNjU1IDIxLjI0NDggMTAuMyAyMS4yNDQ4QzEwLjg4MzQgMjEuMjQ0OCAxMS40NDMgMjEuNDc2NSAxMS44NTU2IDIxLjg4OTFMMjAuODQ2NyAzMC44ODAyTDM4LjE3NTYgMTMuNTY2OUMzOC4zNzk4IDEzLjM2MjYgMzguNjIyMyAxMy4yMDA2IDM4Ljg4OTIgMTMuMDlDMzkuMTU2MiAxMi45Nzk1IDM5LjQ0MjIgMTIuOTIyNiAzOS43MzExIDEyLjkyMjZDNDAuMDIgMTIuOTIyNiA0MC4zMDYxIDEyLjk3OTUgNDAuNTczIDEzLjA5QzQwLjgzOTkgMTMuMjAwNiA0MS4wODI0IDEzLjM2MjYgNDEuMjg2NyAxMy41NjY5QzQxLjQ5MDkgMTMuNzcxMiA0MS42NTMgMTQuMDEzNyA0MS43NjM1IDE0LjI4MDZDNDEuODc0MSAxNC41NDc1IDQxLjkzMSAxNC44MzM1IDQxLjkzMSAxNS4xMjI0QzQxLjkzMSAxNS40MTEzIDQxLjg3NDEgMTUuNjk3NCA0MS43NjM1IDE1Ljk2NDNDNDEuNjUzIDE2LjIzMTIgNDEuNDkwOSAxNi40NzM3IDQxLjI4NjcgMTYuNjc4TDQxLjI1NTYgMTYuNjQ2OVoiIGZpbGw9IiM4RURGQzIiLz4KPC9zdmc+Cg==\">\n <div>Payment completed successfully</div>\n </div>\n </div>\n</div>\n";
|
|
2435
2676
|
|