@tonder.io/ionic-full-sdk 0.0.1 → 0.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonder.io/ionic-full-sdk",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Tonder ionic full SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.js",
@@ -1,7 +1,8 @@
1
1
  import { Card, cardItemsTemplate, cardTemplate, CollectorIds } from '../helpers/template'
2
2
  import { LiteCheckout } from '@tonder.io/ionic-lite-sdk';
3
3
  import {
4
- showError
4
+ showError,
5
+ showMessage
5
6
  } from '../helpers/utils';
6
7
  import { initSkyflow } from '../helpers/skyflow'
7
8
  import { ThreeDSHandler } from './3dsHandler';
@@ -27,7 +28,6 @@ export type InlineCheckoutConstructor = {
27
28
  export class InlineCheckout {
28
29
  paymentData = {}
29
30
  items = []
30
- //@ts-ignore
31
31
  baseUrl = "https://stage.tonder.io";
32
32
  collectContainer: any = null
33
33
  cartTotal?: string | null | number
@@ -59,6 +59,7 @@ export class InlineCheckout {
59
59
  platforms?: string[]
60
60
  liteCheckout: LiteCheckout
61
61
  clientCards: Card[]
62
+ radioChecked: string | null
62
63
 
63
64
  constructor ({
64
65
  apiKey,
@@ -103,9 +104,11 @@ export class InlineCheckout {
103
104
  expirationYear: "collectExpirationYear",
104
105
  cvv: "collectCvv",
105
106
  tonderPayButton: "tonderPayButton",
106
- msgError: "msgError"
107
+ msgError: "msgError",
108
+ msgNotification: "msgNotification"
107
109
  }
108
110
  this.clientCards = []
111
+ this.radioChecked = "new"
109
112
  }
110
113
 
111
114
  #mountPayButton() {
@@ -160,6 +163,25 @@ export class InlineCheckout {
160
163
  });
161
164
  }
162
165
 
166
+ #mountRadioButtons () {
167
+ const radioButtons: NodeListOf<HTMLElement> = document.getElementsByName(`card_selected`);
168
+ for (const radio of radioButtons) {
169
+ radio.style.display = "block";
170
+ radio.onclick = async (event) => {
171
+ //event.preventDefault();
172
+ await this.#handleRadioButtonClick(radio);
173
+ };
174
+ }
175
+ }
176
+
177
+ async #handleRadioButtonClick (radio: HTMLElement) {
178
+ const containerForm: HTMLElement | null = document.querySelector(".container-form");
179
+ if(containerForm) {
180
+ containerForm.style.display = radio.id === "new" ? "block" : "none";
181
+ }
182
+ this.radioChecked = radio.id;
183
+ }
184
+
163
185
  #handleCustomer(customer: Customer) {
164
186
  if (!customer) return
165
187
 
@@ -223,6 +245,7 @@ export class InlineCheckout {
223
245
  if (queryElement && this.injected) {
224
246
  queryElement.innerHTML = cardItemsTemplate(this.customStyles ? true : false, cards)
225
247
  clearInterval(injectInterval)
248
+ this.#mountRadioButtons()
226
249
  this.cardsInjected = true
227
250
  }
228
251
  }, 500);
@@ -311,13 +334,23 @@ export class InlineCheckout {
311
334
 
312
335
  const total = Number(this.cartTotal)
313
336
 
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;
337
+ let cardTokensSkyflowTonder: any = null;
338
+
339
+ if(this.radioChecked === "new") {
340
+ try {
341
+ const collectResponseSkyflowTonder = await this.collectContainer?.collect();
342
+ cardTokensSkyflowTonder = await collectResponseSkyflowTonder["records"][0]["fields"];
343
+ } catch (error) {
344
+ showError("Por favor, verifica todos los campos de tu tarjeta", this.collectorIds.msgError, this.collectorIds.tonderPayButton)
345
+ throw error;
346
+ }
347
+
348
+ } else {
349
+
350
+ cardTokensSkyflowTonder = {
351
+ skyflow_id: this.radioChecked
352
+ }
353
+
321
354
  }
322
355
 
323
356
  try {
@@ -339,17 +372,25 @@ export class InlineCheckout {
339
372
 
340
373
  const { auth_token } = customerResponse;
341
374
 
342
- const cards = await this.liteCheckout.getCustomerCards(auth_token);
343
-
344
- if("cards" in cards) {
375
+ const saveCard: HTMLElement | null = document.getElementById("save-checkout-card");
376
+
377
+ if(saveCard && "checked" in saveCard && saveCard.checked) {
345
378
 
346
- const cardExist = cards.cards.records.find((record: any) => record.fields.skyflow_id === cardTokensSkyflowTonder.skyflow_id)
379
+ await this.liteCheckout.registerCustomerCard(auth_token, { skyflow_id: cardTokensSkyflowTonder.skyflow_id });
380
+
381
+ this.cardsInjected = false;
382
+
383
+ const cards = await this.liteCheckout.getCustomerCards(auth_token);
347
384
 
348
- if(!cardExist) {
385
+ if("cards" in cards) {
349
386
 
350
- await this.liteCheckout.registerCustomerCard(auth_token, { skyflow_id: cardTokensSkyflowTonder.skyflow_id });
387
+ const cardsMapped: Card[] = cards.cards.records.map(record => ({ ...record.fields }))
388
+
389
+ this.loadCardsList(cardsMapped)
351
390
 
352
391
  }
392
+
393
+ showMessage("Tarjeta registrada con éxito", this.collectorIds.msgNotification);
353
394
 
354
395
  }
355
396
 
@@ -381,6 +422,7 @@ export class InlineCheckout {
381
422
  date: dateString,
382
423
  order: jsonResponseOrder.id
383
424
  };
425
+
384
426
  const jsonResponsePayment = await this.liteCheckout.createPayment(
385
427
  paymentItems
386
428
  );
@@ -8,6 +8,7 @@ export type CollectorIds = {
8
8
  cvv: string,
9
9
  tonderPayButton: string,
10
10
  msgError: string,
11
+ msgNotification: string,
11
12
  cardsListContainer: string
12
13
  }
13
14
 
@@ -15,25 +16,37 @@ export type Card = {
15
16
  cardholder_name: string,
16
17
  card_number: string,
17
18
  expiration_month: string,
18
- expiration_year: string
19
+ expiration_year: string,
20
+ skyflow_id: string
19
21
  }
20
22
 
21
23
  export const cardTemplate = (external: boolean, collectorIds: CollectorIds) => `
22
24
  <div class="container-tonder">
23
25
  <div id="${collectorIds.cardsListContainer}" class="cards-list-container"></div>
24
- <div id="${collectorIds.holderName}" class="empty-div"></div>
25
- <div id="${collectorIds.cardNumber}" class="empty-div"></div>
26
- <div class="collect-row">
27
- <div id="${collectorIds.expirationMonth}" class="empty-div"></div>
28
- <div id="${collectorIds.expirationYear}" class="expiration-year"></div>
29
- <div id="${collectorIds.cvv}" class="empty-div"></div>
26
+ <div class="pay-new-card">
27
+ <input checked id="new" name="card_selected" type="radio"/>
28
+ <label class="card-item-label" for="new">
29
+ <img class="card-image" src="${getCardType("XXXX")}" />
30
+ <div class="card-number">Pagar con tarjeta</div>
31
+ </label>
32
+ </div>
33
+ <div class="container-form">
34
+ <div id="${collectorIds.holderName}" class="empty-div"></div>
35
+ <div id="${collectorIds.cardNumber}" class="empty-div"></div>
36
+ <div class="collect-row">
37
+ <div id="${collectorIds.expirationMonth}" class="empty-div"></div>
38
+ <div id="${collectorIds.expirationYear}" class="expiration-year"></div>
39
+ <div id="${collectorIds.cvv}" class="empty-div"></div>
40
+ </div>
41
+ <div class="checkbox"><input id="save-checkout-card" type="checkbox"><label for="save-checkout-card">Guardar tarjeta para futuros pagos</label></div>
42
+ <div id="${collectorIds.msgError}"></div>
43
+ <div id="${collectorIds.msgNotification}"></div>
30
44
  </div>
31
- <div class="checkbox"><input id="save-checkout-card" type="checkbox"><label for="save-checkout-card">Guardar tarjeta para futuros pagos</label></div>
32
- <div id="${collectorIds.msgError}"></div>
33
45
  <button id="${collectorIds.tonderPayButton}" class="pay-button">Pagar</button>
34
46
  </div>
35
47
 
36
48
  ${external ? `` : `<style>
49
+
37
50
  .container-tonder {
38
51
  background-color: #F9F9F9;
39
52
  margin: 0 auto !important;
@@ -42,7 +55,6 @@ ${external ? `` : `<style>
42
55
  transition: max-height 0.5s ease-out;
43
56
  max-width: 600px;
44
57
  border: solid 1px #e3e3e3;
45
- max-height: 100vh;
46
58
  }
47
59
 
48
60
  .collect-row {
@@ -77,6 +89,16 @@ ${external ? `` : `<style>
77
89
  text-align: left !important;
78
90
  }
79
91
 
92
+ .message-container{
93
+ color: green !important;
94
+ background-color: #90EE90 !important;
95
+ margin-bottom: 13px !important;
96
+ font-size: 80% !important;
97
+ padding: 8px 10px !important;
98
+ border-radius: 10px !important;
99
+ text-align: left !important;
100
+ }
101
+
80
102
  .pay-button {
81
103
  font-size: 16px;
82
104
  font-weight: bold;
@@ -131,7 +153,9 @@ ${external ? `` : `<style>
131
153
 
132
154
  .cards-list-container {
133
155
  display: flex;
134
- flex-direction: column
156
+ flex-direction: column;
157
+ padding: 0px 10px 0px 10px;
158
+ gap: 33% 20px;
135
159
  }
136
160
 
137
161
  .checkbox label {
@@ -154,6 +178,29 @@ ${external ? `` : `<style>
154
178
  text-align: left;
155
179
  }
156
180
 
181
+ .pay-new-card {
182
+ display: flex;
183
+ justify-content: start;
184
+ align-items: center;
185
+ color: #1D1D1D;
186
+ gap: 33% 20px;
187
+ margin-top: 10px;
188
+ margin-bottom: 10px;
189
+ padding-left: 10px;
190
+ padding-right: 10px;
191
+ width: 90%;
192
+ }
193
+
194
+ .pay-new-card .card-number {
195
+ font-size: 14px;
196
+ }
197
+
198
+ .card-image {
199
+ width: 27px;
200
+ height: 20px;
201
+ text-align: left;
202
+ }
203
+
157
204
  </style>
158
205
  `}`
159
206
 
@@ -162,26 +209,54 @@ export const cardItemsTemplate = (external: boolean, cards: Card[]) => {
162
209
  const cardItemsHTML = cards.reduce((total: string, card: Card) => {
163
210
  return `${total}
164
211
  <div class="card-item">
165
- <img class="card-image" src="${getCardType(card.card_number)}" />
166
- <div class="card-number">${card.card_number}</div>
167
- <div class="card-expiration">${card.expiration_month}/${card.expiration_year}</div>
212
+ <input id="${card.skyflow_id}" name="card_selected" type="radio"/>
213
+ <label class="card-item-label" for="${card.skyflow_id}">
214
+ <img class="card-image" src="${getCardType(card.card_number)}" />
215
+ <div class="card-number">${card.card_number}</div>
216
+ <div class="card-expiration">${card.expiration_month}/${card.expiration_year}</div>
217
+ </label>
168
218
  </div>`
169
219
  }, ``);
170
220
 
171
221
  const cardItemStyle = external ? '' : `
172
222
  <style>
173
223
 
174
- .card-item {
224
+ .card-item-label {
175
225
  display: flex;
176
- justify-content: space-between;
226
+ justify-content: start;
177
227
  align-items: center;
178
228
  color: #1D1D1D;
179
- gap: 30px 20px;
229
+ gap: 33% 20px;
230
+ margin-top: 10px;
231
+ margin-bottom: 10px;
232
+ padding-left: 10px;
233
+ padding-right: 10px;
234
+ width: 90%;
235
+ }
236
+
237
+ .card_selected {
238
+ width: 10%;
239
+ }
240
+
241
+ .card-item {
242
+ display: flex;
243
+ justify-content: start;
244
+ align-items: center;
245
+ gap: 33% 20px;
246
+ }
247
+
248
+ .card-item .card-number {
249
+ font-size: 14px;
250
+ }
251
+
252
+ .card-item .card-expiration {
253
+ font-size: 14px;
180
254
  }
181
255
 
182
256
  .card-image {
183
- width: 20px;
257
+ width: 27px;
184
258
  height: 20px;
259
+ text-align: left;
185
260
  }
186
261
 
187
262
  </style>
@@ -42,19 +42,34 @@ export function toCurrency(value: string | number) {
42
42
  }
43
43
 
44
44
  export function showError(message: string, containerId: string, payButtonId: string) {
45
- var msgErrorDiv: any = document.getElementById(`#${containerId}`);
46
- msgErrorDiv.classList.add("error-container");
47
- msgErrorDiv.innerHTML = message;
48
- setTimeout(function () {
49
- try {
50
- const selector: any = document.querySelector(`#${payButtonId}`)
51
- selector.disabled = false;
52
- } catch (error) {}
53
- msgErrorDiv.classList.remove("error-container");
54
- msgErrorDiv.innerHTML = "";
55
- }, 3000);
45
+ const msgErrorDiv: any = document.getElementById(`${containerId}`);
46
+ if(msgErrorDiv) {
47
+ msgErrorDiv.classList.add("error-container");
48
+ msgErrorDiv.innerHTML = message;
49
+ setTimeout(function () {
50
+ try {
51
+ const selector: any = document.querySelector(`#${payButtonId}`)
52
+ selector.disabled = false;
53
+ } catch (error) {}
54
+ msgErrorDiv.classList.remove("error-container");
55
+ msgErrorDiv.innerHTML = "";
56
+ }, 3000);
57
+ }
56
58
  }
57
59
 
60
+ export function showMessage(message: string, containerId: string) {
61
+ const msgDiv: any = document.getElementById(`${containerId}`);
62
+ if(msgDiv) {
63
+ msgDiv.classList.add("message-container");
64
+ msgDiv.innerHTML = message;
65
+ setTimeout(function () {
66
+ msgDiv.classList.remove("message-container");
67
+ msgDiv.innerHTML = "";
68
+ }, 3000);
69
+ }
70
+ }
71
+
72
+
58
73
  export const createObserver = ({ target }: { target: string }): Promise<any> => {
59
74
 
60
75
  return new Promise((resolve, reject) => {