Skip to content

Commit

Permalink
Merge branch 'feature/agregar-logica-para-carga-de-iframe' into 'main'
Browse files Browse the repository at this point in the history
Feature/agregar logica para carga de iframe

See merge request grupoapok/tonder/sdk/ionic/lite!45
  • Loading branch information
rbapdev committed Oct 21, 2024
2 parents 47bb390 + e6ea6d7 commit a93baf8
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 10 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { LiteCheckout } from "@tonder.io/ionic-lite-sdk"
const liteCheckout = new LiteCheckout({
signal,
baseUrlTonder,
publicApiKeyTonder
apiKeyTonder
})

// The configureCheckout function allows you to set initial information,
Expand Down Expand Up @@ -93,7 +93,7 @@ const paymentResponse = await liteCheckout.payment(paymentData);
| Property | Type | Description |
|:---------:|:--------:|:--------------------------------------------------------------------------------------------:|
| mode | string | Environment mode. Options: 'stage', 'production', 'sandbox', 'development'. Default: 'stage' |
| publicApiKey | string | Your API key from the Tonder Dashboard |
| apiKey | string | Your API key from the Tonder Dashboard |
| returnrl | string | URL where the checkout form is mounted (used for 3DS) |
| callBack | function | Callback function to be invoked after the payment process ends successfully. |

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tonder.io/ionic-lite-sdk",
"version": "0.0.40-beta.1",
"version": "0.0.42-beta.1",
"description": "Tonder ionic lite SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
114 changes: 112 additions & 2 deletions src/classes/3dsHandler.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,56 @@
import { CustomizationOptions } from "../types/commons"

type ThreeDSHandlerContructor = {
payload?: any,
apiKey?: string,
baseUrl?: string,
customization?: CustomizationOptions,
tdsIframeId?: string,
tonderPayButtonId?: string,
callBack?: (params: any) => any
}

export class ThreeDSHandler {

callBack?: (params: any) => any
baseUrl?: string
apiKey?: string
payload?: any
localStorageKey: string = "verify_transaction_status_url"
customization: CustomizationOptions = {
saveCards: {
showSaveCardOption: true,
showSaved: true,
autoSave: false
},
redirectOnComplete: true
}
tdsIframeId?: string
tonderPayButtonId?: string

constructor({
payload = null,
apiKey,
baseUrl,
customization,
tdsIframeId,
tonderPayButtonId,
callBack
}: ThreeDSHandlerContructor) {
this.baseUrl = baseUrl,
this.apiKey = apiKey,
this.payload = payload
this.tdsIframeId = tdsIframeId
this.tonderPayButtonId = tonderPayButtonId
this.customization = {
...this.customization,
...(customization || {}),
saveCards: {
...this.customization.saveCards,
...(customization?.saveCards || {}),
},
}
this.callBack = callBack
}

setStorageItem (data: any) {
Expand Down Expand Up @@ -128,10 +160,88 @@ export class ThreeDSHandler {
const url = this.getRedirectUrl()
if (url) {
this.saveVerifyTransactionUrl()
window.location = url;
if(this.customization) {
if(this.customization?.redirectOnComplete) {
window.location = url;
} else {
const iframe = document.querySelector(`#${this.tdsIframeId}`)
if(iframe) {

iframe.setAttribute("src", url);
iframe.setAttribute("style", "display: block");

const self = this;

const listenerHandler = async (event: any) => {

const checkStatus = (result: any) => result?.transaction_status !== "Pending";

const executeAction = () => {
try {
const selector: any = document.querySelector(`#${this.tonderPayButtonId}`);
if(selector) {
selector.disabled = false;
}
} catch {}
if(iframe) {
iframe.setAttribute("style", "display: none");
}
if(self.callBack) self.callBack(self.payload);
iframe.removeEventListener("load", listenerHandler);
}

const chainPromises = async (promise: Promise<any>) => {
const result = await new Promise((resolve, reject) => resolve(promise))
if(result) {
if(checkStatus(result)) {
return executeAction()
} else {
const timer = setTimeout(async () => {
clearTimeout(timer);
await chainPromises(self.requestTransactionStatus());
}, 7000)
}
}
}

await chainPromises(self.requestTransactionStatus())
}

iframe.addEventListener("load", listenerHandler)

} else {
console.log('No iframe found');
}
}
} else {
window.location = url;
}
} else {
if (this.callBack) this.callBack!(this.payload);
}
}

async requestTransactionStatus() {

const verifyUrl = this.getUrlWithExpiration();
const url = `${this.baseUrl}${verifyUrl}`;
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${this.apiKey}`,
},
// body: JSON.stringify(data),
});

if (response.status !== 200) {
console.error('La verificación de la transacción falló.');
return null;
} else {
console.log('No redirection found');
const response_json = await response.json();
return response_json;
}

}

// Returns an object
Expand Down
38 changes: 35 additions & 3 deletions src/classes/BaseInlineCheckout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
saveCustomerCard,
} from "../data/cardApi";
import { fetchCustomerPaymentMethods } from "../data/paymentMethodApi";
import {Business, IConfigureCheckout, IInlineCheckoutBaseOptions} 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";
Expand All @@ -31,11 +31,21 @@ export class BaseInlineCheckout {
mode?: "production" | "sandbox" | "stage" | "development" | undefined;
apiKeyTonder: string;
returnUrl?: string;
tdsIframeId?: string;
tonderPayButtonId?: string;
callBack?: ((response: IStartCheckoutResponse | Record<string, any>) => void) | undefined;
merchantData?: Business;
abortController: AbortController;
secureToken: string = "";
customer?: ICustomer | { email: string };
customization: CustomizationOptions = {
saveCards: {
showSaveCardOption: true,
showSaved: true,
autoSave: false
},
redirectOnComplete: true
}

cartItems?: IItem[];
metadata = {};
Expand All @@ -46,11 +56,14 @@ export class BaseInlineCheckout {

constructor({
mode = "stage",
customization,
apiKey,
apiKeyTonder,
returnUrl,
tdsIframeId,
callBack = () => {},
baseUrlTonder
baseUrlTonder,
tonderPayButtonId
}: IInlineCheckoutBaseOptions) {
this.apiKeyTonder = apiKeyTonder || apiKey || "";
this.returnUrl = returnUrl;
Expand All @@ -62,7 +75,20 @@ export class BaseInlineCheckout {
this.process3ds = new ThreeDSHandler({
apiKey: apiKey,
baseUrl: this.baseUrl,
customization: customization,
tdsIframeId: tdsIframeId,
tonderPayButtonId: tonderPayButtonId,
callBack: callBack
});
this.tdsIframeId = tdsIframeId;
this.customization = {
...this.customization,
...(customization || {}),
saveCards: {
...this.customization.saveCards,
...(customization?.saveCards || {})
}
}
}

configureCheckout(data: IConfigureCheckout) {
Expand All @@ -88,9 +114,15 @@ export class BaseInlineCheckout {
this.#handleCard(data);
const response = await this._checkout(data);
this.process3ds.setPayload(response);
if (this.callBack) this.callBack!(response);
const payload = await this._handle3dsRedirect(response);
if (payload) {
try {
const selector: any = document.querySelector(`#${this.tonderPayButtonId}`);
if(selector) {
selector.disabled = false;
}
} catch {}
if (this.callBack) this.callBack!(response);
resolve(response);
}
} catch (error) {
Expand Down
12 changes: 12 additions & 0 deletions src/types/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ export interface IInlineCheckoutBaseOptions {
apiKey: string;
returnUrl?: string;
callBack?: (response: IStartCheckoutResponse | Record<string, any>) => void;
customization?: CustomizationOptions;
tdsIframeId?: string,
tonderPayButtonId?: string
}

export interface IInlineLiteCheckoutOptions
Expand All @@ -129,3 +132,12 @@ export interface IPublicError {
message: string;
detail: Record<string, any> | string;
}

export type CustomizationOptions = {
saveCards?: {
showSaveCardOption?: boolean;
showSaved?: boolean;
autoSave?: boolean;
},
redirectOnComplete?: boolean
}

0 comments on commit a93baf8

Please sign in to comment.