From 75e830c659ef4c47eefc61aaef810d58687d8787 Mon Sep 17 00:00:00 2001 From: David Hernandez Date: Tue, 22 Oct 2024 17:23:56 -0500 Subject: [PATCH] improve: [DEV-1350] Replicate secure token logic improve: [DEV-1350] Replicate secure token logic --- package-lock.json | 4 ++-- package.json | 2 +- src/classes/BaseInlineCheckout.ts | 36 ++++++++++++++++++++++++++----- src/classes/liteCheckout.ts | 22 +------------------ src/data/cardApi.ts | 28 ++++++++++++++---------- src/data/paymentMethodApi.ts | 3 +-- src/data/tokenApi.ts | 27 +++++++++++++++++++++++ src/shared/constants/messages.ts | 3 ++- src/types/liteInlineCheckout.ts | 15 +++++++++++-- 9 files changed, 95 insertions(+), 45 deletions(-) create mode 100644 src/data/tokenApi.ts diff --git a/package-lock.json b/package-lock.json index 90b7005..3915995 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tonder.io/ionic-lite-sdk", - "version": "0.0.42-beta.1", + "version": "0.0.42-beta.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tonder.io/ionic-lite-sdk", - "version": "0.0.42-beta.1", + "version": "0.0.42-beta.9", "license": "ISC", "dependencies": { "lodash.get": "^4.4.2", diff --git a/package.json b/package.json index ed37e5f..fabd01a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tonder.io/ionic-lite-sdk", - "version": "0.0.42-beta.1", + "version": "0.0.42-beta.9", "description": "Tonder ionic lite SDK", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/classes/BaseInlineCheckout.ts b/src/classes/BaseInlineCheckout.ts index 5b21c2a..407c3e6 100644 --- a/src/classes/BaseInlineCheckout.ts +++ b/src/classes/BaseInlineCheckout.ts @@ -9,7 +9,12 @@ import { startCheckoutRouter, } from "../data/checkoutApi"; import { getOpenpayDeviceSessionID } from "../data/openPayApi"; -import { getBrowserInfo } from "../helpers/utils"; +import { + buildErrorResponse, + buildErrorResponseFromCatch, + formatPublicErrorResponse, + getBrowserInfo +} from "../helpers/utils"; import { registerOrFetchCustomer } from "../data/customerApi"; import { get } from "lodash"; import { @@ -18,12 +23,20 @@ import { saveCustomerCard, } from "../data/cardApi"; import { fetchCustomerPaymentMethods } from "../data/paymentMethodApi"; -import {Business, IConfigureCheckout, IInlineCheckoutBaseOptions, CustomizationOptions} from "../types/commons"; +import { + Business, + IConfigureCheckout, + IInlineCheckoutBaseOptions, + CustomizationOptions, +} from "../types/commons"; import {ICustomer} from "../types/customer"; import {ICardFields, IItem, IProcessPaymentRequest, IStartCheckoutResponse} from "../types/checkout"; import {ICustomerCardsResponse, ISaveCardResponse, ISaveCardSkyflowRequest} from "../types/card"; import {IPaymentMethodResponse} from "../types/paymentMethod"; import {ITransaction} from "../types/transaction"; +import {GetSecureTokenResponse} from "../types/responses"; +import {getSecureToken} from "../data/tokenApi"; +import {MESSAGES} from "../shared/constants/messages"; export class BaseInlineCheckout { baseUrl = ""; cartTotal: string | number = "0"; @@ -131,6 +144,19 @@ export class BaseInlineCheckout { }); } + async getSecureToken(secretApikey: string): Promise { + try { + return await getSecureToken(this.baseUrl, secretApikey) + } catch (error) { + throw formatPublicErrorResponse( + { + message: MESSAGES.secureTokenError, + }, + error, + ); + } + } + async _initializeCheckout() { const business_response = await this._fetchMerchantData(); @@ -300,19 +326,18 @@ export class BaseInlineCheckout { authToken: string, businessId: string | number, ): Promise { - return await fetchCustomerCards(this.baseUrl, authToken, businessId); + return await fetchCustomerCards(this.baseUrl, authToken, this.secureToken, businessId); } async _saveCustomerCard( authToken: string, - secureToken: string, businessId: string | number, skyflowTokens: ISaveCardSkyflowRequest, ): Promise { return await saveCustomerCard( this.baseUrl, - this.secureToken, authToken, + this.secureToken, businessId, skyflowTokens, ); @@ -326,6 +351,7 @@ export class BaseInlineCheckout { return await removeCustomerCard( this.baseUrl, authToken, + this.secureToken, skyflowId, businessId, ); diff --git a/src/classes/liteCheckout.ts b/src/classes/liteCheckout.ts index e99636b..c47006d 100644 --- a/src/classes/liteCheckout.ts +++ b/src/classes/liteCheckout.ts @@ -24,7 +24,7 @@ import { CreateOrderResponse, CreatePaymentResponse, CustomerRegisterResponse, - GetBusinessResponse, IErrorResponse, RegisterCustomerCardResponse, StartCheckoutResponse, GetSecureTokenResponse + GetBusinessResponse, IErrorResponse, RegisterCustomerCardResponse, StartCheckoutResponse } from "../types/responses"; import { CreateOrderRequest, @@ -80,7 +80,6 @@ export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{ } public async saveCustomerCard( - secureToken: string, card: ISaveCardRequest, ): Promise { try { @@ -97,7 +96,6 @@ export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{ }); return await this._saveCustomerCard( - secureToken, auth_token, business?.pk, skyflowTokens, @@ -570,22 +568,4 @@ export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{ return []; } } - - async getSecureToken(token: string): Promise { - try { - const response = await fetch(`${this.baseUrl}/api/secure-token/`, { - method: 'POST', - headers: { - 'Authorization': `Token ${token}`, - 'Content-Type': 'application/json' - }, - signal: this.abortController.signal - }); - - if (response.ok) return await response.json() as GetSecureTokenResponse; - throw await buildErrorResponse(response); - } catch (error) { - throw buildErrorResponseFromCatch(error); - } - } } diff --git a/src/data/cardApi.ts b/src/data/cardApi.ts index 813943e..f99093c 100644 --- a/src/data/cardApi.ts +++ b/src/data/cardApi.ts @@ -8,6 +8,7 @@ import {ICustomerCardsResponse, ISaveCardResponse, ISaveCardSkyflowRequest} from export async function fetchCustomerCards( baseUrl: string, customerToken: string, + secureToken: string, businessId: string | number, signal = null, ): Promise { @@ -16,15 +17,21 @@ export async function fetchCustomerCards( const response = await fetch(url, { method: "GET", headers: { - Authorization: `Token ${customerToken}`, + Authorization: `Bearer ${secureToken}`, "Content-Type": "application/json", + 'User-token': customerToken, }, signal, }); if (response.ok) return await response.json(); - const res_json = await response.json(); + if (response.status === 401) { + return { + user_id: 0, + cards: [], + }; + } - throw await buildErrorResponse(response, res_json); + throw await buildErrorResponse(response); } catch (error) { throw buildErrorResponseFromCatch(error); } @@ -32,8 +39,8 @@ export async function fetchCustomerCards( export async function saveCustomerCard( baseUrl: string, - secureToken: string, customerToken: string, + secureToken: string, businessId: string | number, data: ISaveCardSkyflowRequest, ): Promise { @@ -51,9 +58,7 @@ export async function saveCustomerCard( if (response.ok) return await response.json(); - const res_json = await response.json(); - - throw await buildErrorResponse(response, res_json); + throw await buildErrorResponse(response); } catch (error) { throw buildErrorResponseFromCatch(error); } @@ -62,6 +67,7 @@ export async function saveCustomerCard( export async function removeCustomerCard( baseUrl: string, customerToken: string, + secureToken: string, skyflowId = "", businessId: string | number, ): Promise { @@ -71,16 +77,16 @@ export async function removeCustomerCard( const response = await fetch(url, { method: "DELETE", headers: { - Authorization: `Token ${customerToken}`, + Authorization: `Bearer ${secureToken}`, "Content-Type": "application/json", + 'User-token': customerToken, }, }); - if (response.status === 204) return MESSAGES.cardSaved; + if (response.status === 204) return MESSAGES.removedCard; if (response.ok && "json" in response) return await response.json(); - const res_json = await response.json(); - throw await buildErrorResponse(response, res_json); + throw await buildErrorResponse(response); } catch (error) { throw buildErrorResponseFromCatch(error); } diff --git a/src/data/paymentMethodApi.ts b/src/data/paymentMethodApi.ts index 52d5b36..ac03251 100644 --- a/src/data/paymentMethodApi.ts +++ b/src/data/paymentMethodApi.ts @@ -29,8 +29,7 @@ export async function fetchCustomerPaymentMethods( ); if (response.ok) return await response.json(); - const res_json = await response.json(); - throw await buildErrorResponse(response, res_json); + throw await buildErrorResponse(response); } catch (error) { throw buildErrorResponseFromCatch(error); } diff --git a/src/data/tokenApi.ts b/src/data/tokenApi.ts new file mode 100644 index 0000000..3c0a5e1 --- /dev/null +++ b/src/data/tokenApi.ts @@ -0,0 +1,27 @@ +import { GetSecureTokenResponse } from "../types/responses"; +import { + buildErrorResponse, + buildErrorResponseFromCatch, +} from "../helpers/utils"; + +export async function getSecureToken( + baseUrl: string, + token: string, + signal = null, +): Promise { + try { + const response = await fetch(`${baseUrl}/api/secure-token/`, { + method: "POST", + headers: { + Authorization: `Token ${token}`, + "Content-Type": "application/json", + }, + signal, + }); + + if (response.ok) return (await response.json()) as GetSecureTokenResponse; + throw await buildErrorResponse(response); + } catch (error) { + throw buildErrorResponseFromCatch(error); + } +} diff --git a/src/shared/constants/messages.ts b/src/shared/constants/messages.ts index 013ca32..843da3e 100644 --- a/src/shared/constants/messages.ts +++ b/src/shared/constants/messages.ts @@ -7,5 +7,6 @@ export const MESSAGES = Object.freeze({ errorCheckout: "No se ha podido procesar el pago", cardSaved: "Tarjeta registrada con éxito.", getPaymentMethodsError: "Ha ocurrido un error obteniendo las métodos de pago del customer. Inténtalo nuevamente.", - getBusinessError: "Ha ocurrido un error obteniendo los datos del comercio. Inténtalo nuevamente." + getBusinessError: "Ha ocurrido un error obteniendo los datos del comercio. Inténtalo nuevamente.", + secureTokenError: "Ha ocurrido un error obteniendo el token de seguridad.", }) \ No newline at end of file diff --git a/src/types/liteInlineCheckout.ts b/src/types/liteInlineCheckout.ts index 058280f..558d02b 100644 --- a/src/types/liteInlineCheckout.ts +++ b/src/types/liteInlineCheckout.ts @@ -22,7 +22,7 @@ import { CreateOrderResponse, CreatePaymentResponse, CustomerRegisterResponse, - GetBusinessResponse, + GetBusinessResponse, GetSecureTokenResponse, RegisterCustomerCardResponse, StartCheckoutResponse, } from "./responses"; @@ -86,7 +86,7 @@ export interface ILiteCheckout { * * @public */ - saveCustomerCard(secureToken: string, card: ISaveCardRequest): Promise; + saveCustomerCard(card: ISaveCardRequest): Promise; /** * Removes a card from a customer's account. @@ -109,6 +109,17 @@ export interface ILiteCheckout { */ getCustomerPaymentMethods(): Promise; + /** + * Retrieves security token to access the saved cards functionality. + * @param {string} secretApikey + * @returns {Promise} A promise that resolves with the token. + * + * @throws {import("./index").IPublicError} Throws an error object if the operation fails. + * + * @public + */ + getSecureToken(secretApikey: string): Promise + /** * @deprecated This method is deprecated and will be removed in a future release. * It is no longer necessary to use this method, now automatically handled