@idonatedev/idonate-sdk 1.2.0-dev14 → 1.2.0-dev15
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 +5 -1
- package/dist/esm/tokenize/CardConnectTokenizer.js +151 -50
- package/dist/esm/tokenize/PayPalTokenizer.d.ts +1 -0
- package/dist/esm/tokenize/PayPalTokenizer.js +50 -16
- package/dist/esm/tokenize/SpreedlyTokenizer.d.ts +5 -0
- package/dist/esm/tokenize/SpreedlyTokenizer.js +103 -64
- package/dist/esm/tokenize/Tokenizer.d.ts +2 -2
- package/dist/esm/tokenize/Tokenizer.js +0 -1
- 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 +3 -1
- package/dist/esm/tokenize/tokenizer-utils.js +2 -2
- package/dist/esm/tokenize/types.d.ts +3 -2
- package/dist/tokenize/CardConnectTokenizer.d.ts +5 -1
- package/dist/tokenize/CardConnectTokenizer.js +151 -53
- package/dist/tokenize/PayPalTokenizer.d.ts +1 -0
- package/dist/tokenize/PayPalTokenizer.js +50 -16
- package/dist/tokenize/SpreedlyTokenizer.d.ts +5 -0
- package/dist/tokenize/SpreedlyTokenizer.js +103 -64
- package/dist/tokenize/Tokenizer.d.ts +2 -2
- package/dist/tokenize/Tokenizer.js +0 -1
- package/dist/tokenize/gateway-utils.js +3 -2
- package/dist/tokenize/index.d.ts +1 -1
- package/dist/tokenize/spreedly-secure.js +3 -1
- package/dist/tokenize/tokenizer-utils.js +2 -2
- package/dist/tokenize/types.d.ts +3 -2
- 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-dev15';
|
|
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-dev15';
|
|
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';
|
|
@@ -20,6 +20,8 @@ export declare class CardConnectTokenizer extends Tokenizer {
|
|
|
20
20
|
private tokenizationResolve?;
|
|
21
21
|
private tokenizationReject?;
|
|
22
22
|
private currentCardType?;
|
|
23
|
+
private tokenizationTimeout?;
|
|
24
|
+
private mergedStyles?;
|
|
23
25
|
private constructor();
|
|
24
26
|
static create(gateway: PaymentGateway, container: TokenizerContainer, config: {
|
|
25
27
|
organizationId: string;
|
|
@@ -29,6 +31,8 @@ export declare class CardConnectTokenizer extends Tokenizer {
|
|
|
29
31
|
private createInternalElements;
|
|
30
32
|
private createCreditCardFields;
|
|
31
33
|
private createBankAccountFields;
|
|
34
|
+
private addBankAccountValidationListeners;
|
|
35
|
+
private updateBankAccountValidation;
|
|
32
36
|
private init;
|
|
33
37
|
tokenize(paymentData: PaymentData): Promise<PaymentToken>;
|
|
34
38
|
private tokenizeCardInternal;
|
|
@@ -47,5 +51,5 @@ export declare class CardConnectTokenizer extends Tokenizer {
|
|
|
47
51
|
private static generateIframeUrl;
|
|
48
52
|
private static createIframe;
|
|
49
53
|
private static generateCardConnectCss;
|
|
50
|
-
static tokenizeBankAccount(routingNumber: string, accountNumber: string,
|
|
54
|
+
static tokenizeBankAccount(routingNumber: string, accountNumber: string, configOrBaseUrl: ConfigHandler | string): Promise<TokenizeCardConnectBankAccountResult>;
|
|
51
55
|
}
|
|
@@ -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';
|
|
@@ -34,7 +33,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
34
33
|
}
|
|
35
34
|
static create(gateway, container, config) {
|
|
36
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
var _a;
|
|
36
|
+
var _a, _b;
|
|
38
37
|
if (container.mode === 'bank_account' && container.bankCountry === 'CA') {
|
|
39
38
|
throw new Error('CardConnect does not support Canadian bank accounts');
|
|
40
39
|
}
|
|
@@ -42,7 +41,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
42
41
|
if (container.layout === 'responsive') {
|
|
43
42
|
const containerEl = document.getElementById(container.containerId);
|
|
44
43
|
const containerWidth = (containerEl === null || containerEl === void 0 ? void 0 : containerEl.offsetWidth) || 0;
|
|
45
|
-
const breakpoint = container.responsiveBreakpoint
|
|
44
|
+
const breakpoint = (_a = container.responsiveBreakpoint) !== null && _a !== void 0 ? _a : RESPONSIVE_BREAKPOINT;
|
|
46
45
|
effectiveLayout =
|
|
47
46
|
containerWidth < breakpoint ? 'two-line' : 'single-line';
|
|
48
47
|
}
|
|
@@ -50,8 +49,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
50
49
|
effectiveLayout = 'two-line';
|
|
51
50
|
}
|
|
52
51
|
const resolvedContainer = Object.assign(Object.assign({}, container), { layout: effectiveLayout });
|
|
53
|
-
|
|
54
|
-
config.cardConnectBaseUrl = baseUrl;
|
|
52
|
+
const baseUrl = ((_b = gateway.config) === null || _b === void 0 ? void 0 : _b.baseUrl) || config.clientConfig.cardConnectBaseUrl;
|
|
55
53
|
const mergedStyles = mergeStyles(DEFAULT_UNIFIED_STYLES, container.styling);
|
|
56
54
|
const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, resolvedContainer);
|
|
57
55
|
const iframe = CardConnectTokenizer.createIframe(iframeUrl, mergedStyles);
|
|
@@ -139,6 +137,66 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
139
137
|
this.applyInputStyles(this.accountTypeEl, mergedStyles, 'right');
|
|
140
138
|
containerEl.appendChild(this.accountTypeEl);
|
|
141
139
|
}
|
|
140
|
+
this.mergedStyles = mergedStyles;
|
|
141
|
+
this.currentValidationState = {
|
|
142
|
+
isValid: false,
|
|
143
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
144
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
145
|
+
};
|
|
146
|
+
this.addBankAccountValidationListeners(mergedStyles);
|
|
147
|
+
}
|
|
148
|
+
addBankAccountValidationListeners(styles) {
|
|
149
|
+
if (this.routingNumberEl) {
|
|
150
|
+
this.routingNumberEl.addEventListener('blur', () => {
|
|
151
|
+
this.updateBankAccountValidation(styles);
|
|
152
|
+
});
|
|
153
|
+
this.routingNumberEl.addEventListener('input', () => {
|
|
154
|
+
this.updateBankAccountValidation(styles);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (this.accountNumberEl) {
|
|
158
|
+
this.accountNumberEl.addEventListener('blur', () => {
|
|
159
|
+
this.updateBankAccountValidation(styles);
|
|
160
|
+
});
|
|
161
|
+
this.accountNumberEl.addEventListener('input', () => {
|
|
162
|
+
this.updateBankAccountValidation(styles);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
updateBankAccountValidation(styles) {
|
|
167
|
+
var _a, _b;
|
|
168
|
+
const routingValue = ((_a = this.routingNumberEl) === null || _a === void 0 ? void 0 : _a.value) || '';
|
|
169
|
+
const accountValue = ((_b = this.accountNumberEl) === null || _b === void 0 ? void 0 : _b.value) || '';
|
|
170
|
+
const routingValid = routingValue.length > 0 && validateRoutingNumber(routingValue);
|
|
171
|
+
const accountValid = accountValue.length > 0 && validateAccountNumber(accountValue);
|
|
172
|
+
if (this.routingNumberEl) {
|
|
173
|
+
if (routingValue.length > 0 && !routingValid) {
|
|
174
|
+
this.routingNumberEl.style.borderColor = styles.error.borderColor;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
this.routingNumberEl.style.borderColor = '';
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (this.accountNumberEl) {
|
|
181
|
+
if (accountValue.length > 0 && !accountValid) {
|
|
182
|
+
this.accountNumberEl.style.borderColor = styles.error.borderColor;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
this.accountNumberEl.style.borderColor = '';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
this.currentValidationState = {
|
|
189
|
+
isValid: routingValid && accountValid,
|
|
190
|
+
routingNumber: {
|
|
191
|
+
isValid: routingValid,
|
|
192
|
+
isEmpty: routingValue.length === 0,
|
|
193
|
+
},
|
|
194
|
+
accountNumber: {
|
|
195
|
+
isValid: accountValid,
|
|
196
|
+
isEmpty: accountValue.length === 0,
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
this.emit('validation', this.currentValidationState);
|
|
142
200
|
}
|
|
143
201
|
init() {
|
|
144
202
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -208,6 +266,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
208
266
|
}
|
|
209
267
|
tokenizeCardInternal(cardData) {
|
|
210
268
|
return __awaiter(this, void 0, void 0, function* () {
|
|
269
|
+
var _a, _b, _c;
|
|
211
270
|
if (this.cachedTokenResult && this.cachedTokenResult.errorCode === '0') {
|
|
212
271
|
return {
|
|
213
272
|
token: this.cachedTokenResult.token,
|
|
@@ -219,20 +278,22 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
219
278
|
if (this.tokenizationPromise) {
|
|
220
279
|
return this.tokenizationPromise;
|
|
221
280
|
}
|
|
281
|
+
if (!this.currentValidationState.isValid &&
|
|
282
|
+
(((_a = this.currentValidationState.cardNumber) === null || _a === void 0 ? void 0 : _a.isEmpty) ||
|
|
283
|
+
((_b = this.currentValidationState.cvv) === null || _b === void 0 ? void 0 : _b.isEmpty) ||
|
|
284
|
+
((_c = this.currentValidationState.expiry) === null || _c === void 0 ? void 0 : _c.isEmpty))) {
|
|
285
|
+
throw new TokenizationError('Card fields are incomplete', 'VALIDATION_ERROR');
|
|
286
|
+
}
|
|
222
287
|
this.tokenizationPromise = new Promise((resolve, reject) => {
|
|
223
288
|
this.tokenizationResolve = resolve;
|
|
224
289
|
this.tokenizationReject = reject;
|
|
225
|
-
|
|
290
|
+
this.tokenizationTimeout = setTimeout(() => {
|
|
291
|
+
this.tokenizationTimeout = undefined;
|
|
226
292
|
this.tokenizationPromise = undefined;
|
|
227
293
|
this.tokenizationResolve = undefined;
|
|
228
294
|
this.tokenizationReject = undefined;
|
|
229
295
|
reject(new TokenizationError('Tokenization timeout - ensure all card fields are filled in iframe', 'TIMEOUT'));
|
|
230
296
|
}, TOKENIZE_TIMEOUT);
|
|
231
|
-
const tokenizationHandler = (data) => {
|
|
232
|
-
clearTimeout(timeout);
|
|
233
|
-
this.off('tokenization', tokenizationHandler);
|
|
234
|
-
};
|
|
235
|
-
this.on('tokenization', tokenizationHandler);
|
|
236
297
|
});
|
|
237
298
|
return this.tokenizationPromise;
|
|
238
299
|
});
|
|
@@ -254,9 +315,7 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
254
315
|
throw new TokenizationError('Invalid account number', 'VALIDATION_ERROR');
|
|
255
316
|
}
|
|
256
317
|
const baseUrl = new URL(this.iframeUrl).origin;
|
|
257
|
-
const
|
|
258
|
-
config.cardConnectBaseUrl = baseUrl;
|
|
259
|
-
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, config);
|
|
318
|
+
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, baseUrl);
|
|
260
319
|
return {
|
|
261
320
|
token: result.token,
|
|
262
321
|
lastFour: accountNumber.slice(-4),
|
|
@@ -400,12 +459,25 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
400
459
|
action: 'clear',
|
|
401
460
|
}, this.expectedOrigin);
|
|
402
461
|
}
|
|
403
|
-
this.
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
462
|
+
this.cachedTokenResult = undefined;
|
|
463
|
+
this.tokenizationPromise = undefined;
|
|
464
|
+
this.tokenizationResolve = undefined;
|
|
465
|
+
this.tokenizationReject = undefined;
|
|
466
|
+
if (this.mode === 'bank_account') {
|
|
467
|
+
this.currentValidationState = {
|
|
468
|
+
isValid: false,
|
|
469
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
470
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
this.currentValidationState = {
|
|
475
|
+
isValid: false,
|
|
476
|
+
cardNumber: { isValid: false, isEmpty: true },
|
|
477
|
+
cvv: { isValid: false, isEmpty: true },
|
|
478
|
+
expiry: { isValid: false, isEmpty: true },
|
|
479
|
+
};
|
|
480
|
+
}
|
|
409
481
|
this.emit('validation', this.currentValidationState);
|
|
410
482
|
}
|
|
411
483
|
focus(field) {
|
|
@@ -434,8 +506,21 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
434
506
|
}
|
|
435
507
|
}
|
|
436
508
|
destroy() {
|
|
509
|
+
if (this.tokenizationTimeout) {
|
|
510
|
+
clearTimeout(this.tokenizationTimeout);
|
|
511
|
+
this.tokenizationTimeout = undefined;
|
|
512
|
+
}
|
|
513
|
+
if (this.tokenizationReject) {
|
|
514
|
+
const reject = this.tokenizationReject;
|
|
515
|
+
this.tokenizationPromise = undefined;
|
|
516
|
+
this.tokenizationResolve = undefined;
|
|
517
|
+
this.tokenizationReject = undefined;
|
|
518
|
+
reject(new TokenizationError('Tokenizer destroyed', 'DESTROYED'));
|
|
519
|
+
}
|
|
520
|
+
this.cachedTokenResult = undefined;
|
|
437
521
|
if (this.messageHandler) {
|
|
438
522
|
window.removeEventListener('message', this.messageHandler);
|
|
523
|
+
this.messageHandler = undefined;
|
|
439
524
|
}
|
|
440
525
|
if (this.containerEl) {
|
|
441
526
|
this.containerEl.innerHTML = '';
|
|
@@ -475,7 +560,10 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
475
560
|
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
476
561
|
if (data.token && data.errorCode !== undefined) {
|
|
477
562
|
this.cachedTokenResult = data;
|
|
478
|
-
this.
|
|
563
|
+
if (this.tokenizationTimeout) {
|
|
564
|
+
clearTimeout(this.tokenizationTimeout);
|
|
565
|
+
this.tokenizationTimeout = undefined;
|
|
566
|
+
}
|
|
479
567
|
if (data.errorCode === '0') {
|
|
480
568
|
const cardType = data.cardType
|
|
481
569
|
? this.normalizeCardType(data.cardType)
|
|
@@ -502,12 +590,14 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
502
590
|
cvv: { isValid: true, isEmpty: false },
|
|
503
591
|
expiry: { isValid: true, isEmpty: false },
|
|
504
592
|
};
|
|
505
|
-
this.emit('validation',
|
|
593
|
+
this.emit('validation', this.currentValidationState);
|
|
506
594
|
this.emit('tokenReady', token);
|
|
507
595
|
}
|
|
508
596
|
else {
|
|
597
|
+
const error = new TokenizationError(data.errorMessage || 'Tokenization failed', data.errorCode || 'UNKNOWN');
|
|
598
|
+
this.emit('error', error);
|
|
509
599
|
if (this.tokenizationReject) {
|
|
510
|
-
this.tokenizationReject(
|
|
600
|
+
this.tokenizationReject(error);
|
|
511
601
|
this.tokenizationPromise = undefined;
|
|
512
602
|
this.tokenizationResolve = undefined;
|
|
513
603
|
this.tokenizationReject = undefined;
|
|
@@ -517,17 +607,12 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
517
607
|
if (data.event === 'validation' || data.validationError !== undefined) {
|
|
518
608
|
this.handleValidationMessage(data);
|
|
519
609
|
}
|
|
520
|
-
if (data.event === '
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
const cardType = this.normalizeCardType(data.cardType);
|
|
527
|
-
if (cardType !== this.currentCardType) {
|
|
528
|
-
this.currentCardType = cardType;
|
|
529
|
-
this.emit('cardTypeChange', { cardType });
|
|
530
|
-
}
|
|
610
|
+
if ((data.event === 'input' || data.event === 'change') &&
|
|
611
|
+
data.cardType) {
|
|
612
|
+
const cardType = this.normalizeCardType(data.cardType);
|
|
613
|
+
if (cardType !== this.currentCardType) {
|
|
614
|
+
this.currentCardType = cardType;
|
|
615
|
+
this.emit('cardTypeChange', { cardType });
|
|
531
616
|
}
|
|
532
617
|
}
|
|
533
618
|
}
|
|
@@ -535,7 +620,6 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
535
620
|
}
|
|
536
621
|
}
|
|
537
622
|
handleValidationMessage(data) {
|
|
538
|
-
var _a, _b, _c, _d, _e, _f;
|
|
539
623
|
if (data.validationError) {
|
|
540
624
|
const errorLower = data.validationError.toLowerCase();
|
|
541
625
|
if (errorLower.includes('card') || errorLower.includes('number')) {
|
|
@@ -557,10 +641,14 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
557
641
|
this.emit('validation', this.currentValidationState);
|
|
558
642
|
}
|
|
559
643
|
else {
|
|
560
|
-
this.currentValidationState.
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
644
|
+
this.currentValidationState.cardNumber = {
|
|
645
|
+
isValid: true,
|
|
646
|
+
isEmpty: false,
|
|
647
|
+
};
|
|
648
|
+
this.currentValidationState.cvv = { isValid: true, isEmpty: false };
|
|
649
|
+
this.currentValidationState.expiry = { isValid: true, isEmpty: false };
|
|
650
|
+
this.currentValidationState.isValid = true;
|
|
651
|
+
this.emit('validation', this.currentValidationState);
|
|
564
652
|
}
|
|
565
653
|
}
|
|
566
654
|
static generateIframeUrl(baseUrl, container) {
|
|
@@ -740,16 +828,29 @@ export class CardConnectTokenizer extends Tokenizer {
|
|
|
740
828
|
}
|
|
741
829
|
return encodeURIComponent(css.join(''));
|
|
742
830
|
}
|
|
743
|
-
static tokenizeBankAccount(routingNumber, accountNumber,
|
|
744
|
-
return
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
831
|
+
static tokenizeBankAccount(routingNumber, accountNumber, configOrBaseUrl) {
|
|
832
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
833
|
+
const baseUrl = typeof configOrBaseUrl === 'string'
|
|
834
|
+
? configOrBaseUrl
|
|
835
|
+
: configOrBaseUrl.cardConnectBaseUrl;
|
|
836
|
+
const response = yield fetch(`${baseUrl}/cardsecure/api/v1/ccn/tokenize`, {
|
|
837
|
+
method: 'POST',
|
|
838
|
+
headers: {
|
|
839
|
+
'Content-Type': 'application/json',
|
|
840
|
+
},
|
|
841
|
+
body: JSON.stringify({
|
|
842
|
+
account: `${routingNumber}/${accountNumber}`,
|
|
843
|
+
unique: true,
|
|
844
|
+
}),
|
|
845
|
+
});
|
|
846
|
+
if (!response.ok) {
|
|
847
|
+
throw new TokenizationError(`Bank account tokenization failed: HTTP ${response.status}`, 'API_ERROR');
|
|
848
|
+
}
|
|
849
|
+
const result = yield response.json();
|
|
850
|
+
if (!result.token) {
|
|
851
|
+
throw new TokenizationError(result.message || 'Bank account tokenization failed: no token returned', 'API_ERROR');
|
|
852
|
+
}
|
|
853
|
+
return result;
|
|
854
|
+
});
|
|
754
855
|
}
|
|
755
856
|
}
|
|
@@ -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) => {
|
|
@@ -241,6 +264,9 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
241
264
|
}
|
|
242
265
|
validate() {
|
|
243
266
|
return __awaiter(this, void 0, void 0, function* () {
|
|
267
|
+
if (!this.isReady) {
|
|
268
|
+
throw new Error('Tokenizer not initialized');
|
|
269
|
+
}
|
|
244
270
|
return {
|
|
245
271
|
isValid: true,
|
|
246
272
|
errors: [],
|
|
@@ -254,6 +280,14 @@ export class PayPalTokenizer extends Tokenizer {
|
|
|
254
280
|
focus(field) {
|
|
255
281
|
}
|
|
256
282
|
destroy() {
|
|
283
|
+
if (this.buttonsInstance) {
|
|
284
|
+
try {
|
|
285
|
+
this.buttonsInstance.close();
|
|
286
|
+
}
|
|
287
|
+
catch (_a) {
|
|
288
|
+
}
|
|
289
|
+
this.buttonsInstance = undefined;
|
|
290
|
+
}
|
|
257
291
|
if (this.containerEl) {
|
|
258
292
|
this.containerEl.innerHTML = '';
|
|
259
293
|
}
|
|
@@ -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;
|
|
@@ -50,6 +54,7 @@ export declare class SpreedlyTokenizer extends Tokenizer {
|
|
|
50
54
|
private determineLayout;
|
|
51
55
|
private setupResizeObserver;
|
|
52
56
|
private applyLayoutStyles;
|
|
57
|
+
private clearTokenizationState;
|
|
53
58
|
destroy(): void;
|
|
54
59
|
hasToken(): boolean;
|
|
55
60
|
getToken(): PaymentToken | null;
|