@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
package/dist/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CLIENT_HEADERS = exports.CARD_CONNECT_DEFAULT_STYLE = exports.DEFAULT_APP_NAME = exports.DEFAULT_CF_TURNSTILE_CDN_EXPLICIT_URL = exports.FALLBACK_CF_TURNSTILE_SITE_KEY = exports.FALLBACK_PC_SCRIPT_ID = exports.FALLBACK_PC_SCRIPT_URL = exports.SANDBOX_APPLE_PAY_URL = exports.APPLE_PAY_URL = exports.SPREEDLY_TOKENIZER_URL = exports.SANDBOX_CARD_CONNECT_BASE_URL = exports.PRODUCTION_CARD_CONNECT_BASE_URL = exports.SANDBOX_BASE_URL = exports.PRODUCTION_BASE_URL = exports.SDK_VERSION = void 0;
|
|
4
|
-
exports.SDK_VERSION = '1.2.0-
|
|
4
|
+
exports.SDK_VERSION = '1.2.0-dev16';
|
|
5
5
|
exports.PRODUCTION_BASE_URL = 'https://secure-api.idonate.com';
|
|
6
6
|
exports.SANDBOX_BASE_URL = 'https://api.qa-idonate.com';
|
|
7
7
|
exports.PRODUCTION_CARD_CONNECT_BASE_URL = 'https://boltgw.cardconnect.com:8443';
|
package/dist/esm/constants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const SDK_VERSION = '1.2.0-
|
|
1
|
+
export const SDK_VERSION = '1.2.0-dev16';
|
|
2
2
|
export const PRODUCTION_BASE_URL = 'https://secure-api.idonate.com';
|
|
3
3
|
export const SANDBOX_BASE_URL = 'https://api.qa-idonate.com';
|
|
4
4
|
export const PRODUCTION_CARD_CONNECT_BASE_URL = 'https://boltgw.cardconnect.com:8443';
|
|
@@ -16,10 +16,13 @@ export declare class CardConnectTokenizer extends Tokenizer {
|
|
|
16
16
|
private accountTypeEl?;
|
|
17
17
|
private enableTestMode;
|
|
18
18
|
private cachedTokenResult?;
|
|
19
|
+
private acceptAutoToken;
|
|
19
20
|
private tokenizationPromise?;
|
|
20
21
|
private tokenizationResolve?;
|
|
21
22
|
private tokenizationReject?;
|
|
22
23
|
private currentCardType?;
|
|
24
|
+
private tokenizationTimeout?;
|
|
25
|
+
private mergedStyles?;
|
|
23
26
|
private constructor();
|
|
24
27
|
static create(gateway: PaymentGateway, container: TokenizerContainer, config: {
|
|
25
28
|
organizationId: string;
|
|
@@ -29,6 +32,8 @@ export declare class CardConnectTokenizer extends Tokenizer {
|
|
|
29
32
|
private createInternalElements;
|
|
30
33
|
private createCreditCardFields;
|
|
31
34
|
private createBankAccountFields;
|
|
35
|
+
private addBankAccountValidationListeners;
|
|
36
|
+
private updateBankAccountValidation;
|
|
32
37
|
private init;
|
|
33
38
|
tokenize(paymentData: PaymentData): Promise<PaymentToken>;
|
|
34
39
|
private tokenizeCardInternal;
|
|
@@ -47,5 +52,5 @@ export declare class CardConnectTokenizer extends Tokenizer {
|
|
|
47
52
|
private static generateIframeUrl;
|
|
48
53
|
private static createIframe;
|
|
49
54
|
private static generateCardConnectCss;
|
|
50
|
-
static tokenizeBankAccount(routingNumber: string, accountNumber: string,
|
|
55
|
+
static tokenizeBankAccount(routingNumber: string, accountNumber: string, configOrBaseUrl: ConfigHandler | string): Promise<TokenizeCardConnectBankAccountResult>;
|
|
51
56
|
}
|
|
@@ -9,7 +9,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { Tokenizer } from './Tokenizer';
|
|
11
11
|
import { TokenizationError, } from './types';
|
|
12
|
-
import ConfigHandler from '../config-handler';
|
|
13
12
|
import { DEFAULT_UNIFIED_STYLES, mergeStyles, getContainerStylesForLayout, } from './styles';
|
|
14
13
|
import { INIT_TIMEOUT, TOKENIZE_TIMEOUT, BANK_FIELD_FLEX, RESPONSIVE_BREAKPOINT, } from './tokenizer-constants';
|
|
15
14
|
import { createInputElement, validateRoutingNumber, validateAccountNumber, createAccountTypeSelect, } from './tokenizer-utils';
|
|
@@ -20,6 +19,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
20
19
|
this.containerId = containerId;
|
|
21
20
|
this.layout = layout;
|
|
22
21
|
this.enableTestMode = false;
|
|
22
|
+
this.acceptAutoToken = true;
|
|
23
23
|
this.mode = mode;
|
|
24
24
|
this.enableTestMode = enableTestMode;
|
|
25
25
|
this.iframe = iframe;
|
|
@@ -34,7 +34,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
34
34
|
}
|
|
35
35
|
static create(gateway, container, config) {
|
|
36
36
|
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
var _a;
|
|
37
|
+
var _a, _b;
|
|
38
38
|
if (container.mode === 'bank_account' && container.bankCountry === 'CA') {
|
|
39
39
|
throw new Error('CardConnect does not support Canadian bank accounts');
|
|
40
40
|
}
|
|
@@ -42,7 +42,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
42
42
|
if (container.layout === 'responsive') {
|
|
43
43
|
const containerEl = document.getElementById(container.containerId);
|
|
44
44
|
const containerWidth = (containerEl === null || containerEl === void 0 ? void 0 : containerEl.offsetWidth) || 0;
|
|
45
|
-
const breakpoint = container.responsiveBreakpoint
|
|
45
|
+
const breakpoint = (_a = container.responsiveBreakpoint) !== null && _a !== void 0 ? _a : RESPONSIVE_BREAKPOINT;
|
|
46
46
|
effectiveLayout =
|
|
47
47
|
containerWidth < breakpoint ? 'two-line' : 'single-line';
|
|
48
48
|
}
|
|
@@ -50,8 +50,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
50
50
|
effectiveLayout = 'two-line';
|
|
51
51
|
}
|
|
52
52
|
const resolvedContainer = Object.assign(Object.assign({}, container), { layout: effectiveLayout });
|
|
53
|
-
|
|
54
|
-
config.cardConnectBaseUrl = baseUrl;
|
|
53
|
+
const baseUrl = ((_b = gateway.config) === null || _b === void 0 ? void 0 : _b.baseUrl) || config.clientConfig.cardConnectBaseUrl;
|
|
55
54
|
const mergedStyles = mergeStyles(DEFAULT_UNIFIED_STYLES, container.styling);
|
|
56
55
|
const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, resolvedContainer);
|
|
57
56
|
const iframe = CardConnectTokenizer.createIframe(iframeUrl, mergedStyles);
|
|
@@ -139,6 +138,66 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
139
138
|
this.applyInputStyles(this.accountTypeEl, mergedStyles, 'right');
|
|
140
139
|
containerEl.appendChild(this.accountTypeEl);
|
|
141
140
|
}
|
|
141
|
+
this.mergedStyles = mergedStyles;
|
|
142
|
+
this.currentValidationState = {
|
|
143
|
+
isValid: false,
|
|
144
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
145
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
146
|
+
};
|
|
147
|
+
this.addBankAccountValidationListeners(mergedStyles);
|
|
148
|
+
}
|
|
149
|
+
addBankAccountValidationListeners(styles) {
|
|
150
|
+
if (this.routingNumberEl) {
|
|
151
|
+
this.routingNumberEl.addEventListener('blur', () => {
|
|
152
|
+
this.updateBankAccountValidation(styles);
|
|
153
|
+
});
|
|
154
|
+
this.routingNumberEl.addEventListener('input', () => {
|
|
155
|
+
this.updateBankAccountValidation(styles);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (this.accountNumberEl) {
|
|
159
|
+
this.accountNumberEl.addEventListener('blur', () => {
|
|
160
|
+
this.updateBankAccountValidation(styles);
|
|
161
|
+
});
|
|
162
|
+
this.accountNumberEl.addEventListener('input', () => {
|
|
163
|
+
this.updateBankAccountValidation(styles);
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
updateBankAccountValidation(styles) {
|
|
168
|
+
var _a, _b;
|
|
169
|
+
const routingValue = ((_a = this.routingNumberEl) === null || _a === void 0 ? void 0 : _a.value) || '';
|
|
170
|
+
const accountValue = ((_b = this.accountNumberEl) === null || _b === void 0 ? void 0 : _b.value) || '';
|
|
171
|
+
const routingValid = routingValue.length > 0 && validateRoutingNumber(routingValue);
|
|
172
|
+
const accountValid = accountValue.length > 0 && validateAccountNumber(accountValue);
|
|
173
|
+
if (this.routingNumberEl) {
|
|
174
|
+
if (routingValue.length > 0 && !routingValid) {
|
|
175
|
+
this.routingNumberEl.style.borderColor = styles.error.borderColor;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
this.routingNumberEl.style.borderColor = '';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (this.accountNumberEl) {
|
|
182
|
+
if (accountValue.length > 0 && !accountValid) {
|
|
183
|
+
this.accountNumberEl.style.borderColor = styles.error.borderColor;
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
this.accountNumberEl.style.borderColor = '';
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
this.currentValidationState = {
|
|
190
|
+
isValid: routingValid && accountValid,
|
|
191
|
+
routingNumber: {
|
|
192
|
+
isValid: routingValid,
|
|
193
|
+
isEmpty: routingValue.length === 0,
|
|
194
|
+
},
|
|
195
|
+
accountNumber: {
|
|
196
|
+
isValid: accountValid,
|
|
197
|
+
isEmpty: accountValue.length === 0,
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
this.emit('validation', this.currentValidationState);
|
|
142
201
|
}
|
|
143
202
|
init() {
|
|
144
203
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -208,31 +267,39 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
208
267
|
}
|
|
209
268
|
tokenizeCardInternal(cardData) {
|
|
210
269
|
return __awaiter(this, void 0, void 0, function* () {
|
|
270
|
+
var _a, _b, _c;
|
|
211
271
|
if (this.cachedTokenResult && this.cachedTokenResult.errorCode === '0') {
|
|
272
|
+
const cardType = this.cachedTokenResult.cardType
|
|
273
|
+
? this.normalizeCardType(this.cachedTokenResult.cardType)
|
|
274
|
+
: this.normalizeCardType('unknown');
|
|
212
275
|
return {
|
|
213
276
|
token: this.cachedTokenResult.token,
|
|
214
|
-
lastFour: this.cachedTokenResult.
|
|
215
|
-
|
|
277
|
+
lastFour: this.cachedTokenResult.last4 ||
|
|
278
|
+
this.cachedTokenResult.token.slice(-4),
|
|
279
|
+
cardType,
|
|
280
|
+
paymentMethodType: 'credit_card',
|
|
216
281
|
provider: 'cardconnect',
|
|
217
282
|
};
|
|
218
283
|
}
|
|
219
284
|
if (this.tokenizationPromise) {
|
|
220
285
|
return this.tokenizationPromise;
|
|
221
286
|
}
|
|
287
|
+
if (!this.currentValidationState.isValid &&
|
|
288
|
+
(((_a = this.currentValidationState.cardNumber) === null || _a === void 0 ? void 0 : _a.isEmpty) ||
|
|
289
|
+
((_b = this.currentValidationState.cvv) === null || _b === void 0 ? void 0 : _b.isEmpty) ||
|
|
290
|
+
((_c = this.currentValidationState.expiry) === null || _c === void 0 ? void 0 : _c.isEmpty))) {
|
|
291
|
+
throw new TokenizationError('Card fields are incomplete', 'VALIDATION_ERROR');
|
|
292
|
+
}
|
|
222
293
|
this.tokenizationPromise = new Promise((resolve, reject) => {
|
|
223
294
|
this.tokenizationResolve = resolve;
|
|
224
295
|
this.tokenizationReject = reject;
|
|
225
|
-
|
|
296
|
+
this.tokenizationTimeout = setTimeout(() => {
|
|
297
|
+
this.tokenizationTimeout = undefined;
|
|
226
298
|
this.tokenizationPromise = undefined;
|
|
227
299
|
this.tokenizationResolve = undefined;
|
|
228
300
|
this.tokenizationReject = undefined;
|
|
229
301
|
reject(new TokenizationError('Tokenization timeout - ensure all card fields are filled in iframe', 'TIMEOUT'));
|
|
230
302
|
}, TOKENIZE_TIMEOUT);
|
|
231
|
-
const tokenizationHandler = (data) => {
|
|
232
|
-
clearTimeout(timeout);
|
|
233
|
-
this.off('tokenization', tokenizationHandler);
|
|
234
|
-
};
|
|
235
|
-
this.on('tokenization', tokenizationHandler);
|
|
236
303
|
});
|
|
237
304
|
return this.tokenizationPromise;
|
|
238
305
|
});
|
|
@@ -254,16 +321,16 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
254
321
|
throw new TokenizationError('Invalid account number', 'VALIDATION_ERROR');
|
|
255
322
|
}
|
|
256
323
|
const baseUrl = new URL(this.iframeUrl).origin;
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, config);
|
|
260
|
-
return {
|
|
324
|
+
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, baseUrl);
|
|
325
|
+
const paymentToken = {
|
|
261
326
|
token: result.token,
|
|
262
327
|
lastFour: accountNumber.slice(-4),
|
|
263
328
|
accountType: accountType,
|
|
264
329
|
paymentMethodType: 'bank_account',
|
|
265
330
|
provider: 'cardconnect',
|
|
266
331
|
};
|
|
332
|
+
this.emit('tokenReady', paymentToken);
|
|
333
|
+
return paymentToken;
|
|
267
334
|
});
|
|
268
335
|
}
|
|
269
336
|
validate() {
|
|
@@ -400,12 +467,39 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
400
467
|
action: 'clear',
|
|
401
468
|
}, this.expectedOrigin);
|
|
402
469
|
}
|
|
403
|
-
this.
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
470
|
+
this.cachedTokenResult = undefined;
|
|
471
|
+
this.acceptAutoToken = false;
|
|
472
|
+
if (this.tokenizationTimeout) {
|
|
473
|
+
clearTimeout(this.tokenizationTimeout);
|
|
474
|
+
this.tokenizationTimeout = undefined;
|
|
475
|
+
}
|
|
476
|
+
if (this.tokenizationReject) {
|
|
477
|
+
const reject = this.tokenizationReject;
|
|
478
|
+
this.tokenizationPromise = undefined;
|
|
479
|
+
this.tokenizationResolve = undefined;
|
|
480
|
+
this.tokenizationReject = undefined;
|
|
481
|
+
reject(new TokenizationError('Tokenizer cleared', 'CLEARED'));
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
this.tokenizationPromise = undefined;
|
|
485
|
+
this.tokenizationResolve = undefined;
|
|
486
|
+
this.tokenizationReject = undefined;
|
|
487
|
+
}
|
|
488
|
+
if (this.mode === 'bank_account') {
|
|
489
|
+
this.currentValidationState = {
|
|
490
|
+
isValid: false,
|
|
491
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
492
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
else {
|
|
496
|
+
this.currentValidationState = {
|
|
497
|
+
isValid: false,
|
|
498
|
+
cardNumber: { isValid: false, isEmpty: true },
|
|
499
|
+
cvv: { isValid: false, isEmpty: true },
|
|
500
|
+
expiry: { isValid: false, isEmpty: true },
|
|
501
|
+
};
|
|
502
|
+
}
|
|
409
503
|
this.emit('validation', this.currentValidationState);
|
|
410
504
|
}
|
|
411
505
|
focus(field) {
|
|
@@ -434,8 +528,22 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
434
528
|
}
|
|
435
529
|
}
|
|
436
530
|
destroy() {
|
|
531
|
+
this.markDestroyed();
|
|
532
|
+
if (this.tokenizationTimeout) {
|
|
533
|
+
clearTimeout(this.tokenizationTimeout);
|
|
534
|
+
this.tokenizationTimeout = undefined;
|
|
535
|
+
}
|
|
536
|
+
if (this.tokenizationReject) {
|
|
537
|
+
const reject = this.tokenizationReject;
|
|
538
|
+
this.tokenizationPromise = undefined;
|
|
539
|
+
this.tokenizationResolve = undefined;
|
|
540
|
+
this.tokenizationReject = undefined;
|
|
541
|
+
reject(new TokenizationError('Tokenizer destroyed', 'DESTROYED'));
|
|
542
|
+
}
|
|
543
|
+
this.cachedTokenResult = undefined;
|
|
437
544
|
if (this.messageHandler) {
|
|
438
545
|
window.removeEventListener('message', this.messageHandler);
|
|
546
|
+
this.messageHandler = undefined;
|
|
439
547
|
}
|
|
440
548
|
if (this.containerEl) {
|
|
441
549
|
this.containerEl.innerHTML = '';
|
|
@@ -462,6 +570,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
462
570
|
lastFour: this.cachedTokenResult.last4 ||
|
|
463
571
|
this.cachedTokenResult.token.slice(-4),
|
|
464
572
|
cardType,
|
|
573
|
+
paymentMethodType: 'credit_card',
|
|
465
574
|
provider: 'cardconnect',
|
|
466
575
|
};
|
|
467
576
|
}
|
|
@@ -474,8 +583,14 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
474
583
|
try {
|
|
475
584
|
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
476
585
|
if (data.token && data.errorCode !== undefined) {
|
|
586
|
+
if (!this.acceptAutoToken && !this.tokenizationResolve) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
477
589
|
this.cachedTokenResult = data;
|
|
478
|
-
this.
|
|
590
|
+
if (this.tokenizationTimeout) {
|
|
591
|
+
clearTimeout(this.tokenizationTimeout);
|
|
592
|
+
this.tokenizationTimeout = undefined;
|
|
593
|
+
}
|
|
479
594
|
if (data.errorCode === '0') {
|
|
480
595
|
const cardType = data.cardType
|
|
481
596
|
? this.normalizeCardType(data.cardType)
|
|
@@ -488,6 +603,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
488
603
|
token: data.token,
|
|
489
604
|
lastFour: data.last4 || data.token.slice(-4),
|
|
490
605
|
cardType,
|
|
606
|
+
paymentMethodType: 'credit_card',
|
|
491
607
|
provider: 'cardconnect',
|
|
492
608
|
};
|
|
493
609
|
if (this.tokenizationResolve) {
|
|
@@ -502,12 +618,14 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
502
618
|
cvv: { isValid: true, isEmpty: false },
|
|
503
619
|
expiry: { isValid: true, isEmpty: false },
|
|
504
620
|
};
|
|
505
|
-
this.emit('validation',
|
|
621
|
+
this.emit('validation', this.currentValidationState);
|
|
506
622
|
this.emit('tokenReady', token);
|
|
507
623
|
}
|
|
508
624
|
else {
|
|
625
|
+
const error = new TokenizationError(data.errorMessage || 'Tokenization failed', data.errorCode || 'UNKNOWN');
|
|
626
|
+
this.emit('error', error);
|
|
509
627
|
if (this.tokenizationReject) {
|
|
510
|
-
this.tokenizationReject(
|
|
628
|
+
this.tokenizationReject(error);
|
|
511
629
|
this.tokenizationPromise = undefined;
|
|
512
630
|
this.tokenizationResolve = undefined;
|
|
513
631
|
this.tokenizationReject = undefined;
|
|
@@ -515,19 +633,16 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
515
633
|
}
|
|
516
634
|
}
|
|
517
635
|
if (data.event === 'validation' || data.validationError !== undefined) {
|
|
636
|
+
this.acceptAutoToken = true;
|
|
518
637
|
this.handleValidationMessage(data);
|
|
519
638
|
}
|
|
520
|
-
if (data.event === '
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if (cardType !== this.currentCardType) {
|
|
528
|
-
this.currentCardType = cardType;
|
|
529
|
-
this.emit('cardTypeChange', { cardType });
|
|
530
|
-
}
|
|
639
|
+
if ((data.event === 'input' || data.event === 'change') &&
|
|
640
|
+
data.cardType) {
|
|
641
|
+
this.acceptAutoToken = true;
|
|
642
|
+
const cardType = this.normalizeCardType(data.cardType);
|
|
643
|
+
if (cardType !== this.currentCardType) {
|
|
644
|
+
this.currentCardType = cardType;
|
|
645
|
+
this.emit('cardTypeChange', { cardType });
|
|
531
646
|
}
|
|
532
647
|
}
|
|
533
648
|
}
|
|
@@ -535,7 +650,6 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
535
650
|
}
|
|
536
651
|
}
|
|
537
652
|
handleValidationMessage(data) {
|
|
538
|
-
var _a, _b, _c, _d, _e, _f;
|
|
539
653
|
if (data.validationError) {
|
|
540
654
|
const errorLower = data.validationError.toLowerCase();
|
|
541
655
|
if (errorLower.includes('card') || errorLower.includes('number')) {
|
|
@@ -557,10 +671,14 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
557
671
|
this.emit('validation', this.currentValidationState);
|
|
558
672
|
}
|
|
559
673
|
else {
|
|
560
|
-
this.currentValidationState.
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
674
|
+
this.currentValidationState.cardNumber = {
|
|
675
|
+
isValid: true,
|
|
676
|
+
isEmpty: false,
|
|
677
|
+
};
|
|
678
|
+
this.currentValidationState.cvv = { isValid: true, isEmpty: false };
|
|
679
|
+
this.currentValidationState.expiry = { isValid: true, isEmpty: false };
|
|
680
|
+
this.currentValidationState.isValid = true;
|
|
681
|
+
this.emit('validation', this.currentValidationState);
|
|
564
682
|
}
|
|
565
683
|
}
|
|
566
684
|
static generateIframeUrl(baseUrl, container) {
|
|
@@ -740,16 +858,29 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
740
858
|
}
|
|
741
859
|
return encodeURIComponent(css.join(''));
|
|
742
860
|
}
|
|
743
|
-
static tokenizeBankAccount(routingNumber, accountNumber,
|
|
744
|
-
return
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
861
|
+
static tokenizeBankAccount(routingNumber, accountNumber, configOrBaseUrl) {
|
|
862
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
863
|
+
const baseUrl = typeof configOrBaseUrl === 'string'
|
|
864
|
+
? configOrBaseUrl
|
|
865
|
+
: configOrBaseUrl.cardConnectBaseUrl;
|
|
866
|
+
const response = yield fetch(`${baseUrl}/cardsecure/api/v1/ccn/tokenize`, {
|
|
867
|
+
method: 'POST',
|
|
868
|
+
headers: {
|
|
869
|
+
'Content-Type': 'application/json',
|
|
870
|
+
},
|
|
871
|
+
body: JSON.stringify({
|
|
872
|
+
account: `${routingNumber}/${accountNumber}`,
|
|
873
|
+
unique: true,
|
|
874
|
+
}),
|
|
875
|
+
});
|
|
876
|
+
if (!response.ok) {
|
|
877
|
+
throw new TokenizationError(`Bank account tokenization failed: HTTP ${response.status}`, 'API_ERROR');
|
|
878
|
+
}
|
|
879
|
+
const result = yield response.json();
|
|
880
|
+
if (!result.token) {
|
|
881
|
+
throw new TokenizationError(result.message || 'Bank account tokenization failed: no token returned', 'API_ERROR');
|
|
882
|
+
}
|
|
883
|
+
return result;
|
|
884
|
+
});
|
|
754
885
|
}
|
|
755
886
|
}
|
|
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { Tokenizer } from './Tokenizer';
|
|
11
11
|
import { TokenizationError, } from './types';
|
|
12
|
+
import { CLIENT_HEADERS } from '../constants';
|
|
12
13
|
const PAYPAL_SDK_URL = 'https://www.paypal.com/sdk/js';
|
|
13
14
|
const PAYPAL_SCRIPT_ID = 'paypal-sdk-script';
|
|
14
15
|
const INIT_TIMEOUT = 10000;
|
|
@@ -19,7 +20,7 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
19
20
|
this.gateway = gateway;
|
|
20
21
|
this.containerId = containerId;
|
|
21
22
|
this.configContext = configContext;
|
|
22
|
-
this.mode = '
|
|
23
|
+
this.mode = 'paypal';
|
|
23
24
|
const gatewayConfig = gateway.config;
|
|
24
25
|
if (!(gatewayConfig === null || gatewayConfig === void 0 ? void 0 : gatewayConfig.client_id)) {
|
|
25
26
|
throw new Error('PayPal gateway configuration missing client_id');
|
|
@@ -66,7 +67,7 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
66
67
|
})
|
|
67
68
|
.then(() => {
|
|
68
69
|
this.emit('ready');
|
|
69
|
-
this.emit('validation', { isValid: true });
|
|
70
|
+
this.emit('validation', { isValid: true, hasToken: false });
|
|
70
71
|
resolve();
|
|
71
72
|
})
|
|
72
73
|
.catch((error) => {
|
|
@@ -79,11 +80,20 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
79
80
|
}
|
|
80
81
|
loadPayPalSDK() {
|
|
81
82
|
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
const configKey = `${this.clientId}|${this.currency}`;
|
|
84
|
+
const existingScript = document.getElementById(PAYPAL_SCRIPT_ID);
|
|
85
|
+
if (existingScript) {
|
|
86
|
+
const loadedConfig = existingScript.getAttribute('data-config-key');
|
|
87
|
+
if (loadedConfig && loadedConfig !== configKey) {
|
|
88
|
+
existingScript.remove();
|
|
89
|
+
delete window.paypal;
|
|
90
|
+
}
|
|
91
|
+
else if (window.paypal) {
|
|
92
|
+
return Promise.resolve();
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return this.waitForPayPalGlobal();
|
|
96
|
+
}
|
|
87
97
|
}
|
|
88
98
|
const params = new URLSearchParams({
|
|
89
99
|
'client-id': this.clientId,
|
|
@@ -102,6 +112,7 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
102
112
|
script.id = PAYPAL_SCRIPT_ID;
|
|
103
113
|
script.src = `${PAYPAL_SDK_URL}?${params.toString()}`;
|
|
104
114
|
script.async = true;
|
|
115
|
+
script.setAttribute('data-config-key', configKey);
|
|
105
116
|
return new Promise((resolve, reject) => {
|
|
106
117
|
script.onload = () => {
|
|
107
118
|
this.waitForPayPalGlobal().then(resolve).catch(reject);
|
|
@@ -145,7 +156,7 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
145
156
|
if (!window.paypal || !this.paypalButtonContainer) {
|
|
146
157
|
return;
|
|
147
158
|
}
|
|
148
|
-
|
|
159
|
+
this.buttonsInstance = window.paypal.Buttons({
|
|
149
160
|
createOrder: () => this.createOrder(),
|
|
150
161
|
onApprove: (data) => this.handleApprove(data),
|
|
151
162
|
onCancel: (data) => this.handleCancel(data),
|
|
@@ -156,36 +167,48 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
156
167
|
height: 40,
|
|
157
168
|
},
|
|
158
169
|
});
|
|
159
|
-
yield
|
|
170
|
+
yield this.buttonsInstance.render(this.paypalButtonContainer);
|
|
160
171
|
});
|
|
161
172
|
}
|
|
162
173
|
createOrder() {
|
|
163
174
|
const endpoint = `${this.clientConfig.embedApiBaseUrl}/payment/paypal/create-order`;
|
|
175
|
+
this.paymentTransactionId = undefined;
|
|
176
|
+
this.paymentMethodId = undefined;
|
|
164
177
|
let orderAmount;
|
|
165
178
|
let orderCurrency = this.currency;
|
|
166
179
|
if (this.onCreateOrder) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
try {
|
|
181
|
+
const orderData = this.onCreateOrder();
|
|
182
|
+
orderAmount = orderData.amount;
|
|
183
|
+
orderCurrency = orderData.currency || this.currency;
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
const error = err instanceof Error
|
|
187
|
+
? err
|
|
188
|
+
: new Error('onCreateOrder callback failed');
|
|
189
|
+
this.handleError(error, 'Order creation failed');
|
|
190
|
+
return Promise.reject(error);
|
|
191
|
+
}
|
|
170
192
|
}
|
|
171
193
|
else {
|
|
172
194
|
orderAmount = this.amount;
|
|
173
195
|
}
|
|
174
|
-
if (orderAmount === undefined || orderAmount <= 0) {
|
|
196
|
+
if (orderAmount === undefined || isNaN(orderAmount) || orderAmount <= 0) {
|
|
175
197
|
const error = new Error('Amount is required to create PayPal order');
|
|
176
198
|
this.handleError(error, 'Order creation failed');
|
|
177
199
|
return Promise.reject(error);
|
|
178
200
|
}
|
|
179
201
|
const requestBody = {
|
|
180
202
|
payment_gateway_id: this.gateway.id,
|
|
203
|
+
organization_id: this.organizationId,
|
|
204
|
+
embed_id: this.embedId,
|
|
181
205
|
currency: orderCurrency,
|
|
182
206
|
amount: orderAmount,
|
|
183
207
|
};
|
|
184
208
|
return fetch(endpoint, {
|
|
185
209
|
method: 'POST',
|
|
186
|
-
headers:
|
|
187
|
-
|
|
188
|
-
},
|
|
210
|
+
headers: CLIENT_HEADERS,
|
|
211
|
+
credentials: 'include',
|
|
189
212
|
body: JSON.stringify(requestBody),
|
|
190
213
|
})
|
|
191
214
|
.then((response) => {
|
|
@@ -212,6 +235,7 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
212
235
|
const token = {
|
|
213
236
|
token: data.orderID,
|
|
214
237
|
lastFour: data.orderID.slice(-4),
|
|
238
|
+
paymentMethodType: 'paypal',
|
|
215
239
|
provider: 'paypal_checkout',
|
|
216
240
|
paymentMethodId: this.paymentMethodId,
|
|
217
241
|
paymentTransactionId: this.paymentTransactionId,
|
|
@@ -241,6 +265,9 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
241
265
|
}
|
|
242
266
|
validate() {
|
|
243
267
|
return __awaiter(this, void 0, void 0, function* () {
|
|
268
|
+
if (!this.isReady) {
|
|
269
|
+
throw new Error('Tokenizer not initialized');
|
|
270
|
+
}
|
|
244
271
|
return {
|
|
245
272
|
isValid: true,
|
|
246
273
|
errors: [],
|
|
@@ -254,6 +281,15 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
254
281
|
focus(field) {
|
|
255
282
|
}
|
|
256
283
|
destroy() {
|
|
284
|
+
this.markDestroyed();
|
|
285
|
+
if (this.buttonsInstance) {
|
|
286
|
+
try {
|
|
287
|
+
this.buttonsInstance.close();
|
|
288
|
+
}
|
|
289
|
+
catch (_a) {
|
|
290
|
+
}
|
|
291
|
+
this.buttonsInstance = undefined;
|
|
292
|
+
}
|
|
257
293
|
if (this.containerEl) {
|
|
258
294
|
this.containerEl.innerHTML = '';
|
|
259
295
|
}
|
|
@@ -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;
|