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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/esm/apple-pay.d.ts +12 -0
  2. package/dist/esm/apple-pay.js +74 -0
  3. package/dist/esm/cloudflare-challenge-handler.d.ts +5 -0
  4. package/dist/esm/cloudflare-challenge-handler.js +77 -0
  5. package/dist/esm/config-handler.d.ts +22 -0
  6. package/dist/esm/config-handler.js +47 -0
  7. package/dist/esm/constants.d.ts +18 -0
  8. package/dist/esm/constants.js +82 -0
  9. package/dist/esm/google-pay.d.ts +18 -0
  10. package/dist/esm/google-pay.js +140 -0
  11. package/dist/esm/idonate-client.d.ts +28 -0
  12. package/dist/esm/idonate-client.js +256 -0
  13. package/dist/esm/index.d.ts +11 -0
  14. package/dist/esm/index.js +11 -0
  15. package/dist/esm/recaptcha.d.ts +12 -0
  16. package/dist/esm/recaptcha.js +89 -0
  17. package/dist/esm/shared.d.ts +3 -0
  18. package/dist/esm/shared.js +13 -0
  19. package/dist/esm/test-utils.d.ts +81 -0
  20. package/dist/esm/test-utils.js +94 -0
  21. package/dist/esm/tokenize/CardConnectTokenizer.d.ts +51 -0
  22. package/dist/esm/tokenize/CardConnectTokenizer.js +706 -0
  23. package/dist/esm/tokenize/SpreedlyTokenizer.d.ts +92 -0
  24. package/dist/esm/tokenize/SpreedlyTokenizer.js +1140 -0
  25. package/dist/esm/tokenize/Tokenizer.d.ts +37 -0
  26. package/dist/esm/tokenize/Tokenizer.js +146 -0
  27. package/dist/esm/tokenize/iats.d.ts +3 -0
  28. package/dist/esm/tokenize/iats.js +48 -0
  29. package/dist/esm/tokenize/index.d.ts +6 -0
  30. package/dist/esm/tokenize/index.js +6 -0
  31. package/dist/esm/tokenize/spreedly-secure.d.ts +8 -0
  32. package/dist/esm/tokenize/spreedly-secure.js +40 -0
  33. package/dist/esm/tokenize/styles.d.ts +4 -0
  34. package/dist/esm/tokenize/styles.js +46 -0
  35. package/dist/esm/tokenize/tokenizer-constants.d.ts +62 -0
  36. package/dist/esm/tokenize/tokenizer-constants.js +62 -0
  37. package/dist/esm/tokenize/tokenizer-utils.d.ts +19 -0
  38. package/dist/esm/tokenize/tokenizer-utils.js +139 -0
  39. package/dist/esm/tokenize/types.d.ts +144 -0
  40. package/dist/esm/tokenize/types.js +26 -0
  41. package/dist/esm/typeAdapters.d.ts +29 -0
  42. package/dist/esm/typeAdapters.js +188 -0
  43. package/dist/esm/types.d.ts +367 -0
  44. package/dist/esm/types.js +14 -0
  45. package/dist/esm/util.d.ts +17 -0
  46. package/dist/esm/util.js +113 -0
  47. package/package.json +12 -2
  48. package/umd/idonate-sdk.js +1 -1
@@ -0,0 +1,256 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { ClientError, } from './types';
11
+ import { buildDonationResult, buildCashPaymentPayload } from './typeAdapters';
12
+ import { CLIENT_HEADERS, SDK_VERSION } from './constants';
13
+ import { parseResponse } from './util';
14
+ import ApplePay from './apple-pay';
15
+ import ConfigHandler from './config-handler';
16
+ import { SpreedlyTokenizer } from './tokenize/SpreedlyTokenizer';
17
+ import * as shared from './shared';
18
+ import { v4 as uuidv4 } from 'uuid';
19
+ import { handleCFChallenge } from './cloudflare-challenge-handler';
20
+ import { Tokenizer, } from './tokenize';
21
+ const clientDefaults = {
22
+ enableSandboxMode: false,
23
+ overrideBaseUrl: undefined,
24
+ enableDelay: false,
25
+ secondsToDelay: 0,
26
+ };
27
+ export default class iDonateClient {
28
+ get organizationId() {
29
+ if (!this.currentOrganizationId) {
30
+ throw new Error('organizationId undefined');
31
+ }
32
+ return this.currentOrganizationId;
33
+ }
34
+ constructor(clientKey, embedId, options) {
35
+ var _a;
36
+ this.clientKey = clientKey;
37
+ this.embedId = embedId;
38
+ this.currentOrganizationId = clientKey;
39
+ this.options = Object.assign({}, clientDefaults, options);
40
+ this.allowTransaction = false;
41
+ this.config = new ConfigHandler(this.options);
42
+ const configEntries = Object.entries(this.config);
43
+ for (const [key, value] of configEntries) {
44
+ const descriptor = Object.getOwnPropertyDescriptor(this, key);
45
+ if (!descriptor || descriptor.set !== undefined) {
46
+ try {
47
+ this[key] = value;
48
+ }
49
+ catch (e) {
50
+ }
51
+ }
52
+ }
53
+ if (this.options.enableDelay && this.options.secondsToDelay) {
54
+ const delay = this.options.secondsToDelay * 1000;
55
+ setTimeout(() => {
56
+ this.allowTransaction = true;
57
+ }, delay);
58
+ }
59
+ else {
60
+ this.allowTransaction = true;
61
+ }
62
+ if (this.options.enableSandboxMode && console !== undefined) {
63
+ console.info(`[Sandbox] iDonate SDK Configuration (v${SDK_VERSION}):`, JSON.parse(JSON.stringify(this)));
64
+ }
65
+ try {
66
+ const { pcScriptBase, pcScriptId } = this.config;
67
+ if (!pcScriptBase || !pcScriptId) {
68
+ throw new Error('missing config');
69
+ }
70
+ const uuid = uuidv4();
71
+ const script = window.document.createElement('script');
72
+ script.setAttribute('src', pcScriptBase + '/' + uuid + '.js');
73
+ script.setAttribute('id', pcScriptId);
74
+ let appended = false;
75
+ const appendScript = () => {
76
+ var _a;
77
+ try {
78
+ if (appended)
79
+ return;
80
+ window.document.body.append(script);
81
+ appended = true;
82
+ }
83
+ catch (e) {
84
+ (_a = console === null || console === void 0 ? void 0 : console.warn) === null || _a === void 0 ? void 0 : _a.call(console, 'not appended');
85
+ }
86
+ };
87
+ appendScript();
88
+ window.addEventListener('DOMContentLoaded', () => {
89
+ window.document.body.append(script);
90
+ });
91
+ }
92
+ catch (e) {
93
+ (_a = console === null || console === void 0 ? void 0 : console.warn) === null || _a === void 0 ? void 0 : _a.call(console, 'Warning, partial initialization: ', String(e));
94
+ }
95
+ if (!this.currentOrganizationId) {
96
+ this.setOrganizationId(this.clientKey);
97
+ }
98
+ }
99
+ createDonation(donation) {
100
+ if (!this.allowTransaction) {
101
+ throw new Error('Wow, that was fast - try again');
102
+ }
103
+ if (!donation.embedId) {
104
+ donation.embedId = this.embedId;
105
+ }
106
+ const payload = buildCashPaymentPayload(this.organizationId, donation);
107
+ const fetchCall = (clearanceToken) => fetch(`${this.config.embedApiBaseUrl}/donate/cash-payment`, {
108
+ method: 'POST',
109
+ headers: Object.assign(Object.assign(Object.assign({}, CLIENT_HEADERS), (clearanceToken ? { 'cf-validation-token': clearanceToken } : {})), { 'User-Agent': CLIENT_HEADERS['User-Agent'] + ' source:' + this.config.client }),
110
+ body: JSON.stringify(payload),
111
+ credentials: 'include',
112
+ });
113
+ return (fetchCall()
114
+ .then((response) => __awaiter(this, void 0, void 0, function* () {
115
+ if (response.headers.get('cf-mitigated') === 'challenge') {
116
+ const clearance = yield handleCFChallenge(response, this);
117
+ return fetchCall(clearance === null || clearance === void 0 ? void 0 : clearance.token);
118
+ }
119
+ return response;
120
+ }))
121
+ .then((response) => parseResponse(response, { throwErrors: true }))
122
+ .then((response) => buildDonationResult(response)));
123
+ }
124
+ createTransaction(donation) {
125
+ return this.createDonation(donation).then((result) => {
126
+ var _a;
127
+ return {
128
+ transactionId: (_a = result.transaction) === null || _a === void 0 ? void 0 : _a.id,
129
+ _raw_response: result._raw_response,
130
+ };
131
+ });
132
+ }
133
+ createPaymentMethod(paymentMethod) {
134
+ if (!paymentMethod.embedId) {
135
+ paymentMethod.embedId = this.embedId;
136
+ }
137
+ return shared.createPaymentMethod(paymentMethod, this.config);
138
+ }
139
+ setOrganizationId(organizationId) {
140
+ this.currentOrganizationId = organizationId;
141
+ }
142
+ waitForDonationResult(donationId, afterEachCheck) {
143
+ function isReady(response) {
144
+ return !!response.processed && !!response.transaction;
145
+ }
146
+ return new Promise((resolve, reject) => {
147
+ setTimeout(() => {
148
+ let pollHandle;
149
+ pollHandle = setInterval(() => {
150
+ fetch(`${this.config.embedApiBaseUrl}/donate/cash-payment/${donationId}/payment_status`, {
151
+ method: 'GET',
152
+ headers: {
153
+ 'Content-Type': 'application/json',
154
+ },
155
+ })
156
+ .then((response) => response.json())
157
+ .then((rawResponse) => rawResponse.result)
158
+ .then((response) => {
159
+ if (isReady(response)) {
160
+ if (pollHandle) {
161
+ clearInterval(pollHandle);
162
+ pollHandle = null;
163
+ }
164
+ if (response.error) {
165
+ reject(new ClientError(response.error));
166
+ }
167
+ resolve(buildDonationResult({
168
+ _raw_response: Object.assign({ campaign: null, designation: {}, donor: {}, form_data: {}, id: null, schedule: {}, transaction: {} }, response),
169
+ }));
170
+ }
171
+ else {
172
+ }
173
+ afterEachCheck === null || afterEachCheck === void 0 ? void 0 : afterEachCheck();
174
+ })
175
+ .catch((e) => {
176
+ if (pollHandle) {
177
+ clearInterval(pollHandle);
178
+ pollHandle = null;
179
+ }
180
+ reject(e);
181
+ });
182
+ }, 2000);
183
+ }, 2000);
184
+ });
185
+ }
186
+ tokenizeCardConnectApplePay(applePayRequest) {
187
+ const applePay = new ApplePay(applePayRequest);
188
+ let merchantSessionId = '';
189
+ const promiseStart = applePay.begin();
190
+ return new Promise((resolve, reject) => {
191
+ promiseStart
192
+ .then((session) => {
193
+ session.onvalidatemerchant = (event) => {
194
+ const validationPayload = {
195
+ apple_pay_url: this.config.applePayUrl,
196
+ organization_id: this.organizationId,
197
+ };
198
+ applePay
199
+ .createSession(validationPayload, this.config.embedApiBaseUrl)
200
+ .then((merchantSession) => {
201
+ merchantSessionId =
202
+ merchantSession.result.merchantSessionIdentifier;
203
+ session.completeMerchantValidation(merchantSession.result);
204
+ })
205
+ .catch((err) => {
206
+ session.abort();
207
+ reject(err);
208
+ });
209
+ };
210
+ session.onpaymentauthorized = (event) => {
211
+ applePay
212
+ .tokenizeWithCardConnect(event.payment, this.config.cardConnectBaseUrl)
213
+ .then((data) => {
214
+ var _a, _b;
215
+ const unifiedContact = Object.assign(Object.assign({}, event.payment.billingContact), { email: (_a = event.payment.shippingContact) === null || _a === void 0 ? void 0 : _a.emailAddress, phone: (_b = event.payment.shippingContact) === null || _b === void 0 ? void 0 : _b.phoneNumber });
216
+ const result = {
217
+ applePaySession: session,
218
+ cardConnectResponse: data,
219
+ billingContact: unifiedContact,
220
+ merchantSessionId,
221
+ };
222
+ resolve(result);
223
+ })
224
+ .catch((err) => {
225
+ session.abort();
226
+ reject(err);
227
+ });
228
+ };
229
+ session.oncancel = (event) => {
230
+ reject(new Error('Apple Pay has been closed'));
231
+ };
232
+ })
233
+ .catch((err) => reject(err));
234
+ });
235
+ }
236
+ createTokenizer(gateway, container) {
237
+ return __awaiter(this, void 0, void 0, function* () {
238
+ return Tokenizer.create(gateway, container, {
239
+ organizationId: this.organizationId,
240
+ embedId: this.embedId,
241
+ clientConfig: this.config,
242
+ });
243
+ });
244
+ }
245
+ tokenizeSpreedlyPayPal(data) {
246
+ return SpreedlyTokenizer.tokenizePayPal(data, this.config);
247
+ }
248
+ selectGateway(availableGateways, paymentType, preferredGatewayId) {
249
+ if (preferredGatewayId) {
250
+ const preferred = availableGateways.find((g) => g.id === preferredGatewayId);
251
+ if (preferred)
252
+ return preferred;
253
+ }
254
+ return availableGateways[0];
255
+ }
256
+ }
@@ -0,0 +1,11 @@
1
+ import * as tokenize from './tokenize';
2
+ import * as util from './util';
3
+ import * as recaptcha from './recaptcha';
4
+ import * as constants from './constants';
5
+ import * as shared from './shared';
6
+ import iDonateClient from './idonate-client';
7
+ import ConfigHandler from './config-handler';
8
+ import ApplePay from './apple-pay';
9
+ import GooglePay from './google-pay';
10
+ export * from './types';
11
+ export { tokenize, util, shared, iDonateClient as Client, ConfigHandler, recaptcha, constants, ApplePay, GooglePay, };
@@ -0,0 +1,11 @@
1
+ import * as tokenize from './tokenize';
2
+ import * as util from './util';
3
+ import * as recaptcha from './recaptcha';
4
+ import * as constants from './constants';
5
+ import * as shared from './shared';
6
+ import iDonateClient from './idonate-client';
7
+ import ConfigHandler from './config-handler';
8
+ import ApplePay from './apple-pay';
9
+ import GooglePay from './google-pay';
10
+ export * from './types';
11
+ export { tokenize, util, shared, iDonateClient as Client, ConfigHandler, recaptcha, constants, ApplePay, GooglePay, };
@@ -0,0 +1,12 @@
1
+ export declare function injectScript(callback?: () => void): void;
2
+ export declare class RecaptchaElement {
3
+ private readonly container;
4
+ private readonly params;
5
+ private widgetId;
6
+ private executeResolveQueue;
7
+ private resolvedToken;
8
+ constructor(container: string, params: ReCaptchaV2.Parameters);
9
+ render(): Promise<void>;
10
+ resolveToken(): Promise<string>;
11
+ }
12
+ export declare function wrapElement(container: string, sitekey: string, extraParams?: any): RecaptchaElement;
@@ -0,0 +1,89 @@
1
+ function resolveLib() {
2
+ const startWait = new Date();
3
+ return new Promise((resolve, reject) => {
4
+ function poll() {
5
+ if (window.grecaptcha !== undefined &&
6
+ window.grecaptcha.render !== undefined) {
7
+ resolve(window.grecaptcha);
8
+ }
9
+ else {
10
+ const elapsedMs = new Date().valueOf() - startWait.valueOf();
11
+ if (elapsedMs > 15000) {
12
+ reject(new Error('grecaptcha not loaded after 15 seconds'));
13
+ }
14
+ else {
15
+ setTimeout(poll, 250);
16
+ }
17
+ }
18
+ }
19
+ poll();
20
+ });
21
+ }
22
+ export function injectScript(callback) {
23
+ if (window.grecaptcha !== undefined) {
24
+ throw new Error('grecaptcha is already defined');
25
+ }
26
+ const script = document.createElement('script');
27
+ script.src = 'https://www.google.com/recaptcha/api.js?render=explicit';
28
+ script.async = true;
29
+ script.defer = true;
30
+ script.onload = callback || null;
31
+ if (document.readyState === 'interactive' ||
32
+ document.readyState === 'complete') {
33
+ document.body.appendChild(script);
34
+ }
35
+ else {
36
+ window.addEventListener('DOMContentLoaded', () => {
37
+ document.body.appendChild(script);
38
+ });
39
+ }
40
+ }
41
+ export class RecaptchaElement {
42
+ constructor(container, params) {
43
+ this.container = container;
44
+ this.params = params;
45
+ this.executeResolveQueue = [];
46
+ }
47
+ render() {
48
+ if (this.widgetId !== undefined) {
49
+ console.warn('rendering an already-rendered widget');
50
+ }
51
+ return resolveLib().then((lib) => {
52
+ this.widgetId = lib.render(this.container, Object.assign(Object.assign({}, this.params), { callback: (token) => {
53
+ var _a;
54
+ this.resolvedToken = token;
55
+ (_a = this.executeResolveQueue.pop()) === null || _a === void 0 ? void 0 : _a(token);
56
+ }, 'expired-callback': () => {
57
+ this.resolvedToken = undefined;
58
+ } }));
59
+ });
60
+ }
61
+ resolveToken() {
62
+ return new Promise((resolve, reject) => {
63
+ resolveLib()
64
+ .then((lib) => {
65
+ if (this.params.size !== 'invisible') {
66
+ const response = lib.getResponse();
67
+ return response
68
+ ? resolve(response)
69
+ : reject(new Error('checkbox recaptcha is not checked'));
70
+ }
71
+ this.executeResolveQueue.push(resolve);
72
+ if (this.resolvedToken !== undefined) {
73
+ this.resolvedToken = undefined;
74
+ lib.reset(this.widgetId);
75
+ }
76
+ lib.execute(this.widgetId);
77
+ })
78
+ .catch((e) => {
79
+ reject(e);
80
+ });
81
+ });
82
+ }
83
+ }
84
+ export function wrapElement(container, sitekey, extraParams) {
85
+ const params = Object.assign(Object.assign({}, (extraParams || {})), { sitekey });
86
+ const captcha = new RecaptchaElement(container, params);
87
+ captcha.render();
88
+ return captcha;
89
+ }
@@ -0,0 +1,3 @@
1
+ import { CreatePaymentMethodRequest, CreatePaymentMethodResult } from './types';
2
+ import ConfigHandler from './config-handler';
3
+ export declare function createPaymentMethod(paymentMethod: CreatePaymentMethodRequest, config: ConfigHandler): Promise<CreatePaymentMethodResult>;
@@ -0,0 +1,13 @@
1
+ import { buildCreatePaymentMethodPayload, buildCreatePaymentMethodResult, } from './typeAdapters';
2
+ import { CLIENT_HEADERS } from './constants';
3
+ import { parseResponse } from './util';
4
+ export function createPaymentMethod(paymentMethod, config) {
5
+ const payload = buildCreatePaymentMethodPayload(paymentMethod);
6
+ return fetch(`${config.embedApiBaseUrl}/payment/payment-methods`, {
7
+ method: 'POST',
8
+ headers: CLIENT_HEADERS,
9
+ body: JSON.stringify(payload),
10
+ })
11
+ .then((response) => parseResponse(response, { throwErrors: true }))
12
+ .then((response) => buildCreatePaymentMethodResult(response));
13
+ }
@@ -0,0 +1,81 @@
1
+ export declare const createMockFetch: (response: any, options?: {
2
+ ok?: boolean;
3
+ status?: number;
4
+ }) => jest.Mock<any, any, any>;
5
+ export declare const createMockFetchError: (message: string) => jest.Mock<any, any, any>;
6
+ export declare const createMockFetchWithImplementation: (implementation: (url: string, options?: any) => Promise<any>) => jest.Mock<any, any, any>;
7
+ export declare const setupFetchMock: () => jest.Mock<any, any, any>;
8
+ export declare const setupDocumentMock: () => {
9
+ mockScript: {
10
+ src: string;
11
+ async: boolean;
12
+ defer: boolean;
13
+ };
14
+ mockAppendChild: jest.Mock<any, any, any>;
15
+ mockCreateElement: jest.Mock<any, [], any>;
16
+ };
17
+ export declare const setupApplePayEnvironment: (options?: {
18
+ canMakePayments?: boolean;
19
+ supportsVersion?: boolean;
20
+ }) => {
21
+ mockSession: {
22
+ begin: jest.Mock<any, any, any>;
23
+ abort: jest.Mock<any, any, any>;
24
+ completeMerchantValidation: jest.Mock<any, any, any>;
25
+ completePayment: jest.Mock<any, any, any>;
26
+ };
27
+ ApplePaySessionMock: any;
28
+ };
29
+ export declare const setupGooglePayEnvironment: (options?: {
30
+ autoLoad?: boolean;
31
+ }) => {
32
+ mockPaymentsClient: {
33
+ isReadyToPay: jest.Mock<any, any, any>;
34
+ loadPaymentData: jest.Mock<any, any, any>;
35
+ };
36
+ googlePayMock: {
37
+ payments: {
38
+ api: {
39
+ PaymentsClient: jest.Mock<{
40
+ isReadyToPay: jest.Mock<any, any, any>;
41
+ loadPaymentData: jest.Mock<any, any, any>;
42
+ }, [], any>;
43
+ };
44
+ };
45
+ };
46
+ };
47
+ export declare const setupRecaptchaEnvironment: () => {
48
+ render: jest.Mock<any, any, any>;
49
+ reset: jest.Mock<any, any, any>;
50
+ execute: jest.Mock<any, any, any>;
51
+ getResponse: jest.Mock<any, any, any>;
52
+ };
53
+ export declare const createTestContact: (overrides?: {}) => {
54
+ salutation: string;
55
+ firstName: string;
56
+ lastName: string;
57
+ company: string;
58
+ email: string;
59
+ primaryPhone: string;
60
+ };
61
+ export declare const createTestAddress: (overrides?: {}) => {
62
+ address1: string;
63
+ address2: string;
64
+ city: string;
65
+ state: string;
66
+ zip: string;
67
+ country: string;
68
+ };
69
+ export declare const createTestCreditCard: (overrides?: {}) => {
70
+ cardNumber: string;
71
+ expirationMonth: string;
72
+ expirationYear: string;
73
+ verificationValue: string;
74
+ };
75
+ export declare const createTestBankAccount: (overrides?: {}) => {
76
+ accountNumber: string;
77
+ routingNumber: string;
78
+ accountType: "checking";
79
+ accountHolderType: "personal";
80
+ };
81
+ export declare const cleanupWindowMocks: () => void;
@@ -0,0 +1,94 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ export const createMockFetch = (response, options = {}) => {
11
+ return jest.fn().mockResolvedValue({
12
+ ok: options.ok !== false,
13
+ status: options.status || 200,
14
+ json: () => __awaiter(void 0, void 0, void 0, function* () { return response; }),
15
+ text: () => __awaiter(void 0, void 0, void 0, function* () { return JSON.stringify(response); }),
16
+ });
17
+ };
18
+ export const createMockFetchError = (message) => {
19
+ return jest.fn().mockRejectedValue(new Error(message));
20
+ };
21
+ export const createMockFetchWithImplementation = (implementation) => {
22
+ return jest.fn().mockImplementation(implementation);
23
+ };
24
+ export const setupFetchMock = () => {
25
+ const mockFetch = jest.fn();
26
+ global.fetch = mockFetch;
27
+ return mockFetch;
28
+ };
29
+ export const setupDocumentMock = () => {
30
+ const mockScript = {
31
+ src: '',
32
+ async: false,
33
+ defer: false,
34
+ };
35
+ const mockAppendChild = jest.fn();
36
+ const mockCreateElement = jest.fn(() => mockScript);
37
+ Object.defineProperty(document, 'createElement', {
38
+ value: mockCreateElement,
39
+ writable: true,
40
+ });
41
+ Object.defineProperty(document.body, 'appendChild', {
42
+ value: mockAppendChild,
43
+ writable: true,
44
+ });
45
+ return { mockScript, mockAppendChild, mockCreateElement };
46
+ };
47
+ export const setupApplePayEnvironment = (options = {}) => {
48
+ const mockSession = {
49
+ begin: jest.fn(),
50
+ abort: jest.fn(),
51
+ completeMerchantValidation: jest.fn(),
52
+ completePayment: jest.fn(),
53
+ };
54
+ const ApplePaySessionMock = jest.fn(() => mockSession);
55
+ ApplePaySessionMock.canMakePayments = jest.fn(() => options.canMakePayments !== false);
56
+ ApplePaySessionMock.supportsVersion = jest.fn(() => options.supportsVersion !== false);
57
+ window.ApplePaySession = ApplePaySessionMock;
58
+ return { mockSession, ApplePaySessionMock };
59
+ };
60
+ export const setupGooglePayEnvironment = (options = {}) => {
61
+ const mockPaymentsClient = {
62
+ isReadyToPay: jest.fn(),
63
+ loadPaymentData: jest.fn(),
64
+ };
65
+ const googlePayMock = {
66
+ payments: {
67
+ api: {
68
+ PaymentsClient: jest.fn(() => mockPaymentsClient),
69
+ },
70
+ },
71
+ };
72
+ if (options.autoLoad) {
73
+ window.google = googlePayMock;
74
+ }
75
+ return { mockPaymentsClient, googlePayMock };
76
+ };
77
+ export const setupRecaptchaEnvironment = () => {
78
+ const mockGrecaptcha = {
79
+ render: jest.fn().mockReturnValue(123),
80
+ reset: jest.fn(),
81
+ execute: jest.fn(),
82
+ getResponse: jest.fn().mockReturnValue(null),
83
+ };
84
+ return mockGrecaptcha;
85
+ };
86
+ export const createTestContact = (overrides = {}) => (Object.assign({ salutation: 'Mr', firstName: 'John', lastName: 'Doe', company: 'Test Corp', email: 'test@example.com', primaryPhone: '555-1234' }, overrides));
87
+ export const createTestAddress = (overrides = {}) => (Object.assign({ address1: '123 Test St', address2: 'Suite 100', city: 'Test City', state: 'NY', zip: '10001', country: 'US' }, overrides));
88
+ export const createTestCreditCard = (overrides = {}) => (Object.assign({ cardNumber: '4111111111111111', expirationMonth: '12', expirationYear: '2025', verificationValue: '123' }, overrides));
89
+ export const createTestBankAccount = (overrides = {}) => (Object.assign({ accountNumber: '1234567890', routingNumber: '021000021', accountType: 'checking', accountHolderType: 'personal' }, overrides));
90
+ export const cleanupWindowMocks = () => {
91
+ delete window.ApplePaySession;
92
+ delete window.google;
93
+ delete window.grecaptcha;
94
+ };
@@ -0,0 +1,51 @@
1
+ import { Tokenizer } from './Tokenizer';
2
+ import { PaymentData, PaymentToken, ValidationResult, PaymentGateway, TokenizerContainer } from './types';
3
+ import { TokenizeCardConnectBankAccountResult } from '../types';
4
+ import ConfigHandler from '../config-handler';
5
+ export declare class CardConnectTokenizer extends Tokenizer {
6
+ private iframeUrl;
7
+ private containerId;
8
+ private layout;
9
+ private iframe;
10
+ private messageHandler?;
11
+ private expectedOrigin;
12
+ private isReady;
13
+ private currentValidationState;
14
+ private containerEl?;
15
+ private routingNumberEl?;
16
+ private accountNumberEl?;
17
+ private accountTypeEl?;
18
+ private enableTestMode;
19
+ private cachedTokenResult?;
20
+ private tokenizationPromise?;
21
+ private tokenizationResolve?;
22
+ private tokenizationReject?;
23
+ private constructor();
24
+ static create(gateway: PaymentGateway, container: TokenizerContainer, config: {
25
+ organizationId: string;
26
+ embedId: string;
27
+ clientConfig: ConfigHandler;
28
+ }): Promise<CardConnectTokenizer>;
29
+ private createInternalElements;
30
+ private createCreditCardFields;
31
+ private createBankAccountFields;
32
+ private init;
33
+ tokenize(paymentData: PaymentData): Promise<PaymentToken>;
34
+ private tokenizeCardInternal;
35
+ private tokenizeBankAccountInternal;
36
+ validate(): Promise<ValidationResult>;
37
+ private validateCardInternal;
38
+ private validateBankAccountInternal;
39
+ clear(): void;
40
+ focus(field: 'cardNumber' | 'cvv' | 'expiry' | 'routingNumber' | 'accountNumber'): void;
41
+ destroy(): void;
42
+ hasToken(): boolean;
43
+ getToken(): PaymentToken | null;
44
+ get tokenizationMode(): 'auto' | 'manual';
45
+ private handleMessage;
46
+ private handleValidationMessage;
47
+ private static generateIframeUrl;
48
+ private static createIframe;
49
+ private static generateCardConnectCss;
50
+ static tokenizeBankAccount(routingNumber: string, accountNumber: string, config: ConfigHandler): Promise<TokenizeCardConnectBankAccountResult>;
51
+ }