@tonder.io/ionic-lite-sdk 0.0.57 → 0.0.58
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/README.md +202 -11
- package/dist/classes/liteCheckout.d.ts +7 -2
- package/dist/helpers/skyflow.d.ts +20 -0
- package/dist/index.js +1 -1
- package/dist/shared/constants/skyflow.contants.d.ts +36 -0
- package/dist/shared/styles/skyflow.styles.d.ts +14 -0
- package/dist/types/card.d.ts +14 -0
- package/dist/types/commons.d.ts +82 -0
- package/dist/types/liteInlineCheckout.d.ts +8 -0
- package/dist/types/requests.d.ts +1 -1
- package/package.json +2 -2
- package/src/classes/3dsHandler.ts +0 -1
- package/src/classes/liteCheckout.ts +67 -17
- package/src/helpers/mercadopago.ts +1 -3
- package/src/helpers/skyflow.ts +306 -34
- package/src/shared/constants/skyflow.contants.ts +63 -0
- package/src/shared/styles/skyflow.styles.ts +63 -0
- package/src/types/card.ts +12 -0
- package/src/types/commons.ts +95 -1
- package/src/types/liteInlineCheckout.ts +9 -1
- package/src/types/requests.ts +1 -1
- package/tests/classes/liteCheckout.test.ts +0 -57
- package/tests/methods/createOrder.test.ts +0 -142
- package/tests/methods/createPayment.test.ts +0 -122
- package/tests/methods/customerRegister.test.ts +0 -119
- package/tests/methods/getBusiness.test.ts +0 -114
- package/tests/methods/getCustomerCards.test.ts +0 -113
- package/tests/methods/registerCustomerCard.test.ts +0 -118
- package/tests/methods/startCheckoutRouter.test.ts +0 -120
- package/tests/methods/startCheckoutRouterFull.test.ts +0 -139
- package/tests/utils/defaultMock.ts +0 -22
- package/tests/utils/mockClasses.ts +0 -659
package/dist/types/commons.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { ICustomer } from "./customer";
|
|
2
2
|
import { IProcessPaymentRequest, IStartCheckoutResponse } from "./checkout";
|
|
3
|
+
import CollectorContainer from "skyflow-js/types/core/external/collect/collect-container";
|
|
4
|
+
import ComposableContainer from "skyflow-js/types/core/external/collect/compose-collect-container";
|
|
5
|
+
import RevealContainer from "skyflow-js/types/core/external/reveal/reveal-container";
|
|
6
|
+
import CollectElement from "skyflow-js/types/core/external/collect/collect-element";
|
|
7
|
+
import ComposableElement from "skyflow-js/types/core/external/collect/compose-collect-element";
|
|
8
|
+
import RevealElement from "skyflow-js/types/core/external/reveal/reveal-element";
|
|
9
|
+
import { LabelStyles } from "skyflow-js/types/utils/common";
|
|
3
10
|
export type Business = {
|
|
4
11
|
business: {
|
|
5
12
|
pk: number;
|
|
@@ -112,6 +119,28 @@ export interface IInlineLiteCheckoutOptions extends IInlineCheckoutBaseOptions {
|
|
|
112
119
|
collectorIds?: {
|
|
113
120
|
tdsIframe?: string;
|
|
114
121
|
};
|
|
122
|
+
customization?: ILiteCustomizationOptions;
|
|
123
|
+
events?: IEvents;
|
|
124
|
+
}
|
|
125
|
+
export interface ICardFormEvents {
|
|
126
|
+
cardHolderEvents?: IInputEvents;
|
|
127
|
+
cardNumberEvents?: IInputEvents;
|
|
128
|
+
cvvEvents?: IInputEvents;
|
|
129
|
+
monthEvents?: IInputEvents;
|
|
130
|
+
yearEvents?: IInputEvents;
|
|
131
|
+
}
|
|
132
|
+
export interface IInputEvents {
|
|
133
|
+
onChange?: (event: IEventSecureInput) => void;
|
|
134
|
+
onFocus?: (event: IEventSecureInput) => void;
|
|
135
|
+
onBlur?: (event: IEventSecureInput) => void;
|
|
136
|
+
}
|
|
137
|
+
export interface IEventSecureInput {
|
|
138
|
+
elementType: string;
|
|
139
|
+
isEmpty: boolean;
|
|
140
|
+
isFocused: boolean;
|
|
141
|
+
isValid: boolean;
|
|
142
|
+
}
|
|
143
|
+
export interface IEvents extends ICardFormEvents {
|
|
115
144
|
}
|
|
116
145
|
export interface IApiError {
|
|
117
146
|
code: string;
|
|
@@ -128,3 +157,56 @@ export interface IPublicError {
|
|
|
128
157
|
export type CustomizationOptions = {
|
|
129
158
|
redirectOnComplete?: boolean;
|
|
130
159
|
};
|
|
160
|
+
export interface InCollectorContainer {
|
|
161
|
+
container: CollectorContainer | ComposableContainer | RevealContainer;
|
|
162
|
+
elements: (CollectElement | ComposableElement | RevealElement)[];
|
|
163
|
+
}
|
|
164
|
+
export interface ILiteCustomizationOptions extends CustomizationOptions {
|
|
165
|
+
styles?: IStyles;
|
|
166
|
+
labels?: IFormLabels;
|
|
167
|
+
placeholders?: IFormPlaceholder;
|
|
168
|
+
}
|
|
169
|
+
export interface IFormLabels {
|
|
170
|
+
name?: string;
|
|
171
|
+
card_number?: string;
|
|
172
|
+
cvv?: string;
|
|
173
|
+
expiry_date?: string;
|
|
174
|
+
expiration_year?: string;
|
|
175
|
+
expiration_month?: string;
|
|
176
|
+
}
|
|
177
|
+
export interface IFormPlaceholder {
|
|
178
|
+
name?: string;
|
|
179
|
+
card_number?: string;
|
|
180
|
+
cvv?: string;
|
|
181
|
+
expiration_month?: string;
|
|
182
|
+
expiration_year?: string;
|
|
183
|
+
}
|
|
184
|
+
export interface IStyles {
|
|
185
|
+
cardForm?: ILiteCardFormStyles;
|
|
186
|
+
}
|
|
187
|
+
export interface ILiteCardFormStyles extends StylesBaseVariant, IElementStyle {
|
|
188
|
+
}
|
|
189
|
+
export interface StylesBaseVariant {
|
|
190
|
+
base?: Record<string, any>;
|
|
191
|
+
}
|
|
192
|
+
export interface IElementStyle {
|
|
193
|
+
inputStyles?: CollectInputStylesVariant;
|
|
194
|
+
labelStyles?: LabelStyles;
|
|
195
|
+
errorStyles?: StylesBaseVariant;
|
|
196
|
+
}
|
|
197
|
+
export interface StylesFocusVariant {
|
|
198
|
+
focus?: Record<string, any>;
|
|
199
|
+
}
|
|
200
|
+
export interface CollectInputStylesVariant extends StylesBaseVariant, StylesFocusVariant {
|
|
201
|
+
complete?: Record<string, any>;
|
|
202
|
+
invalid?: Record<string, any>;
|
|
203
|
+
empty?: Record<string, any>;
|
|
204
|
+
cardIcon?: Record<string, any>;
|
|
205
|
+
dropdownIcon?: Record<string, any>;
|
|
206
|
+
dropdown?: Record<string, any>;
|
|
207
|
+
dropdownListItem?: Record<string, any>;
|
|
208
|
+
global: Record<string, any>;
|
|
209
|
+
}
|
|
210
|
+
export interface CollectLabelStylesVariant extends StylesBaseVariant, StylesFocusVariant {
|
|
211
|
+
requiredAsterisk?: Record<string, any>;
|
|
212
|
+
}
|
|
@@ -158,4 +158,12 @@ export interface ILiteCheckout {
|
|
|
158
158
|
* during the payment process.
|
|
159
159
|
*/
|
|
160
160
|
getOpenpayDeviceSessionID(merchant_id: string, public_key: string, is_sandbox: boolean): Promise<string | ErrorResponse>;
|
|
161
|
+
/**
|
|
162
|
+
* Displays and renders card input fields in the checkout.
|
|
163
|
+
* Uses the provided configuration to show the required fields in the payment form.
|
|
164
|
+
* @param {import("./card").IMountCardFieldsRequest} event - Configuration for the card fields to render.
|
|
165
|
+
* @returns {Promise<void>} Resolves when the fields have been successfully rendered.
|
|
166
|
+
* @public
|
|
167
|
+
*/
|
|
168
|
+
mountCardFields(event: import("./card").IMountCardFieldsRequest): Promise<void>;
|
|
161
169
|
}
|
package/dist/types/requests.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tonder.io/ionic-lite-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.58",
|
|
4
4
|
"description": "Tonder ionic lite SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"license": "ISC",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"lodash.get": "^4.4.2",
|
|
16
|
-
"skyflow-js": "
|
|
16
|
+
"skyflow-js": "2.4.4",
|
|
17
17
|
"ts-node": "^10.9.2"
|
|
18
18
|
},
|
|
19
19
|
"publishConfig": {
|
|
@@ -1,40 +1,59 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
declare const MP_DEVICE_SESSION_ID: string | undefined;
|
|
4
|
-
import { ErrorResponse } from "./errorResponse";
|
|
1
|
+
import {fetchBusiness} from "../data/businessApi";
|
|
2
|
+
import {ErrorResponse} from "./errorResponse";
|
|
5
3
|
import {
|
|
6
4
|
buildErrorResponse,
|
|
7
5
|
buildErrorResponseFromCatch,
|
|
6
|
+
formatPublicErrorResponse,
|
|
8
7
|
getBrowserInfo,
|
|
9
8
|
getBusinessId,
|
|
10
|
-
formatPublicErrorResponse,
|
|
11
9
|
getCardType,
|
|
12
10
|
} from "../helpers/utils";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
|
|
11
|
+
import {getCustomerAPMs} from "../data/api";
|
|
12
|
+
import {BaseInlineCheckout} from "./BaseInlineCheckout";
|
|
13
|
+
import {MESSAGES} from "../shared/constants/messages";
|
|
14
|
+
import {getSkyflowTokens, initSkyflowInstance, mountSkyflowFields} from "../helpers/skyflow";
|
|
15
|
+
import {startCheckoutRouter} from "../data/checkoutApi";
|
|
16
|
+
import {getOpenpayDeviceSessionID} from "../data/openPayApi";
|
|
17
|
+
import {getPaymentMethodDetails} from "../shared/catalog/paymentMethodsCatalog";
|
|
18
|
+
import {
|
|
19
|
+
APM, IEvents,
|
|
20
|
+
IInlineLiteCheckoutOptions,
|
|
21
|
+
ILiteCustomizationOptions,
|
|
22
|
+
InCollectorContainer,
|
|
23
|
+
TonderAPM
|
|
24
|
+
} from "../types/commons";
|
|
25
|
+
import {
|
|
26
|
+
ICustomerCardsResponse,
|
|
27
|
+
IMountCardFieldsRequest,
|
|
28
|
+
ISaveCardRequest,
|
|
29
|
+
ISaveCardResponse,
|
|
30
|
+
ISaveCardSkyflowRequest
|
|
31
|
+
} from "../types/card";
|
|
22
32
|
import {IPaymentMethod} from "../types/paymentMethod";
|
|
23
33
|
import {
|
|
24
34
|
CreateOrderResponse,
|
|
25
35
|
CreatePaymentResponse,
|
|
26
36
|
CustomerRegisterResponse,
|
|
27
|
-
GetBusinessResponse,
|
|
37
|
+
GetBusinessResponse,
|
|
38
|
+
IErrorResponse,
|
|
39
|
+
RegisterCustomerCardResponse,
|
|
40
|
+
StartCheckoutResponse
|
|
28
41
|
} from "../types/responses";
|
|
29
42
|
import {
|
|
30
43
|
CreateOrderRequest,
|
|
31
|
-
CreatePaymentRequest,
|
|
44
|
+
CreatePaymentRequest,
|
|
45
|
+
RegisterCustomerCardRequest,
|
|
46
|
+
StartCheckoutFullRequest,
|
|
32
47
|
StartCheckoutIdRequest,
|
|
33
48
|
StartCheckoutRequest,
|
|
34
49
|
TokensRequest
|
|
35
50
|
} from "../types/requests";
|
|
36
51
|
import {ICardFields, IStartCheckoutResponse} from "../types/checkout";
|
|
37
52
|
import {ILiteCheckout} from "../types/liteInlineCheckout";
|
|
53
|
+
import CollectorContainer from "skyflow-js/types/core/external/collect/collect-container";
|
|
54
|
+
import Skyflow from "skyflow-js";
|
|
55
|
+
|
|
56
|
+
declare const MP_DEVICE_SESSION_ID: string | undefined;
|
|
38
57
|
|
|
39
58
|
declare global {
|
|
40
59
|
interface Window {
|
|
@@ -44,9 +63,15 @@ declare global {
|
|
|
44
63
|
|
|
45
64
|
export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{
|
|
46
65
|
activeAPMs: APM[] = [];
|
|
66
|
+
private collectContainer: InCollectorContainer | null;
|
|
67
|
+
private skyflowInstance: Skyflow | null;
|
|
68
|
+
private readonly events: IEvents
|
|
47
69
|
|
|
48
|
-
constructor({ apiKey, mode, returnUrl, callBack, apiKeyTonder, baseUrlTonder, customization, collectorIds }: IInlineLiteCheckoutOptions) {
|
|
70
|
+
constructor({ apiKey, mode, returnUrl, callBack, apiKeyTonder, baseUrlTonder, customization, collectorIds, events }: IInlineLiteCheckoutOptions) {
|
|
49
71
|
super({ mode, apiKey, returnUrl, callBack, apiKeyTonder, baseUrlTonder, customization, tdsIframeId: collectorIds && 'tdsIframe' in collectorIds ? collectorIds?.tdsIframe : "tdsIframe"});
|
|
72
|
+
this.collectContainer = null;
|
|
73
|
+
this.skyflowInstance = null;
|
|
74
|
+
this.events = events || {}
|
|
50
75
|
}
|
|
51
76
|
|
|
52
77
|
public async injectCheckout() {
|
|
@@ -169,6 +194,16 @@ export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{
|
|
|
169
194
|
}
|
|
170
195
|
}
|
|
171
196
|
|
|
197
|
+
public async mountCardFields(event: IMountCardFieldsRequest): Promise<void> {
|
|
198
|
+
await this.createSkyflowInstance();
|
|
199
|
+
this.collectContainer = await mountSkyflowFields({
|
|
200
|
+
skyflowInstance: this.skyflowInstance!,
|
|
201
|
+
data: event,
|
|
202
|
+
customization: this.customization,
|
|
203
|
+
events: this.events,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
172
207
|
public async getBusiness(): Promise<GetBusinessResponse> {
|
|
173
208
|
try {
|
|
174
209
|
return await fetchBusiness(
|
|
@@ -186,6 +221,19 @@ export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{
|
|
|
186
221
|
}
|
|
187
222
|
}
|
|
188
223
|
|
|
224
|
+
|
|
225
|
+
private async createSkyflowInstance() {
|
|
226
|
+
if(this.skyflowInstance) return this.skyflowInstance
|
|
227
|
+
await this._fetchMerchantData();
|
|
228
|
+
const { vault_id, vault_url } = this.merchantData!;
|
|
229
|
+
this.skyflowInstance = await initSkyflowInstance({
|
|
230
|
+
vault_id: vault_id,
|
|
231
|
+
vault_url: vault_url,
|
|
232
|
+
baseUrl: this.baseUrl,
|
|
233
|
+
apiKey: this.apiKeyTonder,
|
|
234
|
+
})
|
|
235
|
+
}
|
|
236
|
+
|
|
189
237
|
// TODO: DEPRECATED
|
|
190
238
|
async getOpenpayDeviceSessionID(
|
|
191
239
|
merchant_id: string,
|
|
@@ -240,6 +288,8 @@ export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{
|
|
|
240
288
|
let skyflowTokens;
|
|
241
289
|
if (!payment_method || payment_method === "" || payment_method === null) {
|
|
242
290
|
if (typeof card === "string") {
|
|
291
|
+
const container = this.collectContainer?.container as CollectorContainer;
|
|
292
|
+
await container.collect()
|
|
243
293
|
skyflowTokens = {
|
|
244
294
|
skyflow_id: card,
|
|
245
295
|
};
|
|
@@ -3,9 +3,7 @@ export function injectMercadoPagoSecurity() {
|
|
|
3
3
|
const script = document.createElement("script");
|
|
4
4
|
script.src = "https://www.mercadopago.com/v2/security.js";
|
|
5
5
|
script.setAttribute("view", "");
|
|
6
|
-
script.onload = () => {
|
|
7
|
-
console.log("Mercado Pago script loaded successfully.");
|
|
8
|
-
};
|
|
6
|
+
script.onload = () => {};
|
|
9
7
|
script.onerror = (error) => {
|
|
10
8
|
console.error("Error loading Mercado Pago script:", error);
|
|
11
9
|
};
|
package/src/helpers/skyflow.ts
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
|
-
import {ErrorResponse} from "../classes/errorResponse";
|
|
1
|
+
import { ErrorResponse } from "../classes/errorResponse";
|
|
2
2
|
import Skyflow from "skyflow-js";
|
|
3
3
|
import CollectContainer from "skyflow-js/types/core/external/collect/collect-container";
|
|
4
|
-
import {buildErrorResponseFromCatch} from "./utils";
|
|
4
|
+
import { buildErrorResponseFromCatch } from "./utils";
|
|
5
5
|
import CollectElement from "skyflow-js/types/core/external/collect/collect-element";
|
|
6
|
-
import {getVaultToken} from "../data/skyflowApi";
|
|
7
|
-
import {TokensSkyflowRequest} from "../types/requests";
|
|
6
|
+
import { getVaultToken } from "../data/skyflowApi";
|
|
7
|
+
import { TokensSkyflowRequest } from "../types/requests";
|
|
8
|
+
import { CardFieldEnum, IMountCardFieldsRequest } from "../types/card";
|
|
9
|
+
import {
|
|
10
|
+
IEvents,
|
|
11
|
+
IInputEvents,
|
|
12
|
+
ILiteCustomizationOptions,
|
|
13
|
+
StylesBaseVariant,
|
|
14
|
+
} from "../types/commons";
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_SKYFLOW_lABELS,
|
|
17
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS,
|
|
18
|
+
lengthMatchRule,
|
|
19
|
+
regexMatchRule,
|
|
20
|
+
} from "../shared/constants/skyflow.contants";
|
|
21
|
+
import {
|
|
22
|
+
DEFAULT_SKYFLOW_ERROR_TEXT_STYLES,
|
|
23
|
+
DEFAULT_SKYFLOW_INPUT_STYLES,
|
|
24
|
+
DEFAULT_SKYFLOW_lABEL_STYLES,
|
|
25
|
+
} from "../shared/styles/skyflow.styles";
|
|
26
|
+
import { get } from "lodash";
|
|
8
27
|
|
|
28
|
+
/**
|
|
29
|
+
* [DEPRECATION WARNING]
|
|
30
|
+
* This function should be deprecated in favor of using mountSkyflowFields for security,
|
|
31
|
+
* to prevent users from creating their own inputs.
|
|
32
|
+
*/
|
|
9
33
|
export async function getSkyflowTokens({
|
|
10
34
|
baseUrl,
|
|
11
35
|
apiKey,
|
|
@@ -19,7 +43,7 @@ export async function getSkyflowTokens({
|
|
|
19
43
|
getBearerToken: async () => await getVaultToken(baseUrl, apiKey),
|
|
20
44
|
options: {
|
|
21
45
|
logLevel: Skyflow.LogLevel.ERROR,
|
|
22
|
-
env: Skyflow.Env.DEV,
|
|
46
|
+
env: Skyflow.Env.DEV, // ⚠️ This should be Env.PROD, but currently it cannot be changed because getSkyflowTokens must be deprecated first, since .setValue does not work in PROD.
|
|
23
47
|
},
|
|
24
48
|
});
|
|
25
49
|
|
|
@@ -52,40 +76,288 @@ export async function getSkyflowTokens({
|
|
|
52
76
|
}
|
|
53
77
|
}
|
|
54
78
|
|
|
55
|
-
async function getFieldsPromise(
|
|
56
|
-
|
|
57
|
-
|
|
79
|
+
async function getFieldsPromise(
|
|
80
|
+
data: any,
|
|
81
|
+
collectContainer: CollectContainer,
|
|
82
|
+
): Promise<Promise<boolean>[]> {
|
|
83
|
+
const fields = await getFields(data, collectContainer);
|
|
84
|
+
if (!fields) return [];
|
|
58
85
|
|
|
59
|
-
return fields.map((field: { element: CollectElement
|
|
86
|
+
return fields.map((field: { element: CollectElement; key: string }) => {
|
|
60
87
|
return new Promise((resolve) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}, 120);
|
|
88
|
+
const div = document.createElement("div");
|
|
89
|
+
div.hidden = true;
|
|
90
|
+
div.id = `id-${field.key}`;
|
|
91
|
+
document.querySelector(`body`)?.appendChild(div);
|
|
92
|
+
setTimeout(() => {
|
|
93
|
+
field.element.mount(`#id-${field.key}`);
|
|
94
|
+
setInterval(() => {
|
|
95
|
+
if (field.element.isMounted()) {
|
|
96
|
+
const value = data[field.key];
|
|
97
|
+
field.element.setValue(value);
|
|
98
|
+
return resolve(field.element.isMounted());
|
|
99
|
+
}
|
|
74
100
|
}, 120);
|
|
101
|
+
}, 120);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function getFields(
|
|
107
|
+
data: any,
|
|
108
|
+
collectContainer: CollectContainer,
|
|
109
|
+
): Promise<{ element: CollectElement; key: string }[]> {
|
|
110
|
+
return await Promise.all(
|
|
111
|
+
Object.keys(data).map(async (key) => {
|
|
112
|
+
const cardHolderNameElement = await collectContainer.create({
|
|
113
|
+
table: "cards",
|
|
114
|
+
column: key,
|
|
115
|
+
type: Skyflow.ElementType.INPUT_FIELD,
|
|
116
|
+
});
|
|
117
|
+
return { element: cardHolderNameElement, key: key };
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function initSkyflowInstance({
|
|
123
|
+
baseUrl,
|
|
124
|
+
apiKey,
|
|
125
|
+
vault_id,
|
|
126
|
+
vault_url,
|
|
127
|
+
}: TokensSkyflowRequest): Promise<Skyflow> {
|
|
128
|
+
return Skyflow.init({
|
|
129
|
+
vaultID: vault_id,
|
|
130
|
+
vaultURL: vault_url,
|
|
131
|
+
getBearerToken: async () => await getVaultToken(baseUrl, apiKey),
|
|
132
|
+
options: {
|
|
133
|
+
logLevel: Skyflow.LogLevel.ERROR,
|
|
134
|
+
env: Skyflow.Env.DEV,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function mountSkyflowFields(event: {
|
|
140
|
+
skyflowInstance: Skyflow;
|
|
141
|
+
data: IMountCardFieldsRequest;
|
|
142
|
+
customization?: ILiteCustomizationOptions;
|
|
143
|
+
events?: IEvents;
|
|
144
|
+
}): Promise<{ elements: CollectElement[]; container: CollectContainer }> {
|
|
145
|
+
const { skyflowInstance, data, customization, events } = event;
|
|
146
|
+
const collectContainer: CollectContainer = skyflowInstance.container(
|
|
147
|
+
Skyflow.ContainerType.COLLECT,
|
|
148
|
+
) as CollectContainer;
|
|
149
|
+
const elements: { element: CollectElement; containerId: string }[] = [];
|
|
150
|
+
const typeByField: Record<
|
|
151
|
+
CardFieldEnum,
|
|
152
|
+
(typeof Skyflow.ElementType)[keyof typeof Skyflow.ElementType]
|
|
153
|
+
> = {
|
|
154
|
+
[CardFieldEnum.CVV]: Skyflow.ElementType.CVV,
|
|
155
|
+
[CardFieldEnum.CARD_NUMBER]: Skyflow.ElementType.CARD_NUMBER,
|
|
156
|
+
[CardFieldEnum.EXPIRATION_MONTH]: Skyflow.ElementType.EXPIRATION_MONTH,
|
|
157
|
+
[CardFieldEnum.EXPIRATION_YEAR]: Skyflow.ElementType.EXPIRATION_YEAR,
|
|
158
|
+
[CardFieldEnum.CARDHOLDER_NAME]: Skyflow.ElementType.CARDHOLDER_NAME,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const validationsByField = {
|
|
162
|
+
[CardFieldEnum.CVV]: [regexMatchRule],
|
|
163
|
+
[CardFieldEnum.CARD_NUMBER]: [regexMatchRule],
|
|
164
|
+
[CardFieldEnum.EXPIRATION_MONTH]: [regexMatchRule],
|
|
165
|
+
[CardFieldEnum.EXPIRATION_YEAR]: [regexMatchRule],
|
|
166
|
+
[CardFieldEnum.CARDHOLDER_NAME]: [lengthMatchRule, regexMatchRule],
|
|
167
|
+
};
|
|
168
|
+
const customStyles = {
|
|
169
|
+
errorStyles:
|
|
170
|
+
customization?.styles?.cardForm?.errorStyles ||
|
|
171
|
+
DEFAULT_SKYFLOW_ERROR_TEXT_STYLES,
|
|
172
|
+
inputStyles:
|
|
173
|
+
customization?.styles?.cardForm?.inputStyles ||
|
|
174
|
+
DEFAULT_SKYFLOW_INPUT_STYLES,
|
|
175
|
+
labelStyles:
|
|
176
|
+
customization?.styles?.cardForm?.labelStyles ||
|
|
177
|
+
DEFAULT_SKYFLOW_lABEL_STYLES,
|
|
178
|
+
};
|
|
179
|
+
const labels: Record<string, string> = {
|
|
180
|
+
name: customization?.labels?.name || DEFAULT_SKYFLOW_lABELS.name,
|
|
181
|
+
card_number:
|
|
182
|
+
customization?.labels?.card_number || DEFAULT_SKYFLOW_lABELS.card_number,
|
|
183
|
+
cvv: customization?.labels?.cvv || DEFAULT_SKYFLOW_lABELS.cvv,
|
|
184
|
+
expiration_date:
|
|
185
|
+
customization?.labels?.expiry_date ||
|
|
186
|
+
DEFAULT_SKYFLOW_lABELS.expiration_date,
|
|
187
|
+
expiration_month:
|
|
188
|
+
customization?.labels?.expiration_month ||
|
|
189
|
+
DEFAULT_SKYFLOW_lABELS.expiration_month,
|
|
190
|
+
expiration_year:
|
|
191
|
+
customization?.labels?.expiration_year ||
|
|
192
|
+
DEFAULT_SKYFLOW_lABELS.expiration_year,
|
|
193
|
+
};
|
|
194
|
+
const placeholders: Record<string, string> = {
|
|
195
|
+
name:
|
|
196
|
+
customization?.placeholders?.name || DEFAULT_SKYFLOW_PLACEHOLDERS.name,
|
|
197
|
+
card_number:
|
|
198
|
+
customization?.placeholders?.card_number ||
|
|
199
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS.card_number,
|
|
200
|
+
cvv: customization?.placeholders?.cvv || DEFAULT_SKYFLOW_PLACEHOLDERS.cvv,
|
|
201
|
+
expiration_month:
|
|
202
|
+
customization?.placeholders?.expiration_month ||
|
|
203
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS.expiration_month,
|
|
204
|
+
expiration_year:
|
|
205
|
+
customization?.placeholders?.expiration_year ||
|
|
206
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS.expiration_year,
|
|
207
|
+
};
|
|
208
|
+
const eventsByField: Record<CardFieldEnum, IInputEvents | undefined> = {
|
|
209
|
+
[CardFieldEnum.CVV]: events?.cvvEvents,
|
|
210
|
+
[CardFieldEnum.CARD_NUMBER]: events?.cardNumberEvents,
|
|
211
|
+
[CardFieldEnum.EXPIRATION_MONTH]: events?.monthEvents,
|
|
212
|
+
[CardFieldEnum.EXPIRATION_YEAR]: events?.yearEvents,
|
|
213
|
+
[CardFieldEnum.CARDHOLDER_NAME]: events?.cardHolderEvents,
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if ("fields" in data && Array.isArray(data.fields)) {
|
|
217
|
+
if (data.fields.length > 0 && typeof data.fields[0] === "string") {
|
|
218
|
+
for (const field of data.fields as CardFieldEnum[]) {
|
|
219
|
+
const element = collectContainer.create({
|
|
220
|
+
table: "cards",
|
|
221
|
+
column: field,
|
|
222
|
+
type: typeByField[field],
|
|
223
|
+
validations: validationsByField[field],
|
|
224
|
+
...customStyles,
|
|
225
|
+
label: labels[field],
|
|
226
|
+
placeholder: placeholders[field],
|
|
227
|
+
...(data.card_id ? { skyflowID: data.card_id } : {}),
|
|
228
|
+
});
|
|
229
|
+
handleSkyflowElementEvents({
|
|
230
|
+
element,
|
|
231
|
+
errorStyles: customStyles.errorStyles,
|
|
232
|
+
fieldMessage: [CardFieldEnum.CVV, CardFieldEnum.EXPIRATION_MONTH, CardFieldEnum.EXPIRATION_YEAR].includes(field) ? "":labels[field],
|
|
233
|
+
events: eventsByField[field],
|
|
234
|
+
});
|
|
235
|
+
const containerId =
|
|
236
|
+
`#collect_${String(field)}` +
|
|
237
|
+
(data.card_id ? `_${data.card_id}` : "");
|
|
238
|
+
element.mount(containerId);
|
|
239
|
+
elements.push({ element, containerId });
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
for (const fieldObj of data.fields as {
|
|
243
|
+
container_id?: string;
|
|
244
|
+
field: CardFieldEnum;
|
|
245
|
+
}[]) {
|
|
246
|
+
const key = fieldObj.field;
|
|
247
|
+
const element = collectContainer.create({
|
|
248
|
+
table: "cards",
|
|
249
|
+
column: key,
|
|
250
|
+
type: typeByField[key],
|
|
251
|
+
validations: validationsByField[key],
|
|
252
|
+
...customStyles,
|
|
253
|
+
label: labels[key],
|
|
254
|
+
placeholder: placeholders[key],
|
|
255
|
+
...(data.card_id ? { skyflowID: data.card_id } : {}),
|
|
256
|
+
});
|
|
257
|
+
const containerId =
|
|
258
|
+
fieldObj.container_id ||
|
|
259
|
+
`#collect_${String(key)}` + (data.card_id ? `_${data.card_id}` : "");
|
|
260
|
+
element.mount(containerId);
|
|
261
|
+
elements.push({ element, containerId });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
elements: elements.map((e) => e.element),
|
|
268
|
+
container: collectContainer,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function handleSkyflowElementEvents(event: {
|
|
273
|
+
element: CollectElement;
|
|
274
|
+
fieldMessage?: string;
|
|
275
|
+
errorStyles?: StylesBaseVariant;
|
|
276
|
+
requiredMessage?: string;
|
|
277
|
+
invalidMessage?: string;
|
|
278
|
+
events?: IInputEvents;
|
|
279
|
+
}) {
|
|
280
|
+
const {
|
|
281
|
+
element,
|
|
282
|
+
fieldMessage = "",
|
|
283
|
+
errorStyles = {},
|
|
284
|
+
requiredMessage = "Campo requerido",
|
|
285
|
+
invalidMessage = "Campo no válido",
|
|
286
|
+
events
|
|
287
|
+
} = event;
|
|
288
|
+
if ("on" in element) {
|
|
289
|
+
element.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
290
|
+
executeEvent({eventName: "onChange", data: state, events});
|
|
291
|
+
updateErrorLabel({
|
|
292
|
+
element,
|
|
293
|
+
errorStyles,
|
|
294
|
+
color: "transparent",
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
element.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
299
|
+
executeEvent({eventName: "onBlur", data: state, events});
|
|
300
|
+
if (!state.isValid) {
|
|
301
|
+
const msj_error = state.isEmpty
|
|
302
|
+
? requiredMessage
|
|
303
|
+
: fieldMessage != ""
|
|
304
|
+
? `El campo ${fieldMessage} no es válido`
|
|
305
|
+
: invalidMessage;
|
|
306
|
+
element.setError(msj_error);
|
|
307
|
+
}
|
|
308
|
+
updateErrorLabel({
|
|
309
|
+
element,
|
|
310
|
+
errorStyles,
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
element.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
315
|
+
executeEvent({eventName: "onFocus", data: state, events});
|
|
316
|
+
updateErrorLabel({
|
|
317
|
+
element,
|
|
318
|
+
errorStyles,
|
|
319
|
+
color: "transparent",
|
|
320
|
+
});
|
|
321
|
+
element.resetError();
|
|
75
322
|
});
|
|
76
|
-
}
|
|
323
|
+
}
|
|
77
324
|
}
|
|
78
325
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
326
|
+
function updateErrorLabel(event: {
|
|
327
|
+
element: CollectElement;
|
|
328
|
+
errorStyles?: StylesBaseVariant;
|
|
329
|
+
color?: string;
|
|
330
|
+
}) {
|
|
331
|
+
const { element, errorStyles = {}, color = "" } = event;
|
|
332
|
+
if (Object.keys(errorStyles).length > 0) {
|
|
333
|
+
element.update({
|
|
334
|
+
errorTextStyles: {
|
|
335
|
+
...errorStyles,
|
|
336
|
+
base: {
|
|
337
|
+
// @ts-ignore
|
|
338
|
+
...(errorStyles.base && { ...errorStyles.base }),
|
|
339
|
+
...(color != "" && { color }),
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
}
|
|
90
344
|
}
|
|
91
345
|
|
|
346
|
+
const executeEvent = (event: {
|
|
347
|
+
eventName: "onChange" | "onBlur" | "onFocus";
|
|
348
|
+
data: any;
|
|
349
|
+
events?: IInputEvents;
|
|
350
|
+
}) => {
|
|
351
|
+
const { eventName, data, events } = event;
|
|
352
|
+
if (events && eventName in events) {
|
|
353
|
+
const eventHandler = events[eventName];
|
|
354
|
+
if (typeof eventHandler === "function") {
|
|
355
|
+
eventHandler({
|
|
356
|
+
elementType: get(data, "elementType", ""),
|
|
357
|
+
isEmpty: get(data, "isEmpty", ""),
|
|
358
|
+
isFocused: get(data, "isFocused", ""),
|
|
359
|
+
isValid: get(data, "isValid", ""),
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
};
|