@tonder.io/ionic-full-sdk 0.0.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/.gitlab-ci.yml +19 -0
- package/README.md +197 -0
- package/cypress.config.js +9 -0
- package/dist/classes/3dsHandler.d.ts +20 -0
- package/dist/classes/checkout.d.ts +39 -0
- package/dist/classes/inlineCheckout.d.ts +66 -0
- package/dist/data/api.d.ts +18 -0
- package/dist/helpers/skyflow.d.ts +5 -0
- package/dist/helpers/styles.d.ts +1 -0
- package/dist/helpers/template.d.ts +18 -0
- package/dist/helpers/utils.d.ts +7 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/types/commons-ds.d.ts +40 -0
- package/dist/types/commons.d.ts +40 -0
- package/dist/types/skyflow.d.ts +39 -0
- package/dist/types/skyflow.ds.d.ts +39 -0
- package/index.js.example +50 -0
- package/package.json +27 -0
- package/rollup.config.js +15 -0
- package/src/classes/3dsHandler.ts +103 -0
- package/src/classes/checkout.ts +148 -0
- package/src/classes/inlineCheckout.ts +440 -0
- package/src/helpers/skyflow.ts +146 -0
- package/src/helpers/styles.ts +60 -0
- package/src/helpers/template.ts +194 -0
- package/src/helpers/utils.ts +106 -0
- package/src/images/amex.png +0 -0
- package/src/images/master.png +0 -0
- package/src/images/other.png +0 -0
- package/src/images/visa.png +0 -0
- package/src/index-dev.js +120 -0
- package/src/index.html +57 -0
- package/src/index.ts +7 -0
- package/src/types/commons.ts +43 -0
- package/src/types/skyflow.ts +41 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { Card, cardItemsTemplate, cardTemplate, CollectorIds } from '../helpers/template'
|
|
2
|
+
import { LiteCheckout } from '@tonder.io/ionic-lite-sdk';
|
|
3
|
+
import {
|
|
4
|
+
showError
|
|
5
|
+
} from '../helpers/utils';
|
|
6
|
+
import { initSkyflow } from '../helpers/skyflow'
|
|
7
|
+
import { ThreeDSHandler } from './3dsHandler';
|
|
8
|
+
import { ErrorResponse } from '@tonder.io/ionic-lite-sdk/dist/classes/errorResponse';
|
|
9
|
+
import { Business, Customer, PaymentData, OrderItem } from '@tonder.io/ionic-lite-sdk/dist/types/commons';
|
|
10
|
+
import { CustomerRegisterResponse, StartCheckoutResponse } from '@tonder.io/ionic-lite-sdk/dist/types/responses';
|
|
11
|
+
import { StartCheckoutRequest, CreatePaymentRequest, CreateOrderRequest } from '@tonder.io/ionic-lite-sdk/dist/types/requests';
|
|
12
|
+
|
|
13
|
+
export type InlineCheckoutConstructor = {
|
|
14
|
+
returnUrl: string,
|
|
15
|
+
apiKey: string,
|
|
16
|
+
successUrl?: string,
|
|
17
|
+
renderPaymentButton: boolean,
|
|
18
|
+
callBack?: (params: any) => void,
|
|
19
|
+
styles?: any,
|
|
20
|
+
form?: any,
|
|
21
|
+
totalElement?: any,
|
|
22
|
+
containerId?: string,
|
|
23
|
+
collectorIds?: CollectorIds,
|
|
24
|
+
platforms?: string[]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class InlineCheckout {
|
|
28
|
+
paymentData = {}
|
|
29
|
+
items = []
|
|
30
|
+
//@ts-ignore
|
|
31
|
+
baseUrl = "https://stage.tonder.io";
|
|
32
|
+
collectContainer: any = null
|
|
33
|
+
cartTotal?: string | null | number
|
|
34
|
+
apiKeyTonder: string
|
|
35
|
+
returnUrl?: string
|
|
36
|
+
successUrl?: string
|
|
37
|
+
renderPaymentButton: boolean
|
|
38
|
+
callBack: (params: any) => void
|
|
39
|
+
customStyles: any
|
|
40
|
+
abortController: AbortController
|
|
41
|
+
process3ds: ThreeDSHandler
|
|
42
|
+
cb?: () => void
|
|
43
|
+
firstName?: string
|
|
44
|
+
lastName?: string
|
|
45
|
+
country?: string
|
|
46
|
+
address?: string
|
|
47
|
+
city?: string
|
|
48
|
+
state?: string
|
|
49
|
+
postCode?: string
|
|
50
|
+
email?: string
|
|
51
|
+
phone?: string
|
|
52
|
+
merchantData?: Business | ErrorResponse
|
|
53
|
+
cartItems?: any
|
|
54
|
+
injectInterval: any
|
|
55
|
+
containerId: string
|
|
56
|
+
injected: boolean
|
|
57
|
+
cardsInjected: boolean
|
|
58
|
+
collectorIds: CollectorIds
|
|
59
|
+
platforms?: string[]
|
|
60
|
+
liteCheckout: LiteCheckout
|
|
61
|
+
clientCards: Card[]
|
|
62
|
+
|
|
63
|
+
constructor ({
|
|
64
|
+
apiKey,
|
|
65
|
+
returnUrl,
|
|
66
|
+
successUrl,
|
|
67
|
+
renderPaymentButton = false,
|
|
68
|
+
callBack = () => {},
|
|
69
|
+
styles,
|
|
70
|
+
containerId,
|
|
71
|
+
collectorIds,
|
|
72
|
+
platforms
|
|
73
|
+
}: InlineCheckoutConstructor) {
|
|
74
|
+
this.apiKeyTonder = apiKey;
|
|
75
|
+
this.returnUrl = returnUrl;
|
|
76
|
+
this.successUrl = successUrl;
|
|
77
|
+
this.renderPaymentButton = renderPaymentButton;
|
|
78
|
+
this.callBack = callBack;
|
|
79
|
+
this.customStyles = styles
|
|
80
|
+
this.platforms = platforms
|
|
81
|
+
|
|
82
|
+
this.abortController = new AbortController()
|
|
83
|
+
|
|
84
|
+
this.liteCheckout = new LiteCheckout({
|
|
85
|
+
apiKeyTonder: apiKey,
|
|
86
|
+
baseUrlTonder: this.baseUrl,
|
|
87
|
+
signal: this.abortController.signal
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
this.process3ds = new ThreeDSHandler({
|
|
91
|
+
apiKey: apiKey,
|
|
92
|
+
baseUrl: this.baseUrl,
|
|
93
|
+
successUrl: successUrl
|
|
94
|
+
})
|
|
95
|
+
this.containerId = containerId ? containerId : "tonder-checkout"
|
|
96
|
+
this.injected = false;
|
|
97
|
+
this.cardsInjected = false;
|
|
98
|
+
this.collectorIds = collectorIds ? collectorIds : {
|
|
99
|
+
cardsListContainer: "cardsListContainer",
|
|
100
|
+
holderName: "collectCardholderName",
|
|
101
|
+
cardNumber: "collectCardNumber",
|
|
102
|
+
expirationMonth: "collectExpirationMonth",
|
|
103
|
+
expirationYear: "collectExpirationYear",
|
|
104
|
+
cvv: "collectCvv",
|
|
105
|
+
tonderPayButton: "tonderPayButton",
|
|
106
|
+
msgError: "msgError"
|
|
107
|
+
}
|
|
108
|
+
this.clientCards = []
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#mountPayButton() {
|
|
112
|
+
if (!this.renderPaymentButton) return;
|
|
113
|
+
|
|
114
|
+
const payButton: HTMLElement | null = document.querySelector(`#${this.collectorIds.tonderPayButton}`);
|
|
115
|
+
if (!payButton) {
|
|
116
|
+
console.error("Pay button not found");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
payButton.style.display = "block";
|
|
121
|
+
payButton.textContent = `Pagar $${this.cartTotal}`;
|
|
122
|
+
payButton.onclick = async (event) => {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
await this.#handlePaymentClick(payButton);
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async #handlePaymentClick(payButton: any) {
|
|
129
|
+
const prevButtonContent = payButton.innerHTML;
|
|
130
|
+
payButton.innerHTML = `<div class="lds-dual-ring"></div>`;
|
|
131
|
+
try {
|
|
132
|
+
const response = await this.payment(this.paymentData);
|
|
133
|
+
this.callBack(response);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
console.error("Payment error:", error);
|
|
136
|
+
} finally {
|
|
137
|
+
payButton.innerHTML = prevButtonContent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
payment(data: any) {
|
|
142
|
+
return new Promise(async (resolve, reject) => {
|
|
143
|
+
try {
|
|
144
|
+
this.#handleCustomer(data.customer)
|
|
145
|
+
this.setCartTotal(data.cart?.total)
|
|
146
|
+
this.setCartItems(data.cart?.items)
|
|
147
|
+
const response: ErrorResponse | StartCheckoutResponse | false | undefined = await this.#checkout()
|
|
148
|
+
if (response) {
|
|
149
|
+
const process3ds = new ThreeDSHandler({ payload: response });
|
|
150
|
+
this.callBack(response);
|
|
151
|
+
if (!process3ds.redirectTo3DS()) {
|
|
152
|
+
resolve(response);
|
|
153
|
+
} else {
|
|
154
|
+
resolve(response);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} catch (error) {
|
|
158
|
+
reject(error);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#handleCustomer(customer: Customer) {
|
|
164
|
+
if (!customer) return
|
|
165
|
+
|
|
166
|
+
this.firstName = customer?.firstName
|
|
167
|
+
this.lastName = customer?.lastName
|
|
168
|
+
this.country = customer?.country
|
|
169
|
+
this.address = customer?.street
|
|
170
|
+
this.city = customer?.city
|
|
171
|
+
this.state = customer?.state
|
|
172
|
+
this.postCode = customer?.postCode
|
|
173
|
+
this.email = customer?.email
|
|
174
|
+
this.phone = customer?.phone
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
setCartItems (items: OrderItem[]) {
|
|
178
|
+
this.cartItems = items
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
setCustomerEmail (email: string) {
|
|
182
|
+
this.email = email
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
setPaymentData (data?: PaymentData) {
|
|
186
|
+
if (!data) return
|
|
187
|
+
this.paymentData = data
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
setCartTotal (total: string | number) {
|
|
191
|
+
this.cartTotal = total
|
|
192
|
+
this.#updatePayButton()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
#updatePayButton() {
|
|
196
|
+
const payButton = document.querySelector(`#${this.collectorIds.tonderPayButton}`);
|
|
197
|
+
if (!payButton) return
|
|
198
|
+
payButton.textContent = `Pagar $${this.cartTotal}`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
setCallback (cb: any) {
|
|
202
|
+
this.cb = cb
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
injectCheckout() {
|
|
206
|
+
if (this.injected) return
|
|
207
|
+
this.process3ds.verifyTransactionStatus()
|
|
208
|
+
const injectInterval = setInterval(() => {
|
|
209
|
+
const queryElement = document.querySelector(`#${this.containerId}`)
|
|
210
|
+
if (queryElement) {
|
|
211
|
+
queryElement.innerHTML = cardTemplate(this.customStyles ? true : false, this.collectorIds)
|
|
212
|
+
this.#mountTonder();
|
|
213
|
+
clearInterval(injectInterval);
|
|
214
|
+
this.injected = true
|
|
215
|
+
}
|
|
216
|
+
}, 500);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
loadCardsList (cards: Card[]) {
|
|
220
|
+
if(this.cardsInjected) return;
|
|
221
|
+
const injectInterval = setInterval(() => {
|
|
222
|
+
const queryElement = document.querySelector(`#${this.collectorIds.cardsListContainer}`);
|
|
223
|
+
if (queryElement && this.injected) {
|
|
224
|
+
queryElement.innerHTML = cardItemsTemplate(this.customStyles ? true : false, cards)
|
|
225
|
+
clearInterval(injectInterval)
|
|
226
|
+
this.cardsInjected = true
|
|
227
|
+
}
|
|
228
|
+
}, 500);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async #fetchMerchantData() {
|
|
232
|
+
this.merchantData = await this.liteCheckout.getBusiness();
|
|
233
|
+
return this.merchantData
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async getCustomer(email: string) {
|
|
237
|
+
return await this.liteCheckout.customerRegister(email);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async #mountTonder() {
|
|
241
|
+
|
|
242
|
+
this.#mountPayButton()
|
|
243
|
+
|
|
244
|
+
const result = await this.#fetchMerchantData();
|
|
245
|
+
|
|
246
|
+
if(result && "vault_id" in result) {
|
|
247
|
+
|
|
248
|
+
const { vault_id, vault_url } = result;
|
|
249
|
+
|
|
250
|
+
if(this.email) {
|
|
251
|
+
|
|
252
|
+
const customerResponse : CustomerRegisterResponse | ErrorResponse = await this.getCustomer(this.email);
|
|
253
|
+
|
|
254
|
+
if("auth_token" in customerResponse) {
|
|
255
|
+
|
|
256
|
+
const { auth_token } = customerResponse
|
|
257
|
+
|
|
258
|
+
const cards = await this.liteCheckout.getCustomerCards(auth_token);
|
|
259
|
+
|
|
260
|
+
if("cards" in cards) {
|
|
261
|
+
|
|
262
|
+
const cardsMapped: Card[] = cards.cards.records.map(record => ({ ...record.fields }))
|
|
263
|
+
|
|
264
|
+
this.loadCardsList(cardsMapped)
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
this.collectContainer = await initSkyflow(
|
|
273
|
+
vault_id,
|
|
274
|
+
vault_url,
|
|
275
|
+
this.baseUrl,
|
|
276
|
+
this.abortController.signal,
|
|
277
|
+
this.customStyles,
|
|
278
|
+
this.collectorIds,
|
|
279
|
+
this.apiKeyTonder
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
removeCheckout() {
|
|
287
|
+
this.injected = false
|
|
288
|
+
this.cardsInjected = false
|
|
289
|
+
// Cancel all requests
|
|
290
|
+
this.abortController.abort();
|
|
291
|
+
this.abortController = new AbortController();
|
|
292
|
+
|
|
293
|
+
clearInterval(this.injectInterval);
|
|
294
|
+
console.log("InlineCheckout removed from DOM and cleaned up.");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async #checkout() {
|
|
298
|
+
try {
|
|
299
|
+
const selector: any = document.querySelector(`#${this.collectorIds.tonderPayButton}`);
|
|
300
|
+
if(selector){
|
|
301
|
+
selector.disabled = true;
|
|
302
|
+
}
|
|
303
|
+
} catch (error) {
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if(this.merchantData) {
|
|
307
|
+
|
|
308
|
+
if("openpay_keys" in this.merchantData) {
|
|
309
|
+
|
|
310
|
+
const { openpay_keys, reference, business } = this.merchantData
|
|
311
|
+
|
|
312
|
+
const total = Number(this.cartTotal)
|
|
313
|
+
|
|
314
|
+
var cardTokensSkyflowTonder: any = null;
|
|
315
|
+
try {
|
|
316
|
+
const collectResponseSkyflowTonder = await this.collectContainer?.collect();
|
|
317
|
+
cardTokensSkyflowTonder = await collectResponseSkyflowTonder["records"][0]["fields"];
|
|
318
|
+
} catch (error) {
|
|
319
|
+
showError("Por favor, verifica todos los campos de tu tarjeta", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
|
|
320
|
+
throw error;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
try {
|
|
324
|
+
|
|
325
|
+
let deviceSessionIdTonder: any;
|
|
326
|
+
|
|
327
|
+
if (openpay_keys.merchant_id && openpay_keys.public_key) {
|
|
328
|
+
deviceSessionIdTonder = await this.liteCheckout.getOpenpayDeviceSessionID(
|
|
329
|
+
openpay_keys.merchant_id,
|
|
330
|
+
openpay_keys.public_key
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if(this.email) {
|
|
335
|
+
|
|
336
|
+
const customerResponse : CustomerRegisterResponse | ErrorResponse = await this.getCustomer(this.email);
|
|
337
|
+
|
|
338
|
+
if("auth_token" in customerResponse) {
|
|
339
|
+
|
|
340
|
+
const { auth_token } = customerResponse;
|
|
341
|
+
|
|
342
|
+
const cards = await this.liteCheckout.getCustomerCards(auth_token);
|
|
343
|
+
|
|
344
|
+
if("cards" in cards) {
|
|
345
|
+
|
|
346
|
+
const cardExist = cards.cards.records.find((record: any) => record.fields.skyflow_id === cardTokensSkyflowTonder.skyflow_id)
|
|
347
|
+
|
|
348
|
+
if(!cardExist) {
|
|
349
|
+
|
|
350
|
+
await this.liteCheckout.registerCustomerCard(auth_token, { skyflow_id: cardTokensSkyflowTonder.skyflow_id });
|
|
351
|
+
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const orderItems: CreateOrderRequest = {
|
|
357
|
+
business: this.apiKeyTonder,
|
|
358
|
+
client: auth_token,
|
|
359
|
+
billing_address_id: null,
|
|
360
|
+
shipping_address_id: null,
|
|
361
|
+
amount: total,
|
|
362
|
+
status: "A",
|
|
363
|
+
reference: reference,
|
|
364
|
+
is_oneclick: true,
|
|
365
|
+
items: this.cartItems,
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
const jsonResponseOrder = await this.liteCheckout.createOrder(
|
|
369
|
+
orderItems
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
// Create payment
|
|
373
|
+
const now = new Date();
|
|
374
|
+
const dateString = now.toISOString();
|
|
375
|
+
|
|
376
|
+
if("id" in jsonResponseOrder) {
|
|
377
|
+
|
|
378
|
+
const paymentItems: CreatePaymentRequest = {
|
|
379
|
+
business_pk: business.pk,
|
|
380
|
+
amount: total,
|
|
381
|
+
date: dateString,
|
|
382
|
+
order: jsonResponseOrder.id
|
|
383
|
+
};
|
|
384
|
+
const jsonResponsePayment = await this.liteCheckout.createPayment(
|
|
385
|
+
paymentItems
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
// Checkout router
|
|
389
|
+
const routerItems: StartCheckoutRequest = {
|
|
390
|
+
card: cardTokensSkyflowTonder,
|
|
391
|
+
name: cardTokensSkyflowTonder.cardholder_name,
|
|
392
|
+
last_name: "",
|
|
393
|
+
email_client: this.email,
|
|
394
|
+
phone_number: this.phone,
|
|
395
|
+
return_url: this.returnUrl,
|
|
396
|
+
id_product: "no_id",
|
|
397
|
+
quantity_product: 1,
|
|
398
|
+
id_ship: "0",
|
|
399
|
+
instance_id_ship: "0",
|
|
400
|
+
amount: total,
|
|
401
|
+
title_ship: "shipping",
|
|
402
|
+
description: "transaction",
|
|
403
|
+
device_session_id: deviceSessionIdTonder ? deviceSessionIdTonder : null,
|
|
404
|
+
token_id: "",
|
|
405
|
+
order_id: ("id" in jsonResponseOrder) && jsonResponseOrder.id,
|
|
406
|
+
business_id: business.pk,
|
|
407
|
+
payment_id: ("pk" in jsonResponsePayment) && jsonResponsePayment.pk,
|
|
408
|
+
source: 'sdk',
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
const jsonResponseRouter = await this.liteCheckout.startCheckoutRouter(
|
|
412
|
+
routerItems
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
if (jsonResponseRouter) {
|
|
416
|
+
try {
|
|
417
|
+
const selector: any = document.querySelector(`#${this.collectorIds.tonderPayButton}`);
|
|
418
|
+
if(selector) {
|
|
419
|
+
selector.disabled = false;
|
|
420
|
+
}
|
|
421
|
+
} catch {}
|
|
422
|
+
return jsonResponseRouter;
|
|
423
|
+
} else {
|
|
424
|
+
showError("No se ha podido procesar el pago", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
} catch (error) {
|
|
431
|
+
console.log(error);
|
|
432
|
+
showError("Ha ocurrido un error", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
|
|
433
|
+
throw error;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import CollectElement from "skyflow-js/types/core/external/collect/collect-element";
|
|
2
|
+
import { defaultStyles } from "./styles";
|
|
3
|
+
import Skyflow from 'skyflow-js'
|
|
4
|
+
import { CollectorIds } from "./template";
|
|
5
|
+
import CollectorContainer from "skyflow-js/types/core/external/collect/collect-container"
|
|
6
|
+
import ComposableContainer from "skyflow-js/types/core/external/collect/compose-collect-container"
|
|
7
|
+
import RevealContainer from "skyflow-js/types/core/external/reveal/reveal-container"
|
|
8
|
+
|
|
9
|
+
export async function initSkyflow(
|
|
10
|
+
vaultId: string,
|
|
11
|
+
vaultUrl: string,
|
|
12
|
+
baseUrl: string,
|
|
13
|
+
signal: AbortSignal,
|
|
14
|
+
customStyles: any = {},
|
|
15
|
+
collectorIds: CollectorIds,
|
|
16
|
+
apiKey: string
|
|
17
|
+
): Promise <CollectorContainer | ComposableContainer | RevealContainer> {
|
|
18
|
+
const skyflow = await Skyflow.init({
|
|
19
|
+
vaultID: vaultId,
|
|
20
|
+
vaultURL: vaultUrl,
|
|
21
|
+
getBearerToken: async () => {
|
|
22
|
+
// Pass the signal to the fetch call
|
|
23
|
+
const response = await fetch(`${baseUrl}/api/v1/vault-token/`, {
|
|
24
|
+
method: 'GET',
|
|
25
|
+
headers: {
|
|
26
|
+
'Authorization': `Token ${apiKey}`,
|
|
27
|
+
},
|
|
28
|
+
signal: signal,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (response.ok) {
|
|
32
|
+
const responseBody = await response.json();
|
|
33
|
+
return responseBody.token;
|
|
34
|
+
} else {
|
|
35
|
+
throw new Error('Failed to retrieve bearer token');
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
options: {
|
|
39
|
+
logLevel: Skyflow.LogLevel.ERROR,
|
|
40
|
+
env: Skyflow.Env.DEV,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Create collect Container.
|
|
45
|
+
const collectContainer = await skyflow.container(
|
|
46
|
+
Skyflow.ContainerType.COLLECT
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
// Custom styles for collect elements.
|
|
50
|
+
var collectStylesOptions: any = Object.keys(customStyles).length === 0 ? defaultStyles : customStyles
|
|
51
|
+
|
|
52
|
+
const stylesForCardNumber = { ...collectStylesOptions.inputStyles.base };
|
|
53
|
+
stylesForCardNumber.textIndent = '44px';
|
|
54
|
+
|
|
55
|
+
const lengthMatchRule = {
|
|
56
|
+
type: Skyflow.ValidationRuleType.LENGTH_MATCH_RULE,
|
|
57
|
+
params: {
|
|
58
|
+
max: 70,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const cardHolderNameElement: any = await collectContainer.create({
|
|
63
|
+
table: "cards",
|
|
64
|
+
column: "cardholder_name",
|
|
65
|
+
...collectStylesOptions,
|
|
66
|
+
label: "Titular de la tarjeta",
|
|
67
|
+
placeholder: "Nombre como aparece en la tarjeta",
|
|
68
|
+
type: Skyflow.ElementType.CARDHOLDER_NAME,
|
|
69
|
+
validations: [lengthMatchRule],
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
cardHolderNameElement.setError('Inválido')
|
|
73
|
+
|
|
74
|
+
// Create collect elements.
|
|
75
|
+
const cardNumberElement: any = await collectContainer.create({
|
|
76
|
+
table: "cards",
|
|
77
|
+
column: "card_number",
|
|
78
|
+
...collectStylesOptions,
|
|
79
|
+
inputStyles: {
|
|
80
|
+
...collectStylesOptions.inputStyles,
|
|
81
|
+
base: stylesForCardNumber
|
|
82
|
+
},
|
|
83
|
+
label: "Número de tarjeta",
|
|
84
|
+
placeholder: "1234 1234 1234 1234",
|
|
85
|
+
type: Skyflow.ElementType.CARD_NUMBER,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
cardNumberElement.setError('Inválido')
|
|
89
|
+
|
|
90
|
+
const cvvElement: any = await collectContainer.create({
|
|
91
|
+
table: "cards",
|
|
92
|
+
column: "cvv",
|
|
93
|
+
...collectStylesOptions,
|
|
94
|
+
label: "CVC/CVV",
|
|
95
|
+
placeholder: "3-4 dígitos",
|
|
96
|
+
type: Skyflow.ElementType.CVV,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
cvvElement.setError('Inválido')
|
|
100
|
+
|
|
101
|
+
const expiryMonthElement: any = await collectContainer.create({
|
|
102
|
+
table: "cards",
|
|
103
|
+
column: "expiration_month",
|
|
104
|
+
...collectStylesOptions,
|
|
105
|
+
label: "Fecha de expiración",
|
|
106
|
+
placeholder: "MM",
|
|
107
|
+
type: Skyflow.ElementType.EXPIRATION_MONTH,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expiryMonthElement.setError('Inválido')
|
|
111
|
+
|
|
112
|
+
const expiryYearElement: any = await collectContainer.create({
|
|
113
|
+
table: "cards",
|
|
114
|
+
column: "expiration_year",
|
|
115
|
+
...collectStylesOptions,
|
|
116
|
+
label: "",
|
|
117
|
+
placeholder: "AA",
|
|
118
|
+
type: Skyflow.ElementType.EXPIRATION_YEAR,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
expiryYearElement.setError('Inválido')
|
|
122
|
+
|
|
123
|
+
await mountElements(
|
|
124
|
+
{ id: collectorIds.cardNumber, element: cardNumberElement },
|
|
125
|
+
{ id: collectorIds.cvv, element: cvvElement },
|
|
126
|
+
{ id: collectorIds.expirationMonth, element: expiryMonthElement },
|
|
127
|
+
{ id: collectorIds.expirationYear, element: expiryYearElement },
|
|
128
|
+
{ id: collectorIds.holderName, element: cardHolderNameElement }
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
return collectContainer
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function mountElements(
|
|
135
|
+
cardNumberElement: any,
|
|
136
|
+
cvvElement: any,
|
|
137
|
+
expiryMonthElement: any,
|
|
138
|
+
expiryYearElement: any,
|
|
139
|
+
cardHolderNameElement: any,
|
|
140
|
+
) {
|
|
141
|
+
cardNumberElement.element.mount(`#${cardNumberElement.id}`);
|
|
142
|
+
cvvElement.element.mount(`#${cvvElement.id}`);
|
|
143
|
+
expiryMonthElement.element.mount(`#${expiryMonthElement.id}`);
|
|
144
|
+
expiryYearElement.element.mount(`#${expiryYearElement.id}`);
|
|
145
|
+
cardHolderNameElement.element.mount(`#${cardHolderNameElement.id}`);
|
|
146
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export const defaultStyles: any = {
|
|
2
|
+
inputStyles: {
|
|
3
|
+
base: {
|
|
4
|
+
border: "1px solid #e0e0e0",
|
|
5
|
+
padding: "10px 7px",
|
|
6
|
+
borderRadius: "5px",
|
|
7
|
+
color: "#1d1d1d",
|
|
8
|
+
marginTop: "2px",
|
|
9
|
+
backgroundColor: "white",
|
|
10
|
+
fontFamily: '"Inter", sans-serif',
|
|
11
|
+
fontSize: '16px',
|
|
12
|
+
'&::placeholder': {
|
|
13
|
+
color: "#ccc",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
cardIcon: {
|
|
17
|
+
position: 'absolute',
|
|
18
|
+
left: '6px',
|
|
19
|
+
bottom: 'calc(50% - 12px)',
|
|
20
|
+
},
|
|
21
|
+
complete: {
|
|
22
|
+
color: "#4caf50",
|
|
23
|
+
},
|
|
24
|
+
empty: {},
|
|
25
|
+
focus: {},
|
|
26
|
+
invalid: {
|
|
27
|
+
border: "1px solid #f44336",
|
|
28
|
+
},
|
|
29
|
+
global: {
|
|
30
|
+
'@import': 'url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;700&display=swap")',
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
labelStyles: {
|
|
34
|
+
base: {
|
|
35
|
+
fontSize: '12px',
|
|
36
|
+
fontWeight: '500',
|
|
37
|
+
fontFamily: '"Inter", sans-serif'
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
errorTextStyles: {
|
|
41
|
+
base: {
|
|
42
|
+
fontSize: '12px',
|
|
43
|
+
fontWeight: '500',
|
|
44
|
+
color: "#f44336",
|
|
45
|
+
fontFamily: '"Inter", sans-serif'
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
labels: {
|
|
49
|
+
cardLabel: '',
|
|
50
|
+
cvvLabel: '',
|
|
51
|
+
expiryMonthLabel: '',
|
|
52
|
+
expiryYearLabel: ''
|
|
53
|
+
},
|
|
54
|
+
placeholders: {
|
|
55
|
+
cardPlaceholder: '',
|
|
56
|
+
cvvPlaceholder: '',
|
|
57
|
+
expiryMonthPlaceholder: '',
|
|
58
|
+
expiryYearPlaceholder: ''
|
|
59
|
+
}
|
|
60
|
+
}
|