@idonatedev/idonate-sdk 1.2.0-dev13 → 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/esm/types.d.ts +4 -4
- 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/dist/types.d.ts +4 -4
- package/package.json +1 -1
- package/umd/idonate-sdk.js +1 -1
|
@@ -8,14 +8,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
12
|
exports.CardConnectTokenizer = void 0;
|
|
16
13
|
const Tokenizer_1 = require("./Tokenizer");
|
|
17
14
|
const types_1 = require("./types");
|
|
18
|
-
const config_handler_1 = __importDefault(require("../config-handler"));
|
|
19
15
|
const styles_1 = require("./styles");
|
|
20
16
|
const tokenizer_constants_1 = require("./tokenizer-constants");
|
|
21
17
|
const tokenizer_utils_1 = require("./tokenizer-utils");
|
|
@@ -40,7 +36,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
40
36
|
}
|
|
41
37
|
static create(gateway, container, config) {
|
|
42
38
|
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
-
var _a;
|
|
39
|
+
var _a, _b;
|
|
44
40
|
if (container.mode === 'bank_account' && container.bankCountry === 'CA') {
|
|
45
41
|
throw new Error('CardConnect does not support Canadian bank accounts');
|
|
46
42
|
}
|
|
@@ -48,7 +44,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
48
44
|
if (container.layout === 'responsive') {
|
|
49
45
|
const containerEl = document.getElementById(container.containerId);
|
|
50
46
|
const containerWidth = (containerEl === null || containerEl === void 0 ? void 0 : containerEl.offsetWidth) || 0;
|
|
51
|
-
const breakpoint = container.responsiveBreakpoint
|
|
47
|
+
const breakpoint = (_a = container.responsiveBreakpoint) !== null && _a !== void 0 ? _a : tokenizer_constants_1.RESPONSIVE_BREAKPOINT;
|
|
52
48
|
effectiveLayout =
|
|
53
49
|
containerWidth < breakpoint ? 'two-line' : 'single-line';
|
|
54
50
|
}
|
|
@@ -56,8 +52,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
56
52
|
effectiveLayout = 'two-line';
|
|
57
53
|
}
|
|
58
54
|
const resolvedContainer = Object.assign(Object.assign({}, container), { layout: effectiveLayout });
|
|
59
|
-
|
|
60
|
-
config.cardConnectBaseUrl = baseUrl;
|
|
55
|
+
const baseUrl = ((_b = gateway.config) === null || _b === void 0 ? void 0 : _b.baseUrl) || config.clientConfig.cardConnectBaseUrl;
|
|
61
56
|
const mergedStyles = (0, styles_1.mergeStyles)(styles_1.DEFAULT_UNIFIED_STYLES, container.styling);
|
|
62
57
|
const iframeUrl = CardConnectTokenizer.generateIframeUrl(baseUrl, resolvedContainer);
|
|
63
58
|
const iframe = CardConnectTokenizer.createIframe(iframeUrl, mergedStyles);
|
|
@@ -145,6 +140,66 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
145
140
|
this.applyInputStyles(this.accountTypeEl, mergedStyles, 'right');
|
|
146
141
|
containerEl.appendChild(this.accountTypeEl);
|
|
147
142
|
}
|
|
143
|
+
this.mergedStyles = mergedStyles;
|
|
144
|
+
this.currentValidationState = {
|
|
145
|
+
isValid: false,
|
|
146
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
147
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
148
|
+
};
|
|
149
|
+
this.addBankAccountValidationListeners(mergedStyles);
|
|
150
|
+
}
|
|
151
|
+
addBankAccountValidationListeners(styles) {
|
|
152
|
+
if (this.routingNumberEl) {
|
|
153
|
+
this.routingNumberEl.addEventListener('blur', () => {
|
|
154
|
+
this.updateBankAccountValidation(styles);
|
|
155
|
+
});
|
|
156
|
+
this.routingNumberEl.addEventListener('input', () => {
|
|
157
|
+
this.updateBankAccountValidation(styles);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (this.accountNumberEl) {
|
|
161
|
+
this.accountNumberEl.addEventListener('blur', () => {
|
|
162
|
+
this.updateBankAccountValidation(styles);
|
|
163
|
+
});
|
|
164
|
+
this.accountNumberEl.addEventListener('input', () => {
|
|
165
|
+
this.updateBankAccountValidation(styles);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
updateBankAccountValidation(styles) {
|
|
170
|
+
var _a, _b;
|
|
171
|
+
const routingValue = ((_a = this.routingNumberEl) === null || _a === void 0 ? void 0 : _a.value) || '';
|
|
172
|
+
const accountValue = ((_b = this.accountNumberEl) === null || _b === void 0 ? void 0 : _b.value) || '';
|
|
173
|
+
const routingValid = routingValue.length > 0 && (0, tokenizer_utils_1.validateRoutingNumber)(routingValue);
|
|
174
|
+
const accountValid = accountValue.length > 0 && (0, tokenizer_utils_1.validateAccountNumber)(accountValue);
|
|
175
|
+
if (this.routingNumberEl) {
|
|
176
|
+
if (routingValue.length > 0 && !routingValid) {
|
|
177
|
+
this.routingNumberEl.style.borderColor = styles.error.borderColor;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
this.routingNumberEl.style.borderColor = '';
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (this.accountNumberEl) {
|
|
184
|
+
if (accountValue.length > 0 && !accountValid) {
|
|
185
|
+
this.accountNumberEl.style.borderColor = styles.error.borderColor;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
this.accountNumberEl.style.borderColor = '';
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
this.currentValidationState = {
|
|
192
|
+
isValid: routingValid && accountValid,
|
|
193
|
+
routingNumber: {
|
|
194
|
+
isValid: routingValid,
|
|
195
|
+
isEmpty: routingValue.length === 0,
|
|
196
|
+
},
|
|
197
|
+
accountNumber: {
|
|
198
|
+
isValid: accountValid,
|
|
199
|
+
isEmpty: accountValue.length === 0,
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
this.emit('validation', this.currentValidationState);
|
|
148
203
|
}
|
|
149
204
|
init() {
|
|
150
205
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -214,6 +269,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
214
269
|
}
|
|
215
270
|
tokenizeCardInternal(cardData) {
|
|
216
271
|
return __awaiter(this, void 0, void 0, function* () {
|
|
272
|
+
var _a, _b, _c;
|
|
217
273
|
if (this.cachedTokenResult && this.cachedTokenResult.errorCode === '0') {
|
|
218
274
|
return {
|
|
219
275
|
token: this.cachedTokenResult.token,
|
|
@@ -225,20 +281,22 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
225
281
|
if (this.tokenizationPromise) {
|
|
226
282
|
return this.tokenizationPromise;
|
|
227
283
|
}
|
|
284
|
+
if (!this.currentValidationState.isValid &&
|
|
285
|
+
(((_a = this.currentValidationState.cardNumber) === null || _a === void 0 ? void 0 : _a.isEmpty) ||
|
|
286
|
+
((_b = this.currentValidationState.cvv) === null || _b === void 0 ? void 0 : _b.isEmpty) ||
|
|
287
|
+
((_c = this.currentValidationState.expiry) === null || _c === void 0 ? void 0 : _c.isEmpty))) {
|
|
288
|
+
throw new types_1.TokenizationError('Card fields are incomplete', 'VALIDATION_ERROR');
|
|
289
|
+
}
|
|
228
290
|
this.tokenizationPromise = new Promise((resolve, reject) => {
|
|
229
291
|
this.tokenizationResolve = resolve;
|
|
230
292
|
this.tokenizationReject = reject;
|
|
231
|
-
|
|
293
|
+
this.tokenizationTimeout = setTimeout(() => {
|
|
294
|
+
this.tokenizationTimeout = undefined;
|
|
232
295
|
this.tokenizationPromise = undefined;
|
|
233
296
|
this.tokenizationResolve = undefined;
|
|
234
297
|
this.tokenizationReject = undefined;
|
|
235
298
|
reject(new types_1.TokenizationError('Tokenization timeout - ensure all card fields are filled in iframe', 'TIMEOUT'));
|
|
236
299
|
}, tokenizer_constants_1.TOKENIZE_TIMEOUT);
|
|
237
|
-
const tokenizationHandler = (data) => {
|
|
238
|
-
clearTimeout(timeout);
|
|
239
|
-
this.off('tokenization', tokenizationHandler);
|
|
240
|
-
};
|
|
241
|
-
this.on('tokenization', tokenizationHandler);
|
|
242
300
|
});
|
|
243
301
|
return this.tokenizationPromise;
|
|
244
302
|
});
|
|
@@ -260,9 +318,7 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
260
318
|
throw new types_1.TokenizationError('Invalid account number', 'VALIDATION_ERROR');
|
|
261
319
|
}
|
|
262
320
|
const baseUrl = new URL(this.iframeUrl).origin;
|
|
263
|
-
const
|
|
264
|
-
config.cardConnectBaseUrl = baseUrl;
|
|
265
|
-
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, config);
|
|
321
|
+
const result = yield CardConnectTokenizer.tokenizeBankAccount(routingNumber, accountNumber, baseUrl);
|
|
266
322
|
return {
|
|
267
323
|
token: result.token,
|
|
268
324
|
lastFour: accountNumber.slice(-4),
|
|
@@ -406,12 +462,25 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
406
462
|
action: 'clear',
|
|
407
463
|
}, this.expectedOrigin);
|
|
408
464
|
}
|
|
409
|
-
this.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
465
|
+
this.cachedTokenResult = undefined;
|
|
466
|
+
this.tokenizationPromise = undefined;
|
|
467
|
+
this.tokenizationResolve = undefined;
|
|
468
|
+
this.tokenizationReject = undefined;
|
|
469
|
+
if (this.mode === 'bank_account') {
|
|
470
|
+
this.currentValidationState = {
|
|
471
|
+
isValid: false,
|
|
472
|
+
routingNumber: { isValid: false, isEmpty: true },
|
|
473
|
+
accountNumber: { isValid: false, isEmpty: true },
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
this.currentValidationState = {
|
|
478
|
+
isValid: false,
|
|
479
|
+
cardNumber: { isValid: false, isEmpty: true },
|
|
480
|
+
cvv: { isValid: false, isEmpty: true },
|
|
481
|
+
expiry: { isValid: false, isEmpty: true },
|
|
482
|
+
};
|
|
483
|
+
}
|
|
415
484
|
this.emit('validation', this.currentValidationState);
|
|
416
485
|
}
|
|
417
486
|
focus(field) {
|
|
@@ -440,8 +509,21 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
440
509
|
}
|
|
441
510
|
}
|
|
442
511
|
destroy() {
|
|
512
|
+
if (this.tokenizationTimeout) {
|
|
513
|
+
clearTimeout(this.tokenizationTimeout);
|
|
514
|
+
this.tokenizationTimeout = undefined;
|
|
515
|
+
}
|
|
516
|
+
if (this.tokenizationReject) {
|
|
517
|
+
const reject = this.tokenizationReject;
|
|
518
|
+
this.tokenizationPromise = undefined;
|
|
519
|
+
this.tokenizationResolve = undefined;
|
|
520
|
+
this.tokenizationReject = undefined;
|
|
521
|
+
reject(new types_1.TokenizationError('Tokenizer destroyed', 'DESTROYED'));
|
|
522
|
+
}
|
|
523
|
+
this.cachedTokenResult = undefined;
|
|
443
524
|
if (this.messageHandler) {
|
|
444
525
|
window.removeEventListener('message', this.messageHandler);
|
|
526
|
+
this.messageHandler = undefined;
|
|
445
527
|
}
|
|
446
528
|
if (this.containerEl) {
|
|
447
529
|
this.containerEl.innerHTML = '';
|
|
@@ -481,7 +563,10 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
481
563
|
const data = typeof event.data === 'string' ? JSON.parse(event.data) : event.data;
|
|
482
564
|
if (data.token && data.errorCode !== undefined) {
|
|
483
565
|
this.cachedTokenResult = data;
|
|
484
|
-
this.
|
|
566
|
+
if (this.tokenizationTimeout) {
|
|
567
|
+
clearTimeout(this.tokenizationTimeout);
|
|
568
|
+
this.tokenizationTimeout = undefined;
|
|
569
|
+
}
|
|
485
570
|
if (data.errorCode === '0') {
|
|
486
571
|
const cardType = data.cardType
|
|
487
572
|
? this.normalizeCardType(data.cardType)
|
|
@@ -508,12 +593,14 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
508
593
|
cvv: { isValid: true, isEmpty: false },
|
|
509
594
|
expiry: { isValid: true, isEmpty: false },
|
|
510
595
|
};
|
|
511
|
-
this.emit('validation',
|
|
596
|
+
this.emit('validation', this.currentValidationState);
|
|
512
597
|
this.emit('tokenReady', token);
|
|
513
598
|
}
|
|
514
599
|
else {
|
|
600
|
+
const error = new types_1.TokenizationError(data.errorMessage || 'Tokenization failed', data.errorCode || 'UNKNOWN');
|
|
601
|
+
this.emit('error', error);
|
|
515
602
|
if (this.tokenizationReject) {
|
|
516
|
-
this.tokenizationReject(
|
|
603
|
+
this.tokenizationReject(error);
|
|
517
604
|
this.tokenizationPromise = undefined;
|
|
518
605
|
this.tokenizationResolve = undefined;
|
|
519
606
|
this.tokenizationReject = undefined;
|
|
@@ -523,17 +610,12 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
523
610
|
if (data.event === 'validation' || data.validationError !== undefined) {
|
|
524
611
|
this.handleValidationMessage(data);
|
|
525
612
|
}
|
|
526
|
-
if (data.event === '
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
const cardType = this.normalizeCardType(data.cardType);
|
|
533
|
-
if (cardType !== this.currentCardType) {
|
|
534
|
-
this.currentCardType = cardType;
|
|
535
|
-
this.emit('cardTypeChange', { cardType });
|
|
536
|
-
}
|
|
613
|
+
if ((data.event === 'input' || data.event === 'change') &&
|
|
614
|
+
data.cardType) {
|
|
615
|
+
const cardType = this.normalizeCardType(data.cardType);
|
|
616
|
+
if (cardType !== this.currentCardType) {
|
|
617
|
+
this.currentCardType = cardType;
|
|
618
|
+
this.emit('cardTypeChange', { cardType });
|
|
537
619
|
}
|
|
538
620
|
}
|
|
539
621
|
}
|
|
@@ -541,7 +623,6 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
541
623
|
}
|
|
542
624
|
}
|
|
543
625
|
handleValidationMessage(data) {
|
|
544
|
-
var _a, _b, _c, _d, _e, _f;
|
|
545
626
|
if (data.validationError) {
|
|
546
627
|
const errorLower = data.validationError.toLowerCase();
|
|
547
628
|
if (errorLower.includes('card') || errorLower.includes('number')) {
|
|
@@ -563,10 +644,14 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
563
644
|
this.emit('validation', this.currentValidationState);
|
|
564
645
|
}
|
|
565
646
|
else {
|
|
566
|
-
this.currentValidationState.
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
647
|
+
this.currentValidationState.cardNumber = {
|
|
648
|
+
isValid: true,
|
|
649
|
+
isEmpty: false,
|
|
650
|
+
};
|
|
651
|
+
this.currentValidationState.cvv = { isValid: true, isEmpty: false };
|
|
652
|
+
this.currentValidationState.expiry = { isValid: true, isEmpty: false };
|
|
653
|
+
this.currentValidationState.isValid = true;
|
|
654
|
+
this.emit('validation', this.currentValidationState);
|
|
570
655
|
}
|
|
571
656
|
}
|
|
572
657
|
static generateIframeUrl(baseUrl, container) {
|
|
@@ -746,17 +831,30 @@ class CardConnectTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
746
831
|
}
|
|
747
832
|
return encodeURIComponent(css.join(''));
|
|
748
833
|
}
|
|
749
|
-
static tokenizeBankAccount(routingNumber, accountNumber,
|
|
750
|
-
return
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
834
|
+
static tokenizeBankAccount(routingNumber, accountNumber, configOrBaseUrl) {
|
|
835
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
836
|
+
const baseUrl = typeof configOrBaseUrl === 'string'
|
|
837
|
+
? configOrBaseUrl
|
|
838
|
+
: configOrBaseUrl.cardConnectBaseUrl;
|
|
839
|
+
const response = yield fetch(`${baseUrl}/cardsecure/api/v1/ccn/tokenize`, {
|
|
840
|
+
method: 'POST',
|
|
841
|
+
headers: {
|
|
842
|
+
'Content-Type': 'application/json',
|
|
843
|
+
},
|
|
844
|
+
body: JSON.stringify({
|
|
845
|
+
account: `${routingNumber}/${accountNumber}`,
|
|
846
|
+
unique: true,
|
|
847
|
+
}),
|
|
848
|
+
});
|
|
849
|
+
if (!response.ok) {
|
|
850
|
+
throw new types_1.TokenizationError(`Bank account tokenization failed: HTTP ${response.status}`, 'API_ERROR');
|
|
851
|
+
}
|
|
852
|
+
const result = yield response.json();
|
|
853
|
+
if (!result.token) {
|
|
854
|
+
throw new types_1.TokenizationError(result.message || 'Bank account tokenization failed: no token returned', 'API_ERROR');
|
|
855
|
+
}
|
|
856
|
+
return result;
|
|
857
|
+
});
|
|
760
858
|
}
|
|
761
859
|
}
|
|
762
860
|
exports.CardConnectTokenizer = CardConnectTokenizer;
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.PayPalTokenizer = void 0;
|
|
13
13
|
const Tokenizer_1 = require("./Tokenizer");
|
|
14
14
|
const types_1 = require("./types");
|
|
15
|
+
const constants_1 = require("../constants");
|
|
15
16
|
const PAYPAL_SDK_URL = 'https://www.paypal.com/sdk/js';
|
|
16
17
|
const PAYPAL_SCRIPT_ID = 'paypal-sdk-script';
|
|
17
18
|
const INIT_TIMEOUT = 10000;
|
|
@@ -22,7 +23,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
22
23
|
this.gateway = gateway;
|
|
23
24
|
this.containerId = containerId;
|
|
24
25
|
this.configContext = configContext;
|
|
25
|
-
this.mode = '
|
|
26
|
+
this.mode = 'paypal';
|
|
26
27
|
const gatewayConfig = gateway.config;
|
|
27
28
|
if (!(gatewayConfig === null || gatewayConfig === void 0 ? void 0 : gatewayConfig.client_id)) {
|
|
28
29
|
throw new Error('PayPal gateway configuration missing client_id');
|
|
@@ -69,7 +70,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
69
70
|
})
|
|
70
71
|
.then(() => {
|
|
71
72
|
this.emit('ready');
|
|
72
|
-
this.emit('validation', { isValid: true });
|
|
73
|
+
this.emit('validation', { isValid: true, hasToken: false });
|
|
73
74
|
resolve();
|
|
74
75
|
})
|
|
75
76
|
.catch((error) => {
|
|
@@ -82,11 +83,20 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
82
83
|
}
|
|
83
84
|
loadPayPalSDK() {
|
|
84
85
|
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
const configKey = `${this.clientId}|${this.currency}`;
|
|
87
|
+
const existingScript = document.getElementById(PAYPAL_SCRIPT_ID);
|
|
88
|
+
if (existingScript) {
|
|
89
|
+
const loadedConfig = existingScript.getAttribute('data-config-key');
|
|
90
|
+
if (loadedConfig && loadedConfig !== configKey) {
|
|
91
|
+
existingScript.remove();
|
|
92
|
+
delete window.paypal;
|
|
93
|
+
}
|
|
94
|
+
else if (window.paypal) {
|
|
95
|
+
return Promise.resolve();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
return this.waitForPayPalGlobal();
|
|
99
|
+
}
|
|
90
100
|
}
|
|
91
101
|
const params = new URLSearchParams({
|
|
92
102
|
'client-id': this.clientId,
|
|
@@ -105,6 +115,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
105
115
|
script.id = PAYPAL_SCRIPT_ID;
|
|
106
116
|
script.src = `${PAYPAL_SDK_URL}?${params.toString()}`;
|
|
107
117
|
script.async = true;
|
|
118
|
+
script.setAttribute('data-config-key', configKey);
|
|
108
119
|
return new Promise((resolve, reject) => {
|
|
109
120
|
script.onload = () => {
|
|
110
121
|
this.waitForPayPalGlobal().then(resolve).catch(reject);
|
|
@@ -148,7 +159,7 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
148
159
|
if (!window.paypal || !this.paypalButtonContainer) {
|
|
149
160
|
return;
|
|
150
161
|
}
|
|
151
|
-
|
|
162
|
+
this.buttonsInstance = window.paypal.Buttons({
|
|
152
163
|
createOrder: () => this.createOrder(),
|
|
153
164
|
onApprove: (data) => this.handleApprove(data),
|
|
154
165
|
onCancel: (data) => this.handleCancel(data),
|
|
@@ -159,36 +170,48 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
159
170
|
height: 40,
|
|
160
171
|
},
|
|
161
172
|
});
|
|
162
|
-
yield
|
|
173
|
+
yield this.buttonsInstance.render(this.paypalButtonContainer);
|
|
163
174
|
});
|
|
164
175
|
}
|
|
165
176
|
createOrder() {
|
|
166
177
|
const endpoint = `${this.clientConfig.embedApiBaseUrl}/payment/paypal/create-order`;
|
|
178
|
+
this.paymentTransactionId = undefined;
|
|
179
|
+
this.paymentMethodId = undefined;
|
|
167
180
|
let orderAmount;
|
|
168
181
|
let orderCurrency = this.currency;
|
|
169
182
|
if (this.onCreateOrder) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
try {
|
|
184
|
+
const orderData = this.onCreateOrder();
|
|
185
|
+
orderAmount = orderData.amount;
|
|
186
|
+
orderCurrency = orderData.currency || this.currency;
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
const error = err instanceof Error
|
|
190
|
+
? err
|
|
191
|
+
: new Error('onCreateOrder callback failed');
|
|
192
|
+
this.handleError(error, 'Order creation failed');
|
|
193
|
+
return Promise.reject(error);
|
|
194
|
+
}
|
|
173
195
|
}
|
|
174
196
|
else {
|
|
175
197
|
orderAmount = this.amount;
|
|
176
198
|
}
|
|
177
|
-
if (orderAmount === undefined || orderAmount <= 0) {
|
|
199
|
+
if (orderAmount === undefined || isNaN(orderAmount) || orderAmount <= 0) {
|
|
178
200
|
const error = new Error('Amount is required to create PayPal order');
|
|
179
201
|
this.handleError(error, 'Order creation failed');
|
|
180
202
|
return Promise.reject(error);
|
|
181
203
|
}
|
|
182
204
|
const requestBody = {
|
|
183
205
|
payment_gateway_id: this.gateway.id,
|
|
206
|
+
organization_id: this.organizationId,
|
|
207
|
+
embed_id: this.embedId,
|
|
184
208
|
currency: orderCurrency,
|
|
185
209
|
amount: orderAmount,
|
|
186
210
|
};
|
|
187
211
|
return fetch(endpoint, {
|
|
188
212
|
method: 'POST',
|
|
189
|
-
headers:
|
|
190
|
-
|
|
191
|
-
},
|
|
213
|
+
headers: constants_1.CLIENT_HEADERS,
|
|
214
|
+
credentials: 'include',
|
|
192
215
|
body: JSON.stringify(requestBody),
|
|
193
216
|
})
|
|
194
217
|
.then((response) => {
|
|
@@ -244,6 +267,9 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
244
267
|
}
|
|
245
268
|
validate() {
|
|
246
269
|
return __awaiter(this, void 0, void 0, function* () {
|
|
270
|
+
if (!this.isReady) {
|
|
271
|
+
throw new Error('Tokenizer not initialized');
|
|
272
|
+
}
|
|
247
273
|
return {
|
|
248
274
|
isValid: true,
|
|
249
275
|
errors: [],
|
|
@@ -257,6 +283,14 @@ class PayPalTokenizer extends Tokenizer_1.Tokenizer {
|
|
|
257
283
|
focus(field) {
|
|
258
284
|
}
|
|
259
285
|
destroy() {
|
|
286
|
+
if (this.buttonsInstance) {
|
|
287
|
+
try {
|
|
288
|
+
this.buttonsInstance.close();
|
|
289
|
+
}
|
|
290
|
+
catch (_a) {
|
|
291
|
+
}
|
|
292
|
+
this.buttonsInstance = undefined;
|
|
293
|
+
}
|
|
260
294
|
if (this.containerEl) {
|
|
261
295
|
this.containerEl.innerHTML = '';
|
|
262
296
|
}
|
|
@@ -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;
|