@funnelfox/billing 0.5.2 → 0.5.4
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 +3 -1
- package/dist/chunk-index.cjs2.js +3 -1
- package/dist/chunk-index.es.js +3 -1
- package/dist/chunk-index.es2.js +3 -1
- package/dist/funnelfox-billing.cjs.js +207 -115
- package/dist/funnelfox-billing.esm.js +207 -115
- package/dist/funnelfox-billing.js +213 -117
- package/dist/funnelfox-billing.min.js +1 -1
- package/package.json +2 -2
- package/src/types.d.ts +13 -9
|
@@ -147,61 +147,6 @@ class NetworkError extends FunnefoxSDKError {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
151
|
-
/**
|
|
152
|
-
* @fileoverview Helper utilities for Funnefox SDK
|
|
153
|
-
*/
|
|
154
|
-
function merge(...objects) {
|
|
155
|
-
const result = {};
|
|
156
|
-
for (const obj of objects) {
|
|
157
|
-
if (obj && typeof obj === 'object') {
|
|
158
|
-
for (const key in obj) {
|
|
159
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
160
|
-
if (typeof obj[key] === 'object' &&
|
|
161
|
-
!Array.isArray(obj[key]) &&
|
|
162
|
-
obj[key] !== null) {
|
|
163
|
-
result[key] = merge(result[key] || {}, obj[key]);
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
result[key] = obj[key];
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
function generateId(prefix = '') {
|
|
175
|
-
const timestamp = Date.now().toString(36);
|
|
176
|
-
const random = Math.random().toString(36).substr(2, 5);
|
|
177
|
-
return `${prefix}${timestamp}_${random}`;
|
|
178
|
-
}
|
|
179
|
-
function sleep(ms) {
|
|
180
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
181
|
-
}
|
|
182
|
-
async function retry(fn, maxAttempts = 3, baseDelay = 1000) {
|
|
183
|
-
let lastError;
|
|
184
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
185
|
-
try {
|
|
186
|
-
return await fn();
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
lastError = error;
|
|
190
|
-
if (attempt === maxAttempts)
|
|
191
|
-
throw lastError;
|
|
192
|
-
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
193
|
-
await sleep(delay);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
throw lastError;
|
|
197
|
-
}
|
|
198
|
-
function withTimeout(promise, timeoutMs, message = 'Operation timed out') {
|
|
199
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
200
|
-
setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
201
|
-
});
|
|
202
|
-
return Promise.race([promise, timeoutPromise]);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
150
|
/**
|
|
206
151
|
* @fileoverview Dynamic loader for Primer SDK
|
|
207
152
|
* Loads Primer script and CSS from CDN independently of bundler
|
|
@@ -328,6 +273,142 @@ async function loadPrimerSDK(version) {
|
|
|
328
273
|
return loadingPromise;
|
|
329
274
|
}
|
|
330
275
|
|
|
276
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
277
|
+
/**
|
|
278
|
+
* @fileoverview Helper utilities for Funnefox SDK
|
|
279
|
+
*/
|
|
280
|
+
function merge(...objects) {
|
|
281
|
+
const result = {};
|
|
282
|
+
for (const obj of objects) {
|
|
283
|
+
if (obj && typeof obj === 'object') {
|
|
284
|
+
for (const key in obj) {
|
|
285
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
286
|
+
if (typeof obj[key] === 'object' &&
|
|
287
|
+
!Array.isArray(obj[key]) &&
|
|
288
|
+
obj[key] !== null) {
|
|
289
|
+
result[key] = merge(result[key] || {}, obj[key]);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
result[key] = obj[key];
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
function generateId(prefix = '') {
|
|
301
|
+
const timestamp = Date.now().toString(36);
|
|
302
|
+
const random = Math.random().toString(36).substr(2, 5);
|
|
303
|
+
return `${prefix}${timestamp}_${random}`;
|
|
304
|
+
}
|
|
305
|
+
function sleep(ms) {
|
|
306
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
307
|
+
}
|
|
308
|
+
async function retry(fn, maxAttempts = 3, baseDelay = 1000) {
|
|
309
|
+
let lastError;
|
|
310
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
311
|
+
try {
|
|
312
|
+
return await fn();
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
lastError = error;
|
|
316
|
+
if (attempt === maxAttempts)
|
|
317
|
+
throw lastError;
|
|
318
|
+
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
319
|
+
await sleep(delay);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
throw lastError;
|
|
323
|
+
}
|
|
324
|
+
function withTimeout(promise, timeoutMs, message = 'Operation timed out') {
|
|
325
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
326
|
+
setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
327
|
+
});
|
|
328
|
+
return Promise.race([promise, timeoutPromise]);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* @fileoverview Headless checkout cache manager
|
|
333
|
+
*/
|
|
334
|
+
/**
|
|
335
|
+
* Manages caching and sequential creation of Primer headless checkout instances.
|
|
336
|
+
* Ensures that multiple checkouts with the same configuration reuse the same instance,
|
|
337
|
+
* and that creations happen sequentially to avoid race conditions.
|
|
338
|
+
*/
|
|
339
|
+
class HeadlessManager {
|
|
340
|
+
constructor() {
|
|
341
|
+
this.cache = new Map();
|
|
342
|
+
this.queue = Promise.resolve();
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Generates a cache key from clientToken and serializable options
|
|
346
|
+
*/
|
|
347
|
+
generateKey(clientToken, options) {
|
|
348
|
+
const serializableOptions = {
|
|
349
|
+
paymentHandling: options.paymentHandling,
|
|
350
|
+
apiVersion: options.apiVersion,
|
|
351
|
+
style: options.style,
|
|
352
|
+
card: options.card,
|
|
353
|
+
applePay: options.applePay,
|
|
354
|
+
paypal: options.paypal,
|
|
355
|
+
googlePay: options.googlePay,
|
|
356
|
+
};
|
|
357
|
+
return `${clientToken}:${JSON.stringify(serializableOptions)}`;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Gets a cached headless instance or creates a new one.
|
|
361
|
+
* Ensures sequential creation order to avoid race conditions.
|
|
362
|
+
*/
|
|
363
|
+
getOrCreate(clientToken, options) {
|
|
364
|
+
const key = this.generateKey(clientToken, options);
|
|
365
|
+
// Return cached promise if exists
|
|
366
|
+
const cached = this.cache.get(key);
|
|
367
|
+
if (cached)
|
|
368
|
+
return cached;
|
|
369
|
+
// Create new headless in sequential order
|
|
370
|
+
const previousQueue = this.queue;
|
|
371
|
+
const promise = (async () => {
|
|
372
|
+
await previousQueue; // Wait for previous creation
|
|
373
|
+
const primerOptions = merge({
|
|
374
|
+
paymentHandling: 'MANUAL',
|
|
375
|
+
apiVersion: '2.4',
|
|
376
|
+
}, options);
|
|
377
|
+
try {
|
|
378
|
+
const headlessResult = await window.Primer.createHeadless(clientToken, primerOptions);
|
|
379
|
+
const headless = await headlessResult;
|
|
380
|
+
await headless.start();
|
|
381
|
+
return headless;
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
// Remove from cache on failure
|
|
385
|
+
this.cache.delete(key);
|
|
386
|
+
throw new PrimerError('Failed to create Primer headless checkout', error);
|
|
387
|
+
}
|
|
388
|
+
})();
|
|
389
|
+
this.cache.set(key, promise);
|
|
390
|
+
this.queue = promise.catch(() => { }); // Update queue, ignore errors
|
|
391
|
+
return promise;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Removes a headless instance from the cache
|
|
395
|
+
*/
|
|
396
|
+
remove(headlessPromise) {
|
|
397
|
+
for (const [key, value] of this.cache.entries()) {
|
|
398
|
+
if (value === headlessPromise) {
|
|
399
|
+
this.cache.delete(key);
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Clears all cached instances
|
|
406
|
+
*/
|
|
407
|
+
clear() {
|
|
408
|
+
this.cache.clear();
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
331
412
|
var PaymentMethod;
|
|
332
413
|
(function (PaymentMethod) {
|
|
333
414
|
PaymentMethod["GOOGLE_PAY"] = "GOOGLE_PAY";
|
|
@@ -339,7 +420,7 @@ var PaymentMethod;
|
|
|
339
420
|
/**
|
|
340
421
|
* @fileoverview Constants for Funnefox SDK
|
|
341
422
|
*/
|
|
342
|
-
const SDK_VERSION = '0.5.
|
|
423
|
+
const SDK_VERSION = '0.5.4';
|
|
343
424
|
const DEFAULTS = {
|
|
344
425
|
BASE_URL: 'https://billing.funnelfox.com',
|
|
345
426
|
REGION: 'default',
|
|
@@ -432,6 +513,7 @@ class PrimerWrapper {
|
|
|
432
513
|
constructor() {
|
|
433
514
|
this.isInitialized = false;
|
|
434
515
|
this.destroyCallbacks = [];
|
|
516
|
+
this.currentHeadless = null;
|
|
435
517
|
this.availableMethods = [];
|
|
436
518
|
this.paymentMethodsInterfaces = [];
|
|
437
519
|
}
|
|
@@ -461,26 +543,9 @@ class PrimerWrapper {
|
|
|
461
543
|
}
|
|
462
544
|
}
|
|
463
545
|
async createHeadlessCheckout(clientToken, options) {
|
|
464
|
-
if (PrimerWrapper.headless) {
|
|
465
|
-
return PrimerWrapper.headless;
|
|
466
|
-
}
|
|
467
|
-
// Load Primer SDK if not already available
|
|
468
546
|
await this.ensurePrimerLoaded();
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
apiVersion: '2.4',
|
|
472
|
-
}, options);
|
|
473
|
-
try {
|
|
474
|
-
PrimerWrapper.headless = window.Primer.createHeadless(clientToken, primerOptions).then(async (headlessPromise) => {
|
|
475
|
-
const headless = await headlessPromise;
|
|
476
|
-
await headless.start();
|
|
477
|
-
return headless;
|
|
478
|
-
});
|
|
479
|
-
return await PrimerWrapper.headless;
|
|
480
|
-
}
|
|
481
|
-
catch (error) {
|
|
482
|
-
throw new PrimerError('Failed to create Primer headless checkout', error);
|
|
483
|
-
}
|
|
547
|
+
this.currentHeadless = PrimerWrapper.headlessManager.getOrCreate(clientToken, options);
|
|
548
|
+
return this.currentHeadless;
|
|
484
549
|
}
|
|
485
550
|
disableButtons(disabled) {
|
|
486
551
|
if (!this.paymentMethodsInterfaces)
|
|
@@ -493,11 +558,11 @@ class PrimerWrapper {
|
|
|
493
558
|
let button;
|
|
494
559
|
// Ensure Primer SDK is loaded
|
|
495
560
|
await this.ensurePrimerLoaded();
|
|
496
|
-
if (!
|
|
561
|
+
if (!this.currentHeadless) {
|
|
497
562
|
throw new PrimerError('Headless checkout not found');
|
|
498
563
|
}
|
|
499
564
|
try {
|
|
500
|
-
const headless = await
|
|
565
|
+
const headless = await this.currentHeadless;
|
|
501
566
|
const pmManager = await headless.createPaymentMethodManager(allowedPaymentMethod);
|
|
502
567
|
if (!pmManager) {
|
|
503
568
|
throw new Error('Payment method manager is not available');
|
|
@@ -551,7 +616,10 @@ class PrimerWrapper {
|
|
|
551
616
|
}
|
|
552
617
|
async renderCardCheckoutWithElements(elements, { onSubmit, onInputChange, onMethodRenderError, onMethodRender, }) {
|
|
553
618
|
try {
|
|
554
|
-
|
|
619
|
+
if (!this.currentHeadless) {
|
|
620
|
+
throw new PrimerError('Headless checkout not found');
|
|
621
|
+
}
|
|
622
|
+
const headless = await this.currentHeadless;
|
|
555
623
|
const pmManager = await headless.createPaymentMethodManager('PAYMENT_CARD');
|
|
556
624
|
if (!pmManager) {
|
|
557
625
|
throw new Error('Payment method manager is not available');
|
|
@@ -727,7 +795,10 @@ class PrimerWrapper {
|
|
|
727
795
|
};
|
|
728
796
|
}
|
|
729
797
|
async destroy() {
|
|
730
|
-
|
|
798
|
+
if (this.currentHeadless) {
|
|
799
|
+
PrimerWrapper.headlessManager.remove(this.currentHeadless);
|
|
800
|
+
this.currentHeadless = null;
|
|
801
|
+
}
|
|
731
802
|
if (this.destroyCallbacks) {
|
|
732
803
|
try {
|
|
733
804
|
Promise.all(this.destroyCallbacks.map(destroy => destroy()));
|
|
@@ -775,7 +846,7 @@ class PrimerWrapper {
|
|
|
775
846
|
return element;
|
|
776
847
|
}
|
|
777
848
|
}
|
|
778
|
-
PrimerWrapper.
|
|
849
|
+
PrimerWrapper.headlessManager = new HeadlessManager();
|
|
779
850
|
|
|
780
851
|
/**
|
|
781
852
|
* @fileoverview Input validation utilities for Funnefox SDK
|
|
@@ -1142,9 +1213,9 @@ class CheckoutInstance extends EventEmitter {
|
|
|
1142
1213
|
].join('-');
|
|
1143
1214
|
let sessionResponse;
|
|
1144
1215
|
// Return cached response if payload hasn't changed
|
|
1145
|
-
const cachedResponse =
|
|
1216
|
+
const cachedResponse = CheckoutInstance.sessionCache.get(cacheKey);
|
|
1146
1217
|
if (cachedResponse) {
|
|
1147
|
-
sessionResponse = cachedResponse;
|
|
1218
|
+
sessionResponse = await cachedResponse;
|
|
1148
1219
|
}
|
|
1149
1220
|
else {
|
|
1150
1221
|
const sessionRequest = this.apiClient.createClientSession(sessionParams);
|
|
@@ -1281,6 +1352,7 @@ class CheckoutInstance extends EventEmitter {
|
|
|
1281
1352
|
this.emit(EVENTS.PURCHASE_FAILURE, error);
|
|
1282
1353
|
},
|
|
1283
1354
|
onTokenizeShouldStart: data => {
|
|
1355
|
+
wasPaymentProcessedStarted = true;
|
|
1284
1356
|
this.emit(EVENTS.ERROR, undefined);
|
|
1285
1357
|
this.emit(EVENTS.START_PURCHASE, data.paymentMethodType);
|
|
1286
1358
|
return true;
|
|
@@ -1401,6 +1473,7 @@ class CheckoutInstance extends EventEmitter {
|
|
|
1401
1473
|
this.on(EVENTS.INPUT_ERROR, skin.onInputError);
|
|
1402
1474
|
this.on(EVENTS.METHOD_RENDER, skin.onMethodRender);
|
|
1403
1475
|
this.on(EVENTS.SUCCESS, skin.onDestroy);
|
|
1476
|
+
this.on(EVENTS.DESTROY, skin.onDestroy);
|
|
1404
1477
|
return skin.getCheckoutOptions();
|
|
1405
1478
|
}
|
|
1406
1479
|
showInitializingLoader() {
|
|
@@ -1409,6 +1482,48 @@ class CheckoutInstance extends EventEmitter {
|
|
|
1409
1482
|
hideInitializingLoader() {
|
|
1410
1483
|
hideLoader();
|
|
1411
1484
|
}
|
|
1485
|
+
async initMethod(method, element, callbacks) {
|
|
1486
|
+
this._ensureNotDestroyed();
|
|
1487
|
+
if (!this.isReady()) {
|
|
1488
|
+
await this.createSession();
|
|
1489
|
+
}
|
|
1490
|
+
this.on(EVENTS.METHOD_RENDER, callbacks.onRenderSuccess);
|
|
1491
|
+
this.on(EVENTS.METHOD_RENDER_ERROR, callbacks.onRenderError);
|
|
1492
|
+
this.on(EVENTS.LOADER_CHANGE, callbacks.onLoaderChange);
|
|
1493
|
+
this.on(EVENTS.SUCCESS, callbacks.onPaymentSuccess);
|
|
1494
|
+
this.on(EVENTS.PURCHASE_FAILURE, callbacks.onPaymentFail);
|
|
1495
|
+
this.on(EVENTS.PURCHASE_CANCELLED, callbacks.onPaymentCancel);
|
|
1496
|
+
this.on(EVENTS.ERROR, callbacks.onErrorMessageChange);
|
|
1497
|
+
this.on(EVENTS.START_PURCHASE, callbacks.onPaymentStarted);
|
|
1498
|
+
this.on(EVENTS.METHODS_AVAILABLE, callbacks.onMethodsAvailable);
|
|
1499
|
+
let checkoutOptions = this.getCheckoutOptions({});
|
|
1500
|
+
let methodOptions = {
|
|
1501
|
+
onMethodRender: this.handleMethodRender,
|
|
1502
|
+
onMethodRenderError: this.handleMethodRenderError,
|
|
1503
|
+
};
|
|
1504
|
+
if (method === PaymentMethod.PAYMENT_CARD) {
|
|
1505
|
+
const cardDefaultOptions = await this.getCardDefaultSkinCheckoutOptions(element);
|
|
1506
|
+
checkoutOptions = this.getCheckoutOptions({
|
|
1507
|
+
...cardDefaultOptions,
|
|
1508
|
+
});
|
|
1509
|
+
methodOptions = {
|
|
1510
|
+
cardElements: cardDefaultOptions.cardElements,
|
|
1511
|
+
onSubmit: this.handleSubmit,
|
|
1512
|
+
onInputChange: this.handleInputChange,
|
|
1513
|
+
onMethodRender: this.handleMethodRender,
|
|
1514
|
+
onMethodRenderError: this.handleMethodRenderError,
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
await this.primerWrapper.initializeHeadlessCheckout(this.clientToken, checkoutOptions);
|
|
1518
|
+
const methodInterface = await this.primerWrapper.initMethod(method, element, methodOptions);
|
|
1519
|
+
return {
|
|
1520
|
+
...methodInterface,
|
|
1521
|
+
destroy: async () => {
|
|
1522
|
+
await methodInterface.destroy();
|
|
1523
|
+
await this.destroy();
|
|
1524
|
+
},
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1412
1527
|
}
|
|
1413
1528
|
CheckoutInstance.sessionCache = new Map();
|
|
1414
1529
|
|
|
@@ -1490,9 +1605,6 @@ async function silentPurchase(options) {
|
|
|
1490
1605
|
return true;
|
|
1491
1606
|
}
|
|
1492
1607
|
async function initMethod(method, element, options) {
|
|
1493
|
-
// Ensure Primer SDK is loaded before initializing payment method
|
|
1494
|
-
const primerWrapper = new PrimerWrapper();
|
|
1495
|
-
await primerWrapper.ensurePrimerLoaded();
|
|
1496
1608
|
const checkoutInstance = new CheckoutInstance({
|
|
1497
1609
|
orgId: options.orgId,
|
|
1498
1610
|
baseUrl: options.baseUrl,
|
|
@@ -1511,36 +1623,16 @@ async function initMethod(method, element, options) {
|
|
|
1511
1623
|
googlePay: options.googlePay,
|
|
1512
1624
|
},
|
|
1513
1625
|
});
|
|
1514
|
-
checkoutInstance.
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
checkoutInstance.on(EVENTS.ERROR, options.onErrorMessageChange);
|
|
1525
|
-
checkoutInstance.on(EVENTS.START_PURCHASE, options.onPaymentStarted);
|
|
1526
|
-
if (method === PaymentMethod.PAYMENT_CARD) {
|
|
1527
|
-
const cardDefaultOptions = await checkoutInstance['getCardDefaultSkinCheckoutOptions'](element);
|
|
1528
|
-
const checkoutOptions = checkoutInstance['getCheckoutOptions']({
|
|
1529
|
-
...cardDefaultOptions,
|
|
1530
|
-
});
|
|
1531
|
-
await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutOptions);
|
|
1532
|
-
return checkoutInstance.primerWrapper.initMethod(method, element, {
|
|
1533
|
-
cardElements: cardDefaultOptions.cardElements,
|
|
1534
|
-
onSubmit: checkoutInstance['handleSubmit'],
|
|
1535
|
-
onInputChange: checkoutInstance['handleInputChange'],
|
|
1536
|
-
onMethodRender: checkoutInstance['handleMethodRender'],
|
|
1537
|
-
onMethodRenderError: checkoutInstance['handleMethodRenderError'],
|
|
1538
|
-
});
|
|
1539
|
-
}
|
|
1540
|
-
await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutInstance['getCheckoutOptions']({}));
|
|
1541
|
-
return checkoutInstance.primerWrapper.initMethod(method, element, {
|
|
1542
|
-
onMethodRender: checkoutInstance['handleMethodRender'],
|
|
1543
|
-
onMethodRenderError: checkoutInstance['handleMethodRenderError'],
|
|
1626
|
+
return checkoutInstance.initMethod(method, element, {
|
|
1627
|
+
onRenderSuccess: options.onRenderSuccess,
|
|
1628
|
+
onRenderError: options.onRenderError,
|
|
1629
|
+
onLoaderChange: options.onLoaderChange,
|
|
1630
|
+
onPaymentSuccess: options.onPaymentSuccess,
|
|
1631
|
+
onPaymentFail: options.onPaymentFail,
|
|
1632
|
+
onPaymentCancel: options.onPaymentCancel,
|
|
1633
|
+
onErrorMessageChange: options.onErrorMessageChange,
|
|
1634
|
+
onPaymentStarted: options.onPaymentStarted,
|
|
1635
|
+
onMethodsAvailable: options.onMethodsAvailable,
|
|
1544
1636
|
});
|
|
1545
1637
|
}
|
|
1546
1638
|
|