tonder-web-sdk 1.12.0-beta.9 → 1.14.0

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-web-sdk",
3
- "version": "1.12.0-beta.9",
3
+ "version": "1.14.0",
4
4
  "description": "tonder sdk for integrations",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -17,6 +17,7 @@
17
17
  "devDependencies": {
18
18
  "@babel/core": "^7.20.12",
19
19
  "@babel/preset-env": "^7.20.2",
20
+ "@maskito/core": "^3.0.1",
20
21
  "babel-loader": "^9.1.2",
21
22
  "css-loader": "^6.7.3",
22
23
  "cypress": "^13.6.2",
@@ -6,7 +6,8 @@ export class ThreeDSHandler {
6
6
  }) {
7
7
  this.baseUrl = baseUrl,
8
8
  this.apiKey = apiKey,
9
- this.payload = payload
9
+ this.payload = payload,
10
+ this.isTransactionPending = false
10
11
  }
11
12
 
12
13
  saveVerifyTransactionUrl() {
@@ -127,8 +128,6 @@ export class ThreeDSHandler {
127
128
  return response;
128
129
  }
129
130
 
130
- // TODO: the method below needs to be tested with a real 3DS challenge
131
- // since we couldn't get a test card that works with this feature
132
131
  async handle3dsChallenge(response_json) {
133
132
  // Create the form element:
134
133
  const form = document.createElement('form');
@@ -139,15 +138,17 @@ export class ThreeDSHandler {
139
138
  // Add hidden fields:
140
139
  const creqInput = document.createElement('input');
141
140
  creqInput.type = 'hidden';
142
- creqInput.name = response_json.creq;
141
+ creqInput.name = 'creq';
143
142
  creqInput.value = response_json.creq;
144
143
  form.appendChild(creqInput);
145
144
 
146
- const termUrlInput = document.createElement('input');
147
- termUrlInput.type = 'hidden';
148
- termUrlInput.name = response_json.term_url;
149
- termUrlInput.value = response_json.TermUrl;
150
- form.appendChild(termUrlInput);
145
+ if (response_json.term_url) {
146
+ const termUrlInput = document.createElement('input');
147
+ termUrlInput.type = 'hidden';
148
+ termUrlInput.name = 'TermUrl';
149
+ termUrlInput.value = response_json.term_url;
150
+ form.appendChild(termUrlInput);
151
+ }
151
152
 
152
153
  // Append the form to the body:
153
154
  document.body.appendChild(form);
@@ -172,6 +173,14 @@ export class ThreeDSHandler {
172
173
  }
173
174
 
174
175
  async verifyTransactionStatus() {
176
+ console.log('Verificando la transacción...');
177
+
178
+ if (this.isTransactionPending) {
179
+ console.log('La transacción ya está en proceso');
180
+ return
181
+ }
182
+
183
+ this.isTransactionPending = true
175
184
  const verifyUrl = this.getUrlWithExpiration();
176
185
 
177
186
  if (verifyUrl) {
@@ -199,6 +208,8 @@ export class ThreeDSHandler {
199
208
  } else {
200
209
  console.log('No verify_transaction_status_url found');
201
210
  }
211
+
212
+ this.isTransactionPending = false
202
213
  }
203
214
 
204
215
  setPayload = (payload) => {
@@ -13,12 +13,7 @@ import { getBrowserInfo, injectMercadoPagoSecurity } from "../helpers/utils";
13
13
  export class BaseInlineCheckout {
14
14
  baseUrl = "";
15
15
  cartTotal = "0";
16
- constructor({
17
- mode = "stage",
18
- apiKey,
19
- returnUrl,
20
- callBack = () => {},
21
- }) {
16
+ constructor({ mode = "stage", apiKey, returnUrl, callBack = () => {} }) {
22
17
  this.apiKeyTonder = apiKey;
23
18
  this.returnUrl = returnUrl;
24
19
  this.callBack = callBack;
@@ -34,11 +29,12 @@ export class BaseInlineCheckout {
34
29
  /**
35
30
  * The configureCheckout function allows you to set initial information, such as the customer's email, which is used to retrieve a list of saved cards.
36
31
  * @param {import("../../types").IConfigureCheckout} data - Configuration data including customer information and potentially other settings.
37
- * @returns {Promise<void>}.
32
+ * @returns {void}.
38
33
  * @public
39
34
  */
40
35
  configureCheckout(data) {
41
36
  if ("customer" in data) this.#handleCustomer(data["customer"]);
37
+ if ("secureToken" in data) this.#handleSecureToken(data["secureToken"]);
42
38
  }
43
39
 
44
40
  /**
@@ -75,7 +71,6 @@ export class BaseInlineCheckout {
75
71
  this.#handleMetadata(data);
76
72
  this.#handleCurrency(data);
77
73
  this.#handleCard(data);
78
- console.log("data", data)
79
74
  const response = await this._checkout(data);
80
75
  this.process3ds.setPayload(response);
81
76
  this.callBack(response);
@@ -121,7 +116,6 @@ export class BaseInlineCheckout {
121
116
  async _handleCheckout({ card, payment_method, customer }) {
122
117
  const { openpay_keys, reference, business } = this.merchantData;
123
118
  const total = Number(this.cartTotal);
124
-
125
119
  try {
126
120
  let deviceSessionIdTonder;
127
121
  if (
@@ -272,6 +266,10 @@ export class BaseInlineCheckout {
272
266
  this.customer = customer;
273
267
  }
274
268
 
269
+ #handleSecureToken(secureToken) {
270
+ this.secureToken = secureToken;
271
+ }
272
+
275
273
  #handleMetadata(data) {
276
274
  this.metadata = data?.metadata;
277
275
  }
@@ -289,23 +287,19 @@ export class BaseInlineCheckout {
289
287
  }
290
288
 
291
289
  async #handle3dsRedirect(response) {
290
+ console.log('Handling 3DS redirect...');
292
291
  const iframe = response?.next_action?.iframe_resources?.iframe;
292
+ const threeDsChallenge = response?.next_action?.three_ds_challenge;
293
293
 
294
294
  if (iframe) {
295
- this.process3ds
296
- .loadIframe()
297
- .then(() => {
298
- //TODO: Check if this will be necessary on the frontend side
299
- // after some the tests in production, since the 3DS process
300
- // doesn't works properly on the sandbox environment
301
- // setTimeout(() => {
302
- // process3ds.verifyTransactionStatus();
303
- // }, 10000);
304
- this.process3ds.verifyTransactionStatus();
305
- })
306
- .catch((error) => {
307
- console.log("Error loading iframe:", error);
308
- });
295
+ try {
296
+ await this.process3ds.loadIframe();
297
+ await this.process3ds.verifyTransactionStatus();
298
+ } catch (error) {
299
+ console.log("Error loading iframe:", error);
300
+ }
301
+ } else if (threeDsChallenge) {
302
+ await this.process3ds.handle3dsChallenge(threeDsChallenge);
309
303
  } else {
310
304
  const redirectUrl = this.process3ds.getRedirectUrl();
311
305
  if (redirectUrl) {
@@ -8,13 +8,12 @@ import {
8
8
  } from "../data";
9
9
  import { getSkyflowTokens } from "../helpers/skyflow";
10
10
  import { getPaymentMethodDetails } from "../shared/catalog/paymentMethodsCatalog";
11
- import { formatPublicErrorResponse } from "../helpers/utils";
11
+ import { formatPublicErrorResponse, getCardType } from "../helpers/utils";
12
12
  import { MESSAGES } from "../shared/constants/messages";
13
13
 
14
14
  export class LiteInlineCheckout extends BaseInlineCheckout {
15
15
  #customerData;
16
16
  constructor({ mode = "stage", apiKey, returnUrl, callBack = () => {} }) {
17
-
18
17
  super({ mode, apiKey, returnUrl, callBack });
19
18
  }
20
19
 
@@ -40,11 +39,18 @@ export class LiteInlineCheckout extends BaseInlineCheckout {
40
39
  async getCustomerCards() {
41
40
  try {
42
41
  const { auth_token } = await this.#getCustomer();
43
- return await fetchCustomerCards(
42
+ const response = await fetchCustomerCards(
44
43
  this.baseUrl,
45
44
  auth_token,
46
45
  this.merchantData.business.pk,
47
46
  );
47
+ return {
48
+ ...response,
49
+ cards: response.cards.map((ic) => ({
50
+ ...ic,
51
+ icon: getCardType(ic.fields.card_scheme),
52
+ })),
53
+ };
48
54
  } catch (error) {
49
55
  throw formatPublicErrorResponse(
50
56
  {
@@ -104,22 +110,22 @@ export class LiteInlineCheckout extends BaseInlineCheckout {
104
110
  * @public
105
111
  */
106
112
  async removeCustomerCard(skyflowId) {
107
- try{
113
+ try {
108
114
  const { auth_token } = await this.#getCustomer();
109
115
  const { business } = this.merchantData;
110
116
 
111
117
  return await removeCustomerCard(
112
- this.baseUrl,
113
- auth_token,
114
- skyflowId,
115
- business?.pk,
118
+ this.baseUrl,
119
+ auth_token,
120
+ skyflowId,
121
+ business?.pk,
116
122
  );
117
- }catch (error){
123
+ } catch (error) {
118
124
  throw formatPublicErrorResponse(
119
- {
120
- message: MESSAGES.removeCardError,
121
- },
122
- error,
125
+ {
126
+ message: MESSAGES.removeCardError,
127
+ },
128
+ error,
123
129
  );
124
130
  }
125
131
  }
@@ -137,29 +143,29 @@ export class LiteInlineCheckout extends BaseInlineCheckout {
137
143
  const response = await fetchCustomerAPMs(this.baseUrl, this.apiKeyTonder);
138
144
 
139
145
  const apms_results =
140
- response && "results" in response && response["results"].length > 0
141
- ? response["results"]
142
- : [];
146
+ response && "results" in response && response["results"].length > 0
147
+ ? response["results"]
148
+ : [];
143
149
 
144
150
  return apms_results
145
- .filter((apmItem) => apmItem.category.toLowerCase() !== "cards")
146
- .map((apmItem) => {
147
- const apm = {
148
- id: apmItem.pk,
149
- payment_method: apmItem.payment_method,
150
- priority: apmItem.priority,
151
- category: apmItem.category,
152
- ...getPaymentMethodDetails(apmItem.payment_method),
153
- };
154
- return apm;
155
- })
156
- .sort((a, b) => a.priority - b.priority);
157
- }catch (error){
151
+ .filter((apmItem) => apmItem.category.toLowerCase() !== "cards")
152
+ .map((apmItem) => {
153
+ const apm = {
154
+ id: apmItem.pk,
155
+ payment_method: apmItem.payment_method,
156
+ priority: apmItem.priority,
157
+ category: apmItem.category,
158
+ ...getPaymentMethodDetails(apmItem.payment_method),
159
+ };
160
+ return apm;
161
+ })
162
+ .sort((a, b) => a.priority - b.priority);
163
+ } catch (error) {
158
164
  throw formatPublicErrorResponse(
159
- {
160
- message: MESSAGES.getPaymentMethodsError,
161
- },
162
- error,
165
+ {
166
+ message: MESSAGES.getPaymentMethodsError,
167
+ },
168
+ error,
163
169
  );
164
170
  }
165
171
  }
@@ -169,7 +175,6 @@ export class LiteInlineCheckout extends BaseInlineCheckout {
169
175
  }
170
176
 
171
177
  async _checkout({ card, payment_method }) {
172
- console.log("_checkout", card, payment_method)
173
178
  const customer = await this._getCustomer(
174
179
  this.customer,
175
180
  this.abortController.signal,
@@ -177,7 +182,7 @@ export class LiteInlineCheckout extends BaseInlineCheckout {
177
182
  const { vault_id, vault_url } = this.merchantData;
178
183
  let skyflowTokens;
179
184
  if (!payment_method || payment_method !== "" || payment_method === null) {
180
- if (typeof payment_method === "string") {
185
+ if (typeof card === "string") {
181
186
  skyflowTokens = {
182
187
  skyflow_id: card,
183
188
  };
@@ -185,7 +190,7 @@ export class LiteInlineCheckout extends BaseInlineCheckout {
185
190
  skyflowTokens = await getSkyflowTokens({
186
191
  vault_id: vault_id,
187
192
  vault_url: vault_url,
188
- data: card,
193
+ data: {...card, card_number: card.card_number.replace(/\s+/g, '')},
189
194
  baseUrl: this.baseUrl,
190
195
  apiKey: this.apiKeyTonder,
191
196
  });
@@ -200,13 +205,13 @@ export class LiteInlineCheckout extends BaseInlineCheckout {
200
205
  }
201
206
 
202
207
  async #getCustomer() {
203
- if(!!this.#customerData) return this.#customerData;
208
+ if (!!this.#customerData) return this.#customerData;
204
209
 
205
210
  this.#customerData = await registerOrFetchCustomer(
206
- this.baseUrl,
207
- this.apiKeyTonder,
208
- this.customer,
211
+ this.baseUrl,
212
+ this.apiKeyTonder,
213
+ this.customer,
209
214
  );
210
- return this.#customerData
215
+ return this.#customerData;
211
216
  }
212
217
  }
@@ -1,4 +1,4 @@
1
- import {apmItemsTemplate, cardItemsTemplate, cardTemplate} from '../helpers/template.js'
1
+ import { apmItemsTemplate, cardItemsTemplate, cardTemplate } from '../helpers/template.js'
2
2
  import {
3
3
  clearSpace,
4
4
  injectMercadoPagoSecurity,
@@ -6,18 +6,18 @@ import {
6
6
  showError,
7
7
  showMessage
8
8
  } from '../helpers/utils';
9
- import {initSkyflow} from '../helpers/skyflow'
10
- import {globalLoader} from './globalLoader.js';
11
- import {BaseInlineCheckout} from "./BaseInlineCheckout";
9
+ import { initSkyflow } from '../helpers/skyflow'
10
+ import { globalLoader } from './globalLoader.js';
11
+ import { BaseInlineCheckout } from "./BaseInlineCheckout";
12
12
  import {
13
13
  fetchCustomerCards,
14
14
  removeCustomerCard,
15
15
  saveCustomerCard,
16
16
  fetchCustomerAPMs
17
17
  } from "../data";
18
- import {MESSAGES} from "../shared/constants/messages";
18
+ import { MESSAGES } from "../shared/constants/messages";
19
19
 
20
- export class InlineCheckout extends BaseInlineCheckout{
20
+ export class InlineCheckout extends BaseInlineCheckout {
21
21
  static injected = false;
22
22
  static cardsInjected = false
23
23
  static apmsInjected = false
@@ -42,19 +42,35 @@ export class InlineCheckout extends BaseInlineCheckout{
42
42
  msgNotification: "msgNotification",
43
43
  apmsListContainer: "apmsListContainer"
44
44
  }
45
-
45
+ customization = {
46
+ saveCards: {
47
+ showSaveCardOption: false,
48
+ showSaved: false,
49
+ autoSave: false
50
+ }
51
+ }
46
52
  constructor({
47
53
  mode = "stage",
48
54
  apiKey,
49
55
  returnUrl,
50
56
  renderPaymentButton = false,
51
57
  callBack = () => { },
52
- styles
58
+ styles,
59
+ customization,
53
60
  }) {
54
61
  super({ mode, apiKey, returnUrl, callBack });
55
62
  this.renderPaymentButton = renderPaymentButton;
56
63
  this.customStyles = styles
57
- this.abortRefreshCardsController = new AbortController()
64
+ this.abortRefreshCardsController = new AbortController();
65
+ // TODO: Wait until SaveCards is ready (server token).
66
+ this.customization = {
67
+ ...this.customization,
68
+ ...(customization || {}),
69
+ saveCards: {
70
+ ...this.customization.saveCards,
71
+ ...(customization?.saveCards || {}),
72
+ },
73
+ }
58
74
  }
59
75
 
60
76
  #mountPayButton() {
@@ -130,20 +146,20 @@ export class InlineCheckout extends BaseInlineCheckout{
130
146
  }
131
147
 
132
148
  async #mount(containerTonderCheckout) {
133
- containerTonderCheckout.innerHTML = cardTemplate({renderPaymentButton: this.renderPaymentButton, customStyles: this.customStyles});
149
+ containerTonderCheckout.innerHTML = cardTemplate({ renderPaymentButton: this.renderPaymentButton, customStyles: this.customStyles, customization: this.customization });
134
150
  globalLoader.show()
135
151
  await this.#mountTonder();
136
152
  InlineCheckout.injected = true;
137
153
  }
138
154
 
139
155
  async #mountAPMs() {
140
- try{
156
+ try {
141
157
  const apms = await fetchCustomerAPMs(this.baseUrl, this.apiKeyTonder);
142
- if(apms && apms['results'] && apms['results'].length > 0){
158
+ if (apms && apms['results'] && apms['results'].length > 0) {
143
159
  this.apmsData = apms['results']
144
160
  this.#loadAPMList(apms['results'])
145
161
  }
146
- }catch(e){
162
+ } catch (e) {
147
163
  console.warn("Error getting APMS")
148
164
  }
149
165
  }
@@ -160,16 +176,7 @@ export class InlineCheckout extends BaseInlineCheckout{
160
176
  const customerResponse = await this._getCustomer({ email: this.email });
161
177
  if ("auth_token" in customerResponse) {
162
178
  const { auth_token } = customerResponse
163
- const cards = await fetchCustomerCards(
164
- this.baseUrl,
165
- auth_token,
166
- this.merchantData.business.pk
167
- );
168
-
169
- if ("cards" in cards) {
170
- const cardsMapped = cards.cards.map(mapCards)
171
- this.#loadCardsList(cardsMapped, auth_token)
172
- }
179
+ await this.#loadCardsList(auth_token)
173
180
  }
174
181
  }
175
182
 
@@ -256,39 +263,15 @@ export class InlineCheckout extends BaseInlineCheckout{
256
263
  )
257
264
  const { auth_token } = customerData;
258
265
  if (auth_token && this.email) {
259
- const saveCard = document.getElementById("save-checkout-card");
260
- if (saveCard && "checked" in saveCard && saveCard.checked) {
261
- try {
262
- await saveCustomerCard(this.baseUrl, auth_token, business.pk, {
263
- skyflow_id: cardTokens.skyflow_id,
264
- });
265
- showMessage(MESSAGES.cardSaved, this.collectorIds.msgNotification);
266
- } catch (error) {
267
- if (error?.message) {
268
- showError(error.message)
269
- }
270
- }
271
-
272
- this.cardsInjected = false;
273
-
274
- const cards = await fetchCustomerCards(
275
- this.baseUrl,
276
- auth_token,
277
- this.merchantData.business.pk,
278
- );
279
- if ("cards" in cards) {
280
- const cardsMapped = cards.cards.map((card) => mapCards(card))
281
- this.#loadCardsList(cardsMapped, auth_token)
282
- }
283
- }
266
+ await this.#handleSaveCard(auth_token, business.pk, cardTokens)
284
267
  }
285
268
 
286
- const selected_apm = this.apmsData ? this.apmsData.find((iapm) => iapm.pk === this.radioChecked):{};
269
+ const selected_apm = this.apmsData ? this.apmsData.find((iapm) => iapm.pk === this.radioChecked) : {};
287
270
 
288
271
  const jsonResponseRouter = await this._handleCheckout({
289
- ...( selected_apm && Object.keys(selected_apm).length > 0
290
- ? {payment_method: selected_apm.payment_method}
291
- : {card: cardTokens}),
272
+ ...(selected_apm && Object.keys(selected_apm).length > 0
273
+ ? { payment_method: selected_apm.payment_method }
274
+ : { card: cardTokens }),
292
275
  customer: customerData
293
276
  });
294
277
 
@@ -308,17 +291,49 @@ export class InlineCheckout extends BaseInlineCheckout{
308
291
  }
309
292
  };
310
293
 
311
- #loadCardsList(cards, token) {
312
- if (this.cardsInjected) return;
313
- const injectInterval = setInterval(() => {
314
- const queryElement = document.querySelector(`#${this.collectorIds.cardsListContainer}`);
315
- if (queryElement && InlineCheckout.injected) {
316
- queryElement.innerHTML = cardItemsTemplate(cards)
317
- clearInterval(injectInterval)
318
- this.#mountRadioButtons(token)
319
- this.cardsInjected = true
294
+ async #handleSaveCard(auth_token, businessId, cardTokens) {
295
+ const saveCard = document.getElementById("save-checkout-card");
296
+ if ((saveCard && "checked" in saveCard && saveCard.checked) || !!this.customization.saveCards?.autoSave) {
297
+ try {
298
+ await saveCustomerCard(
299
+ this.baseUrl,
300
+ auth_token,
301
+ this.secureToken,
302
+ businessId,
303
+ { skyflow_id: cardTokens.skyflow_id, }
304
+ );
305
+ showMessage(MESSAGES.cardSaved, this.collectorIds.msgNotification);
306
+ } catch (error) {
307
+ if (error?.message) {
308
+ showError(error.message)
309
+ }
320
310
  }
321
- }, 500);
311
+
312
+ await this.#loadCardsList(auth_token)
313
+ }
314
+ }
315
+ async #loadCardsList(token) {
316
+ if(this.cardsInjected || !this.customization.saveCards?.showSaved) return;
317
+ this.cardsInjected = false
318
+ const cardsResponse = await fetchCustomerCards(
319
+ this.baseUrl,
320
+ token,
321
+ this.secureToken,
322
+ this.merchantData.business.pk,
323
+ );
324
+ let cards = []
325
+ if("cards" in cardsResponse) {
326
+ cards = cardsResponse.cards.map(mapCards)
327
+ const injectInterval = setInterval(() => {
328
+ const queryElement = document.querySelector(`#${this.collectorIds.cardsListContainer}`);
329
+ if (queryElement && InlineCheckout.injected) {
330
+ queryElement.innerHTML = cardItemsTemplate(cards)
331
+ clearInterval(injectInterval)
332
+ this.#mountRadioButtons(token)
333
+ this.cardsInjected = true
334
+ }
335
+ }, 500);
336
+ }
322
337
  }
323
338
 
324
339
  #loadAPMList(apms) {
@@ -390,8 +405,14 @@ export class InlineCheckout extends BaseInlineCheckout{
390
405
  this.abortRefreshCardsController = new AbortController();
391
406
  }
392
407
  const businessId = this.merchantData.business.pk
393
- await removeCustomerCard(this.baseUrl, customerToken, skyflow_id, businessId)
394
- } catch(error) {} finally {
408
+ await removeCustomerCard(
409
+ this.baseUrl,
410
+ customerToken,
411
+ this.secureToken,
412
+ skyflow_id,
413
+ businessId
414
+ )
415
+ } catch (error) { } finally {
395
416
  this.deletingCards = this.deletingCards.filter(id => id !== skyflow_id);
396
417
  this.#refreshCardOnDelete(customerToken)
397
418
  }
@@ -399,17 +420,7 @@ export class InlineCheckout extends BaseInlineCheckout{
399
420
  }
400
421
  async #refreshCardOnDelete(customerToken) {
401
422
  if (this.deletingCards.length > 0) return;
402
- this.cardsInjected = false
403
- const cards = await fetchCustomerCards(
404
- this.baseUrl,
405
- customerToken,
406
- this.merchantData.business.pk,
407
- this.abortRefreshCardsController.signal
408
- )
409
- if ("cards" in cards) {
410
- const cardsMapped = cards.cards.map(mapCards)
411
- this.#loadCardsList(cardsMapped, customerToken)
412
- }
423
+ await this.#loadCardsList(customerToken)
413
424
  }
414
425
  #unmountForm() {
415
426
  InlineCheckout.injected = false
@@ -11,6 +11,7 @@ import {MESSAGES} from "../shared/constants/messages";
11
11
  *
12
12
  * @param {string} baseUrl - The base URL of the API.
13
13
  * @param {string} customerToken - The customer's authentication token.
14
+ * @param {string} secureToken - Token generated by secure-token endpoint.
14
15
  * @param {string | number} businessId - The business ID.
15
16
  * @param {import("../../types").ISaveCardSkyflowRequest} data - The card information to be saved.
16
17
  * @returns {Promise<import("../../types").ISaveCardResponse>} The saved card data.
@@ -20,6 +21,7 @@ import {MESSAGES} from "../shared/constants/messages";
20
21
  export async function saveCustomerCard(
21
22
  baseUrl,
22
23
  customerToken,
24
+ secureToken,
23
25
  businessId,
24
26
  data,
25
27
  ) {
@@ -28,7 +30,8 @@ export async function saveCustomerCard(
28
30
  const response = await fetch(url, {
29
31
  method: "POST",
30
32
  headers: {
31
- Authorization: `Token ${customerToken}`,
33
+ Authorization: `Bearer ${secureToken}`,
34
+ "User-Token": customerToken,
32
35
  "Content-Type": "application/json",
33
36
  },
34
37
  body: JSON.stringify(data),
@@ -57,6 +60,7 @@ export async function saveCustomerCard(
57
60
  * Removes a customer's card.
58
61
  * @param {string} baseUrl - The base URL of the API.
59
62
  * @param {string} customerToken - The customer's authentication token.
63
+ * @param {string} secureToken - Token generated by secure-token endpoint.
60
64
  * @param {string} skyflowId - The Skyflow ID of the card to be removed.
61
65
  * @param {string} businessId - The business ID.
62
66
  * @returns {Promise<string>} The result of the card removal operation.
@@ -66,6 +70,7 @@ export async function saveCustomerCard(
66
70
  export async function removeCustomerCard(
67
71
  baseUrl,
68
72
  customerToken,
73
+ secureToken,
69
74
  skyflowId = "",
70
75
  businessId,
71
76
  ) {
@@ -75,8 +80,9 @@ export async function removeCustomerCard(
75
80
  const response = await fetch(url, {
76
81
  method: "DELETE",
77
82
  headers: {
78
- Authorization: `Token ${customerToken}`,
83
+ Authorization: `Bearer ${secureToken}`,
79
84
  "Content-Type": "application/json",
85
+ "User-Token": customerToken,
80
86
  },
81
87
  });
82
88
 
@@ -94,6 +100,7 @@ export async function removeCustomerCard(
94
100
  * Fetches a customer's saved cards.
95
101
  * @param {string} baseUrl - The base URL of the API.
96
102
  * @param {string} customerToken - The customer's authentication token.
103
+ * @param {string} secureToken - Token generated by secure-token endpoint.
97
104
  * @param {string} businessId - The business ID.
98
105
  * @param {AbortSignal} signal - The abort signal to cancel the request.
99
106
  * @returns {Promise<import("../../types").ICustomerCardsResponse>} The customer's saved cards.
@@ -103,6 +110,7 @@ export async function removeCustomerCard(
103
110
  export async function fetchCustomerCards(
104
111
  baseUrl,
105
112
  customerToken,
113
+ secureToken,
106
114
  businessId,
107
115
  signal= null,
108
116
  ) {
@@ -111,12 +119,21 @@ export async function fetchCustomerCards(
111
119
  const response = await fetch(url, {
112
120
  method: "GET",
113
121
  headers: {
114
- Authorization: `Token ${customerToken}`,
115
- "Content-Type": "application/json",
122
+ Authorization: `Bearer ${secureToken}`,
123
+ "User-Token": customerToken,
116
124
  },
117
125
  signal,
118
126
  });
119
127
  if (response.ok) return await response.json();
128
+ if (response.status === 401) {
129
+ return {
130
+ code: 401,
131
+ body: {},
132
+ name: "",
133
+ message: "Unauthorized",
134
+ };
135
+ }
136
+
120
137
  const res_json = await response.json();
121
138
 
122
139
  throw await buildErrorResponse(response, res_json, MESSAGES.getCardsError);