@tonder.io/ionic-lite-sdk 0.0.56 → 0.0.58-beta.DEV-1845.1
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 +1 -0
- package/dist/classes/BaseInlineCheckout.d.ts +1 -0
- 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/checkout.d.ts +1 -0
- package/dist/types/commons.d.ts +82 -0
- package/dist/types/jsx-web-components.d.ts +17 -0
- package/dist/types/liteInlineCheckout.d.ts +8 -0
- package/dist/types/requests.d.ts +1 -1
- package/dist/ui/components/input/CardCVVInput.d.ts +19 -0
- package/package.json +2 -2
- package/src/classes/3dsHandler.ts +0 -1
- package/src/classes/BaseInlineCheckout.ts +10 -1
- package/src/classes/liteCheckout.ts +67 -17
- package/src/helpers/mercadopago.ts +1 -3
- package/src/helpers/skyflow.ts +307 -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/checkout.ts +1 -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
|
@@ -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,289 @@ 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
|
-
|
|
86
|
+
//
|
|
87
|
+
return fields.map((field: { element: CollectElement; key: string }) => {
|
|
60
88
|
return new Promise((resolve) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}, 120);
|
|
89
|
+
const div = document.createElement("div");
|
|
90
|
+
div.hidden = true;
|
|
91
|
+
div.id = `id-${field.key}`;
|
|
92
|
+
document.querySelector(`body`)?.appendChild(div);
|
|
93
|
+
setTimeout(() => {
|
|
94
|
+
field.element.mount(`#id-${field.key}`);
|
|
95
|
+
setInterval(() => {
|
|
96
|
+
if (field.element.isMounted()) {
|
|
97
|
+
const value = data[field.key];
|
|
98
|
+
field.element.setValue(value);
|
|
99
|
+
return resolve(field.element.isMounted());
|
|
100
|
+
}
|
|
74
101
|
}, 120);
|
|
102
|
+
}, 120);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function getFields(
|
|
108
|
+
data: any,
|
|
109
|
+
collectContainer: CollectContainer,
|
|
110
|
+
): Promise<{ element: CollectElement; key: string }[]> {
|
|
111
|
+
return await Promise.all(
|
|
112
|
+
Object.keys(data).map(async (key) => {
|
|
113
|
+
const cardHolderNameElement = await collectContainer.create({
|
|
114
|
+
table: "cards",
|
|
115
|
+
column: key,
|
|
116
|
+
type: Skyflow.ElementType.INPUT_FIELD,
|
|
117
|
+
});
|
|
118
|
+
return { element: cardHolderNameElement, key: key };
|
|
119
|
+
}),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function initSkyflowInstance({
|
|
124
|
+
baseUrl,
|
|
125
|
+
apiKey,
|
|
126
|
+
vault_id,
|
|
127
|
+
vault_url,
|
|
128
|
+
}: TokensSkyflowRequest): Promise<Skyflow> {
|
|
129
|
+
return Skyflow.init({
|
|
130
|
+
vaultID: vault_id,
|
|
131
|
+
vaultURL: vault_url,
|
|
132
|
+
getBearerToken: async () => await getVaultToken(baseUrl, apiKey),
|
|
133
|
+
options: {
|
|
134
|
+
logLevel: Skyflow.LogLevel.ERROR,
|
|
135
|
+
env: Skyflow.Env.DEV,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function mountSkyflowFields(event: {
|
|
141
|
+
skyflowInstance: Skyflow;
|
|
142
|
+
data: IMountCardFieldsRequest;
|
|
143
|
+
customization?: ILiteCustomizationOptions;
|
|
144
|
+
events?: IEvents;
|
|
145
|
+
}): Promise<{ elements: CollectElement[]; container: CollectContainer }> {
|
|
146
|
+
const { skyflowInstance, data, customization, events } = event;
|
|
147
|
+
const collectContainer: CollectContainer = skyflowInstance.container(
|
|
148
|
+
Skyflow.ContainerType.COLLECT,
|
|
149
|
+
) as CollectContainer;
|
|
150
|
+
const elements: { element: CollectElement; containerId: string }[] = [];
|
|
151
|
+
const typeByField: Record<
|
|
152
|
+
CardFieldEnum,
|
|
153
|
+
(typeof Skyflow.ElementType)[keyof typeof Skyflow.ElementType]
|
|
154
|
+
> = {
|
|
155
|
+
[CardFieldEnum.CVV]: Skyflow.ElementType.CVV,
|
|
156
|
+
[CardFieldEnum.CARD_NUMBER]: Skyflow.ElementType.CARD_NUMBER,
|
|
157
|
+
[CardFieldEnum.EXPIRATION_MONTH]: Skyflow.ElementType.EXPIRATION_MONTH,
|
|
158
|
+
[CardFieldEnum.EXPIRATION_YEAR]: Skyflow.ElementType.EXPIRATION_YEAR,
|
|
159
|
+
[CardFieldEnum.CARDHOLDER_NAME]: Skyflow.ElementType.CARDHOLDER_NAME,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const validationsByField = {
|
|
163
|
+
[CardFieldEnum.CVV]: [regexMatchRule],
|
|
164
|
+
[CardFieldEnum.CARD_NUMBER]: [regexMatchRule],
|
|
165
|
+
[CardFieldEnum.EXPIRATION_MONTH]: [regexMatchRule],
|
|
166
|
+
[CardFieldEnum.EXPIRATION_YEAR]: [regexMatchRule],
|
|
167
|
+
[CardFieldEnum.CARDHOLDER_NAME]: [lengthMatchRule, regexMatchRule],
|
|
168
|
+
};
|
|
169
|
+
const customStyles = {
|
|
170
|
+
errorStyles:
|
|
171
|
+
customization?.styles?.cardForm?.errorStyles ||
|
|
172
|
+
DEFAULT_SKYFLOW_ERROR_TEXT_STYLES,
|
|
173
|
+
inputStyles:
|
|
174
|
+
customization?.styles?.cardForm?.inputStyles ||
|
|
175
|
+
DEFAULT_SKYFLOW_INPUT_STYLES,
|
|
176
|
+
labelStyles:
|
|
177
|
+
customization?.styles?.cardForm?.labelStyles ||
|
|
178
|
+
DEFAULT_SKYFLOW_lABEL_STYLES,
|
|
179
|
+
};
|
|
180
|
+
const labels: Record<string, string> = {
|
|
181
|
+
name: customization?.labels?.name || DEFAULT_SKYFLOW_lABELS.name,
|
|
182
|
+
card_number:
|
|
183
|
+
customization?.labels?.card_number || DEFAULT_SKYFLOW_lABELS.card_number,
|
|
184
|
+
cvv: customization?.labels?.cvv || DEFAULT_SKYFLOW_lABELS.cvv,
|
|
185
|
+
expiration_date:
|
|
186
|
+
customization?.labels?.expiry_date ||
|
|
187
|
+
DEFAULT_SKYFLOW_lABELS.expiration_date,
|
|
188
|
+
expiration_month:
|
|
189
|
+
customization?.labels?.expiration_month ||
|
|
190
|
+
DEFAULT_SKYFLOW_lABELS.expiration_month,
|
|
191
|
+
expiration_year:
|
|
192
|
+
customization?.labels?.expiration_year ||
|
|
193
|
+
DEFAULT_SKYFLOW_lABELS.expiration_year,
|
|
194
|
+
};
|
|
195
|
+
const placeholders: Record<string, string> = {
|
|
196
|
+
name:
|
|
197
|
+
customization?.placeholders?.name || DEFAULT_SKYFLOW_PLACEHOLDERS.name,
|
|
198
|
+
card_number:
|
|
199
|
+
customization?.placeholders?.card_number ||
|
|
200
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS.card_number,
|
|
201
|
+
cvv: customization?.placeholders?.cvv || DEFAULT_SKYFLOW_PLACEHOLDERS.cvv,
|
|
202
|
+
expiration_month:
|
|
203
|
+
customization?.placeholders?.expiration_month ||
|
|
204
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS.expiration_month,
|
|
205
|
+
expiration_year:
|
|
206
|
+
customization?.placeholders?.expiration_year ||
|
|
207
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS.expiration_year,
|
|
208
|
+
};
|
|
209
|
+
const eventsByField: Record<CardFieldEnum, IInputEvents | undefined> = {
|
|
210
|
+
[CardFieldEnum.CVV]: events?.cvvEvents,
|
|
211
|
+
[CardFieldEnum.CARD_NUMBER]: events?.cardNumberEvents,
|
|
212
|
+
[CardFieldEnum.EXPIRATION_MONTH]: events?.monthEvents,
|
|
213
|
+
[CardFieldEnum.EXPIRATION_YEAR]: events?.yearEvents,
|
|
214
|
+
[CardFieldEnum.CARDHOLDER_NAME]: events?.cardHolderEvents,
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if ("fields" in data && Array.isArray(data.fields)) {
|
|
218
|
+
if (data.fields.length > 0 && typeof data.fields[0] === "string") {
|
|
219
|
+
for (const field of data.fields as CardFieldEnum[]) {
|
|
220
|
+
const element = collectContainer.create({
|
|
221
|
+
table: "cards",
|
|
222
|
+
column: field,
|
|
223
|
+
type: typeByField[field],
|
|
224
|
+
validations: validationsByField[field],
|
|
225
|
+
...customStyles,
|
|
226
|
+
label: labels[field],
|
|
227
|
+
placeholder: placeholders[field],
|
|
228
|
+
...(data.card_id ? { skyflowID: data.card_id } : {}),
|
|
229
|
+
});
|
|
230
|
+
handleSkyflowElementEvents({
|
|
231
|
+
element,
|
|
232
|
+
errorStyles: customStyles.errorStyles,
|
|
233
|
+
fieldMessage: [CardFieldEnum.CVV, CardFieldEnum.EXPIRATION_MONTH, CardFieldEnum.EXPIRATION_YEAR].includes(field) ? "":labels[field],
|
|
234
|
+
events: eventsByField[field],
|
|
235
|
+
});
|
|
236
|
+
const containerId =
|
|
237
|
+
`#collect_${String(field)}` +
|
|
238
|
+
(data.card_id ? `_${data.card_id}` : "");
|
|
239
|
+
element.mount(containerId);
|
|
240
|
+
elements.push({ element, containerId });
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
for (const fieldObj of data.fields as {
|
|
244
|
+
container_id?: string;
|
|
245
|
+
field: CardFieldEnum;
|
|
246
|
+
}[]) {
|
|
247
|
+
const key = fieldObj.field;
|
|
248
|
+
const element = collectContainer.create({
|
|
249
|
+
table: "cards",
|
|
250
|
+
column: key,
|
|
251
|
+
type: typeByField[key],
|
|
252
|
+
validations: validationsByField[key],
|
|
253
|
+
...customStyles,
|
|
254
|
+
label: labels[key],
|
|
255
|
+
placeholder: placeholders[key],
|
|
256
|
+
...(data.card_id ? { skyflowID: data.card_id } : {}),
|
|
257
|
+
});
|
|
258
|
+
const containerId =
|
|
259
|
+
fieldObj.container_id ||
|
|
260
|
+
`#collect_${String(key)}` + (data.card_id ? `_${data.card_id}` : "");
|
|
261
|
+
element.mount(containerId);
|
|
262
|
+
elements.push({ element, containerId });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
elements: elements.map((e) => e.element),
|
|
269
|
+
container: collectContainer,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function handleSkyflowElementEvents(event: {
|
|
274
|
+
element: CollectElement;
|
|
275
|
+
fieldMessage?: string;
|
|
276
|
+
errorStyles?: StylesBaseVariant;
|
|
277
|
+
requiredMessage?: string;
|
|
278
|
+
invalidMessage?: string;
|
|
279
|
+
events?: IInputEvents;
|
|
280
|
+
}) {
|
|
281
|
+
const {
|
|
282
|
+
element,
|
|
283
|
+
fieldMessage = "",
|
|
284
|
+
errorStyles = {},
|
|
285
|
+
requiredMessage = "Campo requerido",
|
|
286
|
+
invalidMessage = "Campo no válido",
|
|
287
|
+
events
|
|
288
|
+
} = event;
|
|
289
|
+
if ("on" in element) {
|
|
290
|
+
element.on(Skyflow.EventName.CHANGE, (state: any) => {
|
|
291
|
+
executeEvent({eventName: "onChange", data: state, events});
|
|
292
|
+
updateErrorLabel({
|
|
293
|
+
element,
|
|
294
|
+
errorStyles,
|
|
295
|
+
color: "transparent",
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
element.on(Skyflow.EventName.BLUR, (state: any) => {
|
|
300
|
+
executeEvent({eventName: "onBlur", data: state, events});
|
|
301
|
+
if (!state.isValid) {
|
|
302
|
+
const msj_error = state.isEmpty
|
|
303
|
+
? requiredMessage
|
|
304
|
+
: fieldMessage != ""
|
|
305
|
+
? `El campo ${fieldMessage} es inválido`
|
|
306
|
+
: invalidMessage;
|
|
307
|
+
element.setError(msj_error);
|
|
308
|
+
}
|
|
309
|
+
updateErrorLabel({
|
|
310
|
+
element,
|
|
311
|
+
errorStyles,
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
element.on(Skyflow.EventName.FOCUS, (state: any) => {
|
|
316
|
+
executeEvent({eventName: "onFocus", data: state, events});
|
|
317
|
+
updateErrorLabel({
|
|
318
|
+
element,
|
|
319
|
+
errorStyles,
|
|
320
|
+
color: "transparent",
|
|
321
|
+
});
|
|
322
|
+
element.resetError();
|
|
75
323
|
});
|
|
76
|
-
}
|
|
324
|
+
}
|
|
77
325
|
}
|
|
78
326
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
327
|
+
function updateErrorLabel(event: {
|
|
328
|
+
element: CollectElement;
|
|
329
|
+
errorStyles?: StylesBaseVariant;
|
|
330
|
+
color?: string;
|
|
331
|
+
}) {
|
|
332
|
+
const { element, errorStyles = {}, color = "" } = event;
|
|
333
|
+
if (Object.keys(errorStyles).length > 0) {
|
|
334
|
+
element.update({
|
|
335
|
+
errorTextStyles: {
|
|
336
|
+
...errorStyles,
|
|
337
|
+
base: {
|
|
338
|
+
// @ts-ignore
|
|
339
|
+
...(errorStyles.base && { ...errorStyles.base }),
|
|
340
|
+
...(color != "" && { color }),
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
}
|
|
90
345
|
}
|
|
91
346
|
|
|
347
|
+
const executeEvent = (event: {
|
|
348
|
+
eventName: "onChange" | "onBlur" | "onFocus";
|
|
349
|
+
data: any;
|
|
350
|
+
events?: IInputEvents;
|
|
351
|
+
}) => {
|
|
352
|
+
const { eventName, data, events } = event;
|
|
353
|
+
if (events && eventName in events) {
|
|
354
|
+
const eventHandler = events[eventName];
|
|
355
|
+
if (typeof eventHandler === "function") {
|
|
356
|
+
eventHandler({
|
|
357
|
+
elementType: get(data, "elementType", ""),
|
|
358
|
+
isEmpty: get(data, "isEmpty", ""),
|
|
359
|
+
isFocused: get(data, "isFocused", ""),
|
|
360
|
+
isValid: get(data, "isValid", ""),
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import Skyflow from "skyflow-js";
|
|
2
|
+
|
|
3
|
+
const lengthMatchRule = {
|
|
4
|
+
type: Skyflow.ValidationRuleType.LENGTH_MATCH_RULE,
|
|
5
|
+
params: {
|
|
6
|
+
max: 70,
|
|
7
|
+
},
|
|
8
|
+
};
|
|
9
|
+
const regexEmpty = RegExp('^(?!s*$).+');
|
|
10
|
+
|
|
11
|
+
const regexMatchRule = {
|
|
12
|
+
type: Skyflow.ValidationRuleType.REGEX_MATCH_RULE,
|
|
13
|
+
params: {
|
|
14
|
+
regex: regexEmpty,
|
|
15
|
+
error: 'El campo es requerido', // Optional, default error is 'VALIDATION FAILED'.
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const getErrorField = (
|
|
22
|
+
event: {
|
|
23
|
+
elementType?: string;
|
|
24
|
+
isEmpty?: boolean;
|
|
25
|
+
isFocused?: boolean;
|
|
26
|
+
isValid?: boolean;
|
|
27
|
+
value?: string;
|
|
28
|
+
},
|
|
29
|
+
field: string
|
|
30
|
+
) => {
|
|
31
|
+
if (event.isEmpty) {
|
|
32
|
+
return 'El campo es requerido';
|
|
33
|
+
} else if (!event.isValid && !event.isEmpty) {
|
|
34
|
+
return `El campo ${field} es inválido`;
|
|
35
|
+
} else {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const DEFAULT_SKYFLOW_lABELS = {
|
|
41
|
+
name: 'Titular de la tarjeta',
|
|
42
|
+
card_number: 'Número de tarjeta',
|
|
43
|
+
cvv: 'CVC/CVV',
|
|
44
|
+
expiration_month: 'Mes',
|
|
45
|
+
expiration_year: 'Año',
|
|
46
|
+
expiration_date: 'Fecha de expiración',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const DEFAULT_SKYFLOW_PLACEHOLDERS = {
|
|
50
|
+
name: 'Nombre como aparece en la tarjeta',
|
|
51
|
+
card_number: '1234 1234 1234 1234',
|
|
52
|
+
cvv: '3-4 dígitos',
|
|
53
|
+
expiration_month: 'MM',
|
|
54
|
+
expiration_year: 'AA',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
lengthMatchRule,
|
|
59
|
+
regexMatchRule,
|
|
60
|
+
getErrorField,
|
|
61
|
+
DEFAULT_SKYFLOW_lABELS,
|
|
62
|
+
DEFAULT_SKYFLOW_PLACEHOLDERS,
|
|
63
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {CollectInputStylesVariant, CollectLabelStylesVariant} from "../../types/commons";
|
|
2
|
+
import {LabelStyles} from "skyflow-js/types/utils/common";
|
|
3
|
+
|
|
4
|
+
const DEFAULT_SKYFLOW_INPUT_STYLES: CollectInputStylesVariant = {
|
|
5
|
+
base: {
|
|
6
|
+
border: "1px solid #e0e0e0",
|
|
7
|
+
padding: "10px 7px",
|
|
8
|
+
borderRadius: "5px",
|
|
9
|
+
color: "#1d1d1d",
|
|
10
|
+
marginTop: "2px",
|
|
11
|
+
backgroundColor: "white",
|
|
12
|
+
fontFamily: '"Inter", sans-serif',
|
|
13
|
+
fontSize: "16px",
|
|
14
|
+
"&::placeholder": {
|
|
15
|
+
color: "#ccc",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
complete: {
|
|
19
|
+
color: "#4caf50",
|
|
20
|
+
},
|
|
21
|
+
invalid: {
|
|
22
|
+
border: "1px solid #f44336",
|
|
23
|
+
},
|
|
24
|
+
empty: {},
|
|
25
|
+
focus: {},
|
|
26
|
+
global: {
|
|
27
|
+
"@import":
|
|
28
|
+
'url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap")',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const DEFAULT_SKYFLOW_lABEL_STYLES: LabelStyles = {
|
|
33
|
+
base: {
|
|
34
|
+
fontSize: "12px",
|
|
35
|
+
fontWeight: "500",
|
|
36
|
+
fontFamily: '"Inter", sans-serif'
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const DEFAULT_SKYFLOW_ERROR_TEXT_STYLES: CollectLabelStylesVariant = {
|
|
41
|
+
base: {
|
|
42
|
+
fontSize: '12px',
|
|
43
|
+
fontWeight: '500',
|
|
44
|
+
fontFamily: '"Inter", sans-serif',
|
|
45
|
+
color: "#f44336",
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const SKYFLOW_HIDDEN_ERROR_TEXT_STYLES = {
|
|
50
|
+
base: {
|
|
51
|
+
fontSize: '12px',
|
|
52
|
+
fontWeight: '500',
|
|
53
|
+
color: "#f44336",
|
|
54
|
+
fontFamily: '"Inter", sans-serif'
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
DEFAULT_SKYFLOW_INPUT_STYLES,
|
|
60
|
+
DEFAULT_SKYFLOW_lABEL_STYLES,
|
|
61
|
+
DEFAULT_SKYFLOW_ERROR_TEXT_STYLES,
|
|
62
|
+
SKYFLOW_HIDDEN_ERROR_TEXT_STYLES,
|
|
63
|
+
};
|
package/src/types/card.ts
CHANGED
|
@@ -33,3 +33,15 @@ export interface ISaveCardRequest {
|
|
|
33
33
|
expiration_year: string;
|
|
34
34
|
cardholder_name: string;
|
|
35
35
|
}
|
|
36
|
+
export enum CardFieldEnum {
|
|
37
|
+
CARD_NUMBER = 'card_number',
|
|
38
|
+
CVV = 'cvv',
|
|
39
|
+
EXPIRATION_MONTH = 'expiration_month',
|
|
40
|
+
EXPIRATION_YEAR = 'expiration_year',
|
|
41
|
+
CARDHOLDER_NAME = 'cardholder_name',
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface IMountCardFieldsRequest {
|
|
45
|
+
fields: CardFieldEnum[] | { container_id?: string; field: CardFieldEnum}[],
|
|
46
|
+
card_id?: string;
|
|
47
|
+
}
|
package/src/types/checkout.ts
CHANGED