@idonatedev/idonate-sdk 1.1.0-dev13 → 1.1.0-dev14

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.
Files changed (48) hide show
  1. package/dist/esm/apple-pay.d.ts +12 -0
  2. package/dist/esm/apple-pay.js +74 -0
  3. package/dist/esm/cloudflare-challenge-handler.d.ts +5 -0
  4. package/dist/esm/cloudflare-challenge-handler.js +77 -0
  5. package/dist/esm/config-handler.d.ts +22 -0
  6. package/dist/esm/config-handler.js +47 -0
  7. package/dist/esm/constants.d.ts +18 -0
  8. package/dist/esm/constants.js +82 -0
  9. package/dist/esm/google-pay.d.ts +18 -0
  10. package/dist/esm/google-pay.js +140 -0
  11. package/dist/esm/idonate-client.d.ts +28 -0
  12. package/dist/esm/idonate-client.js +256 -0
  13. package/dist/esm/index.d.ts +11 -0
  14. package/dist/esm/index.js +11 -0
  15. package/dist/esm/recaptcha.d.ts +12 -0
  16. package/dist/esm/recaptcha.js +89 -0
  17. package/dist/esm/shared.d.ts +3 -0
  18. package/dist/esm/shared.js +13 -0
  19. package/dist/esm/test-utils.d.ts +81 -0
  20. package/dist/esm/test-utils.js +94 -0
  21. package/dist/esm/tokenize/CardConnectTokenizer.d.ts +51 -0
  22. package/dist/esm/tokenize/CardConnectTokenizer.js +706 -0
  23. package/dist/esm/tokenize/SpreedlyTokenizer.d.ts +92 -0
  24. package/dist/esm/tokenize/SpreedlyTokenizer.js +1140 -0
  25. package/dist/esm/tokenize/Tokenizer.d.ts +37 -0
  26. package/dist/esm/tokenize/Tokenizer.js +146 -0
  27. package/dist/esm/tokenize/iats.d.ts +3 -0
  28. package/dist/esm/tokenize/iats.js +48 -0
  29. package/dist/esm/tokenize/index.d.ts +6 -0
  30. package/dist/esm/tokenize/index.js +6 -0
  31. package/dist/esm/tokenize/spreedly-secure.d.ts +8 -0
  32. package/dist/esm/tokenize/spreedly-secure.js +40 -0
  33. package/dist/esm/tokenize/styles.d.ts +4 -0
  34. package/dist/esm/tokenize/styles.js +46 -0
  35. package/dist/esm/tokenize/tokenizer-constants.d.ts +62 -0
  36. package/dist/esm/tokenize/tokenizer-constants.js +62 -0
  37. package/dist/esm/tokenize/tokenizer-utils.d.ts +19 -0
  38. package/dist/esm/tokenize/tokenizer-utils.js +139 -0
  39. package/dist/esm/tokenize/types.d.ts +144 -0
  40. package/dist/esm/tokenize/types.js +26 -0
  41. package/dist/esm/typeAdapters.d.ts +29 -0
  42. package/dist/esm/typeAdapters.js +188 -0
  43. package/dist/esm/types.d.ts +367 -0
  44. package/dist/esm/types.js +14 -0
  45. package/dist/esm/util.d.ts +17 -0
  46. package/dist/esm/util.js +113 -0
  47. package/package.json +12 -2
  48. package/umd/idonate-sdk.js +1 -1
@@ -0,0 +1,706 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { Tokenizer } from './Tokenizer';
11
+ import { TokenizationError, } from './types';
12
+ import ConfigHandler from '../config-handler';
13
+ import { DEFAULT_UNIFIED_STYLES, mergeStyles, getContainerStylesForLayout, } from './styles';
14
+ import { INIT_TIMEOUT, TOKENIZE_TIMEOUT, BANK_FIELD_FLEX, } from './tokenizer-constants';
15
+ import { createInputElement, validateRoutingNumber, validateAccountNumber, createAccountTypeSelect, } from './tokenizer-utils';
16
+ export class CardConnectTokenizer extends Tokenizer {
17
+ constructor(iframe, iframeUrl, containerId, mode = 'credit_card', enableTestMode = false, layout = 'single-line') {
18
+ super();
19
+ this.iframeUrl = iframeUrl;
20
+ this.containerId = containerId;
21
+ this.layout = layout;
22
+ this.isReady = false;
23
+ this.enableTestMode = false;
24
+ this.mode = mode;
25
+ this.enableTestMode = enableTestMode;
26
+ this.iframe = iframe;
27
+ const url = new URL(iframeUrl);
28
+ this.expectedOrigin = `${url.protocol}//${url.host}`;
29
+ this.currentValidationState = {
30
+ isValid: false,
31
+ cardNumber: { isValid: false, isEmpty: true },
32
+ cvv: { isValid: false, isEmpty: true },
33
+ expiry: { isValid: false, isEmpty: true },
34
+ };
35
+ }
36
+ static create(gateway, container, config) {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ var _a;
39
+ if (container.mode === 'bank_account' && container.bankCountry === 'CA') {
40
+ throw new Error('CardConnect does not support Canadian bank accounts');
41
+ }
42
+ let baseUrl = ((_a = gateway.config) === null || _a === void 0 ? void 0 : _a.base_url) || config.clientConfig.cardConnectBaseUrl;
43
+ config.cardConnectBaseUrl = baseUrl;
44
+ const mergedStyles = mergeStyles(DEFAULT_UNIFIED_STYLES, container.styling);
45
+ const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, container);
46
+ const iframe = CardConnectTokenizer.createIframe(iframeUrl, mergedStyles);
47
+ const tokenizer = new CardConnectTokenizer(iframe, iframeUrl, container.containerId, container.mode || 'credit_card', container.enableTestMode || false, container.layout || 'single-line');
48
+ tokenizer.createInternalElements(container);
49
+ yield tokenizer.init();
50
+ return tokenizer;
51
+ });
52
+ }
53
+ createInternalElements(container) {
54
+ const containerEl = document.getElementById(container.containerId);
55
+ if (!containerEl) {
56
+ throw new Error(`Container element not found: ${container.containerId}`);
57
+ }
58
+ this.containerEl = containerEl;
59
+ containerEl.innerHTML = '';
60
+ const mergedStyles = getContainerStylesForLayout(mergeStyles(DEFAULT_UNIFIED_STYLES, container.styling), this.layout);
61
+ Object.assign(containerEl.style, mergedStyles.container);
62
+ if (this.mode === 'bank_account') {
63
+ this.createBankAccountFields(containerEl, mergedStyles);
64
+ }
65
+ else {
66
+ this.createCreditCardFields(containerEl, mergedStyles);
67
+ }
68
+ }
69
+ createCreditCardFields(containerEl, mergedStyles) {
70
+ this.iframe.style.width = '100%';
71
+ if (this.layout === 'two-line') {
72
+ const inputHeight = mergedStyles.input.height || '40px';
73
+ this.iframe.style.height = `calc((${inputHeight}) * 2 + 10px)`;
74
+ }
75
+ else {
76
+ this.iframe.style.height = mergedStyles.input.height || '40px';
77
+ }
78
+ this.iframe.style.border = 'none';
79
+ this.iframe.style.display = 'block';
80
+ containerEl.appendChild(this.iframe);
81
+ }
82
+ createBankAccountFields(containerEl, mergedStyles) {
83
+ this.iframe.style.display = 'none';
84
+ if (this.layout === 'two-line') {
85
+ this.accountTypeEl = createAccountTypeSelect(`${this.containerId}-account-type`);
86
+ Object.assign(this.accountTypeEl.style, {
87
+ flex: '1',
88
+ minWidth: BANK_FIELD_FLEX.accountType.minWidth,
89
+ });
90
+ this.applyInputStyles(this.accountTypeEl, mergedStyles, 'left');
91
+ containerEl.appendChild(this.accountTypeEl);
92
+ this.routingNumberEl = createInputElement(`${this.containerId}-routing`, 'text', 'Routing *', 9);
93
+ Object.assign(this.routingNumberEl.style, {
94
+ flex: '1',
95
+ minWidth: BANK_FIELD_FLEX.routingNumber.minWidth,
96
+ });
97
+ this.applyInputStyles(this.routingNumberEl, mergedStyles, 'right');
98
+ containerEl.appendChild(this.routingNumberEl);
99
+ this.accountNumberEl = createInputElement(`${this.containerId}-account`, 'text', 'Account Number *', 17);
100
+ Object.assign(this.accountNumberEl.style, {
101
+ flex: '1',
102
+ flexBasis: '100%',
103
+ minWidth: BANK_FIELD_FLEX.accountNumber.minWidth,
104
+ });
105
+ this.applyInputStyles(this.accountNumberEl, mergedStyles);
106
+ containerEl.appendChild(this.accountNumberEl);
107
+ }
108
+ else {
109
+ this.routingNumberEl = createInputElement(`${this.containerId}-routing`, 'text', 'Routing *', 9);
110
+ Object.assign(this.routingNumberEl.style, {
111
+ flex: BANK_FIELD_FLEX.routingNumber.flex,
112
+ minWidth: BANK_FIELD_FLEX.routingNumber.minWidth,
113
+ });
114
+ this.applyInputStyles(this.routingNumberEl, mergedStyles, 'left');
115
+ containerEl.appendChild(this.routingNumberEl);
116
+ this.accountNumberEl = createInputElement(`${this.containerId}-account`, 'text', 'Account Number *', 17);
117
+ Object.assign(this.accountNumberEl.style, {
118
+ flex: BANK_FIELD_FLEX.accountNumber.flex,
119
+ minWidth: BANK_FIELD_FLEX.accountNumber.minWidth,
120
+ });
121
+ this.applyInputStyles(this.accountNumberEl, mergedStyles, 'middle');
122
+ containerEl.appendChild(this.accountNumberEl);
123
+ this.accountTypeEl = createAccountTypeSelect(`${this.containerId}-account-type`);
124
+ Object.assign(this.accountTypeEl.style, {
125
+ flex: BANK_FIELD_FLEX.accountType.flex,
126
+ minWidth: BANK_FIELD_FLEX.accountType.minWidth,
127
+ });
128
+ this.applyInputStyles(this.accountTypeEl, mergedStyles, 'right');
129
+ containerEl.appendChild(this.accountTypeEl);
130
+ }
131
+ }
132
+ init() {
133
+ return __awaiter(this, void 0, void 0, function* () {
134
+ if (this.mode === 'bank_account') {
135
+ this.isReady = true;
136
+ if (this.enableTestMode) {
137
+ setTimeout(() => {
138
+ if (this.routingNumberEl) {
139
+ this.routingNumberEl.value = '021000021';
140
+ this.routingNumberEl.dispatchEvent(new Event('input', { bubbles: true }));
141
+ }
142
+ if (this.accountNumberEl) {
143
+ this.accountNumberEl.value = '9876543210';
144
+ this.accountNumberEl.dispatchEvent(new Event('input', { bubbles: true }));
145
+ }
146
+ if (this.accountTypeEl) {
147
+ this.accountTypeEl.value = 'checking';
148
+ this.accountTypeEl.dispatchEvent(new Event('change', { bubbles: true }));
149
+ }
150
+ }, 100);
151
+ }
152
+ this.emit('ready');
153
+ return Promise.resolve();
154
+ }
155
+ return new Promise((resolve, reject) => {
156
+ const timeout = setTimeout(() => {
157
+ reject(new Error('CardConnect initialization timeout'));
158
+ }, INIT_TIMEOUT);
159
+ this.messageHandler = (event) => {
160
+ if (event.origin !== this.expectedOrigin) {
161
+ return;
162
+ }
163
+ this.handleMessage(event);
164
+ };
165
+ window.addEventListener('message', this.messageHandler);
166
+ this.iframe.onload = () => {
167
+ clearTimeout(timeout);
168
+ this.isReady = true;
169
+ if (this.enableTestMode && this.mode === 'credit_card') {
170
+ }
171
+ this.emit('ready');
172
+ resolve();
173
+ };
174
+ this.iframe.onerror = () => {
175
+ clearTimeout(timeout);
176
+ reject(new Error('Failed to load CardConnect iframe'));
177
+ };
178
+ });
179
+ });
180
+ }
181
+ tokenize(paymentData) {
182
+ return __awaiter(this, void 0, void 0, function* () {
183
+ if (!this.isReady) {
184
+ throw new Error('Tokenizer not initialized');
185
+ }
186
+ if (this.mode === 'credit_card' && this.hasToken()) {
187
+ const cachedToken = this.getToken();
188
+ if (cachedToken) {
189
+ return cachedToken;
190
+ }
191
+ }
192
+ if (this.mode === 'bank_account' || this.isBankAccountData(paymentData)) {
193
+ return this.tokenizeBankAccountInternal(paymentData);
194
+ }
195
+ else {
196
+ return this.tokenizeCardInternal(paymentData);
197
+ }
198
+ });
199
+ }
200
+ tokenizeCardInternal(cardData) {
201
+ return __awaiter(this, void 0, void 0, function* () {
202
+ if (this.cachedTokenResult && this.cachedTokenResult.errorCode === '0') {
203
+ return {
204
+ token: this.cachedTokenResult.token,
205
+ lastFour: this.cachedTokenResult.token.slice(-4),
206
+ cardType: this.normalizeCardType('unknown'),
207
+ provider: 'cardconnect',
208
+ };
209
+ }
210
+ if (this.tokenizationPromise) {
211
+ return this.tokenizationPromise;
212
+ }
213
+ this.tokenizationPromise = new Promise((resolve, reject) => {
214
+ this.tokenizationResolve = resolve;
215
+ this.tokenizationReject = reject;
216
+ const timeout = setTimeout(() => {
217
+ this.tokenizationPromise = undefined;
218
+ this.tokenizationResolve = undefined;
219
+ this.tokenizationReject = undefined;
220
+ reject(new TokenizationError('Tokenization timeout - ensure all card fields are filled in iframe', 'TIMEOUT'));
221
+ }, TOKENIZE_TIMEOUT);
222
+ const tokenizationHandler = (data) => {
223
+ clearTimeout(timeout);
224
+ this.off('tokenization', tokenizationHandler);
225
+ };
226
+ this.on('tokenization', tokenizationHandler);
227
+ });
228
+ return this.tokenizationPromise;
229
+ });
230
+ }
231
+ tokenizeBankAccountInternal(bankData) {
232
+ return __awaiter(this, void 0, void 0, function* () {
233
+ var _a, _b, _c;
234
+ const routingNumber = (_a = this.routingNumberEl) === null || _a === void 0 ? void 0 : _a.value;
235
+ const accountNumber = (_b = this.accountNumberEl) === null || _b === void 0 ? void 0 : _b.value;
236
+ const accountType = ((_c = this.accountTypeEl) === null || _c === void 0 ? void 0 : _c.value) || 'checking';
237
+ const accountHolderType = 'personal';
238
+ if (!routingNumber || !accountNumber) {
239
+ throw new TokenizationError('Routing number and account number are required', 'VALIDATION_ERROR');
240
+ }
241
+ if (!validateRoutingNumber(routingNumber)) {
242
+ throw new TokenizationError('Invalid routing number', 'VALIDATION_ERROR');
243
+ }
244
+ if (!validateAccountNumber(accountNumber)) {
245
+ throw new TokenizationError('Invalid account number', 'VALIDATION_ERROR');
246
+ }
247
+ const baseUrl = new URL(this.iframeUrl).origin;
248
+ const config = new ConfigHandler({});
249
+ config.cardConnectBaseUrl = baseUrl;
250
+ const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, config);
251
+ return {
252
+ token: result.token,
253
+ lastFour: accountNumber.slice(-4),
254
+ accountType: accountType,
255
+ paymentMethodType: 'bank_account',
256
+ provider: 'cardconnect',
257
+ };
258
+ });
259
+ }
260
+ validate() {
261
+ return __awaiter(this, void 0, void 0, function* () {
262
+ if (!this.isReady) {
263
+ throw new Error('Tokenizer not initialized');
264
+ }
265
+ if (this.mode === 'bank_account') {
266
+ return this.validateBankAccountInternal();
267
+ }
268
+ else {
269
+ return this.validateCardInternal();
270
+ }
271
+ });
272
+ }
273
+ validateCardInternal() {
274
+ return __awaiter(this, void 0, void 0, function* () {
275
+ const errors = [];
276
+ if (this.currentValidationState.cardNumber) {
277
+ if (this.currentValidationState.cardNumber.isEmpty) {
278
+ errors.push({
279
+ field: 'cardNumber',
280
+ message: 'Card number is required',
281
+ });
282
+ }
283
+ else if (!this.currentValidationState.cardNumber.isValid) {
284
+ errors.push({
285
+ field: 'cardNumber',
286
+ message: 'Invalid card number',
287
+ });
288
+ }
289
+ }
290
+ else {
291
+ errors.push({
292
+ field: 'cardNumber',
293
+ message: 'Card number is required',
294
+ });
295
+ }
296
+ if (this.currentValidationState.expiry) {
297
+ if (this.currentValidationState.expiry.isEmpty) {
298
+ errors.push({
299
+ field: 'expiry',
300
+ message: 'Expiry date is required',
301
+ });
302
+ }
303
+ else if (!this.currentValidationState.expiry.isValid) {
304
+ errors.push({
305
+ field: 'expiry',
306
+ message: 'Invalid expiry date',
307
+ });
308
+ }
309
+ }
310
+ else {
311
+ errors.push({
312
+ field: 'expiry',
313
+ message: 'Expiry date is required',
314
+ });
315
+ }
316
+ if (this.currentValidationState.cvv) {
317
+ if (this.currentValidationState.cvv.isEmpty) {
318
+ errors.push({
319
+ field: 'cvv',
320
+ message: 'CVV is required',
321
+ });
322
+ }
323
+ else if (!this.currentValidationState.cvv.isValid) {
324
+ errors.push({
325
+ field: 'cvv',
326
+ message: 'Invalid CVV',
327
+ });
328
+ }
329
+ }
330
+ else {
331
+ errors.push({
332
+ field: 'cvv',
333
+ message: 'CVV is required',
334
+ });
335
+ }
336
+ return {
337
+ isValid: this.currentValidationState.isValid,
338
+ errors,
339
+ };
340
+ });
341
+ }
342
+ validateBankAccountInternal() {
343
+ return __awaiter(this, void 0, void 0, function* () {
344
+ var _a, _b;
345
+ const errors = [];
346
+ if (!((_a = this.routingNumberEl) === null || _a === void 0 ? void 0 : _a.value)) {
347
+ errors.push({
348
+ field: 'routingNumber',
349
+ message: 'Routing number is required',
350
+ });
351
+ }
352
+ else if (!validateRoutingNumber(this.routingNumberEl.value)) {
353
+ errors.push({
354
+ field: 'routingNumber',
355
+ message: 'Invalid routing number',
356
+ });
357
+ }
358
+ if (!((_b = this.accountNumberEl) === null || _b === void 0 ? void 0 : _b.value)) {
359
+ errors.push({
360
+ field: 'accountNumber',
361
+ message: 'Account number is required',
362
+ });
363
+ }
364
+ else if (!validateAccountNumber(this.accountNumberEl.value)) {
365
+ errors.push({
366
+ field: 'accountNumber',
367
+ message: 'Invalid account number',
368
+ });
369
+ }
370
+ return {
371
+ isValid: errors.length === 0,
372
+ errors,
373
+ };
374
+ });
375
+ }
376
+ clear() {
377
+ var _a;
378
+ if (this.mode === 'bank_account') {
379
+ if (this.routingNumberEl) {
380
+ this.routingNumberEl.value = '';
381
+ }
382
+ if (this.accountNumberEl) {
383
+ this.accountNumberEl.value = '';
384
+ }
385
+ if (this.accountTypeEl) {
386
+ this.accountTypeEl.value = 'checking';
387
+ }
388
+ }
389
+ else {
390
+ (_a = this.iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage({
391
+ action: 'clear',
392
+ }, this.expectedOrigin);
393
+ }
394
+ this.currentValidationState = {
395
+ isValid: false,
396
+ cardNumber: { isValid: false, isEmpty: true },
397
+ cvv: { isValid: false, isEmpty: true },
398
+ expiry: { isValid: false, isEmpty: true },
399
+ };
400
+ this.emit('validation', this.currentValidationState);
401
+ }
402
+ focus(field) {
403
+ var _a;
404
+ if (this.mode === 'bank_account') {
405
+ if (field === 'routingNumber' && this.routingNumberEl) {
406
+ this.routingNumberEl.focus();
407
+ }
408
+ else if (field === 'accountNumber' && this.accountNumberEl) {
409
+ this.accountNumberEl.focus();
410
+ }
411
+ }
412
+ else {
413
+ const fieldMap = {
414
+ cardNumber: 'number',
415
+ cvv: 'cvv',
416
+ expiry: 'expiry',
417
+ };
418
+ const iframeField = fieldMap[field];
419
+ if (iframeField) {
420
+ (_a = this.iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage({
421
+ action: 'focus',
422
+ field: iframeField,
423
+ }, this.expectedOrigin);
424
+ }
425
+ }
426
+ }
427
+ destroy() {
428
+ if (this.messageHandler) {
429
+ window.removeEventListener('message', this.messageHandler);
430
+ }
431
+ if (this.containerEl) {
432
+ this.containerEl.innerHTML = '';
433
+ }
434
+ this.eventHandlers.clear();
435
+ }
436
+ hasToken() {
437
+ var _a, _b;
438
+ if (this.mode === 'credit_card') {
439
+ return (((_a = this.cachedTokenResult) === null || _a === void 0 ? void 0 : _a.errorCode) === '0' &&
440
+ !!((_b = this.cachedTokenResult) === null || _b === void 0 ? void 0 : _b.token));
441
+ }
442
+ return false;
443
+ }
444
+ getToken() {
445
+ var _a;
446
+ if (this.mode === 'credit_card' &&
447
+ ((_a = this.cachedTokenResult) === null || _a === void 0 ? void 0 : _a.errorCode) === '0') {
448
+ return {
449
+ token: this.cachedTokenResult.token,
450
+ lastFour: this.cachedTokenResult.token.slice(-4),
451
+ cardType: this.normalizeCardType('unknown'),
452
+ provider: 'cardconnect',
453
+ };
454
+ }
455
+ return null;
456
+ }
457
+ get tokenizationMode() {
458
+ return this.mode === 'credit_card' ? 'auto' : 'manual';
459
+ }
460
+ handleMessage(event) {
461
+ try {
462
+ const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
463
+ if (data.token && data.errorCode !== undefined) {
464
+ this.cachedTokenResult = data;
465
+ this.emit('tokenization', data);
466
+ if (data.errorCode === '0') {
467
+ const token = {
468
+ token: data.token,
469
+ lastFour: data.token.slice(-4),
470
+ cardType: this.normalizeCardType('unknown'),
471
+ provider: 'cardconnect',
472
+ };
473
+ if (this.tokenizationResolve) {
474
+ this.tokenizationResolve(token);
475
+ this.tokenizationPromise = undefined;
476
+ this.tokenizationResolve = undefined;
477
+ this.tokenizationReject = undefined;
478
+ }
479
+ this.currentValidationState = {
480
+ isValid: true,
481
+ cardNumber: { isValid: true, isEmpty: false },
482
+ cvv: { isValid: true, isEmpty: false },
483
+ expiry: { isValid: true, isEmpty: false },
484
+ };
485
+ this.emit('validation', { isValid: true });
486
+ this.emit('tokenReady', token);
487
+ }
488
+ else {
489
+ if (this.tokenizationReject) {
490
+ this.tokenizationReject(new TokenizationError(data.errorMessage || 'Tokenization failed', data.errorCode || 'UNKNOWN'));
491
+ this.tokenizationPromise = undefined;
492
+ this.tokenizationResolve = undefined;
493
+ this.tokenizationReject = undefined;
494
+ }
495
+ }
496
+ }
497
+ if (data.event === 'validation' || data.validationError !== undefined) {
498
+ this.handleValidationMessage(data);
499
+ }
500
+ if (data.event === 'focus' || data.event === 'blur') {
501
+ this.emit(data.event, { field: data.data });
502
+ }
503
+ if (data.event === 'input' || data.event === 'change') {
504
+ this.emit('change', { field: data.data });
505
+ }
506
+ }
507
+ catch (error) {
508
+ }
509
+ }
510
+ handleValidationMessage(data) {
511
+ var _a, _b, _c, _d, _e, _f;
512
+ if (data.validationError) {
513
+ const errorLower = data.validationError.toLowerCase();
514
+ if (errorLower.includes('card') || errorLower.includes('number')) {
515
+ this.currentValidationState.cardNumber = {
516
+ isValid: false,
517
+ isEmpty: false,
518
+ };
519
+ }
520
+ else if (errorLower.includes('cvv') ||
521
+ errorLower.includes('security')) {
522
+ this.currentValidationState.cvv = { isValid: false, isEmpty: false };
523
+ }
524
+ else if (errorLower.includes('expir') ||
525
+ errorLower.includes('month') ||
526
+ errorLower.includes('year')) {
527
+ this.currentValidationState.expiry = { isValid: false, isEmpty: false };
528
+ }
529
+ this.emit('error', new TokenizationError(data.validationError));
530
+ }
531
+ this.currentValidationState.isValid =
532
+ ((_b = (_a = this.currentValidationState.cardNumber) === null || _a === void 0 ? void 0 : _a.isValid) !== null && _b !== void 0 ? _b : false) &&
533
+ ((_d = (_c = this.currentValidationState.cvv) === null || _c === void 0 ? void 0 : _c.isValid) !== null && _d !== void 0 ? _d : false) &&
534
+ ((_f = (_e = this.currentValidationState.expiry) === null || _e === void 0 ? void 0 : _e.isValid) !== null && _f !== void 0 ? _f : false);
535
+ }
536
+ static generateIframeUrl(baseUrl, container) {
537
+ const params = new URLSearchParams({
538
+ invalidinputevent: 'true',
539
+ enhancedresponse: 'true',
540
+ useexpiry: 'true',
541
+ usecvv: 'true',
542
+ formatinput: 'true',
543
+ unique: 'true',
544
+ norsa: 'true',
545
+ placeholder: 'Card Number *',
546
+ placeholdercvv: 'CVV',
547
+ invalidcreditcardevent: 'true',
548
+ invalidexpiry: 'true',
549
+ invalidcvv: 'true',
550
+ });
551
+ if (container.layout === 'two-line') {
552
+ params.set('useexpiryfield', 'true');
553
+ params.set('orientation', 'horizontal');
554
+ params.set('placeholdermonth', 'MM');
555
+ params.set('placeholderyear', 'YYYY');
556
+ }
557
+ else {
558
+ params.set('orientation', 'horizontal');
559
+ params.set('placeholdermonth', 'MM');
560
+ params.set('placeholderyear', 'YYYY');
561
+ }
562
+ const mergedStyles = mergeStyles(DEFAULT_UNIFIED_STYLES, container.styling);
563
+ const cssString = CardConnectTokenizer.generateCardConnectCss(mergedStyles, container.layout || 'single-line');
564
+ const queryPairs = [];
565
+ params.forEach((value, key) => {
566
+ queryPairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
567
+ });
568
+ queryPairs.push(`css=${cssString}`);
569
+ const tokenizerPath = '/itoke/ajax-tokenizer.html';
570
+ return `${baseUrl}${tokenizerPath}?${queryPairs.join('&')}`;
571
+ }
572
+ static createIframe(url, styles) {
573
+ const iframe = document.createElement('iframe');
574
+ iframe.src = url;
575
+ iframe.style.width = '100%';
576
+ iframe.style.height = styles.input.height;
577
+ iframe.style.border = 'none';
578
+ iframe.style.overflow = 'hidden';
579
+ iframe.style.display = 'block';
580
+ iframe.style.minWidth = '0';
581
+ if (styles.container) {
582
+ Object.entries(styles.container).forEach(([key, value]) => {
583
+ if (key !== 'height' && key !== 'width') {
584
+ iframe.style[key] = value;
585
+ }
586
+ });
587
+ if (styles.container.width) {
588
+ iframe.style.width = styles.container.width;
589
+ }
590
+ }
591
+ iframe.setAttribute('scrolling', 'no');
592
+ iframe.setAttribute('title', 'Secure card input');
593
+ iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms');
594
+ return iframe;
595
+ }
596
+ static generateCardConnectCss(styles, layout = 'single-line') {
597
+ var _a, _b, _c;
598
+ const css = [];
599
+ if (layout === 'two-line') {
600
+ css.push('html,form,body{margin:0;padding:0;}');
601
+ css.push('label{display:none;}');
602
+ css.push('br{display:none;}');
603
+ }
604
+ else {
605
+ css.push('body{margin:0;padding:0;display:flex;align-items:center;}');
606
+ css.push('form{margin:0;padding:0;display:flex;width:100%;align-items:center;}');
607
+ css.push('label{display:none;}');
608
+ css.push('br{display:none;}');
609
+ }
610
+ const isConnected = styles.container.gap === '0';
611
+ const gap = isConnected ? '0' : styles.container.gap || '1rem';
612
+ if (styles.input) {
613
+ const commonStyles = [];
614
+ if (styles.input.height)
615
+ commonStyles.push(`height:${styles.input.height}`);
616
+ if (styles.input.padding)
617
+ commonStyles.push(`padding:${styles.input.padding}`);
618
+ if (styles.input.fontSize)
619
+ commonStyles.push(`font-size:${styles.input.fontSize}`);
620
+ if (styles.input.fontFamily)
621
+ commonStyles.push(`font-family:${styles.input.fontFamily}`);
622
+ if (styles.input.border)
623
+ commonStyles.push(`border:${styles.input.border}`);
624
+ if (styles.input.backgroundColor)
625
+ commonStyles.push(`background-color:${styles.input.backgroundColor}`);
626
+ if (styles.input.color)
627
+ commonStyles.push(`color:${styles.input.color}`);
628
+ commonStyles.push('box-sizing:border-box');
629
+ const baseStyles = commonStyles.join(';');
630
+ css.push(`input{${baseStyles};}`);
631
+ css.push(`select{${baseStyles};}`);
632
+ }
633
+ if (layout === 'two-line') {
634
+ css.push('input#ccnumfield{width:100%;display:block;margin-bottom:8px;}');
635
+ css.push('input#ccexpiryfieldmonth{width:20%;}');
636
+ css.push('input#ccexpiryfieldyear{width:24%;}');
637
+ css.push('input#cccvvfield{width:calc(56% - 20px);}');
638
+ if ((_a = styles.input) === null || _a === void 0 ? void 0 : _a.borderRadius) {
639
+ css.push(`input{border-radius:${styles.input.borderRadius};}`);
640
+ }
641
+ }
642
+ else if (isConnected) {
643
+ css.push('input#ccnumfield{width:60%;margin:0;}');
644
+ css.push('select#ccexpirymonth{width:10%;margin:0;margin-right:-12px;}');
645
+ css.push('select#ccexpiryyear{width:10%;}');
646
+ css.push('input#cccvvfield{width:20%;margin:0;margin-left:-12px;}');
647
+ if ((_b = styles.input) === null || _b === void 0 ? void 0 : _b.borderRadius) {
648
+ css.push(`input#ccnumfield{border-radius:${styles.input.borderRadius} 0 0 ${styles.input.borderRadius};border-right:none;}`);
649
+ css.push('select#ccexpirymonth{border-radius:0;border-right:none;}');
650
+ css.push('select#ccexpiryyear{border-radius:0;border-right:none;}');
651
+ css.push(`input#cccvvfield{border-radius:0 ${styles.input.borderRadius} ${styles.input.borderRadius} 0;}`);
652
+ }
653
+ else {
654
+ css.push('input#ccnumfield{border-right:none;}');
655
+ css.push('select#ccexpirymonth{border-right:none;}');
656
+ css.push('select#ccexpiryyear{border-right:none;}');
657
+ }
658
+ }
659
+ else {
660
+ const marginRight = gap === '0' ? '0' : '8px';
661
+ css.push(`input#ccnumfield{width:60%;margin-right:${marginRight};}`);
662
+ css.push(`select#ccexpirymonth{width:10%;margin-right:${marginRight};}`);
663
+ css.push(`select#ccexpiryyear{width:10%;margin-right:${marginRight};}`);
664
+ css.push('input#cccvvfield{width:20%;}');
665
+ if ((_c = styles.input) === null || _c === void 0 ? void 0 : _c.borderRadius) {
666
+ css.push(`input,select{border-radius:${styles.input.borderRadius};}`);
667
+ }
668
+ }
669
+ if (styles.focus) {
670
+ const focusStyles = [];
671
+ if (styles.focus.borderColor)
672
+ focusStyles.push(`border-color:${styles.focus.borderColor}`);
673
+ if (styles.focus.outline) {
674
+ focusStyles.push(`outline:none`);
675
+ }
676
+ if (styles.focus.boxShadow)
677
+ focusStyles.push(`box-shadow:${styles.focus.boxShadow}`);
678
+ if (focusStyles.length > 0) {
679
+ css.push(`input:focus{${focusStyles.join(';')};}`);
680
+ }
681
+ }
682
+ if (styles.error) {
683
+ const errorStyles = [];
684
+ if (styles.error.borderColor)
685
+ errorStyles.push(`border-color:${styles.error.borderColor}`);
686
+ if (styles.error.backgroundColor)
687
+ errorStyles.push(`background-color:${styles.error.backgroundColor}`);
688
+ if (errorStyles.length > 0) {
689
+ css.push(`.error{${errorStyles.join(';')};}`);
690
+ }
691
+ }
692
+ return encodeURIComponent(css.join(''));
693
+ }
694
+ static tokenizeBankAccount(routingNumber, accountNumber, config) {
695
+ return fetch(`${config.cardConnectBaseUrl}/cardsecure/api/v1/ccn/tokenize`, {
696
+ method: 'POST',
697
+ headers: {
698
+ 'Content-Type': 'application/json',
699
+ },
700
+ body: JSON.stringify({
701
+ account: `${routingNumber}/${accountNumber}`,
702
+ unique: true,
703
+ }),
704
+ }).then((response) => response.json());
705
+ }
706
+ }