@idonatedev/idonate-sdk 1.2.0-dev14 → 1.2.0-dev16
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/constants.js +1 -1
- package/dist/esm/constants.js +1 -1
- package/dist/esm/tokenize/CardConnectTokenizer.d.ts +6 -1
- package/dist/esm/tokenize/CardConnectTokenizer.js +184 -53
- package/dist/esm/tokenize/PayPalTokenizer.d.ts +1 -0
- package/dist/esm/tokenize/PayPalTokenizer.js +52 -16
- package/dist/esm/tokenize/SpreedlyTokenizer.d.ts +6 -0
- package/dist/esm/tokenize/SpreedlyTokenizer.js +113 -63
- package/dist/esm/tokenize/Tokenizer.d.ts +6 -2
- package/dist/esm/tokenize/Tokenizer.js +13 -3
- package/dist/esm/tokenize/gateway-utils.js +3 -2
- package/dist/esm/tokenize/index.d.ts +1 -1
- package/dist/esm/tokenize/spreedly-secure.js +6 -2
- package/dist/esm/tokenize/tokenizer-utils.d.ts +1 -1
- package/dist/esm/tokenize/tokenizer-utils.js +25 -4
- package/dist/esm/tokenize/types.d.ts +3 -2
- package/dist/esm/typeAdapters.js +6 -4
- package/dist/tokenize/CardConnectTokenizer.d.ts +6 -1
- package/dist/tokenize/CardConnectTokenizer.js +184 -56
- package/dist/tokenize/PayPalTokenizer.d.ts +1 -0
- package/dist/tokenize/PayPalTokenizer.js +52 -16
- package/dist/tokenize/SpreedlyTokenizer.d.ts +6 -0
- package/dist/tokenize/SpreedlyTokenizer.js +113 -63
- package/dist/tokenize/Tokenizer.d.ts +6 -2
- package/dist/tokenize/Tokenizer.js +13 -3
- package/dist/tokenize/gateway-utils.js +3 -2
- package/dist/tokenize/index.d.ts +1 -1
- package/dist/tokenize/spreedly-secure.js +6 -2
- package/dist/tokenize/tokenizer-utils.d.ts +1 -1
- package/dist/tokenize/tokenizer-utils.js +25 -4
- package/dist/tokenize/types.d.ts +3 -2
- package/dist/typeAdapters.js +6 -4
- package/package.json +1 -1
- package/umd/idonate-sdk.js +1 -1
|
@@ -8,14 +8,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
12
|
exports.CardConnectTokenizer = void 0;
|
|
16
13
|
const Tokenizer_1 = require("./Tokenizer");
|
|
17
14
|
const types_1 = require("./types");
|
|
18
|
-
const config_handler_1 = __importDefault(require("../config-handler"));
|
|
19
15
|
const styles_1 = require("./styles");
|
|
20
16
|
const tokenizer_constants_1 = require("./tokenizer-constants");
|
|
21
17
|
const tokenizer_utils_1 = require("./tokenizer-utils");
|
|
@@ -26,6 +22,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
26
22
|
this.containerId = containerId;
|
|
27
23
|
this.layout = layout;
|
|
28
24
|
this.enableTestMode = false;
|
|
25
|
+
this.acceptAutoToken = true;
|
|
29
26
|
this.mode = mode;
|
|
30
27
|
this.enableTestMode = enableTestMode;
|
|
31
28
|
this.iframe = iframe;
|
|
@@ -40,7 +37,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
40
37
|
}
|
|
41
38
|
static create(gateway, container, config) {
|
|
42
39
|
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
-
var _a;
|
|
40
|
+
var _a, _b;
|
|
44
41
|
if (container.mode === 'bank_account' && container.bankCountry === 'CA') {
|
|
45
42
|
throw new Error('CardConnect does not support Canadian bank accounts');
|
|
46
43
|
}
|
|
@@ -48,7 +45,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
48
45
|
if (container.layout === 'responsive') {
|
|
49
46
|
const containerEl = document.getElementById(container.containerId);
|
|
50
47
|
const containerWidth = (containerEl === null || containerEl === void 0 ? void 0 : containerEl.offsetWidth) || 0;
|
|
51
|
-
const breakpoint = container.responsiveBreakpoint
|
|
48
|
+
const breakpoint = (_a = container.responsiveBreakpoint) !== null && _a !== void 0 ? _a : tokenizer_constants_1.RESPONSIVE_BREAKPOINT;
|
|
52
49
|
effectiveLayout =
|
|
53
50
|
containerWidth < breakpoint ? 'two-line' : 'single-line';
|
|
54
51
|
}
|
|
@@ -56,8 +53,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
56
53
|
effectiveLayout = 'two-line';
|
|
57
54
|
}
|
|
58
55
|
const resolvedContainer = Object.assign(Object.assign({}, container), { layout: effectiveLayout });
|
|
59
|
-
|
|
60
|
-
config.cardConnectBaseUrl = baseUrl;
|
|
56
|
+
const baseUrl = ((_b = gateway.config) === null || _b === void 0 ? void 0 : _b.baseUrl) || config.clientConfig.cardConnectBaseUrl;
|
|
61
57
|
const mergedStyles = (0, styles_1.mergeStyles)(styles_1.DEFAULT_UNIFIED_STYLES, container.styling);
|
|
62
58
|
const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, resolvedContainer);
|
|
63
59
|
const iframe = CardConnectTokenizer.createIframe(iframeUrl, mergedStyles);
|
|
@@ -145,6 +141,66 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
145
141
|
this.applyInputStyles(this.accountTypeEl, mergedStyles, 'right');
|
|
146
142
|
containerEl.appendChild(this.accountTypeEl);
|
|
147
143
|
}
|
|
144
|
+
this.mergedStyles = mergedStyles;
|
|
145
|
+
this.currentValidationState = {
|
|
146
|
+
isValid: false,
|
|
147
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
148
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
149
|
+
};
|
|
150
|
+
this.addBankAccountValidationListeners(mergedStyles);
|
|
151
|
+
}
|
|
152
|
+
addBankAccountValidationListeners(styles) {
|
|
153
|
+
if (this.routingNumberEl) {
|
|
154
|
+
this.routingNumberEl.addEventListener('blur', () => {
|
|
155
|
+
this.updateBankAccountValidation(styles);
|
|
156
|
+
});
|
|
157
|
+
this.routingNumberEl.addEventListener('input', () => {
|
|
158
|
+
this.updateBankAccountValidation(styles);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (this.accountNumberEl) {
|
|
162
|
+
this.accountNumberEl.addEventListener('blur', () => {
|
|
163
|
+
this.updateBankAccountValidation(styles);
|
|
164
|
+
});
|
|
165
|
+
this.accountNumberEl.addEventListener('input', () => {
|
|
166
|
+
this.updateBankAccountValidation(styles);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
updateBankAccountValidation(styles) {
|
|
171
|
+
var _a, _b;
|
|
172
|
+
const routingValue = ((_a = this.routingNumberEl) === null || _a === void 0 ? void 0 : _a.value) || '';
|
|
173
|
+
const accountValue = ((_b = this.accountNumberEl) === null || _b === void 0 ? void 0 : _b.value) || '';
|
|
174
|
+
const routingValid = routingValue.length > 0 && (0, tokenizer_utils_1.validateRoutingNumber)(routingValue);
|
|
175
|
+
const accountValid = accountValue.length > 0 && (0, tokenizer_utils_1.validateAccountNumber)(accountValue);
|
|
176
|
+
if (this.routingNumberEl) {
|
|
177
|
+
if (routingValue.length > 0 && !routingValid) {
|
|
178
|
+
this.routingNumberEl.style.borderColor = styles.error.borderColor;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
this.routingNumberEl.style.borderColor = '';
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (this.accountNumberEl) {
|
|
185
|
+
if (accountValue.length > 0 && !accountValid) {
|
|
186
|
+
this.accountNumberEl.style.borderColor = styles.error.borderColor;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
this.accountNumberEl.style.borderColor = '';
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
this.currentValidationState = {
|
|
193
|
+
isValid: routingValid && accountValid,
|
|
194
|
+
routingNumber: {
|
|
195
|
+
isValid: routingValid,
|
|
196
|
+
isEmpty: routingValue.length === 0,
|
|
197
|
+
},
|
|
198
|
+
accountNumber: {
|
|
199
|
+
isValid: accountValid,
|
|
200
|
+
isEmpty: accountValue.length === 0,
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
this.emit('validation', this.currentValidationState);
|
|
148
204
|
}
|
|
149
205
|
init() {
|
|
150
206
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -214,31 +270,39 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
214
270
|
}
|
|
215
271
|
tokenizeCardInternal(cardData) {
|
|
216
272
|
return __awaiter(this, void 0, void 0, function* () {
|
|
273
|
+
var _a, _b, _c;
|
|
217
274
|
if (this.cachedTokenResult && this.cachedTokenResult.errorCode === '0') {
|
|
275
|
+
const cardType = this.cachedTokenResult.cardType
|
|
276
|
+
? this.normalizeCardType(this.cachedTokenResult.cardType)
|
|
277
|
+
: this.normalizeCardType('unknown');
|
|
218
278
|
return {
|
|
219
279
|
token: this.cachedTokenResult.token,
|
|
220
|
-
lastFour: this.cachedTokenResult.
|
|
221
|
-
|
|
280
|
+
lastFour: this.cachedTokenResult.last4 ||
|
|
281
|
+
this.cachedTokenResult.token.slice(-4),
|
|
282
|
+
cardType,
|
|
283
|
+
paymentMethodType: 'credit_card',
|
|
222
284
|
provider: 'cardconnect',
|
|
223
285
|
};
|
|
224
286
|
}
|
|
225
287
|
if (this.tokenizationPromise) {
|
|
226
288
|
return this.tokenizationPromise;
|
|
227
289
|
}
|
|
290
|
+
if (!this.currentValidationState.isValid &&
|
|
291
|
+
(((_a = this.currentValidationState.cardNumber) === null || _a === void 0 ? void 0 : _a.isEmpty) ||
|
|
292
|
+
((_b = this.currentValidationState.cvv) === null || _b === void 0 ? void 0 : _b.isEmpty) ||
|
|
293
|
+
((_c = this.currentValidationState.expiry) === null || _c === void 0 ? void 0 : _c.isEmpty))) {
|
|
294
|
+
throw new types_1.TokenizationError('Card fields are incomplete', 'VALIDATION_ERROR');
|
|
295
|
+
}
|
|
228
296
|
this.tokenizationPromise = new Promise((resolve, reject) => {
|
|
229
297
|
this.tokenizationResolve = resolve;
|
|
230
298
|
this.tokenizationReject = reject;
|
|
231
|
-
|
|
299
|
+
this.tokenizationTimeout = setTimeout(() => {
|
|
300
|
+
this.tokenizationTimeout = undefined;
|
|
232
301
|
this.tokenizationPromise = undefined;
|
|
233
302
|
this.tokenizationResolve = undefined;
|
|
234
303
|
this.tokenizationReject = undefined;
|
|
235
304
|
reject(new types_1.TokenizationError('Tokenization timeout - ensure all card fields are filled in iframe', 'TIMEOUT'));
|
|
236
305
|
}, tokenizer_constants_1.TOKENIZE_TIMEOUT);
|
|
237
|
-
const tokenizationHandler = (data) => {
|
|
238
|
-
clearTimeout(timeout);
|
|
239
|
-
this.off('tokenization', tokenizationHandler);
|
|
240
|
-
};
|
|
241
|
-
this.on('tokenization', tokenizationHandler);
|
|
242
306
|
});
|
|
243
307
|
return this.tokenizationPromise;
|
|
244
308
|
});
|
|
@@ -260,16 +324,16 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
260
324
|
throw new types_1.TokenizationError('Invalid account number', 'VALIDATION_ERROR');
|
|
261
325
|
}
|
|
262
326
|
const baseUrl = new URL(this.iframeUrl).origin;
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, config);
|
|
266
|
-
return {
|
|
327
|
+
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, baseUrl);
|
|
328
|
+
const paymentToken = {
|
|
267
329
|
token: result.token,
|
|
268
330
|
lastFour: accountNumber.slice(-4),
|
|
269
331
|
accountType: accountType,
|
|
270
332
|
paymentMethodType: 'bank_account',
|
|
271
333
|
provider: 'cardconnect',
|
|
272
334
|
};
|
|
335
|
+
this.emit('tokenReady', paymentToken);
|
|
336
|
+
return paymentToken;
|
|
273
337
|
});
|
|
274
338
|
}
|
|
275
339
|
validate() {
|
|
@@ -406,12 +470,39 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
406
470
|
action: 'clear',
|
|
407
471
|
}, this.expectedOrigin);
|
|
408
472
|
}
|
|
409
|
-
this.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
}
|
|
473
|
+
this.cachedTokenResult = undefined;
|
|
474
|
+
this.acceptAutoToken = false;
|
|
475
|
+
if (this.tokenizationTimeout) {
|
|
476
|
+
clearTimeout(this.tokenizationTimeout);
|
|
477
|
+
this.tokenizationTimeout = undefined;
|
|
478
|
+
}
|
|
479
|
+
if (this.tokenizationReject) {
|
|
480
|
+
const reject = this.tokenizationReject;
|
|
481
|
+
this.tokenizationPromise = undefined;
|
|
482
|
+
this.tokenizationResolve = undefined;
|
|
483
|
+
this.tokenizationReject = undefined;
|
|
484
|
+
reject(new types_1.TokenizationError('Tokenizer cleared', 'CLEARED'));
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
this.tokenizationPromise = undefined;
|
|
488
|
+
this.tokenizationResolve = undefined;
|
|
489
|
+
this.tokenizationReject = undefined;
|
|
490
|
+
}
|
|
491
|
+
if (this.mode === 'bank_account') {
|
|
492
|
+
this.currentValidationState = {
|
|
493
|
+
isValid: false,
|
|
494
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
495
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
this.currentValidationState = {
|
|
500
|
+
isValid: false,
|
|
501
|
+
cardNumber: { isValid: false, isEmpty: true },
|
|
502
|
+
cvv: { isValid: false, isEmpty: true },
|
|
503
|
+
expiry: { isValid: false, isEmpty: true },
|
|
504
|
+
};
|
|
505
|
+
}
|
|
415
506
|
this.emit('validation', this.currentValidationState);
|
|
416
507
|
}
|
|
417
508
|
focus(field) {
|
|
@@ -440,8 +531,22 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
440
531
|
}
|
|
441
532
|
}
|
|
442
533
|
destroy() {
|
|
534
|
+
this.markDestroyed();
|
|
535
|
+
if (this.tokenizationTimeout) {
|
|
536
|
+
clearTimeout(this.tokenizationTimeout);
|
|
537
|
+
this.tokenizationTimeout = undefined;
|
|
538
|
+
}
|
|
539
|
+
if (this.tokenizationReject) {
|
|
540
|
+
const reject = this.tokenizationReject;
|
|
541
|
+
this.tokenizationPromise = undefined;
|
|
542
|
+
this.tokenizationResolve = undefined;
|
|
543
|
+
this.tokenizationReject = undefined;
|
|
544
|
+
reject(new types_1.TokenizationError('Tokenizer destroyed', 'DESTROYED'));
|
|
545
|
+
}
|
|
546
|
+
this.cachedTokenResult = undefined;
|
|
443
547
|
if (this.messageHandler) {
|
|
444
548
|
window.removeEventListener('message', this.messageHandler);
|
|
549
|
+
this.messageHandler = undefined;
|
|
445
550
|
}
|
|
446
551
|
if (this.containerEl) {
|
|
447
552
|
this.containerEl.innerHTML = '';
|
|
@@ -468,6 +573,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
468
573
|
lastFour: this.cachedTokenResult.last4 ||
|
|
469
574
|
this.cachedTokenResult.token.slice(-4),
|
|
470
575
|
cardType,
|
|
576
|
+
paymentMethodType: 'credit_card',
|
|
471
577
|
provider: 'cardconnect',
|
|
472
578
|
};
|
|
473
579
|
}
|
|
@@ -480,8 +586,14 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
480
586
|
try {
|
|
481
587
|
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
482
588
|
if (data.token && data.errorCode !== undefined) {
|
|
589
|
+
if (!this.acceptAutoToken && !this.tokenizationResolve) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
483
592
|
this.cachedTokenResult = data;
|
|
484
|
-
this.
|
|
593
|
+
if (this.tokenizationTimeout) {
|
|
594
|
+
clearTimeout(this.tokenizationTimeout);
|
|
595
|
+
this.tokenizationTimeout = undefined;
|
|
596
|
+
}
|
|
485
597
|
if (data.errorCode === '0') {
|
|
486
598
|
const cardType = data.cardType
|
|
487
599
|
? this.normalizeCardType(data.cardType)
|
|
@@ -494,6 +606,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
494
606
|
token: data.token,
|
|
495
607
|
lastFour: data.last4 || data.token.slice(-4),
|
|
496
608
|
cardType,
|
|
609
|
+
paymentMethodType: 'credit_card',
|
|
497
610
|
provider: 'cardconnect',
|
|
498
611
|
};
|
|
499
612
|
if (this.tokenizationResolve) {
|
|
@@ -508,12 +621,14 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
508
621
|
cvv: { isValid: true, isEmpty: false },
|
|
509
622
|
expiry: { isValid: true, isEmpty: false },
|
|
510
623
|
};
|
|
511
|
-
this.emit('validation',
|
|
624
|
+
this.emit('validation', this.currentValidationState);
|
|
512
625
|
this.emit('tokenReady', token);
|
|
513
626
|
}
|
|
514
627
|
else {
|
|
628
|
+
const error = new types_1.TokenizationError(data.errorMessage || 'Tokenization failed', data.errorCode || 'UNKNOWN');
|
|
629
|
+
this.emit('error', error);
|
|
515
630
|
if (this.tokenizationReject) {
|
|
516
|
-
this.tokenizationReject(
|
|
631
|
+
this.tokenizationReject(error);
|
|
517
632
|
this.tokenizationPromise = undefined;
|
|
518
633
|
this.tokenizationResolve = undefined;
|
|
519
634
|
this.tokenizationReject = undefined;
|
|
@@ -521,19 +636,16 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
521
636
|
}
|
|
522
637
|
}
|
|
523
638
|
if (data.event === 'validation' || data.validationError !== undefined) {
|
|
639
|
+
this.acceptAutoToken = true;
|
|
524
640
|
this.handleValidationMessage(data);
|
|
525
641
|
}
|
|
526
|
-
if (data.event === '
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
if (cardType !== this.currentCardType) {
|
|
534
|
-
this.currentCardType = cardType;
|
|
535
|
-
this.emit('cardTypeChange', { cardType });
|
|
536
|
-
}
|
|
642
|
+
if ((data.event === 'input' || data.event === 'change') &&
|
|
643
|
+
data.cardType) {
|
|
644
|
+
this.acceptAutoToken = true;
|
|
645
|
+
const cardType = this.normalizeCardType(data.cardType);
|
|
646
|
+
if (cardType !== this.currentCardType) {
|
|
647
|
+
this.currentCardType = cardType;
|
|
648
|
+
this.emit('cardTypeChange', { cardType });
|
|
537
649
|
}
|
|
538
650
|
}
|
|
539
651
|
}
|
|
@@ -541,7 +653,6 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
541
653
|
}
|
|
542
654
|
}
|
|
543
655
|
handleValidationMessage(data) {
|
|
544
|
-
var _a, _b, _c, _d, _e, _f;
|
|
545
656
|
if (data.validationError) {
|
|
546
657
|
const errorLower = data.validationError.toLowerCase();
|
|
547
658
|
if (errorLower.includes('card') || errorLower.includes('number')) {
|
|
@@ -563,10 +674,14 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
563
674
|
this.emit('validation', this.currentValidationState);
|
|
564
675
|
}
|
|
565
676
|
else {
|
|
566
|
-
this.currentValidationState.
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
677
|
+
this.currentValidationState.cardNumber = {
|
|
678
|
+
isValid: true,
|
|
679
|
+
isEmpty: false,
|
|
680
|
+
};
|
|
681
|
+
this.currentValidationState.cvv = { isValid: true, isEmpty: false };
|
|
682
|
+
this.currentValidationState.expiry = { isValid: true, isEmpty: false };
|
|
683
|
+
this.currentValidationState.isValid = true;
|
|
684
|
+
this.emit('validation', this.currentValidationState);
|
|
570
685
|
}
|
|
571
686
|
}
|
|
572
687
|
static generateIframeUrl(baseUrl, container) {
|
|
@@ -746,17 +861,30 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
746
861
|
}
|
|
747
862
|
return encodeURIComponent(css.join(''));
|
|
748
863
|
}
|
|
749
|
-
static tokenizeBankAccount(routingNumber, accountNumber,
|
|
750
|
-
return
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
864
|
+
static tokenizeBankAccount(routingNumber, accountNumber, configOrBaseUrl) {
|
|
865
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
866
|
+
const baseUrl = typeof configOrBaseUrl === 'string'
|
|
867
|
+
? configOrBaseUrl
|
|
868
|
+
: configOrBaseUrl.cardConnectBaseUrl;
|
|
869
|
+
const response = yield fetch(`${baseUrl}/cardsecure/api/v1/ccn/tokenize`, {
|
|
870
|
+
method: 'POST',
|
|
871
|
+
headers: {
|
|
872
|
+
'Content-Type': 'application/json',
|
|
873
|
+
},
|
|
874
|
+
body: JSON.stringify({
|
|
875
|
+
account: `${routingNumber}/${accountNumber}`,
|
|
876
|
+
unique: true,
|
|
877
|
+
}),
|
|
878
|
+
});
|
|
879
|
+
if (!response.ok) {
|
|
880
|
+
throw new types_1.TokenizationError(`Bank account tokenization failed: HTTP ${response.status}`, 'API_ERROR');
|
|
881
|
+
}
|
|
882
|
+
const result = yield response.json();
|
|
883
|
+
if (!result.token) {
|
|
884
|
+
throw new types_1.TokenizationError(result.message || 'Bank account tokenization failed: no token returned', 'API_ERROR');
|
|
885
|
+
}
|
|
886
|
+
return result;
|
|
887
|
+
});
|
|
760
888
|
}
|
|
761
889
|
}
|
|
762
890
|
exports.CardConnectTokenizer = CardConnectTokenizer;
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.PayPalTokenizer = void 0;
|
|
13
13
|
const Tokenizer_1 = require("./Tokenizer");
|
|
14
14
|
const types_1 = require("./types");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
15
16
|
const PAYPAL_SDK_URL = 'https://www.paypal.com/sdk/js';
|
|
16
17
|
const PAYPAL_SCRIPT_ID = 'paypal-sdk-script';
|
|
17
18
|
const INIT_TIMEOUT = 10000;
|
|
@@ -22,7 +23,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
22
23
|
this.gateway = gateway;
|
|
23
24
|
this.containerId = containerId;
|
|
24
25
|
this.configContext = configContext;
|
|
25
|
-
this.mode = '
|
|
26
|
+
this.mode = 'paypal';
|
|
26
27
|
const gatewayConfig = gateway.config;
|
|
27
28
|
if (!(gatewayConfig === null || gatewayConfig === void 0 ? void 0 : gatewayConfig.client_id)) {
|
|
28
29
|
throw new Error('PayPal gateway configuration missing client_id');
|
|
@@ -69,7 +70,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
69
70
|
})
|
|
70
71
|
.then(() => {
|
|
71
72
|
this.emit('ready');
|
|
72
|
-
this.emit('validation', { isValid: true });
|
|
73
|
+
this.emit('validation', { isValid: true, hasToken: false });
|
|
73
74
|
resolve();
|
|
74
75
|
})
|
|
75
76
|
.catch((error) => {
|
|
@@ -82,11 +83,20 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
82
83
|
}
|
|
83
84
|
loadPayPalSDK() {
|
|
84
85
|
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
const configKey = `${this.clientId}|${this.currency}`;
|
|
87
|
+
const existingScript = document.getElementById(PAYPAL_SCRIPT_ID);
|
|
88
|
+
if (existingScript) {
|
|
89
|
+
const loadedConfig = existingScript.getAttribute('data-config-key');
|
|
90
|
+
if (loadedConfig && loadedConfig !== configKey) {
|
|
91
|
+
existingScript.remove();
|
|
92
|
+
delete window.paypal;
|
|
93
|
+
}
|
|
94
|
+
else if (window.paypal) {
|
|
95
|
+
return Promise.resolve();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
return this.waitForPayPalGlobal();
|
|
99
|
+
}
|
|
90
100
|
}
|
|
91
101
|
const params = new URLSearchParams({
|
|
92
102
|
'client-id': this.clientId,
|
|
@@ -105,6 +115,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
105
115
|
script.id = PAYPAL_SCRIPT_ID;
|
|
106
116
|
script.src = `${PAYPAL_SDK_URL}?${params.toString()}`;
|
|
107
117
|
script.async = true;
|
|
118
|
+
script.setAttribute('data-config-key', configKey);
|
|
108
119
|
return new Promise((resolve, reject) => {
|
|
109
120
|
script.onload = () => {
|
|
110
121
|
this.waitForPayPalGlobal().then(resolve).catch(reject);
|
|
@@ -148,7 +159,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
148
159
|
if (!window.paypal || !this.paypalButtonContainer) {
|
|
149
160
|
return;
|
|
150
161
|
}
|
|
151
|
-
|
|
162
|
+
this.buttonsInstance = window.paypal.Buttons({
|
|
152
163
|
createOrder: () => this.createOrder(),
|
|
153
164
|
onApprove: (data) => this.handleApprove(data),
|
|
154
165
|
onCancel: (data) => this.handleCancel(data),
|
|
@@ -159,36 +170,48 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
159
170
|
height: 40,
|
|
160
171
|
},
|
|
161
172
|
});
|
|
162
|
-
yield
|
|
173
|
+
yield this.buttonsInstance.render(this.paypalButtonContainer);
|
|
163
174
|
});
|
|
164
175
|
}
|
|
165
176
|
createOrder() {
|
|
166
177
|
const endpoint = `${this.clientConfig.embedApiBaseUrl}/payment/paypal/create-order`;
|
|
178
|
+
this.paymentTransactionId = undefined;
|
|
179
|
+
this.paymentMethodId = undefined;
|
|
167
180
|
let orderAmount;
|
|
168
181
|
let orderCurrency = this.currency;
|
|
169
182
|
if (this.onCreateOrder) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
try {
|
|
184
|
+
const orderData = this.onCreateOrder();
|
|
185
|
+
orderAmount = orderData.amount;
|
|
186
|
+
orderCurrency = orderData.currency || this.currency;
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
const error = err instanceof Error
|
|
190
|
+
? err
|
|
191
|
+
: new Error('onCreateOrder callback failed');
|
|
192
|
+
this.handleError(error, 'Order creation failed');
|
|
193
|
+
return Promise.reject(error);
|
|
194
|
+
}
|
|
173
195
|
}
|
|
174
196
|
else {
|
|
175
197
|
orderAmount = this.amount;
|
|
176
198
|
}
|
|
177
|
-
if (orderAmount === undefined || orderAmount <= 0) {
|
|
199
|
+
if (orderAmount === undefined || isNaN(orderAmount) || orderAmount <= 0) {
|
|
178
200
|
const error = new Error('Amount is required to create PayPal order');
|
|
179
201
|
this.handleError(error, 'Order creation failed');
|
|
180
202
|
return Promise.reject(error);
|
|
181
203
|
}
|
|
182
204
|
const requestBody = {
|
|
183
205
|
payment_gateway_id: this.gateway.id,
|
|
206
|
+
organization_id: this.organizationId,
|
|
207
|
+
embed_id: this.embedId,
|
|
184
208
|
currency: orderCurrency,
|
|
185
209
|
amount: orderAmount,
|
|
186
210
|
};
|
|
187
211
|
return fetch(endpoint, {
|
|
188
212
|
method: 'POST',
|
|
189
|
-
headers:
|
|
190
|
-
|
|
191
|
-
},
|
|
213
|
+
headers: constants_1.CLIENT_HEADERS,
|
|
214
|
+
credentials: 'include',
|
|
192
215
|
body: JSON.stringify(requestBody),
|
|
193
216
|
})
|
|
194
217
|
.then((response) => {
|
|
@@ -215,6 +238,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
215
238
|
const token = {
|
|
216
239
|
token: data.orderID,
|
|
217
240
|
lastFour: data.orderID.slice(-4),
|
|
241
|
+
paymentMethodType: 'paypal',
|
|
218
242
|
provider: 'paypal_checkout',
|
|
219
243
|
paymentMethodId: this.paymentMethodId,
|
|
220
244
|
paymentTransactionId: this.paymentTransactionId,
|
|
@@ -244,6 +268,9 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
244
268
|
}
|
|
245
269
|
validate() {
|
|
246
270
|
return __awaiter(this, void 0, void 0, function* () {
|
|
271
|
+
if (!this.isReady) {
|
|
272
|
+
throw new Error('Tokenizer not initialized');
|
|
273
|
+
}
|
|
247
274
|
return {
|
|
248
275
|
isValid: true,
|
|
249
276
|
errors: [],
|
|
@@ -257,6 +284,15 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
257
284
|
focus(field) {
|
|
258
285
|
}
|
|
259
286
|
destroy() {
|
|
287
|
+
this.markDestroyed();
|
|
288
|
+
if (this.buttonsInstance) {
|
|
289
|
+
try {
|
|
290
|
+
this.buttonsInstance.close();
|
|
291
|
+
}
|
|
292
|
+
catch (_a) {
|
|
293
|
+
}
|
|
294
|
+
this.buttonsInstance = undefined;
|
|
295
|
+
}
|
|
260
296
|
if (this.containerEl) {
|
|
261
297
|
this.containerEl.innerHTML = '';
|
|
262
298
|
}
|
|
@@ -29,6 +29,10 @@ export declare class SpreedlyTokenizer extends Tokenizer {
|
|
|
29
29
|
private cardNumberDiv?;
|
|
30
30
|
private cvvDiv?;
|
|
31
31
|
private responsiveBreakpoint;
|
|
32
|
+
private tokenizationPromise?;
|
|
33
|
+
private tokenizationResolve?;
|
|
34
|
+
private tokenizationReject?;
|
|
35
|
+
private tokenizationTimeout?;
|
|
32
36
|
private constructor();
|
|
33
37
|
static create(gateway: PaymentGateway, container: TokenizerContainer, config: {
|
|
34
38
|
organizationId: string;
|
|
@@ -38,6 +42,7 @@ export declare class SpreedlyTokenizer extends Tokenizer {
|
|
|
38
42
|
private init;
|
|
39
43
|
tokenize(paymentData: PaymentData): Promise<PaymentToken>;
|
|
40
44
|
private tokenizeCardInternal;
|
|
45
|
+
private executeCardTokenization;
|
|
41
46
|
private createCanadianBankAccountFields;
|
|
42
47
|
private tokenizeBankAccountInternal;
|
|
43
48
|
validate(): Promise<ValidationResult>;
|
|
@@ -50,6 +55,7 @@ export declare class SpreedlyTokenizer extends Tokenizer {
|
|
|
50
55
|
private determineLayout;
|
|
51
56
|
private setupResizeObserver;
|
|
52
57
|
private applyLayoutStyles;
|
|
58
|
+
private clearTokenizationState;
|
|
53
59
|
destroy(): void;
|
|
54
60
|
hasToken(): boolean;
|
|
55
61
|
getToken(): PaymentToken | null;
|