Skip to content

Commit

Permalink
Merge branch 'DEV-1243' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
David Hernandez committed Aug 8, 2024
2 parents 4b0b24d + 0cc421d commit 4f1ea5c
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 29 deletions.
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.34-beta.1",
"version": "0.0.34-beta.3",
"description": "Tonder ionic lite SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
65 changes: 41 additions & 24 deletions src/classes/liteCheckout.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import {injectMercadoPagoSecurity} from "../helpers/mercadopago";

declare const MP_DEVICE_SESSION_ID: string | undefined;

import Skyflow from "skyflow-js";
import CollectContainer from "skyflow-js/types/core/external/collect/collect-container";
import CollectElement from "skyflow-js/types/core/external/collect/collect-element";
Expand Down Expand Up @@ -41,7 +45,15 @@ export class LiteCheckout implements LiteCheckoutConstructor {
apiKey: this.apiKeyTonder,
baseUrl: this.baseUrlTonder,
})
this.#init()
}

async #init(){
this.getActiveAPMs()
const { mercado_pago } = await this.#fetchMerchantData() as Business
if (!!mercado_pago && mercado_pago.active){
injectMercadoPagoSecurity()
}
}

async getOpenpayDeviceSessionID(
Expand All @@ -63,7 +75,9 @@ export class LiteCheckout implements LiteCheckoutConstructor {
}
async #fetchMerchantData() {
try {
this.merchantData = await this.getBusiness();
if (!this.merchantData){
this.merchantData = await this.getBusiness();
}
return this.merchantData
}catch(e){
return this.merchantData
Expand Down Expand Up @@ -94,28 +108,37 @@ export class LiteCheckout implements LiteCheckoutConstructor {
const result3ds = await this.process3ds.verifyTransactionStatus()
const resultCheckout = await this.resumeCheckout(result3ds)
this.process3ds.setPayload(resultCheckout)
if (resultCheckout && 'is_route_finished' in resultCheckout && 'provider' in resultCheckout && resultCheckout.provider === 'tonder') {
return resultCheckout
}
return this.handle3dsRedirect(resultCheckout)
}

async resumeCheckout(response: any) {
if (["Failed", "Declined", "Cancelled"].includes(response?.status)) {
// Stop the routing process if the transaction is either hard declined or successful
if (response?.decline?.error_type === "Hard") {
return response
}

if (["Success", "Authorized"].includes(response?.transaction_status)) {
return response;
}

if (response) {
const routerItems = {
checkout_id: response.checkout?.id,
checkout_id: response?.checkout?.id,
};
const routerResponse = await this.handleCheckoutRouter(
routerItems
);
return routerResponse
try {
const routerResponse = await this.handleCheckoutRouter(
routerItems
);
return routerResponse
}catch (error){
// throw error
}
return response
}
return response
}

async handle3dsRedirect(response: ErrorResponse | StartCheckoutResponse | false | undefined) {
const iframe = response && 'next_action' in response ? response?.next_action?.iframe_resources?.iframe:null

if (iframe) {
this.process3ds.loadIframe()!.then(() => {
//TODO: Check if this will be necessary on the frontend side
Expand Down Expand Up @@ -206,7 +229,7 @@ export class LiteCheckout implements LiteCheckoutConstructor {
"Content-Type": "application/json",
Authorization: `Token ${this.apiKeyTonder}`,
},
body: JSON.stringify(data),
body: JSON.stringify({...data, ...(typeof MP_DEVICE_SESSION_ID !== "undefined" ? {mp_device_session_id: MP_DEVICE_SESSION_ID}:{})}),
});
if (response.ok) return await response.json() as StartCheckoutResponse;
throw await buildErrorResponse(response);
Expand Down Expand Up @@ -312,7 +335,8 @@ export class LiteCheckout implements LiteCheckoutConstructor {
...( !!payment_method
? {payment_method}
: {card: skyflowTokens}
)
),
...(typeof MP_DEVICE_SESSION_ID !== "undefined" ? {mp_device_session_id: MP_DEVICE_SESSION_ID}:{})
};

const checkoutResult = await this.handleCheckoutRouter(routerItems);
Expand Down Expand Up @@ -432,9 +456,7 @@ export class LiteCheckout implements LiteCheckoutConstructor {

async registerCustomerCard(customerToken: string, data: RegisterCustomerCardRequest): Promise<RegisterCustomerCardResponse | ErrorResponse> {
try {
if(!this.merchantData){
await this.#fetchMerchantData()
}
await this.#fetchMerchantData()

const response = await fetch(`${this.baseUrlTonder}/api/v1/business/${getBusinessId(this.merchantData)}/cards/`, {
method: 'POST',
Expand All @@ -455,9 +477,7 @@ export class LiteCheckout implements LiteCheckoutConstructor {

async getCustomerCards(customerToken: string): Promise<GetCustomerCardsResponse | ErrorResponse> {
try {
if(!this.merchantData){
await this.#fetchMerchantData()
}
await this.#fetchMerchantData()

const response = await fetch(`${this.baseUrlTonder}/api/v1/business/${getBusinessId(this.merchantData)}/cards`, {
method: 'GET',
Expand All @@ -477,10 +497,7 @@ export class LiteCheckout implements LiteCheckoutConstructor {

async deleteCustomerCard(customerToken: string, skyflowId: string = ""): Promise<Boolean | ErrorResponse> {
try {
if(!this.merchantData){
await this.#fetchMerchantData()
}

await this.#fetchMerchantData()
const response = await fetch(`${this.baseUrlTonder}/api/v1/business/${getBusinessId(this.merchantData)}/cards/${skyflowId}`, {
method: 'DELETE',
headers: {
Expand Down
16 changes: 16 additions & 0 deletions src/helpers/mercadopago.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export function injectMercadoPagoSecurity() {
try {
const script = document.createElement('script');
script.src = "https://www.mercadopago.com/v2/security.js";
script.setAttribute('view', '');
script.onload = () => {
console.log("Mercado Pago script loaded successfully.");
};
script.onerror = (error) => {
console.error("Error loading Mercado Pago script:", error);
};
document.head.appendChild(script);
} catch (error) {
console.error("Error attempting to inject Mercado Pago script:", error);
}
}
6 changes: 4 additions & 2 deletions src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const buildErrorResponse = async (
response: Response,
stack: string | undefined = undefined
): Promise<ErrorResponse> => {

let body, status, message = "Error";

if (response && "json" in response) {
Expand All @@ -46,10 +45,13 @@ const buildErrorResponse = async (
status = response.status.toString();
}

if (response && "text" in response) {
if (!body && response && "text" in response) {
message = await response.text();
}

if(body?.detail){
message = body.detail
}
const error = new ErrorResponse({
code: status,
body: body,
Expand Down
3 changes: 3 additions & 0 deletions src/types/commons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ export type Business = {
fintoc_keys: {
public_key: string;
};
mercado_pago: {
active: boolean;
};
vault_id: string;
vault_url: string;
reference: number;
Expand Down
4 changes: 4 additions & 0 deletions tests/utils/mockClasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class BusinessClass implements Business {
vault_url!: string;
reference!: number;
is_installments_available!: boolean;
mercado_pago!: { active: boolean}

get mockObject(): GetBusinessResponse {
return {
Expand All @@ -59,6 +60,9 @@ export class BusinessClass implements Business {
textDetailsColor: '#666666',
checkout_logo: 'assets/images/checkout-logo.png',
},
mercado_pago: {
active: false
},
vault_id: 'mock-vault-id-123',
vault_url: 'https://mock-vault.com',
reference: 987654,
Expand Down

0 comments on commit 4f1ea5c

Please sign in to comment.