@idonatedev/idonate-sdk 1.0.16 → 1.1.0-dev1

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