diff --git a/.gitignore b/.gitignore
index 5d4a1d0..a075919 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,4 @@
lib
.env
/dist
-/types
\ No newline at end of file
+.idea/
diff --git a/README.md b/README.md
index 8dbd6e4..ed3e1b0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,22 @@
# Tonder SDK
-Tonder SDK Lite to integrate REST service
+Tonder SDK helps to integrate the services Tonder offers in your own mobile app
+
+
+## Table of Contents
+
+1. [Installation](#installation)
+2. [Usage](#usage)
+3. [Configuration Options](#configuration-options)
+4. [Mobile Settings](#mobile-settings)
+5. [Payment Data Structure](#payment-data-structure)
+6. [Field Validation Functions](#field-validation-functions)
+7. [API Reference](#api-reference)
+8. [Examples](#examples)
+9. [Deprecated Fields](#deprecated-fields)
+10. [Deprecated Functions](#deprecated-functions)
+11. [License](#license)
+
## Installation
@@ -16,11 +32,12 @@ Add dependencies to the root of the app (index.html)
```
## Usage
-## Import LiteCheckout class
+LiteCheckout allows you to build a custom checkout interface using Tonder's core functionality
+### Import LiteCheckout class
```javascript
import { LiteCheckout } from "@tonder.io/ionic-lite-sdk"
```
-## Create instance
+### Create instance
```javascript
const liteCheckout = new LiteCheckout({
@@ -29,104 +46,391 @@ const liteCheckout = new LiteCheckout({
publicApiKeyTonder
})
+// 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, save new card, etc.
+inlineCheckout.configureCheckout({ customer: { email: "example@email.com" } });
+
+// Initialize the checkout
+await liteCheckout.injectCheckout();
+
// To verify a 3ds transaction you can use the following method
// It should be called after the injectCheckout method
// The response status will be one of the following
// ['Declined', 'Cancelled', 'Failed', 'Success', 'Pending', 'Authorized']
inlineCheckout.verify3dsTransaction().then(response => {
- console.log('Verify 3ds response', response)
+ console.log('Verify 3ds response', response)
})
```
-| Property | Type | Description |
-|:---------------:|:-------------:|:-----------------------------------------------------------------------:|
-| signal | AborSignal | Signal from AbortController instance if it need cancel request |
-| baseUrlTonder | string | Live server: http://stage.tonder.io |
-| | | Mock Server: https://stoplight.io/mocks/tonder/tonder-api-v1-2/3152148 |
-| publicApiKeyTonder | string | You can take this from you Tonder Dashboard |
-| | | |
+```javascript
+// Retrieve customer's saved cards
+const cards = await liteCheckout.getCustomerCards();
+```
-# Class methods
+```javascript
+// Save a new card
+const newCard = await liteCheckout.saveCustomerCard(cardData);
+```
-# Checkout router
+```javascript
+// Remove a saved card
+await liteCheckout.removeCustomerCard(cardId);
+```
-```typescript
+```javascript
+// Get available payment methods
+const paymentMethods = await liteCheckout.getCustomerPaymentMethods();
+```
+
+```javascript
+// Process a payment
+const paymentResponse = await liteCheckout.payment(paymentData);
+```
+
+## Configuration Options
+
+| Property | Type | Description |
+|:---------:|:--------:|:--------------------------------------------------------------------------------------------:|
+| mode | string | Environment mode. Options: 'stage', 'production', 'sandbox', 'development'. Default: 'stage' |
+| publicApiKey | 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. |
+
+## Mobile settings
+
+If you are deploying to Android, edit your AndroidManifest.xml file to add the Internet permission.
+
+```xml
+
+
+```
+
+Likewise, if you are deploying to macOS, edit your macos/Runner/DebugProfile.entitlements and macos/Runner/Release.entitlements files to include the network client entitlement.
+
+```xml
+
+com.apple.security.network.client
+
+```
+
+## Payment Data Structure
+
+When calling the `payment` method, use the following data structure:
-const returnUrl = "http://localhost:8100/payment/success";
+### Field Descriptions
-let checkoutData = {
+- **customer**: Object containing the customer's personal information to be registered in the transaction.
+
+- **cart**: Object containing the total amount and an array of items to be registered in the Tonder order.
+
+ - **total**: The total amount of the transaction.
+ - **items**: An array of objects, each representing a product or service in the order.
+ - name: name of the product
+ - price_unit: valid float string with the price of the product
+ - quantity: valid integer string with the quantity of this product
+
+- **currency**: String representing the currency code for the transaction (e.g., "MXN" for Mexican Peso).
+
+- **metadata**: Object for including any additional information about the transaction. This can be used for internal references or tracking.
+
+- **card**: (for LiteCheckout) Object containing card information. This is used differently depending on whether it's a new card or a saved card:
+
+ - For a new card: Include `card_number`, `cvv`, `expiration_month`, `expiration_year`, and `cardholder_name`.
+ - For a saved card: Include only the `skyflow_id` of the saved card.
+ - This is only used when not paying with a payment_method.
+
+- **payment_method**: (for LiteCheckout) String indicating the alternative payment method to be used (e.g., "Spei"). This is only used when not paying with a card.
+
+```javascript
+const paymentData = {
customer: {
- name: "Jhon",
- lastname: "Doe",
- email: "john.c.calhoun@examplepetstore.com",
- phone: "+58452258525"
+ firstName: "John",
+ lastName: "Doe",
+ country: "USA",
+ address: "123 Main St",
+ city: "Anytown",
+ state: "CA",
+ postCode: "12345",
+ email: "john.doe@example.com",
+ phone: "1234567890",
},
- order: {
+ cart: {
+ total: "100.00",
items: [
{
- description: "Test product description",
+ description: "Product description",
quantity: 1,
- price_unit: 25,
- discount: 1,
- taxes: 12,
- product_reference: 89456123,
- name: "Test product",
- amount_total: 25
- }
- ]
+ price_unit: "100.00",
+ discount: "0.00",
+ taxes: "0.00",
+ product_reference: "PROD123",
+ name: "Product Name",
+ amount_total: "100.00",
+ },
+ ],
},
- return_url: returnUrl,
- total: 25,
- isSandbox: true,
- metadata: {},
currency: "MXN",
- skyflowTokens: {
- cardholder_name: "",
- card_number: "",
- expiration_year: "",
- expiration_month: "",
- cvv: "",
- skyflow_id: ""
- }
-}
+ metadata: {
+ order_id: "ORDER123",
+ },
+ // For a new card:
+ card: {
+ card_number: "4111111111111111",
+ cvv: "123",
+ expiration_month: "12",
+ expiration_year: "25",
+ cardholder_name: "John Doe",
+ },
+ // card: "skyflow_id" // for a selected saved card.
+ // payment_method: "Spei", // For the selected payment method.
+};
+```
+
+## Field Validation Functions
+
+For LiteCheckout implementations, the SDK provides validation functions to ensure the integrity of card data before submitting:
+
+- `validateCardNumber(cardNumber)`: Validates the card number using the Luhn algorithm.
+- `validateCardholderName(name)`: Checks if the cardholder name is valid.
+- `validateCVV(cvv)`: Ensures the CVV is in the correct format.
+- `validateExpirationDate(expirationDate)`: Validates the expiration date in MM/YY format.
+- `validateExpirationMonth(month)`: Checks if the expiration month is valid.
+- `validateExpirationYear(year)`: Validates the expiration year.
+Example usage:
+
+```javascript
+import {
+ validateCardNumber,
+ validateCardholderName,
+ validateCVV,
+ validateExpirationDate,
+} from "@tonder.io/ionic-lite-sdk";
+
+const cardNumber = "4111111111111111";
+const cardholderName = "John Doe";
+const cvv = "123";
+const expirationDate = "12/25";
+
+if (
+ validateCardNumber(cardNumber) &&
+ validateCardholderName(cardholderName) &&
+ validateCVV(cvv) &&
+ validateExpirationDate(expirationDate)
+) {
+ // Proceed with payment
+} else {
+ // Show error message
+}
```
-It is required get the skyflow tokens to add it to the checkout router method, the values of the variable skyflowFields come from your html form
+
+## API Reference
+
+### LiteCheckout Methods
+
+- `configureCheckout(data)`: Set initial checkout data
+- `injectCheckout()`: Initialize the checkout
+- `getCustomerCards()`: Retrieve saved cards
+- `saveCustomerCard(cardData)`: Save a new card
+- `removeCustomerCard(cardId)`: Remove a saved card
+- `getCustomerPaymentMethods()`: Get available payment methods
+- `payment(data)`: Process a payment
+- `verify3dsTransaction()`: Verify a 3DS transaction
+
+
+## Examples
+
+Here are examples of how to implement Tonder Lite SDK:
+
+### Angular
+
+For Angular, we recommend using a service to manage the Tonder instance:
```typescript
+// tonder.service.ts
+import { Injectable } from "@angular/core";
+import { LiteCheckout } from "@tonder.io/ionic-lite-sdk";
+import {ILiteCheckout} from "@tonder.io/ionic-lite-sdk/dist/types/liteInlineCheckout";
+
+@Injectable({
+ providedIn: "root",
+})
+export class TonderService {
+ private liteCheckout!: ILiteCheckout;
+
+ constructor(@Inject(Object) private sdkParameters: IInlineLiteCheckoutOptions) {
+ this.initializeInlineCheckout();
+ }
-const merchantData: any = await liteCheckout.getBusiness();
+ private initializeInlineCheckout(): void {
+ this.liteCheckout = new LiteCheckout({ ...this.sdkParameters });
+ }
-const { vault_id, vault_url } = merchantData;
+ configureCheckout(customerData: IConfigureCheckout): void {
+ return this.liteCheckout.configureCheckout({ ...customerData });
+ }
-const skyflowFields = {
- card_number: this.paymentForm.value.cardNumber,
- cvv: this.paymentForm.value.cvv,
- expiration_month: this.paymentForm.value.month,
- expiration_year: this.paymentForm.value.expirationYear,
- cardholder_name: this.paymentForm.value.name
+ async injectCheckout(): Promise {
+ return await this.liteCheckout.injectCheckout();
+ }
+
+ verify3dsTransaction(): Promise {
+ return this.liteCheckout.verify3dsTransaction();
+ }
+
+ payment(
+ checkoutData: IProcessPaymentRequest,
+ ): Promise {
+ return this.inlineCheckout.payment(checkoutData);
+ }
+
+ // Add more functions, for example for lite sdk: get payment methods
+
+ // getCustomerPaymentMethods(): Promise {
+ // return this.liteCheckout.getCustomerPaymentMethods();
+ // }
}
-const skyflowTokens = await liteCheckout.getSkyflowTokens({
- vault_id: vault_id,
- vault_url: vault_url,
- data: skyflowFields
+// checkout.component.ts
+import { Component, OnInit, OnDestroy } from "@angular/core";
+import { TonderService } from "./tonder.service";
+
+@Component({
+ selector: "app-tonder-checkout",
+ template: `
+
+ `,
+ providers: [
+ {
+ provide: TonderInlineService,
+ // Initialization of the Tonder Lite SDK.
+ // Note: Replace these credentials with your own in development/production.
+ useFactory: () =>
+ new TonderInlineService({
+ apiKey: "11e3d3c3e95e0eaabbcae61ebad34ee5f93c3d27",
+ returnUrl: "http://localhost:8100/tabs/tab5",
+ mode: "stage",
+ }),
+ },
+ ],
})
+export class TonderCheckoutComponent implements OnInit, OnDestroy {
+ loading = false;
+ checkoutData: IProcessPaymentRequest;
+ paymentForm = new FormGroup({
+ name: new FormControl('Pedro Paramo'),
+ cardNumber: new FormControl('4242424242424242'),
+ month: new FormControl('12'),
+ expirationYear: new FormControl('28'),
+ cvv: new FormControl('123')
+ });
+
+ constructor(private tonderService: TonderService) {
+ this.checkoutData = {
+ customer: {
+ firstName: "Jhon",
+ lastName: "Doe",
+ email: "john.c.calhoun@examplepetstore.com",
+ phone: "+58452258525"
+ },
+ cart: {
+ total: 25,
+ items: [
+ {
+ description: "Test product description",
+ quantity: 1,
+ price_unit: 25,
+ discount: 1,
+ taxes: 12,
+ product_reference: 89456123,
+ name: "Test product",
+ amount_total: 25
+ }
+ ]
+ },
+ metadata: {},
+ currency: "MXN"
+ }
+ }
-checkoutData.skyflowTokens = skyflowTokens;
+ ngOnInit() {
+ this.initCheckout();
+ }
-const jsonResponseRouter: any = await liteCheckout.startCheckoutRouterFull(
- checkoutData
-);
+ async initCheckout() {
+ this.tonderService.configureCheckout({
+ customer: { email: "example@email.com" },
+ });
+ await this.tonderService.injectCheckout();
+ this.tonderService.verify3dsTransaction().then((response) => {
+ console.log("Verify 3ds response", response);
+ });
+
+ // Calls more functions to get payment methods, saved cards, etc.
+ }
+ async pay() {
+ this.loading = true;
+ try {
+ const response = await this.tonderService.payment({
+ ...this.checkoutData,
+ card: { // Card details, if not using a payment method.
+ card_number: this.paymentForm.value.cardNumber || "",
+ cvv: this.paymentForm.value.cvv || "",
+ expiration_month: this.paymentForm.value.month || "",
+ expiration_year: this.paymentForm.value.expirationYear || "",
+ cardholder_name: this.paymentForm.value.name || ""
+ },
+ // card: "skyflow_id" // In case a saved card is selected.
+ // payment_method: "" // Payment method if not using the card form
+ });
+ console.log("Payment successful:", response);
+ alert("Payment successful");
+ } catch (error) {
+ console.error("Payment failed:", error);
+ alert("Payment failed");
+ } finally {
+ this.loading = false;
+ }
+ }
+}
```
-Take actions on base to the checkout router response
-
-# Customer Cards(Register)
-
## Request secure token
```typescript
@@ -145,75 +449,82 @@ const jsonResponse = await liteCheckout.getSecureToken(
}
```
+## Deprecated Fields
+
+The following fields have been deprecated and should no longer be used. Consider using the recommended alternatives:
+
## Register customer card
+### `apiKeyTonder` Property
-```typescript
+- **Deprecated Reason:** The `apiKeyTonder` property in the constructor and `IInlineLiteCheckoutOptions` interface is no longer required.
+- **Alternative:** Use the `apiKey` field.
-customer_auth_token: string;
+### `baseUrlTonder` Property
-data: {
- skyflow_id: string;
-};
+- **Deprecated Reason:** The `baseUrlTonder` property in the constructor and `IInlineLiteCheckoutOptions` interface is no longer required.
+- **Alternative:** Use the `mode` field with `stage` | `development` | `sandbox` | `production` options.
-const jsonResponseOrder = await liteCheckout.registerCustomerCard(
- secureToken
- customer_auth_token,
- data
-);
-```
+### `signal` Property
-## Return register customer card
-```typescript
-{
- skyflow_id: string;
- user_id: number;
-}
-```
+- **Deprecated Reason:** The `signal` property in the constructor and `IInlineLiteCheckoutOptions` interface is no longer required.
-# Customer Cards(Get)
-## Get customer cards
+## Deprecated Functions
-```typescript
+The following functions have been deprecated and should no longer be used. Consider using the recommended alternatives:
-customer_auth_token: string;
+### `customerRegister`
-query: string = "?ordering=&search=";
+- **Deprecated Reason:** This function is no longer necessary as registration is now automatically handled during payment processing or when using card management methods.
-const jsonResponseOrder = await liteCheckout.getCustomerCards(
- customer_auth_token,
- query
-);
-```
+### `createOrder` and `createPayment`
-## Return get customer cards
-```typescript
-{
- user_id: number,
- cards: [
- {
- fields: {
- card_number: string,
- cardholder_name: string,
- cvv: string,
- expiration_month: string,
- expiration_year: string,
- skyflow_id: string
- }
- }
- ]
-}
-```
+- **Deprecated Reason:** These functions have been replaced by the `payment` function, which now automatically handles order creation and payment processing.
+- **Alternative:** Use the `payment` function.
-## Delete customer card
+### `startCheckoutRouter` and `startCheckoutRouterFull`
-```typescript
+- **Deprecated Reason:** These functions have been replaced by the `payment` function.
+- **Alternative:** Use the `payment` function.
-const deleted: boolean = await liteCheckout.deleteCustomerCard(
- customer_auth_token,
- skyflow_id
-);
+### `registerCustomerCard`
+
+- **Deprecated Reason:** This function has been renamed to `saveCustomerCard` to better align with its purpose. The method's usage has also been updated.
+- **Alternative:** Use the `saveCustomerCard` method and update your implementation to reflect the changes.
+
+### `deleteCustomerCard`
+- **Deprecated Reason:** This function has been renamed to `removeCustomerCard` to better align with its purpose. The method's usage has also been updated.
+- **Alternative:** Use the `removeCustomerCard` method and update your implementation to reflect the changes.
+
+### `getActiveAPMs`
+
+- **Deprecated Reason:** This function has been renamed to `getCustomerPaymentMethods` to better align with its purpose. The method's usage has also been updated.
+- **Alternative:** Use the `getCustomerPaymentMethods` method and update your implementation to reflect the changes.
+
+### `getSkyflowTokens`
+
+- **Deprecated Reason:** Card registration and checkout are now automatically handled during the payment process or through card management methods, making this method unnecessary.
+
+### `getOpenpayDeviceSessionID`
+
+- **Deprecated Reason:** It is no longer necessary to use this method is now automatically handled during the payment process.
+
+
+## Notes
+
+### General
+
+- Replace `apiKey`, `mode`, `returnUrl` with your actual values.
+- Remember to use the `configureCheckout` function after creating an instance of `LiteCheckout`. This ensures that functions such as payment processing, saving cards, deleting cards, and others work correctly.
+
+### Script Dependencies
+
+For all implementations, ensure you include the necessary scripts:
+
+```html
+
+
```
## License
diff --git a/package-lock.json b/package-lock.json
index 001eb7e..05cde97 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,14 +1,15 @@
{
"name": "@tonder.io/ionic-lite-sdk",
- "version": "0.0.36-beta.1",
+ "version": "0.0.40-beta.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@tonder.io/ionic-lite-sdk",
- "version": "0.0.36-beta.1",
+ "version": "0.0.40-beta.1",
"license": "ISC",
"dependencies": {
+ "lodash.get": "^4.4.2",
"skyflow-js": "^1.34.1",
"ts-node": "^10.9.2"
},
@@ -17,6 +18,8 @@
"@rollup/plugin-typescript": "11.1.6",
"@types/crypto-js": "^4.2.2",
"@types/jest": "^29.5.11",
+ "@types/lodash": "^4.17.10",
+ "@types/lodash.get": "^4.4.9",
"@types/node": "^20.11.5",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
@@ -1595,6 +1598,21 @@
"dev": true,
"peer": true
},
+ "node_modules/@types/lodash": {
+ "version": "4.17.10",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.10.tgz",
+ "integrity": "sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==",
+ "dev": true
+ },
+ "node_modules/@types/lodash.get": {
+ "version": "4.4.9",
+ "resolved": "https://registry.npmjs.org/@types/lodash.get/-/lodash.get-4.4.9.tgz",
+ "integrity": "sha512-J5dvW98sxmGnamqf+/aLP87PYXyrha9xIgc2ZlHl6OHMFR2Ejdxep50QfU0abO1+CH6+ugx+8wEUN1toImAinA==",
+ "dev": true,
+ "dependencies": {
+ "@types/lodash": "*"
+ }
+ },
"node_modules/@types/node": {
"version": "20.11.16",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz",
@@ -4720,6 +4738,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "node_modules/lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
+ },
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
diff --git a/package.json b/package.json
index 8bf1258..b4489b0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@tonder.io/ionic-lite-sdk",
- "version": "0.0.36-beta.1",
+ "version": "0.0.40-beta.1",
"description": "Tonder ionic lite SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -12,6 +12,7 @@
"author": "",
"license": "ISC",
"dependencies": {
+ "lodash.get": "^4.4.2",
"skyflow-js": "^1.34.1",
"ts-node": "^10.9.2"
},
@@ -24,6 +25,8 @@
"@rollup/plugin-typescript": "11.1.6",
"@types/crypto-js": "^4.2.2",
"@types/jest": "^29.5.11",
+ "@types/lodash": "^4.17.10",
+ "@types/lodash.get": "^4.4.9",
"@types/node": "^20.11.5",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
diff --git a/src/classes/BaseInlineCheckout.ts b/src/classes/BaseInlineCheckout.ts
new file mode 100644
index 0000000..638c0b8
--- /dev/null
+++ b/src/classes/BaseInlineCheckout.ts
@@ -0,0 +1,392 @@
+import { ThreeDSHandler } from "./3dsHandler";
+import { ErrorResponse } from "./errorResponse";
+import { fetchBusiness } from "../data/businessApi";
+import { injectMercadoPagoSecurity } from "../helpers/mercadopago";
+import { TONDER_URL_BY_MODE } from "../shared/constants/tonderUrl";
+import {
+ createOrder,
+ createPayment,
+ startCheckoutRouter,
+} from "../data/checkoutApi";
+import { getOpenpayDeviceSessionID } from "../data/openPayApi";
+import { getBrowserInfo } from "../helpers/utils";
+import { registerOrFetchCustomer } from "../data/customerApi";
+import { get } from "lodash";
+import {
+ fetchCustomerCards,
+ removeCustomerCard,
+ saveCustomerCard,
+} from "../data/cardApi";
+import { fetchCustomerPaymentMethods } from "../data/paymentMethodApi";
+import {Business, IConfigureCheckout, IInlineCheckoutBaseOptions} 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";
+export class BaseInlineCheckout {
+ baseUrl = "";
+ cartTotal: string | number = "0";
+ process3ds: ThreeDSHandler;
+ mode?: "production" | "sandbox" | "stage" | "development" | undefined;
+ apiKeyTonder: string;
+ returnUrl?: string;
+ callBack?: ((response: IStartCheckoutResponse | Record) => void) | undefined;
+ merchantData?: Business;
+ abortController: AbortController;
+ secureToken: string = "";
+ customer?: ICustomer | { email: string };
+
+ cartItems?: IItem[];
+ metadata = {};
+ card? = {};
+ currency?: string = "";
+
+ #customerData?: Record;
+
+ constructor({
+ mode = "stage",
+ apiKey,
+ apiKeyTonder,
+ returnUrl,
+ callBack = () => {},
+ baseUrlTonder
+ }: IInlineCheckoutBaseOptions) {
+ this.apiKeyTonder = apiKeyTonder || apiKey || "";
+ this.returnUrl = returnUrl;
+ this.callBack = callBack;
+ this.mode = mode;
+ this.customer = {} as ICustomer
+ this.baseUrl = baseUrlTonder || TONDER_URL_BY_MODE[this.mode] || TONDER_URL_BY_MODE["stage"];
+ this.abortController = new AbortController();
+ this.process3ds = new ThreeDSHandler({
+ apiKey: apiKey,
+ baseUrl: this.baseUrl,
+ });
+ }
+
+ configureCheckout(data: IConfigureCheckout) {
+ if ("customer" in data) this.#handleCustomer(data["customer"]);
+ if ("secureToken" in data) this.#setSecureToken(data["secureToken"]);
+ }
+
+ async verify3dsTransaction(): Promise {
+ const result3ds = await this.process3ds.verifyTransactionStatus();
+ const resultCheckout = await this.#resumeCheckout(result3ds);
+ this.process3ds.setPayload(resultCheckout);
+ return this._handle3dsRedirect(resultCheckout);
+ }
+
+ payment(data: IProcessPaymentRequest): Promise {
+ return new Promise(async (resolve, reject) => {
+ try {
+ this.#handleCustomer(data.customer);
+ this._setCartTotal(data.cart?.total);
+ this.#setCartItems(data.cart?.items);
+ this.#handleMetadata(data);
+ this.#handleCurrency(data);
+ 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) {
+ resolve(response);
+ }
+ } catch (error) {
+ reject(error);
+ }
+ });
+ }
+
+ async _initializeCheckout() {
+ const business_response = await this._fetchMerchantData();
+
+ if (
+ !!business_response &&
+ !!business_response.mercado_pago &&
+ business_response.mercado_pago.active
+ ) {
+ injectMercadoPagoSecurity();
+ }
+ }
+
+ async _checkout(data: any): Promise {
+ throw new Error(
+ "The #checkout method should be implement in child classes.",
+ );
+ }
+
+ _setCartTotal(total: string | number) {
+ throw new Error(
+ "The #setCartTotal method should be implement in child classes.",
+ );
+ }
+
+ async _getCustomer(signal: AbortSignal | null = null) {
+ if (!!this.#customerData) return this.#customerData!;
+
+ this.#customerData = await registerOrFetchCustomer(
+ this.baseUrl,
+ this.apiKeyTonder,
+ this.customer!,
+ signal,
+ );
+ return this.#customerData!;
+ }
+
+ async _handleCheckout({
+ card,
+ payment_method,
+ customer,
+ isSandbox,
+ // TODO: DEPRECATED
+ returnUrl: returnUrlData
+ }: {
+ card?: string;
+ payment_method?: string;
+ customer: Record;
+ isSandbox?: boolean;
+ returnUrl?: string;
+ }) {
+ const { openpay_keys, reference, business } = this.merchantData!;
+ const total = Number(this.cartTotal);
+ try {
+ let deviceSessionIdTonder;
+ if (
+ !deviceSessionIdTonder &&
+ openpay_keys.merchant_id &&
+ openpay_keys.public_key
+ ) {
+ deviceSessionIdTonder = await getOpenpayDeviceSessionID(
+ openpay_keys.merchant_id,
+ openpay_keys.public_key,
+ isSandbox,
+ this.abortController.signal,
+ );
+ }
+
+ const { id, auth_token } = customer;
+
+ const orderItems = {
+ business: this.apiKeyTonder,
+ client: auth_token,
+ billing_address_id: null,
+ shipping_address_id: null,
+ amount: total,
+ status: "A",
+ reference: reference,
+ is_oneclick: true,
+ items: this.cartItems!,
+ };
+ const jsonResponseOrder = await createOrder(
+ this.baseUrl,
+ this.apiKeyTonder,
+ orderItems,
+ );
+
+ // Create payment
+ const now = new Date();
+ const dateString = now.toISOString();
+
+ const paymentItems = {
+ business_pk: business.pk,
+ client_id: id,
+ amount: total,
+ date: dateString,
+ order_id: jsonResponseOrder.id,
+ };
+ const jsonResponsePayment = await createPayment(
+ this.baseUrl,
+ this.apiKeyTonder,
+ paymentItems,
+ );
+
+ // Checkout router
+ const routerItems = {
+ name: get(this.customer, "firstName", get(this.customer, "name", "")),
+ last_name: get(
+ this.customer,
+ "lastName",
+ get(this.customer, "lastname", ""),
+ ),
+ email_client: get(this.customer, "email", ""),
+ phone_number: get(this.customer, "phone", ""),
+ return_url: returnUrlData || this.returnUrl,
+ id_product: "no_id",
+ quantity_product: 1,
+ id_ship: "0",
+ instance_id_ship: "0",
+ amount: total,
+ title_ship: "shipping",
+ description: "transaction",
+ device_session_id: deviceSessionIdTonder ? deviceSessionIdTonder : null,
+ token_id: "",
+ order_id: jsonResponseOrder.id,
+ business_id: business.pk,
+ payment_id: jsonResponsePayment.pk,
+ source: "sdk",
+ metadata: this.metadata,
+ browser_info: getBrowserInfo(),
+ currency: this.currency!,
+ ...(!!payment_method ? { payment_method } : { card }),
+ };
+
+ const jsonResponseRouter = await startCheckoutRouter(
+ this.baseUrl,
+ this.apiKeyTonder,
+ routerItems,
+ );
+
+ if (jsonResponseRouter) {
+ return jsonResponseRouter;
+ } else {
+ return false;
+ }
+ } catch (error) {
+ console.log(error);
+ throw error;
+ }
+ }
+
+ async _fetchMerchantData() {
+ try {
+ if (!this.merchantData) {
+ this.merchantData = await fetchBusiness(
+ this.baseUrl,
+ this.apiKeyTonder,
+ this.abortController.signal,
+ );
+ }
+ return this.merchantData;
+ } catch (e) {
+ return this.merchantData;
+ }
+ }
+
+ async _getCustomerCards(
+ authToken: string,
+ businessId: string | number,
+ ): Promise {
+ return await fetchCustomerCards(this.baseUrl, authToken, businessId);
+ }
+
+ async _saveCustomerCard(
+ authToken: string,
+ secureToken: string,
+ businessId: string | number,
+ skyflowTokens: ISaveCardSkyflowRequest,
+ ): Promise {
+ return await saveCustomerCard(
+ this.baseUrl,
+ this.secureToken,
+ authToken,
+ businessId,
+ skyflowTokens,
+ );
+ }
+
+ async _removeCustomerCard(
+ authToken: string,
+ businessId: string | number,
+ skyflowId: string,
+ ): Promise {
+ return await removeCustomerCard(
+ this.baseUrl,
+ authToken,
+ skyflowId,
+ businessId,
+ );
+ }
+ async _fetchCustomerPaymentMethods(): Promise {
+ return await fetchCustomerPaymentMethods(this.baseUrl, this.apiKeyTonder);
+ }
+
+ #handleCustomer(customer: ICustomer | { email: string }) {
+ if (!customer) return;
+
+ this.customer = customer;
+ }
+
+ #setSecureToken(token: string) {
+ this.secureToken = token;
+ }
+
+ #setCartItems(items: IItem[]) {
+ this.cartItems = items;
+ }
+
+ #handleMetadata(data: { metadata?: any }) {
+ this.metadata = data?.metadata;
+ }
+
+ #handleCurrency(data: { currency?: string }) {
+ this.currency = data?.currency;
+ }
+
+ #handleCard(data: { card?: ICardFields | string }) {
+ this.card = data?.card;
+ }
+
+ // TODO: Make private after remove deprecated functions of liteCheckout
+ async _handle3dsRedirect(
+ response: ITransaction | IStartCheckoutResponse | void,
+ ) {
+ 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
+ // after some the tests in production, since the 3DS process
+ // doesn't works properly on the sandbox environment
+ // setTimeout(() => {
+ // process3ds.verifyTransactionStatus();
+ // }, 10000);
+ this.process3ds.verifyTransactionStatus();
+ })
+ .catch((error) => {
+ console.log("Error loading iframe:", error);
+ });
+ } else {
+ const redirectUrl = this.process3ds.getRedirectUrl();
+ if (redirectUrl) {
+ this.process3ds.redirectToChallenge();
+ } else {
+ return response;
+ }
+ }
+ }
+
+ async #resumeCheckout(response: any) {
+ // 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,
+ };
+
+ try {
+ return await startCheckoutRouter(
+ this.baseUrl,
+ this.apiKeyTonder,
+ routerItems,
+ );
+ } catch (error) {
+ // throw error
+ }
+ return response;
+ }
+ }
+}
diff --git a/src/classes/errorResponse.ts b/src/classes/errorResponse.ts
index 7d1671b..435c5ab 100644
--- a/src/classes/errorResponse.ts
+++ b/src/classes/errorResponse.ts
@@ -1,4 +1,4 @@
-import { IErrorResponse } from "../types/responses";
+import {IErrorResponse} from "../types/responses";
export class ErrorResponse implements IErrorResponse {
code?: string | undefined;
diff --git a/src/classes/liteCheckout.ts b/src/classes/liteCheckout.ts
index 68d3245..e99636b 100644
--- a/src/classes/liteCheckout.ts
+++ b/src/classes/liteCheckout.ts
@@ -1,17 +1,40 @@
-import {injectMercadoPagoSecurity} from "../helpers/mercadopago";
+import { fetchBusiness } from "../data/businessApi";
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";
-import { APM, Business, TonderAPM } from "../types/commons";
-import { CreateOrderRequest, CreatePaymentRequest, RegisterCustomerCardRequest, StartCheckoutRequest, TokensRequest, StartCheckoutFullRequest, StartCheckoutIdRequest } from "../types/requests";
-import { GetSecureTokenResponse, GetBusinessResponse, CustomerRegisterResponse, CreateOrderResponse, CreatePaymentResponse, StartCheckoutResponse, GetVaultTokenResponse, IErrorResponse, GetCustomerCardsResponse, RegisterCustomerCardResponse } from "../types/responses";
import { ErrorResponse } from "./errorResponse";
-import { buildErrorResponse, buildErrorResponseFromCatch, getBrowserInfo, getPaymentMethodDetails, getBusinessId } from "../helpers/utils";
-import { ThreeDSHandler } from "./3dsHandler";
+import {
+ buildErrorResponse,
+ buildErrorResponseFromCatch,
+ getBrowserInfo,
+ getBusinessId,
+ formatPublicErrorResponse,
+ getCardType,
+} from "../helpers/utils";
import { getCustomerAPMs } from "../data/api";
+import { BaseInlineCheckout } from "./BaseInlineCheckout";
+import { MESSAGES } from "../shared/constants/messages";
+import { getSkyflowTokens } from "../helpers/skyflow";
+import { startCheckoutRouter } from "../data/checkoutApi";
+import { getOpenpayDeviceSessionID } from "../data/openPayApi";
+import { getPaymentMethodDetails } from "../shared/catalog/paymentMethodsCatalog";
+import {APM, IInlineLiteCheckoutOptions, TonderAPM} from "../types/commons";
+import {ICustomerCardsResponse, ISaveCardRequest, ISaveCardResponse, ISaveCardSkyflowRequest} from "../types/card";
+import {IPaymentMethod} from "../types/paymentMethod";
+import {
+ CreateOrderResponse,
+ CreatePaymentResponse,
+ CustomerRegisterResponse,
+ GetBusinessResponse, IErrorResponse, RegisterCustomerCardResponse, StartCheckoutResponse, GetSecureTokenResponse
+} from "../types/responses";
+import {
+ CreateOrderRequest,
+ CreatePaymentRequest, RegisterCustomerCardRequest, StartCheckoutFullRequest,
+ StartCheckoutIdRequest,
+ StartCheckoutRequest,
+ TokensRequest
+} from "../types/requests";
+import {ICardFields, IStartCheckoutResponse} from "../types/checkout";
+import {ILiteCheckout} from "../types/liteInlineCheckout";
declare global {
interface Window {
@@ -19,256 +42,341 @@ declare global {
}
}
-export type LiteCheckoutConstructor = {
- signal: AbortSignal;
- baseUrlTonder: string;
- publicApiKeyTonder: string;
-};
-
-export class LiteCheckout implements LiteCheckoutConstructor {
- signal: AbortSignal;
- baseUrlTonder: string;
- publicApiKeyTonder: string;
- process3ds: ThreeDSHandler;
- activeAPMs: APM[] = []
- merchantData?: Business | ErrorResponse;
-
- constructor({
- signal,
- baseUrlTonder,
- publicApiKeyTonder,
- }: LiteCheckoutConstructor) {
- this.baseUrlTonder = baseUrlTonder;
- this.signal = signal;
- this.publicApiKeyTonder = publicApiKeyTonder;
- this.process3ds = new ThreeDSHandler({
- apiKey: this.publicApiKeyTonder,
- baseUrl: this.baseUrlTonder,
- })
- this.#init()
+export class LiteCheckout extends BaseInlineCheckout implements ILiteCheckout{
+ activeAPMs: APM[] = [];
+
+ constructor({ apiKey, mode, returnUrl, callBack, apiKeyTonder, baseUrlTonder }: IInlineLiteCheckoutOptions) {
+ super({ mode, apiKey, returnUrl, callBack, apiKeyTonder, baseUrlTonder });
}
- async #init(){
- this.getActiveAPMs()
- const { mercado_pago } = await this.#fetchMerchantData() as Business
- if (!!mercado_pago && mercado_pago.active){
- injectMercadoPagoSecurity()
- }
+ public async injectCheckout() {
+ await this._initializeCheckout();
}
- async getOpenpayDeviceSessionID(
- merchant_id: string,
- public_key: string,
- is_sandbox: boolean
- ): Promise {
+ public async getCustomerCards(): Promise {
try {
- let openpay = await window.OpenPay;
- openpay.setId(merchant_id);
- openpay.setApiKey(public_key);
- openpay.setSandboxMode(is_sandbox);
- return await openpay.deviceData.setup({
- signal: this.signal,
- }) as string;
- } catch (e) {
- throw buildErrorResponseFromCatch(e);
+ await this._fetchMerchantData();
+ const { auth_token } = await this._getCustomer();
+ const response = await this._getCustomerCards(
+ auth_token,
+ this.merchantData!.business.pk,
+ );
+
+ return {
+ ...response,
+ cards: response.cards.map((ic) => ({
+ ...ic,
+ icon: getCardType(ic.fields.card_scheme),
+ })),
+ };
+ } catch (error) {
+ throw formatPublicErrorResponse(
+ {
+ message: MESSAGES.getCardsError,
+ },
+ error,
+ );
}
}
- async #fetchMerchantData() {
+
+ public async saveCustomerCard(
+ secureToken: string,
+ card: ISaveCardRequest,
+ ): Promise {
try {
- if (!this.merchantData){
- this.merchantData = await this.getBusiness();
- }
- return this.merchantData
- }catch(e){
- return this.merchantData
+ await this._fetchMerchantData();
+ const { auth_token } = await this._getCustomer();
+ const { vault_id, vault_url, business } = this.merchantData!;
+
+ const skyflowTokens: ISaveCardSkyflowRequest = await getSkyflowTokens({
+ vault_id: vault_id,
+ vault_url: vault_url,
+ data: card,
+ baseUrl: this.baseUrl,
+ apiKey: this.apiKeyTonder,
+ });
+
+ return await this._saveCustomerCard(
+ secureToken,
+ auth_token,
+ business?.pk,
+ skyflowTokens,
+ );
+ } catch (error) {
+ throw formatPublicErrorResponse(
+ {
+ message: MESSAGES.saveCardError,
+ },
+ error,
+ );
}
}
- async getBusiness(): Promise {
+ public async removeCustomerCard(skyflowId: string): Promise {
try {
- const getBusiness = await fetch(
- `${this.baseUrlTonder}/api/v1/payments/business/${this.publicApiKeyTonder}`,
+ await this._fetchMerchantData();
+ const { auth_token } = await this._getCustomer();
+ const { business } = this.merchantData!;
+
+ return await this._removeCustomerCard(
+ auth_token,
+ business?.pk,
+ skyflowId,
+ );
+ } catch (error) {
+ throw formatPublicErrorResponse(
{
- headers: {
- Authorization: `Token ${this.publicApiKeyTonder}`,
- },
- signal: this.signal,
- }
+ message: MESSAGES.removeCardError,
+ },
+ error,
);
+ }
+ }
- if (getBusiness.ok) return (await getBusiness.json()) as Business;
+ public async getCustomerPaymentMethods(): Promise {
+ try {
+ const response = await this._fetchCustomerPaymentMethods();
- throw await buildErrorResponse(getBusiness);
- } catch (e) {
- throw buildErrorResponseFromCatch(e);
+ const apms_results =
+ response && "results" in response && response["results"].length > 0
+ ? response["results"]
+ : [];
+
+ return apms_results
+ .filter((apmItem) => apmItem.category.toLowerCase() !== "cards")
+ .map((apmItem) => {
+ const apm = {
+ id: apmItem.pk,
+ payment_method: apmItem.payment_method,
+ priority: apmItem.priority,
+ category: apmItem.category,
+ ...getPaymentMethodDetails(apmItem.payment_method),
+ };
+ return apm;
+ })
+ .sort((a, b) => a.priority - b.priority);
+ } catch (error) {
+ throw formatPublicErrorResponse(
+ {
+ message: MESSAGES.getPaymentMethodsError,
+ },
+ error,
+ );
}
}
- async verify3dsTransaction () {
- const result3ds = await this.process3ds.verifyTransactionStatus()
- const resultCheckout = await this.resumeCheckout(result3ds)
- this.process3ds.setPayload(resultCheckout)
- return this.handle3dsRedirect(resultCheckout)
+ public async getBusiness(): Promise {
+ try {
+ return await fetchBusiness(
+ this.baseUrl,
+ this.apiKeyTonder,
+ this.abortController.signal,
+ );
+ } catch (e) {
+ throw formatPublicErrorResponse(
+ {
+ message: MESSAGES.getBusinessError,
+ },
+ e,
+ );
+ }
}
- async resumeCheckout(response: any) {
- // Stop the routing process if the transaction is either hard declined or successful
- if (response?.decline?.error_type === "Hard") {
- return response
+ // TODO: DEPRECATED
+ async getOpenpayDeviceSessionID(
+ merchant_id: string,
+ public_key: string,
+ is_sandbox: boolean,
+ ): Promise {
+ try {
+ return await getOpenpayDeviceSessionID(
+ merchant_id,
+ public_key,
+ is_sandbox,
+ );
+ } catch (e) {
+ throw buildErrorResponseFromCatch(e);
}
+ }
- if (["Success", "Authorized"].includes(response?.transaction_status)) {
- return response;
- }
+ // TODO: DEPRECATED
+ async getSkyflowTokens({
+ vault_id,
+ vault_url,
+ data,
+ }: TokensRequest): Promise {
+ return await getSkyflowTokens({
+ vault_id: vault_id,
+ vault_url: vault_url,
+ data,
+ baseUrl: this.baseUrl,
+ apiKey: this.apiKeyTonder,
+ });
+ }
- if (response) {
- const routerItems = {
- checkout_id: response?.checkout?.id,
- };
- try {
- const routerResponse = await this.handleCheckoutRouter(
- routerItems
- );
- return routerResponse
- }catch (error){
- // throw error
- }
- return response
- }
+ _setCartTotal(total: string) {
+ this.cartTotal = total;
}
- 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
- // after some the tests in production, since the 3DS process
- // doesn't works properly on the sandbox environment
- // setTimeout(() => {
- // process3ds.verifyTransactionStatus();
- // }, 10000);
- this.process3ds.verifyTransactionStatus();
- }).catch((error: any) => {
- console.log('Error loading iframe:', error)
- })
- } else {
- const redirectUrl = this.process3ds.getRedirectUrl()
- if (redirectUrl) {
- this.process3ds.redirectToChallenge()
+ async _checkout({
+ card,
+ payment_method,
+ isSandbox,
+ // TODO: DEPRECATED
+ returnUrl: returnUrlData
+ }: {
+ card?: ICardFields | string;
+ payment_method?: string;
+ isSandbox?: boolean;
+ returnUrl?: string;
+ }) {
+ await this._fetchMerchantData();
+ const customer = await this._getCustomer(this.abortController.signal);
+ const { vault_id, vault_url } = this.merchantData!;
+ let skyflowTokens;
+ if (!payment_method || payment_method !== "" || payment_method === null) {
+ if (typeof card === "string") {
+ skyflowTokens = {
+ skyflow_id: card,
+ };
} else {
- return response;
+ skyflowTokens = await getSkyflowTokens({
+ vault_id: vault_id,
+ vault_url: vault_url,
+ data: { ...card, card_number: card!.card_number.replace(/\s+/g, "") },
+ baseUrl: this.baseUrl,
+ apiKey: this.apiKeyTonder,
+ });
}
}
+
+ return await this._handleCheckout({
+ card: skyflowTokens,
+ payment_method,
+ customer,
+ isSandbox,
+ returnUrl: returnUrlData
+ });
}
-
- async customerRegister(email: string): Promise {
+
+ // TODO: DEPRECATED
+ async customerRegister(
+ email: string,
+ ): Promise {
try {
- const url = `${this.baseUrlTonder}/api/v1/customer/`;
+ const url = `${this.baseUrl}/api/v1/customer/`;
const data = { email: email };
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
- Authorization: `Token ${this.publicApiKeyTonder}`,
+ Authorization: `Token ${this.apiKeyTonder}`,
},
- signal: this.signal,
+ signal: this.abortController.signal,
body: JSON.stringify(data),
});
- if (response.ok) return await response.json() as CustomerRegisterResponse;
+ if (response.ok)
+ return (await response.json()) as CustomerRegisterResponse;
throw await buildErrorResponse(response);
} catch (e) {
throw buildErrorResponseFromCatch(e);
}
}
- async createOrder(orderItems: CreateOrderRequest): Promise {
+ // TODO: DEPRECATED
+ async createOrder(
+ orderItems: CreateOrderRequest,
+ ): Promise {
try {
- const url = `${this.baseUrlTonder}/api/v1/orders/`;
+ const url = `${this.baseUrl}/api/v1/orders/`;
const data = orderItems;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
- Authorization: `Token ${this.publicApiKeyTonder}`,
+ Authorization: `Token ${this.apiKeyTonder}`,
},
body: JSON.stringify(data),
});
- if (response.ok) return await response.json() as CreateOrderResponse;
+ if (response.ok) return (await response.json()) as CreateOrderResponse;
throw await buildErrorResponse(response);
} catch (e) {
throw buildErrorResponseFromCatch(e);
}
}
- async createPayment(paymentItems: CreatePaymentRequest): Promise {
+ // TODO: DEPRECATED
+ async createPayment(
+ paymentItems: CreatePaymentRequest,
+ ): Promise {
try {
- const url = `${this.baseUrlTonder}/api/v1/business/${paymentItems.business_pk}/payments/`;
+ const url = `${this.baseUrl}/api/v1/business/${paymentItems.business_pk}/payments/`;
const data = paymentItems;
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
- Authorization: `Token ${this.publicApiKeyTonder}`,
+ Authorization: `Token ${this.apiKeyTonder}`,
},
body: JSON.stringify(data),
});
- if (response.ok) return await response.json() as CreatePaymentResponse;
+ if (response.ok) return (await response.json()) as CreatePaymentResponse;
throw await buildErrorResponse(response);
} catch (e) {
throw buildErrorResponseFromCatch(e);
}
}
- async handleCheckoutRouter(routerData: StartCheckoutRequest | StartCheckoutIdRequest){
- try {
- const url = `${this.baseUrlTonder}/api/v1/checkout-router/`;
- const data = routerData;
- const response = await fetch(url, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: `Token ${this.publicApiKeyTonder}`,
- },
- 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);
- } catch (e) {
- throw buildErrorResponseFromCatch(e);
- }
+
+ // TODO: DEPRECATED
+ async startCheckoutRouter(
+ routerData: StartCheckoutRequest | StartCheckoutIdRequest,
+ ): Promise {
+ const checkoutResult = await startCheckoutRouter(
+ this.baseUrl,
+ this.apiKeyTonder,
+ routerData,
+ );
+ const payload = await this.init3DSRedirect(checkoutResult);
+ if (payload) return checkoutResult;
}
- async startCheckoutRouter(routerData: StartCheckoutRequest | StartCheckoutIdRequest): Promise {
- const checkoutResult = await this.handleCheckoutRouter(routerData);
- const payload = await this.init3DSRedirect(checkoutResult)
- if(payload)
- return checkoutResult;
+ // TODO: DEPRECATED
+ async init3DSRedirect(checkoutResult: IStartCheckoutResponse) {
+ this.process3ds.setPayload(checkoutResult);
+ return await this._handle3dsRedirect(checkoutResult);
}
- async startCheckoutRouterFull(routerFullData: StartCheckoutFullRequest): Promise {
-
+ // TODO: DEPRECATED
+ async startCheckoutRouterFull(
+ routerFullData: StartCheckoutFullRequest,
+ ): Promise {
try {
-
- const {
- order,
- total,
- customer,
- skyflowTokens,
- return_url,
- isSandbox,
- metadata,
+ const {
+ order,
+ total,
+ customer,
+ skyflowTokens,
+ return_url,
+ isSandbox,
+ metadata,
currency,
- payment_method
+ payment_method,
} = routerFullData;
- const merchantResult = await this.getBusiness();
-
- const customerResult : CustomerRegisterResponse | ErrorResponse = await this.customerRegister(customer.email);
+ const merchantResult = await this._fetchMerchantData();
- if(customerResult && "auth_token" in customerResult && merchantResult && "reference" in merchantResult) {
+ const customerResult: CustomerRegisterResponse | ErrorResponse =
+ await this.customerRegister(customer.email);
+ if (
+ customerResult &&
+ "auth_token" in customerResult &&
+ merchantResult &&
+ "reference" in merchantResult
+ ) {
const orderData: CreateOrderRequest = {
- business: this.publicApiKeyTonder,
+ business: this.apiKeyTonder,
client: customerResult.auth_token,
billing_address_id: null,
shipping_address_id: null,
@@ -284,29 +392,30 @@ export class LiteCheckout implements LiteCheckoutConstructor {
const dateString = now.toISOString();
- if("id" in orderResult && "id" in customerResult && "business" in merchantResult) {
-
+ if (
+ "id" in orderResult &&
+ "id" in customerResult &&
+ "business" in merchantResult
+ ) {
const paymentItems: CreatePaymentRequest = {
business_pk: merchantResult.business.pk,
amount: total,
date: dateString,
order_id: orderResult.id,
- client_id: customerResult.id
+ client_id: customerResult.id,
};
- const paymentResult = await this.createPayment(
- paymentItems
- );
+ const paymentResult = await this.createPayment(paymentItems);
let deviceSessionIdTonder: any;
- const { openpay_keys, business } = merchantResult
+ const { openpay_keys, business } = merchantResult;
if (openpay_keys.merchant_id && openpay_keys.public_key) {
- deviceSessionIdTonder = await this.getOpenpayDeviceSessionID(
+ deviceSessionIdTonder = await getOpenpayDeviceSessionID(
openpay_keys.merchant_id,
openpay_keys.public_key,
- isSandbox
+ isSandbox,
);
}
@@ -323,192 +432,101 @@ export class LiteCheckout implements LiteCheckoutConstructor {
amount: total,
title_ship: "shipping",
description: "transaction",
- device_session_id: deviceSessionIdTonder ? deviceSessionIdTonder : null,
+ device_session_id: deviceSessionIdTonder
+ ? deviceSessionIdTonder
+ : null,
token_id: "",
- order_id: ("id" in orderResult) && orderResult.id,
+ order_id: "id" in orderResult && orderResult.id,
business_id: business.pk,
- payment_id: ("pk" in paymentResult) && paymentResult.pk,
- source: 'sdk',
+ payment_id: "pk" in paymentResult && paymentResult.pk,
+ source: "sdk",
metadata: metadata,
browser_info: getBrowserInfo(),
currency: currency,
- ...( !!payment_method
- ? {payment_method}
- : {card: skyflowTokens}
- ),
- ...(typeof MP_DEVICE_SESSION_ID !== "undefined" ? {mp_device_session_id: MP_DEVICE_SESSION_ID}:{})
+ ...(!!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);
- const payload = await this.init3DSRedirect(checkoutResult)
- if(payload)
- return checkoutResult;
+ const checkoutResult = await startCheckoutRouter(
+ this.baseUrl,
+ this.apiKeyTonder,
+ routerItems,
+ );
+ const payload = await this.init3DSRedirect(checkoutResult);
+ if (payload) return checkoutResult;
} else {
-
throw new ErrorResponse({
code: "500",
body: orderResult as any,
name: "Keys error",
- message: "Order response errors"
- } as IErrorResponse)
-
+ message: "Order response errors",
+ } as IErrorResponse);
}
-
} else {
-
throw new ErrorResponse({
code: "500",
body: merchantResult as any,
name: "Keys error",
- message: "Merchant or customer reposne errors"
- } as IErrorResponse)
-
+ message: "Merchant or customer reposne errors",
+ } as IErrorResponse);
}
} catch (e) {
-
throw buildErrorResponseFromCatch(e);
-
- }
- }
-
- async init3DSRedirect(checkoutResult: ErrorResponse | StartCheckoutResponse){
- this.process3ds.setPayload(checkoutResult)
- return await this.handle3dsRedirect(checkoutResult)
- }
-
- async getSkyflowTokens({
- vault_id,
- vault_url,
- data,
- }: TokensRequest): Promise {
- const skyflow = Skyflow.init({
- vaultID: vault_id,
- vaultURL: vault_url,
- getBearerToken: async () => await this.getVaultToken(),
- options: {
- logLevel: Skyflow.LogLevel.ERROR,
- env: Skyflow.Env.DEV,
- },
- });
-
- const collectContainer: CollectContainer = skyflow.container(
- Skyflow.ContainerType.COLLECT
- ) as CollectContainer;
-
- const fieldPromises = await this.getFieldsPromise(data, collectContainer);
-
- const result = await Promise.all(fieldPromises);
-
- const mountFail = result.some((item: boolean) => !item);
-
- if (mountFail) {
- throw buildErrorResponseFromCatch(Error("Ocurrió un error al montar los campos de la tarjeta"));
- } else {
- try {
- const collectResponseSkyflowTonder = await collectContainer.collect() as any;
- if (collectResponseSkyflowTonder) return collectResponseSkyflowTonder["records"][0]["fields"];
- throw buildErrorResponseFromCatch(Error("Por favor, verifica todos los campos de tu tarjeta"))
- } catch (error) {
- throw buildErrorResponseFromCatch(error);
- }
}
}
- async getVaultToken(): Promise {
+ // TODO: DEPRECATED
+ async registerCustomerCard(
+ secureToken: string,
+ customerToken: string,
+ data: RegisterCustomerCardRequest,
+ ): Promise {
try {
- const response = await fetch(`${this.baseUrlTonder}/api/v1/vault-token/`, {
- method: "GET",
- headers: {
- Authorization: `Token ${this.publicApiKeyTonder}`,
- },
- signal: this.signal,
- });
- if (response.ok) return (await response.json() as GetVaultTokenResponse)?.token;
- throw new Error(`HTTPCODE: ${response.status}`)
- } catch (e) {
- throw new Error(`Failed to retrieve bearer token; ${typeof e == "string" ? e : (e as Error).message}`)
- }
- }
-
- async getFieldsPromise(data: any, collectContainer: CollectContainer): Promise[]> {
- const fields = await this.getFields(data, collectContainer);
- if (!fields) return [];
-
- return fields.map((field: { element: CollectElement, key: string }) => {
- return new Promise((resolve) => {
- const div = document.createElement("div");
- div.hidden = true;
- div.id = `id-${field.key}`;
- document.querySelector(`body`)?.appendChild(div);
- setTimeout(() => {
- field.element.mount(`#id-${field.key}`);
- setInterval(() => {
- if (field.element.isMounted()) {
- const value = data[field.key];
- field.element.update({ value: value });
- return resolve(field.element.isMounted());
- }
- }, 120);
- }, 120);
- });
- })
- }
-
- async registerCustomerCard(secureToken: string, customerToken: string, data: RegisterCustomerCardRequest): Promise {
- try {
- await this.#fetchMerchantData()
-
- const response = await fetch(`${this.baseUrlTonder}/api/v1/business/${getBusinessId(this.merchantData)}/cards/`, {
- method: 'POST',
- headers: {
- 'Authorization': `Bearer ${secureToken}`,
- 'User-token': customerToken,
- 'Content-Type': 'application/json'
- },
- signal: this.signal,
- body: JSON.stringify({...data})
- });
-
- if (response.ok) return await response.json() as RegisterCustomerCardResponse;
- throw await buildErrorResponse(response);
- } catch (error) {
- throw buildErrorResponseFromCatch(error);
- }
- }
-
- async getCustomerCards(customerToken: string, bearerToken: string): Promise {
- try {
- await this.#fetchMerchantData()
+ await this._fetchMerchantData();
- const response = await fetch(`${this.baseUrlTonder}/api/v1/business/${getBusinessId(this.merchantData)}/cards`, {
- method: 'GET',
- headers: {
- 'Authorization': `Bearer ${bearerToken}`,
- 'User-Token': customerToken,
- 'Content-Type': 'application/json',
- 'Accept': 'application/json'
+ const response = await fetch(
+ `${this.baseUrl}/api/v1/business/${getBusinessId(this.merchantData)}/cards/`,
+ {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${secureToken}`,
+ "User-token": customerToken,
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({ ...data }),
},
- signal: this.signal,
- });
+ );
- if (response.ok) return await response.json() as GetCustomerCardsResponse;
+ if (response.ok)
+ return (await response.json()) as RegisterCustomerCardResponse;
throw await buildErrorResponse(response);
} catch (error) {
throw buildErrorResponseFromCatch(error);
}
}
- async deleteCustomerCard(customerToken: string, skyflowId: string = ""): Promise {
+ // TODO: DEPRECATED
+ async deleteCustomerCard(
+ customerToken: string,
+ skyflowId: string = "",
+ ): Promise {
try {
- await this.#fetchMerchantData()
- const response = await fetch(`${this.baseUrlTonder}/api/v1/business/${getBusinessId(this.merchantData)}/cards/${skyflowId}`, {
- method: 'DELETE',
- headers: {
- 'Authorization': `Token ${customerToken}`,
- 'Content-Type': 'application/json'
+ await this._fetchMerchantData();
+ const response = await fetch(
+ `${this.baseUrl}/api/v1/business/${getBusinessId(this.merchantData)}/cards/${skyflowId}`,
+ {
+ method: "DELETE",
+ headers: {
+ Authorization: `Token ${customerToken}`,
+ "Content-Type": "application/json",
+ },
+ signal: this.abortController.signal,
},
- signal: this.signal,
- });
+ );
if (response.ok) return true;
throw await buildErrorResponse(response);
@@ -517,38 +535,36 @@ export class LiteCheckout implements LiteCheckoutConstructor {
}
}
- private async getFields(data: any, collectContainer: CollectContainer): Promise<{ element: CollectElement, key: string }[]> {
- return await Promise.all(
- Object.keys(data).map(async (key) => {
- const cardHolderNameElement = await collectContainer.create({
- table: "cards",
- column: key,
- type: Skyflow.ElementType.INPUT_FIELD,
- });
- return { element: cardHolderNameElement, key: key };
- })
- )
- }
-
+ // TODO: DEPRECATED
async getActiveAPMs(): Promise {
try {
- const apms_response = await getCustomerAPMs(this.baseUrlTonder, this.publicApiKeyTonder);
- const apms_results = apms_response && apms_response['results'] && apms_response['results'].length > 0 ? apms_response['results'] : []
+ const apms_response = await getCustomerAPMs(
+ this.baseUrl,
+ this.apiKeyTonder,
+ );
+ const apms_results =
+ apms_response &&
+ apms_response["results"] &&
+ apms_response["results"].length > 0
+ ? apms_response["results"]
+ : [];
this.activeAPMs = apms_results
- .filter((apmItem: TonderAPM) =>
- apmItem.category.toLowerCase() !== 'cards')
+ .filter(
+ (apmItem: TonderAPM) => apmItem.category.toLowerCase() !== "cards",
+ )
.map((apmItem: TonderAPM) => {
const apm: APM = {
id: apmItem.pk,
payment_method: apmItem.payment_method,
priority: apmItem.priority,
category: apmItem.category,
- ...getPaymentMethodDetails(apmItem.payment_method,)
- }
+ ...getPaymentMethodDetails(apmItem.payment_method),
+ };
return apm;
- }).sort((a: APM, b: APM) => a.priority - b.priority);
+ })
+ .sort((a: APM, b: APM) => a.priority - b.priority);
- return this.activeAPMs
+ return this.activeAPMs;
} catch (e) {
console.error("Error getting APMS", e);
return [];
@@ -557,13 +573,13 @@ export class LiteCheckout implements LiteCheckoutConstructor {
async getSecureToken(token: string): Promise {
try {
- const response = await fetch(`${this.baseUrlTonder}/api/secure-token/`, {
+ const response = await fetch(`${this.baseUrl}/api/secure-token/`, {
method: 'POST',
headers: {
'Authorization': `Token ${token}`,
'Content-Type': 'application/json'
},
- signal: this.signal,
+ signal: this.abortController.signal
});
if (response.ok) return await response.json() as GetSecureTokenResponse;
diff --git a/src/data/businessApi.ts b/src/data/businessApi.ts
new file mode 100644
index 0000000..51e27f6
--- /dev/null
+++ b/src/data/businessApi.ts
@@ -0,0 +1,18 @@
+import {GetBusinessResponse} from "../types/responses";
+
+export async function fetchBusiness(
+ baseUrl: string,
+ apiKey: string,
+ signal: AbortSignal,
+): Promise {
+ const getBusiness = await fetch(
+ `${baseUrl}/api/v1/payments/business/${apiKey}`,
+ {
+ headers: {
+ Authorization: `Token ${apiKey}`,
+ },
+ signal: signal,
+ },
+ );
+ return await getBusiness.json();
+}
diff --git a/src/data/cardApi.ts b/src/data/cardApi.ts
new file mode 100644
index 0000000..813943e
--- /dev/null
+++ b/src/data/cardApi.ts
@@ -0,0 +1,87 @@
+import {
+ buildErrorResponse,
+ buildErrorResponseFromCatch,
+} from "../helpers/utils";
+import { MESSAGES } from "../shared/constants/messages";
+import {ICustomerCardsResponse, ISaveCardResponse, ISaveCardSkyflowRequest} from "../types/card";
+
+export async function fetchCustomerCards(
+ baseUrl: string,
+ customerToken: string,
+ businessId: string | number,
+ signal = null,
+): Promise {
+ try {
+ const url = `${baseUrl}/api/v1/business/${businessId}/cards/`;
+ const response = await fetch(url, {
+ method: "GET",
+ headers: {
+ Authorization: `Token ${customerToken}`,
+ "Content-Type": "application/json",
+ },
+ signal,
+ });
+ if (response.ok) return await response.json();
+ const res_json = await response.json();
+
+ throw await buildErrorResponse(response, res_json);
+ } catch (error) {
+ throw buildErrorResponseFromCatch(error);
+ }
+}
+
+export async function saveCustomerCard(
+ baseUrl: string,
+ secureToken: string,
+ customerToken: string,
+ businessId: string | number,
+ data: ISaveCardSkyflowRequest,
+): Promise {
+ try {
+ const url = `${baseUrl}/api/v1/business/${businessId}/cards/`;
+ const response = await fetch(url, {
+ method: "POST",
+ headers: {
+ Authorization: `Bearer ${secureToken}`,
+ "Content-Type": "application/json",
+ 'User-token': customerToken,
+ },
+ body: JSON.stringify(data),
+ });
+
+ if (response.ok) return await response.json();
+
+ const res_json = await response.json();
+
+ throw await buildErrorResponse(response, res_json);
+ } catch (error) {
+ throw buildErrorResponseFromCatch(error);
+ }
+}
+
+export async function removeCustomerCard(
+ baseUrl: string,
+ customerToken: string,
+ skyflowId = "",
+ businessId: string | number,
+): Promise {
+ try {
+ const url = `${baseUrl}/api/v1/business/${businessId}/cards/${skyflowId}`;
+
+ const response = await fetch(url, {
+ method: "DELETE",
+ headers: {
+ Authorization: `Token ${customerToken}`,
+ "Content-Type": "application/json",
+ },
+ });
+
+ if (response.status === 204) return MESSAGES.cardSaved;
+ if (response.ok && "json" in response) return await response.json();
+ const res_json = await response.json();
+
+ throw await buildErrorResponse(response, res_json);
+ } catch (error) {
+ throw buildErrorResponseFromCatch(error);
+ }
+}
diff --git a/src/data/checkoutApi.ts b/src/data/checkoutApi.ts
new file mode 100644
index 0000000..2688ba3
--- /dev/null
+++ b/src/data/checkoutApi.ts
@@ -0,0 +1,84 @@
+import {CreateOrderRequest, CreatePaymentRequest} from "../types/requests";
+import {IStartCheckoutIdRequest, IStartCheckoutRequest} from "../types/checkout";
+
+declare const MP_DEVICE_SESSION_ID: string | undefined;
+
+
+export async function createOrder(
+ baseUrl: string,
+ apiKey: string,
+ orderItems: CreateOrderRequest,
+) {
+ const url = `${baseUrl}/api/v1/orders/`;
+ const data = orderItems;
+ const response = await fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${apiKey}`,
+ },
+ body: JSON.stringify(data),
+ });
+ if (response.status === 201) {
+ return await response.json();
+ } else {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+}
+
+export async function createPayment(
+ baseUrl: string,
+ apiKey: string,
+ paymentItems: CreatePaymentRequest,
+) {
+ const url = `${baseUrl}/api/v1/business/${paymentItems.business_pk}/payments/`;
+ const data = paymentItems;
+ const response = await fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${apiKey}`,
+ },
+ body: JSON.stringify(data),
+ });
+ if (response.status >= 200 && response.status <= 299) {
+ return await response.json();
+ } else {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+}
+
+export async function startCheckoutRouter(
+ baseUrl: string,
+ apiKey: string,
+ routerItems: IStartCheckoutRequest | IStartCheckoutIdRequest,
+) {
+ try {
+ const url = `${baseUrl}/api/v1/checkout-router/`;
+ const data = routerItems;
+ const response = await fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${apiKey}`,
+ },
+ body: JSON.stringify({
+ ...data,
+ ...(typeof MP_DEVICE_SESSION_ID !== "undefined"
+ ? { mp_device_session_id: MP_DEVICE_SESSION_ID }
+ : {}),
+ }),
+ });
+ if (response.status >= 200 && response.status <= 299) {
+ return await response.json();
+ } else {
+ const errorResponse = await response.json();
+ const error = new Error("Failed to start checkout router");
+ // @ts-ignore
+ error.details = errorResponse;
+ throw error;
+ }
+ } catch (error) {
+ throw error;
+ }
+}
diff --git a/src/data/customerApi.ts b/src/data/customerApi.ts
new file mode 100644
index 0000000..fcb2b83
--- /dev/null
+++ b/src/data/customerApi.ts
@@ -0,0 +1,31 @@
+import {CustomerRegisterResponse} from "../types/responses";
+
+export async function registerOrFetchCustomer(
+ baseUrl: string,
+ apiKey: string,
+ customer: Record,
+ signal: AbortSignal | null = null,
+): Promise {
+ const url = `${baseUrl}/api/v1/customer/`;
+ const data = {
+ email: customer.email,
+ first_name: customer?.firstName,
+ last_name: customer?.lastName,
+ phone: customer?.phone,
+ };
+ const response = await fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${apiKey}`,
+ },
+ signal: signal,
+ body: JSON.stringify(data),
+ });
+
+ if (response.status === 201) {
+ return await response.json();
+ } else {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+}
diff --git a/src/data/openPayApi.ts b/src/data/openPayApi.ts
new file mode 100644
index 0000000..8d56e91
--- /dev/null
+++ b/src/data/openPayApi.ts
@@ -0,0 +1,12 @@
+export async function getOpenpayDeviceSessionID(
+ merchant_id: string,
+ public_key: string,
+ isSandbox: boolean = true,
+ signal: AbortSignal | null = null,
+): Promise {
+ let openpay = await window.OpenPay;
+ openpay.setId(merchant_id);
+ openpay.setApiKey(public_key);
+ openpay.setSandboxMode(isSandbox);
+ return await openpay.deviceData.setup({ signal });
+}
diff --git a/src/data/paymentMethodApi.ts b/src/data/paymentMethodApi.ts
new file mode 100644
index 0000000..52d5b36
--- /dev/null
+++ b/src/data/paymentMethodApi.ts
@@ -0,0 +1,37 @@
+import {
+ buildErrorResponse,
+ buildErrorResponseFromCatch,
+} from "../helpers/utils";
+import {IPaymentMethodResponse} from "../types/paymentMethod";
+
+export async function fetchCustomerPaymentMethods(
+ baseUrl: string,
+ apiKey: string,
+ params = {
+ status: "active",
+ pagesize: "10000",
+ },
+ signal = null,
+): Promise {
+ try {
+ const queryString = new URLSearchParams(params).toString();
+
+ const response = await fetch(
+ `${baseUrl}/api/v1/payment_methods?${queryString}`,
+ {
+ method: "GET",
+ headers: {
+ Authorization: `Token ${apiKey}`,
+ "Content-Type": "application/json",
+ },
+ signal,
+ },
+ );
+
+ if (response.ok) return await response.json();
+ const res_json = await response.json();
+ throw await buildErrorResponse(response, res_json);
+ } catch (error) {
+ throw buildErrorResponseFromCatch(error);
+ }
+}
diff --git a/src/data/skyflowApi.ts b/src/data/skyflowApi.ts
new file mode 100644
index 0000000..49256c0
--- /dev/null
+++ b/src/data/skyflowApi.ts
@@ -0,0 +1,20 @@
+export async function getVaultToken(
+ baseUrl: string,
+ apiKey: string,
+ signal = null,
+) {
+ const response = await fetch(`${baseUrl}/api/v1/vault-token/`, {
+ method: "GET",
+ headers: {
+ Authorization: `Token ${apiKey}`,
+ },
+ signal: signal,
+ });
+
+ if (response.ok) {
+ const responseBody = await response.json();
+ return responseBody.token;
+ } else {
+ throw new Error("Failed to retrieve bearer token");
+ }
+}
diff --git a/src/helpers/mercadopago.ts b/src/helpers/mercadopago.ts
index 34e6936..861ac9a 100644
--- a/src/helpers/mercadopago.ts
+++ b/src/helpers/mercadopago.ts
@@ -1,16 +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);
- }
+ 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);
+ }
}
\ No newline at end of file
diff --git a/src/helpers/skyflow.ts b/src/helpers/skyflow.ts
new file mode 100644
index 0000000..a50fbe2
--- /dev/null
+++ b/src/helpers/skyflow.ts
@@ -0,0 +1,91 @@
+import {ErrorResponse} from "../classes/errorResponse";
+import Skyflow from "skyflow-js";
+import CollectContainer from "skyflow-js/types/core/external/collect/collect-container";
+import {buildErrorResponseFromCatch} from "./utils";
+import CollectElement from "skyflow-js/types/core/external/collect/collect-element";
+import {getVaultToken} from "../data/skyflowApi";
+import {TokensSkyflowRequest} from "../types/requests";
+
+export async function getSkyflowTokens({
+ baseUrl,
+ apiKey,
+ vault_id,
+ vault_url,
+ data,
+}: TokensSkyflowRequest): Promise {
+ const skyflow = Skyflow.init({
+ vaultID: vault_id,
+ vaultURL: vault_url,
+ getBearerToken: async () => await getVaultToken(baseUrl, apiKey),
+ options: {
+ logLevel: Skyflow.LogLevel.ERROR,
+ env: Skyflow.Env.DEV,
+ },
+ });
+
+ const collectContainer: CollectContainer = skyflow.container(
+ Skyflow.ContainerType.COLLECT,
+ ) as CollectContainer;
+
+ const fieldPromises = await getFieldsPromise(data, collectContainer);
+
+ const result = await Promise.all(fieldPromises);
+
+ const mountFail = result.some((item: boolean) => !item);
+
+ if (mountFail) {
+ throw buildErrorResponseFromCatch(
+ Error("Ocurrió un error al montar los campos de la tarjeta"),
+ );
+ } else {
+ try {
+ const collectResponseSkyflowTonder =
+ (await collectContainer.collect()) as any;
+ if (collectResponseSkyflowTonder)
+ return collectResponseSkyflowTonder["records"][0]["fields"];
+ throw buildErrorResponseFromCatch(
+ Error("Por favor, verifica todos los campos de tu tarjeta"),
+ );
+ } catch (error) {
+ throw buildErrorResponseFromCatch(error);
+ }
+ }
+}
+
+async function getFieldsPromise(data: any, collectContainer: CollectContainer): Promise[]> {
+ const fields = await getFields(data, collectContainer);
+ if (!fields) return [];
+
+return fields.map((field: { element: CollectElement, key: string }) => {
+ return new Promise((resolve) => {
+ const div = document.createElement("div");
+ div.hidden = true;
+ div.id = `id-${field.key}`;
+ document.querySelector(`body`)?.appendChild(div);
+ setTimeout(() => {
+ field.element.mount(`#id-${field.key}`);
+ setInterval(() => {
+ if (field.element.isMounted()) {
+ const value = data[field.key];
+ field.element.update({ value: value });
+ return resolve(field.element.isMounted());
+ }
+ }, 120);
+ }, 120);
+ });
+})
+}
+
+async function getFields(data: any, collectContainer: CollectContainer): Promise<{ element: CollectElement, key: string }[]> {
+ return await Promise.all(
+ Object.keys(data).map(async (key) => {
+ const cardHolderNameElement = await collectContainer.create({
+ table: "cards",
+ column: key,
+ type: Skyflow.ElementType.INPUT_FIELD,
+ });
+ return { element: cardHolderNameElement, key: key };
+ })
+ )
+}
+
diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts
index b053b96..10b14b9 100644
--- a/src/helpers/utils.ts
+++ b/src/helpers/utils.ts
@@ -1,41 +1,47 @@
import { ErrorResponse } from "../classes/errorResponse";
-import { IErrorResponse } from "../types/responses";
-import { PAYMENT_METHOD } from "./constants";
+import {IErrorResponse} from "../types/responses";
export const getBrowserInfo = () => {
const browserInfo = {
- javascript_enabled: true, // Assumed since JavaScript is running
+ javascript_enabled: true, // Assumed since JavaScript is running
time_zone: new Date().getTimezoneOffset(),
- language: navigator.language || 'en-US', // Fallback to 'en-US'
+ language: navigator.language || "en-US", // Fallback to 'en-US'
color_depth: window.screen ? window.screen.colorDepth : null,
- screen_width: window.screen ? window.screen.width * window.devicePixelRatio || window.screen.width : null,
- screen_height: window.screen ? window.screen.height * window.devicePixelRatio || window.screen.height : null,
+ screen_width: window.screen
+ ? window.screen.width * window.devicePixelRatio || window.screen.width
+ : null,
+ screen_height: window.screen
+ ? window.screen.height * window.devicePixelRatio || window.screen.height
+ : null,
user_agent: navigator.userAgent,
};
return browserInfo;
-}
+};
-export const getBusinessId = (merchantData: any) =>{
- return merchantData && "business" in merchantData ? merchantData?.business?.pk:""
-}
+export const getBusinessId = (merchantData: any) => {
+ return merchantData && "business" in merchantData
+ ? merchantData?.business?.pk
+ : "";
+};
const buildErrorResponseFromCatch = (e: any): ErrorResponse => {
-
const error = new ErrorResponse({
code: e?.status ? e.status : e.code,
body: e?.body,
- name: e ? typeof e == "string" ? "catch" : (e as Error).name : "Error",
+ name: e ? (typeof e == "string" ? "catch" : (e as Error).name) : "Error",
message: e ? (typeof e == "string" ? e : (e as Error).message) : "Error",
stack: typeof e == "string" ? undefined : (e as Error).stack,
- })
+ });
return error;
-}
+};
const buildErrorResponse = async (
response: Response,
- stack: string | undefined = undefined
+ stack: string | undefined = undefined,
): Promise => {
- let body, status, message = "Error";
+ let body,
+ status,
+ message = "Error";
if (response && "json" in response) {
body = await response?.json();
@@ -49,8 +55,8 @@ const buildErrorResponse = async (
message = await response.text();
}
- if(body?.detail){
- message = body.detail
+ if (body?.detail) {
+ message = body.detail;
}
const error = new ErrorResponse({
code: status,
@@ -58,263 +64,57 @@ const buildErrorResponse = async (
name: status,
message: message,
stack,
- } as IErrorResponse)
+ } as IErrorResponse);
return error;
-}
-
-const getPaymentMethodDetails = (scheme_data: string): {icon: string; label: string} => {
- const scheme: PAYMENT_METHOD = clearSpace(scheme_data.toUpperCase()) as PAYMENT_METHOD;
-
- const PAYMENT_METHODS_CATALOG: Partial> = {
- [PAYMENT_METHOD.SORIANA]: {
- label: "Soriana",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/soriana.png",
- },
- [PAYMENT_METHOD.OXXO]: {
- label: "Oxxo",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/oxxo.png",
- },
- [PAYMENT_METHOD.CODI]: {
- label: "CoDi",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/codi.png",
- },
- [PAYMENT_METHOD.SPEI]: {
- label: "SPEI",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/spei.png",
- },
- [PAYMENT_METHOD.PAYPAL]: {
- label: "Paypal",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/paypal.png",
- },
- [PAYMENT_METHOD.COMERCIALMEXICANA]: {
- label: "Comercial Mexicana",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/comercial_exicana.png",
- },
- [PAYMENT_METHOD.BANCOMER]: {
- label: "Bancomer",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/bancomer.png",
- },
- [PAYMENT_METHOD.WALMART]: {
- label: "Walmart",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/walmart.png",
- },
- [PAYMENT_METHOD.BODEGA]: {
- label: "Bodega Aurrera",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/bodega_aurrera.png",
- },
- [PAYMENT_METHOD.SAMSCLUB]: {
- label: "Sam´s Club",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/sams_club.png",
- },
- [PAYMENT_METHOD.SUPERAMA]: {
- label: "Superama",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/superama.png",
- },
- [PAYMENT_METHOD.CALIMAX]: {
- label: "Calimax",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/calimax.png",
- },
- [PAYMENT_METHOD.EXTRA]: {
- label: "Tiendas Extra",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/tiendas_extra.png",
- },
- [PAYMENT_METHOD.CIRCULOK]: {
- label: "Círculo K",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/circulo_k.png",
- },
- [PAYMENT_METHOD.SEVEN11]: {
- label: "7 Eleven",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/7_eleven.png",
- },
- [PAYMENT_METHOD.TELECOMM]: {
- label: "Telecomm",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/telecomm.png",
- },
- [PAYMENT_METHOD.BANORTE]: {
- label: "Banorte",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/banorte.png",
- },
- [PAYMENT_METHOD.BENAVIDES]: {
- label: "Farmacias Benavides",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_benavides.png",
- },
- [PAYMENT_METHOD.DELAHORRO]: {
- label: "Farmacias del Ahorro",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_ahorro.png",
- },
- [PAYMENT_METHOD.ELASTURIANO]: {
- label: "El Asturiano",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/asturiano.png",
- },
- [PAYMENT_METHOD.WALDOS]: {
- label: "Waldos",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/waldos.png",
- },
- [PAYMENT_METHOD.ALSUPER]: {
- label: "Alsuper",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/al_super.png",
- },
- [PAYMENT_METHOD.KIOSKO]: {
- label: "Kiosko",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/kiosko.png",
- },
- [PAYMENT_METHOD.STAMARIA]: {
- label: "Farmacias Santa María",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_santa_maria.png",
- },
- [PAYMENT_METHOD.LAMASBARATA]: {
- label: "Farmacias la más barata",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_barata.png",
- },
- [PAYMENT_METHOD.FARMROMA]: {
- label: "Farmacias Roma",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_roma.png",
- },
- [PAYMENT_METHOD.FARMUNION]: {
- label: "Pago en Farmacias Unión",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_union.png",
- },
- [PAYMENT_METHOD.FARMATODO]: {
- label: "Pago en Farmacias Farmatodo",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_farmatodo.png ",
- },
- [PAYMENT_METHOD.SFDEASIS]: {
- label: "Pago en Farmacias San Francisco de Asís",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_san_francisco.png",
- },
- [PAYMENT_METHOD.FARM911]: {
- label: "Farmacias 911",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.FARMECONOMICAS]: {
- label: "Farmacias Economicas",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.FARMMEDICITY]: {
- label: "Farmacias Medicity",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.RIANXEIRA]: {
- label: "Rianxeira",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.WESTERNUNION]: {
- label: "Western Union",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.ZONAPAGO]: {
- label: "Zona Pago",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.CAJALOSANDES]: {
- label: "Caja Los Andes",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.CAJAPAITA]: {
- label: "Caja Paita",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.CAJASANTA]: {
- label: "Caja Santa",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.CAJASULLANA]: {
- label: "Caja Sullana",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.CAJATRUJILLO]: {
- label: "Caja Trujillo",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.EDPYME]: {
- label: "Edpyme",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.KASNET]: {
- label: "KasNet",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.NORANDINO]: {
- label: "Norandino",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.QAPAQ]: {
- label: "Qapaq",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.RAIZ]: {
- label: "Raiz",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.PAYSER]: {
- label: "Paysera",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.WUNION]: {
- label: "Western Union",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.BANCOCONTINENTAL]: {
- label: "Banco Continental",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.GMONEY]: {
- label: "Go money",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.GOPAY]: {
- label: "Go pay",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.WU]: {
- label: "Western Union",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.PUNTOSHEY]: {
- label: "Puntoshey",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.AMPM]: {
- label: "Ampm",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.JUMBOMARKET]: {
- label: "Jumbomarket",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.SMELPUEBLO]: {
- label: "Smelpueblo",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.BAM]: {
- label: "Bam",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.REFACIL]: {
- label: "Refacil",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
- [PAYMENT_METHOD.ACYVALORES]: {
- label: "Acyvalores",
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- },
+};
+
+function formatPublicErrorResponse(data: Record, error: any) {
+ let code = 200;
+ try {
+ code = Number(error?.code || 200);
+ } catch {}
+
+ const default_res = {
+ status: "error",
+ code,
+ message: "",
+ detail:
+ error?.body?.detail ||
+ error?.body?.error ||
+ error.body ||
+ "Ocurrio un error inesperado.",
};
- const _default = {
- icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
- label: ""
+ return {
+ ...default_res,
+ ...data,
};
-
- return PAYMENT_METHODS_CATALOG[scheme] || _default;
}
const clearSpace = (text: string) => {
- return text.trim().replace(/\s+/g, '');
-}
+ return text.trim().replace(/\s+/g, "");
+};
+
+const getCardType = (scheme: string) => {
+ if (scheme === "Visa") {
+ // Check if visa
+ return "https://d35a75syrgujp0.cloudfront.net/cards/visa.png";
+ } else if (scheme === "Mastercard") {
+ // Check if master
+ return "https://d35a75syrgujp0.cloudfront.net/cards/mastercard.png";
+ } else if (scheme === "American Express") {
+ // Check if amex
+ return "https://d35a75syrgujp0.cloudfront.net/cards/american_express.png";
+ } else {
+ return "https://d35a75syrgujp0.cloudfront.net/cards/default_card.png";
+ }
+};
export {
buildErrorResponseFromCatch,
buildErrorResponse,
- getPaymentMethodDetails
-}
\ No newline at end of file
+ getCardType,
+ formatPublicErrorResponse,
+ clearSpace,
+};
diff --git a/src/helpers/validations.ts b/src/helpers/validations.ts
new file mode 100644
index 0000000..06045b2
--- /dev/null
+++ b/src/helpers/validations.ts
@@ -0,0 +1,55 @@
+export function validateCardNumber(cardNumber: string) {
+ const regex = /^\d{12,19}$/;
+ return regex.test(cardNumber) && luhnCheck(cardNumber);
+}
+
+export function validateCardholderName(name: string) {
+ const regex = /^([a-zA-Z\\ \\,\\.\\-\\']{2,})$/;
+ return regex.test(name);
+}
+
+export function validateCVV(cvv: string) {
+ const regex = /^\d{3,4}$/;
+ return regex.test(cvv);
+}
+
+export function validateExpirationDate(expirationDate: string) {
+ const regex = /^(0[1-9]|1[0-2])\/\d{2}$/;
+ if (!regex.test(expirationDate)) {
+ return false;
+ }
+ const [month, year] = expirationDate.split("/");
+ const currentDate = new Date();
+ // @ts-ignore
+ const expiration = new Date(`20${year}`, month - 1);
+ return expiration >= currentDate;
+}
+
+export function validateExpirationMonth(month: string) {
+ const regex = /^(0[1-9]|1[0-2])$/;
+ return regex.test(month);
+}
+
+export function validateExpirationYear(year: string) {
+ const regex = /^\d{2}$/;
+ if (!regex.test(year)) {
+ return false;
+ }
+ const currentYear = new Date().getFullYear() % 100;
+ return parseInt(year, 10) >= currentYear;
+}
+
+const luhnCheck = (num: number | string) => {
+ const arr = `${num}`
+ .split("")
+ .reverse()
+ .map((x) => Number.parseInt(x));
+ const lastDigit = arr.shift();
+ let sum = arr.reduce(
+ (acc, val, i) =>
+ i % 2 !== 0 ? acc + val : acc + ((val *= 2) > 9 ? val - 9 : val),
+ 0,
+ );
+ sum += lastDigit!;
+ return sum % 10 === 0;
+};
diff --git a/src/index.ts b/src/index.ts
index 5e1ac78..64cf8e5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,13 @@
import { LiteCheckout } from './classes/liteCheckout'
+import { BaseInlineCheckout } from './classes/BaseInlineCheckout'
+import { validateCVV, validateCardNumber, validateExpirationMonth, validateCardholderName, validateExpirationYear } from './helpers/validations'
export {
- LiteCheckout
+ LiteCheckout,
+ BaseInlineCheckout,
+ validateCVV,
+ validateCardNumber,
+ validateCardholderName,
+ validateExpirationMonth,
+ validateExpirationYear
}
\ No newline at end of file
diff --git a/src/shared/catalog/paymentMethodsCatalog.ts b/src/shared/catalog/paymentMethodsCatalog.ts
new file mode 100644
index 0000000..24dd14f
--- /dev/null
+++ b/src/shared/catalog/paymentMethodsCatalog.ts
@@ -0,0 +1,248 @@
+import {clearSpace} from "../../helpers/utils";
+import {PAYMENT_METHOD_APM} from "../constants/paymentMethodAPM";
+
+const PAYMENT_METHODS_CATALOG = {
+ [PAYMENT_METHOD_APM.SORIANA]: {
+ label: "Soriana",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/soriana.png",
+ },
+ [PAYMENT_METHOD_APM.OXXO]: {
+ label: "Oxxo",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/oxxo.png",
+ },
+ [PAYMENT_METHOD_APM.CODI]: {
+ label: "CoDi",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/codi.png",
+ },
+ [PAYMENT_METHOD_APM.SPEI]: {
+ label: "SPEI",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/spei.png",
+ },
+ [PAYMENT_METHOD_APM.PAYPAL]: {
+ label: "Paypal",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/paypal.png",
+ },
+ [PAYMENT_METHOD_APM.COMERCIALMEXICANA]: {
+ label: "Comercial Mexicana",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/comercial_exicana.png",
+ },
+ [PAYMENT_METHOD_APM.BANCOMER]: {
+ label: "Bancomer",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/bancomer.png",
+ },
+ [PAYMENT_METHOD_APM.WALMART]: {
+ label: "Walmart",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/walmart.png",
+ },
+ [PAYMENT_METHOD_APM.BODEGA]: {
+ label: "Bodega Aurrera",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/bodega_aurrera.png",
+ },
+ [PAYMENT_METHOD_APM.SAMSCLUB]: {
+ label: "Sam´s Club",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/sams_club.png",
+ },
+ [PAYMENT_METHOD_APM.SUPERAMA]: {
+ label: "Superama",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/superama.png",
+ },
+ [PAYMENT_METHOD_APM.CALIMAX]: {
+ label: "Calimax",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/calimax.png",
+ },
+ [PAYMENT_METHOD_APM.EXTRA]: {
+ label: "Tiendas Extra",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/tiendas_extra.png",
+ },
+ [PAYMENT_METHOD_APM.CIRCULOK]: {
+ label: "Círculo K",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/circulo_k.png",
+ },
+ [PAYMENT_METHOD_APM.SEVEN11]: {
+ label: "7 Eleven",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/7_eleven.png",
+ },
+ [PAYMENT_METHOD_APM.TELECOMM]: {
+ label: "Telecomm",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/telecomm.png",
+ },
+ [PAYMENT_METHOD_APM.BANORTE]: {
+ label: "Banorte",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/banorte.png",
+ },
+ [PAYMENT_METHOD_APM.BENAVIDES]: {
+ label: "Farmacias Benavides",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_benavides.png",
+ },
+ [PAYMENT_METHOD_APM.DELAHORRO]: {
+ label: "Farmacias del Ahorro",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_ahorro.png",
+ },
+ [PAYMENT_METHOD_APM.ELASTURIANO]: {
+ label: "El Asturiano",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/asturiano.png",
+ },
+ [PAYMENT_METHOD_APM.WALDOS]: {
+ label: "Waldos",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/waldos.png",
+ },
+ [PAYMENT_METHOD_APM.ALSUPER]: {
+ label: "Alsuper",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/al_super.png",
+ },
+ [PAYMENT_METHOD_APM.KIOSKO]: {
+ label: "Kiosko",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/kiosko.png",
+ },
+ [PAYMENT_METHOD_APM.STAMARIA]: {
+ label: "Farmacias Santa María",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_santa_maria.png",
+ },
+ [PAYMENT_METHOD_APM.LAMASBARATA]: {
+ label: "Farmacias la más barata",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_barata.png",
+ },
+ [PAYMENT_METHOD_APM.FARMROMA]: {
+ label: "Farmacias Roma",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_roma.png",
+ },
+ [PAYMENT_METHOD_APM.FARMUNION]: {
+ label: "Pago en Farmacias Unión",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_union.png",
+ },
+ [PAYMENT_METHOD_APM.FARMATODO]: {
+ label: "Pago en Farmacias Farmatodo",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_farmatodo.png ",
+ },
+ [PAYMENT_METHOD_APM.SFDEASIS]: {
+ label: "Pago en Farmacias San Francisco de Asís",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/farmacias_san_francisco.png",
+ },
+ [PAYMENT_METHOD_APM.FARM911]: {
+ label: "Farmacias 911",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.FARMECONOMICAS]: {
+ label: "Farmacias Economicas",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.FARMMEDICITY]: {
+ label: "Farmacias Medicity",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.RIANXEIRA]: {
+ label: "Rianxeira",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.WESTERNUNION]: {
+ label: "Western Union",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.ZONAPAGO]: {
+ label: "Zona Pago",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.CAJALOSANDES]: {
+ label: "Caja Los Andes",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.CAJAPAITA]: {
+ label: "Caja Paita",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.CAJASANTA]: {
+ label: "Caja Santa",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.CAJASULLANA]: {
+ label: "Caja Sullana",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.CAJATRUJILLO]: {
+ label: "Caja Trujillo",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.EDPYME]: {
+ label: "Edpyme",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.KASNET]: {
+ label: "KasNet",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.NORANDINO]: {
+ label: "Norandino",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.QAPAQ]: {
+ label: "Qapaq",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.RAIZ]: {
+ label: "Raiz",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.PAYSER]: {
+ label: "Paysera",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.WUNION]: {
+ label: "Western Union",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.BANCOCONTINENTAL]: {
+ label: "Banco Continental",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.GMONEY]: {
+ label: "Go money",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.GOPAY]: {
+ label: "Go pay",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.WU]: {
+ label: "Western Union",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.PUNTOSHEY]: {
+ label: "Puntoshey",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.AMPM]: {
+ label: "Ampm",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.JUMBOMARKET]: {
+ label: "Jumbomarket",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.SMELPUEBLO]: {
+ label: "Smelpueblo",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.BAM]: {
+ label: "Bam",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.REFACIL]: {
+ label: "Refacil",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+ [PAYMENT_METHOD_APM.ACYVALORES]: {
+ label: "Acyvalores",
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ },
+};
+
+
+export const getPaymentMethodDetails = (scheme_data: string) => {
+ const scheme: string = clearSpace(scheme_data.toUpperCase());
+ const _default = {
+ icon: "https://d35a75syrgujp0.cloudfront.net/payment_methods/store.png",
+ label: "",
+ };
+ // @ts-ignore
+ return PAYMENT_METHODS_CATALOG[scheme] || _default;
+};
\ No newline at end of file
diff --git a/src/shared/constants/messages.ts b/src/shared/constants/messages.ts
new file mode 100644
index 0000000..013ca32
--- /dev/null
+++ b/src/shared/constants/messages.ts
@@ -0,0 +1,11 @@
+export const MESSAGES = Object.freeze({
+ saveCardError: "Ha ocurrido un error guardando la tarjeta. Inténtalo nuevamente.",
+ removeCardError: "Ha ocurrido un error eliminado la tarjeta. Inténtalo nuevamente.",
+ getCardsError: "Ha ocurrido un error obteniendo las tarjetas del customer. Inténtalo nuevamente.",
+ cardExist: "La tarjeta fue registrada previamente.",
+ removedCard: "Card deleted successfully",
+ 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."
+})
\ No newline at end of file
diff --git a/src/shared/constants/paymentMethodAPM.ts b/src/shared/constants/paymentMethodAPM.ts
new file mode 100644
index 0000000..fe21505
--- /dev/null
+++ b/src/shared/constants/paymentMethodAPM.ts
@@ -0,0 +1,63 @@
+const PAYMENT_METHOD_APM = Object.freeze({
+ SORIANA: "SORIANA",
+ OXXO: "OXXO",
+ SPEI: "SPEI",
+ CODI: "CODI",
+ MERCADOPAGO: "MERCADOPAGO",
+ PAYPAL: "PAYPAL",
+ COMERCIALMEXICANA: "COMERCIALMEXICANA",
+ BANCOMER: "BANCOMER",
+ WALMART: "WALMART",
+ BODEGA: "BODEGA",
+ SAMSCLUB: "SAMSCLUB",
+ SUPERAMA: "SUPERAMA",
+ CALIMAX: "CALIMAX",
+ EXTRA: "EXTRA",
+ CIRCULOK: "CIRCULOK",
+ SEVEN11: "7ELEVEN",
+ TELECOMM: "TELECOMM",
+ BANORTE: "BANORTE",
+ BENAVIDES: "BENAVIDES",
+ DELAHORRO: "DELAHORRO",
+ ELASTURIANO: "ELASTURIANO",
+ WALDOS: "WALDOS",
+ ALSUPER: "ALSUPER",
+ KIOSKO: "KIOSKO",
+ STAMARIA: "STAMARIA",
+ LAMASBARATA: "LAMASBARATA",
+ FARMROMA: "FARMROMA",
+ FARMUNION: "FARMUNION",
+ FARMATODO: "FARMATODO",
+ SFDEASIS: "SFDEASIS",
+ FARM911: "FARM911",
+ FARMECONOMICAS: "FARMECONOMICAS",
+ FARMMEDICITY: "FARMMEDICITY",
+ RIANXEIRA: "RIANXEIRA",
+ WESTERNUNION: "WESTERNUNION",
+ ZONAPAGO: "ZONAPAGO",
+ CAJALOSANDES: "CAJALOSANDES",
+ CAJAPAITA: "CAJAPAITA",
+ CAJASANTA: "CAJASANTA",
+ CAJASULLANA: "CAJASULLANA",
+ CAJATRUJILLO: "CAJATRUJILLO",
+ EDPYME: "EDPYME",
+ KASNET: "KASNET",
+ NORANDINO: "NORANDINO",
+ QAPAQ: "QAPAQ",
+ RAIZ: "RAIZ",
+ PAYSER: "PAYSER",
+ WUNION: "WUNION",
+ BANCOCONTINENTAL: "BANCOCONTINENTAL",
+ GMONEY: "GMONEY",
+ GOPAY: "GOPAY",
+ WU: "WU",
+ PUNTOSHEY: "PUNTOSHEY",
+ AMPM: "AMPM",
+ JUMBOMARKET: "JUMBOMARKET",
+ SMELPUEBLO: "SMELPUEBLO",
+ BAM: "BAM",
+ REFACIL: "REFACIL",
+ ACYVALORES: "ACYVALORES",
+});
+
+export { PAYMENT_METHOD_APM };
diff --git a/src/shared/constants/tonderUrl.ts b/src/shared/constants/tonderUrl.ts
new file mode 100644
index 0000000..3d0095a
--- /dev/null
+++ b/src/shared/constants/tonderUrl.ts
@@ -0,0 +1,8 @@
+const TONDER_URL_BY_MODE = Object.freeze({
+ production: "https://app.tonder.io",
+ sandbox: "https://sandbox.tonder.io",
+ stage: "https://stage.tonder.io",
+ development: "http://localhost:8000",
+});
+
+export { TONDER_URL_BY_MODE };
diff --git a/src/types/card.ts b/src/types/card.ts
new file mode 100644
index 0000000..8a3b2e7
--- /dev/null
+++ b/src/types/card.ts
@@ -0,0 +1,35 @@
+export interface ICard {
+ fields: ICardSkyflowFields;
+ icon?: string;
+}
+
+export interface ICardSkyflowFields {
+ card_number: string;
+ expiration_month: string;
+ expiration_year: string;
+ skyflow_id: string;
+ card_scheme: string;
+ cardholder_name: string;
+}
+
+export interface ICustomerCardsResponse {
+ user_id: number;
+ cards: ICard[];
+}
+
+export interface ISaveCardResponse {
+ skyflow_id: string;
+ user_id: number;
+}
+
+export interface ISaveCardSkyflowRequest {
+ skyflow_id: string;
+}
+
+export interface ISaveCardRequest {
+ card_number: string;
+ cvv: string;
+ expiration_month: string;
+ expiration_year: string;
+ cardholder_name: string;
+}
diff --git a/src/types/checkout.ts b/src/types/checkout.ts
new file mode 100644
index 0000000..2cd02f2
--- /dev/null
+++ b/src/types/checkout.ts
@@ -0,0 +1,124 @@
+import {ICustomer} from "./customer";
+
+export interface IStartCheckoutRequestBase {
+ name: any;
+ last_name: string;
+ email_client: any;
+ phone_number: any;
+ return_url?: string;
+ id_product: string;
+ quantity_product: number;
+ id_ship: string;
+ instance_id_ship: string;
+ amount: any;
+ title_ship: string;
+ description: string;
+ device_session_id: any;
+ token_id: string;
+ order_id: any;
+ business_id: any;
+ payment_id: any;
+ source: string;
+ browser_info?: any;
+ metadata: any;
+ currency: string;
+}
+
+export type IStartCheckoutRequestWithCard = IStartCheckoutRequestBase & {
+ card: any;
+ payment_method?: never;
+};
+
+export type IStartCheckoutRequestWithPaymentMethod =
+ IStartCheckoutRequestBase & {
+ card?: never;
+ payment_method: string;
+};
+
+export type IStartCheckoutRequest =
+ | IStartCheckoutRequestWithCard
+ | IStartCheckoutRequestWithPaymentMethod;
+
+export interface IStartCheckoutIdRequest {
+ checkout_id: string;
+}
+
+export interface IStartCheckoutErrorResponse {
+ status: string;
+ message: string;
+ psp_response: [
+ {
+ status: number;
+ response: Object;
+ },
+ ];
+ checkout_id: string;
+ is_route_finished: boolean;
+}
+
+export interface IStartCheckoutResponse {
+ status: string;
+ message: string;
+ psp_response: Record;
+ checkout_id: string;
+ is_route_finished: Boolean;
+ transaction_status: string;
+ transaction_id: number;
+ payment_id: number;
+ provider: string;
+ next_action: {
+ redirect_to_url?: {
+ url: string;
+ return_url: string;
+ verify_transaction_status_url: string;
+ };
+ iframe_resources?: {
+ iframe: string;
+ };
+ };
+ actions: IStartCheckoutActionResponse[];
+}
+
+export interface IStartCheckoutActionResponse {
+ name: string;
+ url: string;
+ method: string;
+}
+
+
+export interface IItem {
+ description: string;
+ quantity: number;
+ price_unit: number;
+ discount: number;
+ taxes: number;
+ product_reference: string | number;
+ name: string;
+ amount_total: number;
+}
+
+export interface IProcessPaymentRequest {
+ customer: ICustomer;
+ cart: {
+ total: string | number;
+ items: IItem[];
+ };
+ metadata?: Record;
+ currency?: string;
+ payment_method?: string;
+ card?: ICardFields | string;
+ isSandbox?: boolean;
+ /**
+ * @deprecated This property is deprecated and will be removed in a future release.
+ * Use the `returnUrl` field when creating the instance of LiteCheckout or InlineCheckout.
+ */
+ returnUrl?: string;
+}
+
+export interface ICardFields {
+ card_number: string;
+ cvv: string;
+ expiration_month: string;
+ expiration_year: string;
+ cardholder_name: string;
+}
\ No newline at end of file
diff --git a/src/types/commons.ts b/src/types/commons.ts
index e1bee9a..ea6df15 100644
--- a/src/types/commons.ts
+++ b/src/types/commons.ts
@@ -1,83 +1,131 @@
+import { ICustomer } from "./customer";
+import {IStartCheckoutResponse} from "./checkout";
+
export type Business = {
- business: {
- pk: number;
- name: string;
- categories: {
- pk: number;
- name: string;
- }[];
- web: string;
- logo: string;
- full_logo_url: string;
- background_color: string;
- primary_color: string;
- checkout_mode: boolean;
- textCheckoutColor: string;
- textDetailsColor: string;
- checkout_logo: string;
- };
- openpay_keys: {
- merchant_id: string;
- public_key: string;
- };
- fintoc_keys: {
- public_key: string;
- };
- mercado_pago: {
- active: boolean;
- };
- vault_id: string;
- vault_url: string;
- reference: number;
- is_installments_available: boolean;
+ business: {
+ pk: number;
+ name: string;
+ categories: {
+ pk: number;
+ name: string;
+ }[];
+ web: string;
+ logo: string;
+ full_logo_url: string;
+ background_color: string;
+ primary_color: string;
+ checkout_mode: boolean;
+ textCheckoutColor: string;
+ textDetailsColor: string;
+ checkout_logo: string;
+ };
+ openpay_keys: {
+ merchant_id: string;
+ public_key: string;
+ };
+ fintoc_keys: {
+ public_key: string;
+ };
+ mercado_pago: {
+ active: boolean;
+ };
+ vault_id: string;
+ vault_url: string;
+ reference: number;
+ is_installments_available: boolean;
};
export type Customer = {
- firstName: string;
- lastName: string;
- country: string;
- street: string;
- city: string;
- state: string;
- postCode: string;
- email: string;
- phone: string;
+ firstName: string;
+ lastName: string;
+ country: string;
+ street: string;
+ city: string;
+ state: string;
+ postCode: string;
+ email: string;
+ phone: string;
};
export type OrderItem = {
- description: string;
- quantity: number;
- price_unit: number;
- discount: number;
- taxes: number;
- product_reference: number;
- name: string;
- amount_total: number;
+ description: string;
+ quantity: number;
+ price_unit: number;
+ discount: number;
+ taxes: number;
+ product_reference: number;
+ name: string;
+ amount_total: number;
};
export type PaymentData = {
- customer: Customer;
- currency: string;
- cart: {
- total: string | number;
- items: OrderItem[];
- };
+ customer: Customer;
+ currency: string;
+ cart: {
+ total: string | number;
+ items: OrderItem[];
+ };
};
export type TonderAPM = {
- pk: string;
- payment_method: string;
- priority: number;
- category: string;
- unavailable_countries: string[];
- status: string;
-}
+ pk: string;
+ payment_method: string;
+ priority: number;
+ category: string;
+ unavailable_countries: string[];
+ status: string;
+};
export type APM = {
- id: string;
- payment_method: string;
- priority: number;
- category: string;
- icon: string;
- label: string;
+ id: string;
+ payment_method: string;
+ priority: number;
+ category: string;
+ icon: string;
+ label: string;
+};
+
+export interface IConfigureCheckout {
+ customer: ICustomer | { email: string };
+ secureToken: string
+}
+
+export interface IInlineCheckoutBaseOptions {
+ mode?: "production" | "sandbox" | "stage" | "development";
+ /**
+ * @deprecated This property is deprecated and will be removed in a future release.
+ * `baseUrlTonder` is no longer required.
+ */
+ baseUrlTonder?: string;
+ /**
+ * @deprecated This property is deprecated and will be removed in a future release.
+ * Use `apiKey` instead, as `apiKeyTonder` is no longer required.
+ */
+ apiKeyTonder?: string;
+ /**
+ * @deprecated This property is deprecated and will be removed in a future release.
+ * `signal` is no longer required.
+ */
+ signal?: AbortSignal;
+ apiKey: string;
+ returnUrl?: string;
+ callBack?: (response: IStartCheckoutResponse | Record) => void;
+}
+
+export interface IInlineLiteCheckoutOptions
+ extends IInlineCheckoutBaseOptions {}
+
+
+export interface IApiError {
+ code: string;
+ body: Record | string;
+ name: string;
+ message: string;
+}
+
+export interface IPublicError {
+ status: string;
+ code: number;
+ message: string;
+ detail: Record | string;
}
diff --git a/src/types/customer.ts b/src/types/customer.ts
new file mode 100644
index 0000000..b55a966
--- /dev/null
+++ b/src/types/customer.ts
@@ -0,0 +1,22 @@
+export type ICustomer = {
+ /**
+ * @deprecated This property is deprecated and will be removed in a future release.
+ * Use `firstName` instead, as `name` is no longer required.
+ */
+ name?: string;
+ /**
+ * @deprecated This property is deprecated and will be removed in a future release.
+ * Use `lastName` instead, as `lastname` is no longer required.
+ */
+ lastname?: string;
+ firstName: string;
+ lastName: string;
+ country?: string;
+ street?: string;
+ city?: string;
+ state?: string;
+ postCode?: string;
+ email: string;
+ phone?: string;
+ address?: string;
+};
diff --git a/src/types/liteInlineCheckout.ts b/src/types/liteInlineCheckout.ts
new file mode 100644
index 0000000..058280f
--- /dev/null
+++ b/src/types/liteInlineCheckout.ts
@@ -0,0 +1,216 @@
+import { IConfigureCheckout, IInlineCheckoutBaseOptions } from "./commons";
+import {
+ ICustomerCardsResponse,
+ ISaveCardRequest,
+ ISaveCardResponse,
+} from "./card";
+import { IPaymentMethod } from "./paymentMethod";
+import { IProcessPaymentRequest, IStartCheckoutResponse } from "./checkout";
+import { ITransaction } from "./transaction";
+import { APM } from "./commons";
+import { ErrorResponse } from "../classes/errorResponse";
+import {
+ CreateOrderRequest,
+ CreatePaymentRequest,
+ RegisterCustomerCardRequest,
+ StartCheckoutFullRequest,
+ StartCheckoutIdRequest,
+ StartCheckoutRequest,
+ TokensRequest,
+} from "./requests";
+import {
+ CreateOrderResponse,
+ CreatePaymentResponse,
+ CustomerRegisterResponse,
+ GetBusinessResponse,
+ RegisterCustomerCardResponse,
+ StartCheckoutResponse,
+} from "./responses";
+
+export interface ILiteCheckout {
+
+ /**
+ * 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.
+ * @param {import("./index").IConfigureCheckout} data - Configuration data including customer information and potentially other settings.
+ * @returns {Promise}.
+ * @public
+ */
+ configureCheckout(data: IConfigureCheckout): void;
+
+ /**
+ * Initializes and prepares the checkout for use.
+ * This method set up the initial environment.
+ * @returns {Promise} A promise that resolves when the checkout has been initialized.
+ * @throws {Error} If there's any problem during the checkout initialization.
+ * @public
+ */
+ injectCheckout(): Promise;
+
+ /**
+ * Processes a payment.
+ * @param {import("./index").IProcessPaymentRequest} data - Payment data including customer, cart, and other relevant information.
+ * @returns {Promise} A promise that resolves with the payment response or 3DS redirect or is rejected with an error.
+ *
+ * @throws {Error} Throws an error if the checkout process fails. The error object contains
+ * additional `details` property with the response from the server if available.
+ * @property {import("./index").IStartCheckoutErrorResponse} error.details - The response body from the server when an error occurs.
+ *
+ * @public
+ */
+ payment(data: IProcessPaymentRequest): Promise;
+
+ /**
+ * Verifies the 3DS transaction status.
+ * @returns {Promise} The result of the 3DS verification and checkout resumption.
+ * @public
+ */
+ verify3dsTransaction(): Promise;
+
+ /**
+ * Retrieves the list of cards associated with a customer.
+ * @returns {Promise} A promise that resolves with the customer's card data.
+ *
+ * @throws {import("./index").IPublicError} Throws an error object if the operation fails.
+ *
+ * @public
+ */
+ getCustomerCards(): Promise;
+
+ /**
+ * Saves a card to a customer's account. This method can be used to add a new card
+ * or update an existing one.
+ * @param {import("./index").ISaveCardRequest} card - The card information to be saved.
+ * @returns {Promise} A promise that resolves with the saved card data.
+ *
+ * @throws {import("./index").IPublicError} Throws an error object if the operation fails.
+ *
+ * @public
+ */
+ saveCustomerCard(secureToken: string, card: ISaveCardRequest): Promise;
+
+ /**
+ * Removes a card from a customer's account.
+ * @param {string} skyflowId - The unique identifier of the card to be deleted.
+ * @returns {Promise} A promise that resolves when the card is successfully deleted.
+ *
+ * @throws {import("./index").IPublicError} Throws an error object if the operation fails.
+ *
+ * @public
+ */
+ removeCustomerCard(skyflowId: string): Promise;
+
+ /**
+ * Retrieves the list of available Alternative Payment Methods (APMs).
+ * @returns {Promise} A promise that resolves with the list of APMs.
+ *
+ * @throws {import("./index").IPublicError} Throws an error object if the operation fails.
+ *
+ * @public
+ */
+ getCustomerPaymentMethods(): 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
+ * during the payment process or when using card management methods.
+ *
+ * Retrieves the business information.
+ * @returns {Promise} A promise that resolves with the business information.
+ *
+ * @throws {import("./index").IPublicError} Throws an error object if the operation fails.
+ *
+ * @public
+ */
+ getBusiness(): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * It is no longer necessary to use this method as customer registration is now automatically handled
+ * during the payment process or when using card management methods.
+ */
+ customerRegister(
+ email: string,
+ ): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * It is no longer necessary to use this method as order creation is now automatically
+ * handled when making a payment through the `payment` function.
+ */
+ createOrder(
+ orderItems: CreateOrderRequest,
+ ): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * It is no longer necessary to use this method as payment creation is now automatically
+ * handled when making a payment through the `payment` function.
+ */
+ createPayment(
+ paymentItems: CreatePaymentRequest,
+ ): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * Use the {@link payment} method
+ */
+ startCheckoutRouter(
+ routerData: StartCheckoutRequest | StartCheckoutIdRequest,
+ ): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * Use the {@link payment} method
+ */
+ startCheckoutRouterFull(
+ routerFullData: StartCheckoutFullRequest,
+ ): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * Use the {@link saveCustomerCard} method
+ */
+ registerCustomerCard(
+ secureToken: string,
+ customerToken: string,
+ data: RegisterCustomerCardRequest,
+ ): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * Use the {@link removeCustomerCard} method
+ */
+ deleteCustomerCard(
+ customerToken: string,
+ skyflowId: string,
+ ): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * Use the {@link getCustomerPaymentMethods} method
+ */
+ getActiveAPMs(): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * It is no longer necessary to use this method as card registration or as checkout is now automatically handled
+ * during the payment process or when using card management methods.
+ */
+ getSkyflowTokens({
+ vault_id,
+ vault_url,
+ data,
+ }: TokensRequest): Promise;
+
+ /**
+ * @deprecated This method is deprecated and will be removed in a future release.
+ * It is no longer necessary to use this method is now automatically handled
+ * during the payment process.
+ */
+ getOpenpayDeviceSessionID(
+ merchant_id: string,
+ public_key: string,
+ is_sandbox: boolean,
+ ): Promise;
+}
+
diff --git a/src/types/paymentMethod.ts b/src/types/paymentMethod.ts
new file mode 100644
index 0000000..cb96ec7
--- /dev/null
+++ b/src/types/paymentMethod.ts
@@ -0,0 +1,24 @@
+export interface IPaymentMethodResponse {
+ count: number;
+ next: string | null;
+ previous: string | null;
+ results: ITonderPaymentMethod[];
+}
+
+export interface ITonderPaymentMethod {
+ pk: string;
+ payment_method: string;
+ priority: number;
+ category: string;
+ unavailable_countries: string[];
+ status: string;
+}
+
+export interface IPaymentMethod {
+ id: string;
+ payment_method: string;
+ priority: number;
+ category: string;
+ icon: string;
+ label: string;
+}
\ No newline at end of file
diff --git a/src/types/requests.ts b/src/types/requests.ts
index 4832aab..bad288d 100644
--- a/src/types/requests.ts
+++ b/src/types/requests.ts
@@ -1,5 +1,5 @@
-import { OrderItem } from "./commons";
import { SkyflowRecord } from "./skyflow";
+import {IItem} from "./checkout";
export interface CreateOrderRequest {
business: string,
@@ -10,7 +10,7 @@ export interface CreateOrderRequest {
status?: string,
reference: string | number,
is_oneclick: boolean,
- items: OrderItem[]
+ items: IItem[]
}
export type CreatePaymentRequest = {
@@ -71,6 +71,15 @@ export type RegisterCustomerCardRequest = {
skyflow_id: string;
}
+export type TokensSkyflowRequest = {
+ baseUrl: string;
+ apiKey: string;
+ vault_id: string,
+ vault_url: string,
+ data: {
+ [key: string]: any;
+ }
+}
export type TokensRequest = {
vault_id: string,
vault_url: string,
@@ -81,7 +90,7 @@ export type TokensRequest = {
export type StartCheckoutFullRequest = {
order: {
- items: OrderItem[];
+ items: IItem[];
};
total: number;
customer: {
diff --git a/src/types/transaction.ts b/src/types/transaction.ts
new file mode 100644
index 0000000..9912508
--- /dev/null
+++ b/src/types/transaction.ts
@@ -0,0 +1,101 @@
+export interface ITransaction {
+ id: number;
+ provider: string;
+ country: string;
+ currency_code: string;
+ transaction_status: string;
+ created: string;
+ modified: string;
+ operation_date: string;
+ transaction_reference: string;
+ transaction_type: string;
+ status: string;
+ amount: string;
+ related_transaction_reference?: null | string;
+ reason?: null | string;
+ is_refunded?: null | boolean;
+ is_disputed?: null | boolean;
+ number_of_payment_attempts: number;
+ card_brand?: null | string;
+ number_of_installments: number;
+ payment?: {
+ id: number;
+ created: string;
+ modified: string;
+ amount: string;
+ status: string;
+ date: string;
+ paid_date: null | string;
+ source: null | string;
+ customer_order_reference: null | string;
+ client: number;
+ business: number;
+ shipping_address?: null | string;
+ billing_address?: null | string;
+ order: number;
+ };
+ checkout: {
+ id: string;
+ created: string;
+ modified: string;
+ checkout_data: {
+ name: string;
+ amount: number;
+ source: string;
+ id_ship: string;
+ currency: string;
+ order_id: number;
+ token_id: string;
+ last_name: string;
+ id_product: string;
+ ip_address: string;
+ payment_id: number;
+ return_url: string;
+ title_ship: string;
+ business_id: number;
+ checkout_id: string;
+ description: string;
+ browser_info: {
+ language: string;
+ time_zone: number;
+ user_agent: string;
+ color_depth: number;
+ screen_width: number;
+ screen_height: number;
+ javascript_enabled: boolean;
+ };
+ email_client: string;
+ phone_number: string;
+ instance_id_ship: string;
+ quantity_product: number;
+ device_session_id: null | string;
+ number_of_payment_attempts: number;
+ };
+ number_of_payment_attempts: number;
+ tried_psps: string[];
+ rejected_transactions: string[];
+ routing_step: number;
+ route_length: number;
+ last_status: string;
+ ip_address: string;
+ is_dynamic_routing: boolean;
+ is_route_finished: boolean;
+ business: number;
+ payment: number;
+ };
+ currency: {
+ id: number;
+ name: string;
+ code: string;
+ symbol: string;
+ country: null | string;
+ };
+ payment_method?: null | {
+ id: number;
+ name: string;
+ display_name: string;
+ category: string;
+ is_apm: boolean;
+ };
+ issuing_country?: null | string;
+}
diff --git a/src/types/validations.d.ts b/src/types/validations.d.ts
new file mode 100644
index 0000000..b0064fd
--- /dev/null
+++ b/src/types/validations.d.ts
@@ -0,0 +1,11 @@
+export declare function validateCardNumber(cardNumber: string): boolean;
+
+export declare function validateCardholderName(name: string): boolean;
+
+export declare function validateCVV(cvv: string): boolean;
+
+export declare function validateExpirationMonth(month: string): boolean;
+
+export declare function validateExpirationYear(year: string): boolean;
+
+export declare function validateExpirationDateParts(month: string, year: string): boolean;
diff --git a/tests/classes/liteCheckout.test.ts b/tests/classes/liteCheckout.test.ts
index b900382..0731303 100644
--- a/tests/classes/liteCheckout.test.ts
+++ b/tests/classes/liteCheckout.test.ts
@@ -1,7 +1,7 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
import { constructorFields } from "../utils/defaultMock";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
interface Window {
@@ -11,7 +11,7 @@ declare global {
}
describe("LiteCheckout", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
@@ -38,9 +38,9 @@ describe("LiteCheckout", () => {
it("Can instance LiteCheckout", () => {
expect(liteCheckout).toBeInstanceOf(LiteCheckout);
- expect(liteCheckout.publicApiKeyTonder).toEqual(constructorFields.publicApiKeyTonder);
- expect(liteCheckout.baseUrlTonder).toEqual(constructorFields.baseUrlTonder);
- expect(liteCheckout.signal).toEqual(constructorFields.signal);
+ expect(liteCheckout.apiKeyTonder).toEqual(constructorFields.apiKey);
+ expect(liteCheckout.baseUrl).toEqual(constructorFields.baseUrl);
+ expect(liteCheckout.abortController.signal).toEqual(constructorFields.signal);
});
diff --git a/tests/methods/createOrder.test.ts b/tests/methods/createOrder.test.ts
index 8f6e9ec..59a63a0 100644
--- a/tests/methods/createOrder.test.ts
+++ b/tests/methods/createOrder.test.ts
@@ -1,10 +1,9 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { IErrorResponse } from "../../src/types/responses";
import { constructorFields } from "../utils/defaultMock";
-import { OrderResponseClass, OrderClass, OrderClassEmptyValues, OrderEmptyValuesResponse } from "../utils/mockClasses";
+import { OrderResponseClass, OrderClass, OrderEmptyValuesResponse } from "../utils/mockClasses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
interface Window {
@@ -14,7 +13,7 @@ declare global {
}
describe("createOrder", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
diff --git a/tests/methods/createPayment.test.ts b/tests/methods/createPayment.test.ts
index 21f7444..43fbc24 100644
--- a/tests/methods/createPayment.test.ts
+++ b/tests/methods/createPayment.test.ts
@@ -1,10 +1,9 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { IErrorResponse } from "../../src/types/responses";
import { constructorFields } from "../utils/defaultMock";
import { CreatePaymentResponseClass, CreatePaymentRequestClass } from "../utils/mockClasses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
@@ -15,7 +14,7 @@ declare global {
}
describe("createPayment", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
diff --git a/tests/methods/customerRegister.test.ts b/tests/methods/customerRegister.test.ts
index 0446f0f..e8f4feb 100644
--- a/tests/methods/customerRegister.test.ts
+++ b/tests/methods/customerRegister.test.ts
@@ -1,10 +1,9 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { IErrorResponse } from "../../src/types/responses";
import { constructorFields } from "../utils/defaultMock";
-import { BusinessClass, CustomerRegisterClass } from "../utils/mockClasses";
+import { CustomerRegisterClass } from "../utils/mockClasses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
@@ -15,7 +14,7 @@ declare global {
}
describe("customerRegister", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
diff --git a/tests/methods/getBusiness.test.ts b/tests/methods/getBusiness.test.ts
index 7112fbe..4c94b3e 100644
--- a/tests/methods/getBusiness.test.ts
+++ b/tests/methods/getBusiness.test.ts
@@ -1,10 +1,9 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { IErrorResponse } from "../../src/types/responses";
import { constructorFields } from "../utils/defaultMock";
import { BusinessClass } from "../utils/mockClasses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
interface Window {
@@ -14,7 +13,7 @@ declare global {
}
describe("getBusiness", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
@@ -84,7 +83,7 @@ describe("getBusiness", () => {
let error: ErrorResponse;
try {
- const response = (await liteCheckout.getBusiness()) as IErrorResponse;
+ const response = (await liteCheckout.getBusiness());
} catch (e: any) {
error = e;
expect(error.code).toStrictEqual("400");
@@ -100,7 +99,7 @@ describe("getBusiness", () => {
let error: ErrorResponse;
try {
- const response = (await liteCheckout.getBusiness()) as ErrorResponse;
+ const response = (await liteCheckout.getBusiness());
} catch (e: any) {
error = e;
expect(error.message).toStrictEqual("error");
diff --git a/tests/methods/getCustomerCards.test.ts b/tests/methods/getCustomerCards.test.ts
index b02cf54..5a17acf 100644
--- a/tests/methods/getCustomerCards.test.ts
+++ b/tests/methods/getCustomerCards.test.ts
@@ -1,10 +1,9 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { IErrorResponse } from "../../src/types/responses";
import { constructorFields } from "../utils/defaultMock";
import { GetCustomerCardsResponseClass } from "../utils/mockClasses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
interface Window {
@@ -14,7 +13,7 @@ declare global {
}
describe("getCustomerCards", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
@@ -48,7 +47,7 @@ describe("getCustomerCards", () => {
})
);
- const response = await liteCheckout.getCustomerCards("1234", "123456");
+ const response = await liteCheckout.getCustomerCards();
expect(response).toStrictEqual({ ...new GetCustomerCardsResponseClass() });
expect(liteCheckoutSpy).toHaveBeenCalled();
@@ -65,7 +64,7 @@ describe("getCustomerCards", () => {
})
);
- const response = await liteCheckout.getCustomerCards("1234", "123456");
+ const response = await liteCheckout.getCustomerCards();
expect(liteCheckoutSpy).toHaveBeenCalled();
expect(liteCheckoutSpy).toHaveReturned();
expect(response).toBeUndefined();
@@ -85,10 +84,7 @@ describe("getCustomerCards", () => {
let error: ErrorResponse;
try {
- const response = (await liteCheckout.getCustomerCards(
- "1234",
- "123456"
- )) as IErrorResponse;
+ const response = (await liteCheckout.getCustomerCards());
} catch (e: any) {
error = e;
expect(error.code).toStrictEqual("400");
@@ -104,10 +100,7 @@ describe("getCustomerCards", () => {
let error: ErrorResponse;
try {
- const response = (await liteCheckout.getCustomerCards(
- "1234",
- "123456"
- )) as IErrorResponse;
+ const response = (await liteCheckout.getCustomerCards());
} catch (e: any) {
error = e;
expect(error.message).toStrictEqual("error");
diff --git a/tests/methods/getOpenpayDeviceSessionID.test.ts b/tests/methods/getOpenpayDeviceSessionID.test.ts
deleted file mode 100644
index f01f89e..0000000
--- a/tests/methods/getOpenpayDeviceSessionID.test.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import "../utils/defaultMock";
-import { LiteCheckout } from "../../src";
-import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { IErrorResponse } from "../../src/types/responses";
-import { constructorFields } from "../utils/defaultMock";
-
-declare global {
- interface Window {
- OpenPay: any;
- Skyflow: any;
- }
-}
-
-describe("getOpenpayDeviceSessionID", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
- liteCheckout: LiteCheckout,
- fetchSpy: jest.SpyInstance,
- liteCheckoutSpy: jest.SpyInstance;
-
- beforeEach(async () => {
- window.fetch = jest.fn();
-
- checkoutConstructor = {
- ...constructorFields,
- };
-
- liteCheckout = new LiteCheckout(constructorFields);
-
- fetchSpy = jest.spyOn(global, "fetch");
- });
-
- afterEach(() => {
- jest.restoreAllMocks();
- });
-
- it("getOpenpayDeviceSessionID success", async () => {
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getOpenpayDeviceSessionID");
-
- window.OpenPay = {
- setId: jest.fn(),
- setApiKey: jest.fn(),
- setSandboxMode: jest.fn(),
- deviceData: {
- setup: jest.fn().mockImplementation(() => Promise.resolve("test")),
- },
- };
-
- expect(
- liteCheckout.getOpenpayDeviceSessionID("4321", "1234", true)
- ).resolves.toBe("test");
- expect(liteCheckoutSpy).toHaveBeenCalledWith("4321", "1234", true);
- });
-
- it("getOpenpayDeviceSessionID empty", async () => {
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getOpenpayDeviceSessionID");
-
- window.OpenPay = {
- setId: jest.fn(),
- setApiKey: jest.fn(),
- setSandboxMode: jest.fn(),
- deviceData: {
- setup: jest.fn().mockImplementation(() => Promise.resolve()),
- },
- };
-
- expect(
- liteCheckout.getOpenpayDeviceSessionID("", "", true)
- ).resolves.toBeUndefined();
- expect(liteCheckoutSpy).toHaveBeenCalledWith("", "", true);
- });
-
- it("getOpenpayDeviceSessionID error", async () => {
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getOpenpayDeviceSessionID");
-
- window.OpenPay = {
- setId: jest.fn(),
- setApiKey: jest.fn(),
- setSandboxMode: jest.fn(),
- deviceData: {
- setup: jest.fn().mockRejectedValue("error"),
- },
- };
-
- try {
- await liteCheckout.getOpenpayDeviceSessionID("", "", true);
- } catch (e) {
- const error: IErrorResponse = e as IErrorResponse;
- expect(liteCheckoutSpy).toHaveBeenCalledWith("", "", true);
- expect(liteCheckoutSpy).toHaveReturned();
- expect(error.message).toStrictEqual("error");
- expect(error).toBeInstanceOf(ErrorResponse);
- }
- });
-});
\ No newline at end of file
diff --git a/tests/methods/getSkyflowToken.test.ts b/tests/methods/getSkyflowToken.test.ts
deleted file mode 100644
index 590d211..0000000
--- a/tests/methods/getSkyflowToken.test.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-import "../utils/defaultMock";
-import Skyflow from "skyflow-js";
-import { LiteCheckout } from "../../src";
-import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { IErrorResponse } from "../../src/types/responses";
-import { constructorFields } from "../utils/defaultMock";
-import { TokensRequestClass } from "../utils/mockClasses";
-
-
-declare global {
- interface Window {
- OpenPay: any;
- Skyflow: any;
- }
-}
-
-describe("getSkyflowToken", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
- liteCheckout: LiteCheckout,
- fetchSpy: jest.SpyInstance,
- liteCheckoutSpy: jest.SpyInstance;
-
- beforeEach(async () => {
- window.fetch = jest.fn();
-
- checkoutConstructor = {
- ...constructorFields,
- };
-
- liteCheckout = new LiteCheckout(constructorFields);
-
- fetchSpy = jest.spyOn(global, "fetch");
- });
-
- afterEach(() => {
- jest.restoreAllMocks();
- });
-
- it("getSkyflowTokens success", async () => {
- liteCheckout.getVaultToken = jest
- .fn()
- .mockImplementation(() => Promise.resolve("1234"));
-
- liteCheckout.getFieldsPromise = jest
- .fn()
- .mockImplementation(() =>
- Promise.resolve(new Array(5).fill(Promise.resolve(true)))
- );
-
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getSkyflowTokens");
-
- const response = await liteCheckout.getSkyflowTokens({
- ...new TokensRequestClass(),
- });
- expect(response).toStrictEqual("1234");
- expect(liteCheckoutSpy).toHaveBeenCalled();
- });
-
- it("getSkyflowTokens empty", async () => {
- liteCheckout.getVaultToken = jest
- .fn()
- .mockImplementation(() => Promise.resolve(""));
-
- jest.spyOn(Skyflow, "init").mockImplementation(jest.fn().mockImplementation(() => ({
- container: () => ({
- collect: jest.fn().mockResolvedValue(""),
- }),
- })));
-
- liteCheckout.getFieldsPromise = jest
- .fn()
- .mockImplementation(() =>
- Promise.resolve(new Array(5).fill(Promise.resolve(true)))
- );
-
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getSkyflowTokens");
-
- let error: ErrorResponse;
-
- try {
- const response = await liteCheckout.getSkyflowTokens({
- ...new TokensRequestClass(),
- }) as IErrorResponse;
- } catch (e: any) {
- error = e;
- expect(error).toBeInstanceOf(ErrorResponse);
- expect(error.message).toStrictEqual("Por favor, verifica todos los campos de tu tarjeta");
- }
- });
-
- it("getSkyflowTokens error mount fields", async () => {
- liteCheckout.getVaultToken = jest
- .fn()
- .mockImplementation(() => Promise.resolve(""));
-
- jest.spyOn(Skyflow, "init").mockImplementation(jest.fn().mockImplementation(() => ({
- container: () => ({
- collect: jest.fn().mockResolvedValue(""),
- }),
- })));
-
- liteCheckout.getFieldsPromise = jest
- .fn()
- .mockImplementation(() =>
- new Array(5).fill(false)
- );
-
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getSkyflowTokens");
-
- let error: ErrorResponse;
-
- try {
- const response = (await liteCheckout.getSkyflowTokens({
- ...new TokensRequestClass(),
- })) as IErrorResponse;
- } catch (e: any) {
- error = e;
- expect(error).toBeInstanceOf(ErrorResponse);
- expect(error.message).toStrictEqual("Ocurrió un error al montar los campos de la tarjeta");
- }
- });
-
- it("getSkyflowTokens error collect catch", async () => {
- liteCheckout.getVaultToken = jest
- .fn()
- .mockImplementation(() => Promise.resolve("1234"));
-
- jest.spyOn(Skyflow, "init").mockImplementation(jest.fn().mockImplementation(() => ({
- container: () => ({
- collect: jest.fn().mockRejectedValue("error"),
- }),
- })));
-
- liteCheckout.getFieldsPromise = jest
- .fn()
- .mockImplementation(() =>
- Promise.resolve(new Array(5).fill(Promise.resolve(true)))
- );
-
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getSkyflowTokens");
-
- let error: ErrorResponse;
-
- try {
- const response = (await liteCheckout.getSkyflowTokens({
- ...new TokensRequestClass(),
- })) as IErrorResponse;
- } catch (e: any) {
- error = e;
- expect(error.message).toStrictEqual("error");
- expect(error).toBeInstanceOf(ErrorResponse);
- }
- });
-});
\ No newline at end of file
diff --git a/tests/methods/getVaultToken.test.ts b/tests/methods/getVaultToken.test.ts
deleted file mode 100644
index e1899f0..0000000
--- a/tests/methods/getVaultToken.test.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import "../utils/defaultMock";
-import { LiteCheckout } from "../../src";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
-import { constructorFields } from "../utils/defaultMock";
-
-declare global {
- interface Window {
- OpenPay: any;
- Skyflow: any;
- }
-}
-
-describe("getVaultToken", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
- liteCheckout: LiteCheckout,
- fetchSpy: jest.SpyInstance,
- liteCheckoutSpy: jest.SpyInstance;
-
- beforeEach(async () => {
- window.fetch = jest.fn();
-
- checkoutConstructor = {
- ...constructorFields,
- };
-
- liteCheckout = new LiteCheckout(constructorFields);
-
- fetchSpy = jest.spyOn(global, "fetch");
- });
-
- afterEach(() => {
- jest.restoreAllMocks();
- });
-
- it("getVaultToken success", async () => {
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getVaultToken");
-
- fetchSpy.mockImplementation(() =>
- Promise.resolve({
- json: () => Promise.resolve({ token: "1234" }),
- ok: true,
- })
- );
-
- const response = await liteCheckout.getVaultToken();
- expect(response).toStrictEqual("1234");
- expect(liteCheckoutSpy).toHaveBeenCalled();
- });
-
- it("getVaultToken empty", async () => {
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getVaultToken");
-
- fetchSpy.mockImplementation(() =>
- Promise.resolve({
- json: () => Promise.resolve(),
- ok: true,
- })
- );
-
- const response = await liteCheckout.getVaultToken();
- expect(liteCheckoutSpy).toHaveBeenCalled();
- expect(liteCheckoutSpy).toHaveReturned();
- expect(response).toBeUndefined();
- });
-
- it("getVaultToken errorResponse", async () => {
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getVaultToken");
-
- fetchSpy.mockImplementation(() =>
- Promise.resolve({
- json: () => Promise.resolve(),
- ok: false,
- status: 400,
- })
- );
-
- try {
- await liteCheckout.getVaultToken();
- } catch (e) {
- const error = e as Error;
- expect(liteCheckoutSpy).toHaveBeenCalled();
- expect(liteCheckoutSpy).rejects.toThrow();
- expect(error.message).toStrictEqual(
- "Failed to retrieve bearer token; HTTPCODE: 400"
- );
- expect(error).toBeInstanceOf(Error);
- }
- });
-
- it("getVaultToken errorCatch", async () => {
- liteCheckoutSpy = jest.spyOn(liteCheckout, "getVaultToken");
-
- fetchSpy.mockRejectedValue("error");
-
- try {
- await liteCheckout.getVaultToken();
- } catch (e) {
- const error = e as Error;
- expect(liteCheckoutSpy).toHaveBeenCalled();
- expect(liteCheckoutSpy).rejects.toThrow();
- expect(error.message).toStrictEqual(
- "Failed to retrieve bearer token; error"
- );
- expect(e).toBeInstanceOf(Error);
- }
- });
-});
\ No newline at end of file
diff --git a/tests/methods/registerCustomerCard.test.ts b/tests/methods/registerCustomerCard.test.ts
index e02f826..f31aef3 100644
--- a/tests/methods/registerCustomerCard.test.ts
+++ b/tests/methods/registerCustomerCard.test.ts
@@ -1,10 +1,10 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
import { constructorFields } from "../utils/defaultMock";
import { RegisterCustomerCardRequestClass, RegisterCustomerCardResponseClass } from "../utils/mockClasses";
import { ErrorResponse } from "../../src/classes/errorResponse";
import { IErrorResponse } from "../../src/types/responses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
interface Window {
@@ -14,7 +14,7 @@ declare global {
}
describe("registerCustomerCard", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
diff --git a/tests/methods/startCheckoutRouter.test.ts b/tests/methods/startCheckoutRouter.test.ts
index c45bc51..79ce0ec 100644
--- a/tests/methods/startCheckoutRouter.test.ts
+++ b/tests/methods/startCheckoutRouter.test.ts
@@ -1,10 +1,10 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
import { IErrorResponse } from "../../src/types/responses";
import { constructorFields } from "../utils/defaultMock";
import { StartCheckoutResponseClass, StartCheckoutRequestClass, CreatePaymentRequestClass } from "../utils/mockClasses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
interface Window {
@@ -14,7 +14,7 @@ declare global {
}
describe("startCheckoutRouter", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
diff --git a/tests/methods/startCheckoutRouterFull.test.ts b/tests/methods/startCheckoutRouterFull.test.ts
index 659e4cc..b808880 100644
--- a/tests/methods/startCheckoutRouterFull.test.ts
+++ b/tests/methods/startCheckoutRouterFull.test.ts
@@ -1,10 +1,10 @@
import "../utils/defaultMock";
import { LiteCheckout } from "../../src";
import { ErrorResponse } from "../../src/classes/errorResponse";
-import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
import { IErrorResponse } from "../../src/types/responses";
import { constructorFields } from "../utils/defaultMock";
import { StartCheckoutResponseClass, StartCheckoutFullRequestClass, BusinessClass, CustomerRegisterClass, OrderResponseClass, CreatePaymentResponseClass } from "../utils/mockClasses";
+import {IInlineLiteCheckoutOptions} from "../../src/types/commons";
declare global {
interface Window {
@@ -14,7 +14,7 @@ declare global {
}
describe("startCheckoutRouterFull", () => {
- let checkoutConstructor: LiteCheckoutConstructor,
+ let checkoutConstructor: IInlineLiteCheckoutOptions,
liteCheckout: LiteCheckout,
fetchSpy: jest.SpyInstance,
liteCheckoutSpy: jest.SpyInstance;
diff --git a/tests/utils/defaultMock.ts b/tests/utils/defaultMock.ts
index f797982..db90664 100644
--- a/tests/utils/defaultMock.ts
+++ b/tests/utils/defaultMock.ts
@@ -16,6 +16,7 @@ const abortSignal = new AbortController().signal;
export const constructorFields = {
signal: abortSignal,
- baseUrlTonder: "",
- publicApiKeyTonder: "",
+ baseUrl: "",
+ apiKey: "",
+ returnUrl: ""
};
\ No newline at end of file
diff --git a/tests/utils/mockClasses.ts b/tests/utils/mockClasses.ts
index 0e355bb..e8a9806 100644
--- a/tests/utils/mockClasses.ts
+++ b/tests/utils/mockClasses.ts
@@ -4,9 +4,8 @@ import {
CreatePaymentRequest,
RegisterCustomerCardRequest,
StartCheckoutRequest,
- TokensRequest,
StartCheckoutFullRequest,
- StartCheckoutRequestWithCard
+ StartCheckoutRequestWithCard, TokensSkyflowRequest
} from "../../src/types/requests";
import {
CreateOrderResponse,
@@ -556,13 +555,17 @@ export class StartCheckoutFullRequestClass implements StartCheckoutFullRequest {
}
}
-export class TokensRequestClass implements TokensRequest {
+export class TokensRequestClass implements TokensSkyflowRequest {
+ baseUrl!: string;
+ apiKey!: string;
vault_id!: string;
vault_url!: string;
data: { [key: string]: any } = {};
- get mockObject(): TokensRequest {
+ get mockObject(): TokensSkyflowRequest {
return {
+ baseUrl: "",
+ apiKey: "",
vault_id: "string",
vault_url: "string",
data: {
diff --git a/types/classes/liteCheckout.d.ts b/types/classes/liteCheckout.d.ts
new file mode 100644
index 0000000..e7c4818
--- /dev/null
+++ b/types/classes/liteCheckout.d.ts
@@ -0,0 +1,29 @@
+import { TokensRequest } from "../types/skyflow";
+declare global {
+ interface Window {
+ OpenPay: any;
+ }
+}
+type LiteCheckoutConstructor = {
+ signal: AbortSignal;
+ baseUrlTonder: string;
+ publicApiKeyTonder: string;
+};
+export declare class LiteCheckout {
+ baseUrlTonder: string;
+ signal: AbortSignal;
+ publicApiKeyTonder: string;
+ constructor({ signal, baseUrlTonder, publicApiKeyTonder }: LiteCheckoutConstructor);
+ getOpenpayDeviceSessionID(merchant_id: string, public_key: string): Promise;
+ getBusiness(): Promise;
+ customerRegister(email: string): Promise;
+ createOrder(orderItems: any): Promise;
+ createPayment(paymentItems: {
+ business_pk: string;
+ }): Promise;
+ startCheckoutRouter(routerItems: any): Promise;
+ getSkyflowTokens({ vault_id, vault_url, data }: TokensRequest): Promise;
+ getVaultToken(): Promise;
+ getCustomerCards(customerToken: string, query: string): Promise;
+}
+export {};
diff --git a/types/classes/liteCheckout.js b/types/classes/liteCheckout.js
new file mode 100644
index 0000000..77eb87c
--- /dev/null
+++ b/types/classes/liteCheckout.js
@@ -0,0 +1,225 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __importDefault = (this && this.__importDefault) || function (mod) {
+ return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.LiteCheckout = void 0;
+const skyflow_js_1 = __importDefault(require("skyflow-js"));
+class LiteCheckout {
+ constructor({ signal, baseUrlTonder, publicApiKeyTonder }) {
+ this.baseUrlTonder = baseUrlTonder;
+ this.signal = signal;
+ this.publicApiKeyTonder = publicApiKeyTonder;
+ }
+ getOpenpayDeviceSessionID(merchant_id, public_key) {
+ return __awaiter(this, void 0, void 0, function* () {
+ let openpay = yield window.OpenPay;
+ openpay.setId(merchant_id);
+ openpay.setApiKey(public_key);
+ openpay.setSandboxMode(true);
+ var response = yield openpay.deviceData.setup({ signal: this.signal });
+ return response;
+ });
+ }
+ getBusiness() {
+ return __awaiter(this, void 0, void 0, function* () {
+ const getBusiness = yield fetch(`${this.baseUrlTonder}/api/v1/payments/business/${this.publicApiKeyTonder}`, {
+ headers: {
+ Authorization: `Token ${this.publicApiKeyTonder}`,
+ },
+ signal: this.signal,
+ });
+ const response = yield getBusiness.json();
+ return response;
+ });
+ }
+ customerRegister(email) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const url = `${this.baseUrlTonder}/api/v1/customer/`;
+ const data = { email: email };
+ const response = yield fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${this.publicApiKeyTonder}`,
+ },
+ signal: this.signal,
+ body: JSON.stringify(data),
+ });
+ if (response.status === 201) {
+ const jsonResponse = yield response.json();
+ return jsonResponse;
+ }
+ else {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+ });
+ }
+ createOrder(orderItems) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const url = `${this.baseUrlTonder}/api/v1/orders/`;
+ const data = orderItems;
+ const response = yield fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${this.publicApiKeyTonder}`,
+ },
+ body: JSON.stringify(data),
+ });
+ if (response.status === 201) {
+ const jsonResponse = yield response.json();
+ return jsonResponse;
+ }
+ else {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+ });
+ }
+ createPayment(paymentItems) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const url = `${this.baseUrlTonder}/api/v1/business/${paymentItems.business_pk}/payments/`;
+ const data = paymentItems;
+ const response = yield fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${this.publicApiKeyTonder}`,
+ },
+ body: JSON.stringify(data),
+ });
+ if (response.status >= 200 && response.status <= 299) {
+ const jsonResponse = yield response.json();
+ return jsonResponse;
+ }
+ else {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+ });
+ }
+ startCheckoutRouter(routerItems) {
+ return __awaiter(this, void 0, void 0, function* () {
+ try {
+ const url = `${this.baseUrlTonder}/api/v1/checkout-router/`;
+ const data = routerItems;
+ const response = yield fetch(url, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Token ${this.publicApiKeyTonder}`,
+ },
+ body: JSON.stringify(data),
+ });
+ if (response.status >= 200 && response.status <= 299) {
+ const jsonResponse = yield response.json();
+ return jsonResponse;
+ }
+ else {
+ throw new Error("Failed to start checkout router");
+ }
+ }
+ catch (error) {
+ throw error;
+ }
+ });
+ }
+ getSkyflowTokens({ vault_id, vault_url, data }) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const skyflow = skyflow_js_1.default.init({
+ vaultID: vault_id,
+ vaultURL: vault_url,
+ getBearerToken: () => __awaiter(this, void 0, void 0, function* () { return yield this.getVaultToken(); }),
+ options: {
+ logLevel: skyflow_js_1.default.LogLevel.ERROR,
+ env: skyflow_js_1.default.Env.DEV,
+ },
+ });
+ const collectContainer = skyflow.container(skyflow_js_1.default.ContainerType.COLLECT);
+ const fields = yield Promise.all(Object.keys(data).map((key) => __awaiter(this, void 0, void 0, function* () {
+ const cardHolderNameElement = yield collectContainer.create({
+ table: "cards",
+ column: key,
+ type: skyflow_js_1.default.ElementType.INPUT_FIELD
+ });
+ return { element: cardHolderNameElement, key: key };
+ })));
+ const fieldPromises = fields.map((field) => {
+ return new Promise((resolve, reject) => {
+ var _a;
+ const div = document.createElement("div");
+ div.hidden = true;
+ div.id = `id-${field.key}`;
+ (_a = document.querySelector(`body`)) === null || _a === void 0 ? void 0 : _a.appendChild(div);
+ setTimeout(() => {
+ field.element.mount(`#id-${field.key}`);
+ setInterval(() => {
+ if (field.element.isMounted()) {
+ const value = data[field.key];
+ field.element.update({ value: value });
+ return resolve(field.element.isMounted());
+ }
+ }, 120);
+ }, 120);
+ });
+ });
+ const result = yield Promise.all(fieldPromises);
+ const mountFail = result.find((item) => !item);
+ if (mountFail) {
+ return { error: "Ocurrió un error al montar los campos de la tarjeta" };
+ }
+ else {
+ try {
+ const collectResponseSkyflowTonder = yield collectContainer.collect();
+ return collectResponseSkyflowTonder["records"][0]["fields"];
+ }
+ catch (error) {
+ console.error("Por favor, verifica todos los campos de tu tarjeta");
+ return { error: "Por favor, verifica todos los campos de tu tarjeta" };
+ }
+ }
+ });
+ }
+ getVaultToken() {
+ return __awaiter(this, void 0, void 0, function* () {
+ const response = yield fetch(`${this.baseUrlTonder}/api/v1/vault-token/`, {
+ method: 'GET',
+ headers: {
+ 'Authorization': `Token ${this.publicApiKeyTonder}`
+ },
+ signal: this.signal,
+ });
+ if (response.ok) {
+ const responseBody = yield response.json();
+ return responseBody.token;
+ }
+ else {
+ throw new Error('Failed to retrieve bearer token');
+ }
+ });
+ }
+ getCustomerCards(customerToken, query) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const response = yield fetch(`${this.baseUrlTonder}/api/v1/cards/${query}`, {
+ method: 'GET',
+ headers: {
+ 'Authorization': `Token ${customerToken}`
+ },
+ signal: this.signal,
+ });
+ const jsonResponse = yield response.json();
+ console.log("jsonResponse: ", jsonResponse);
+ return jsonResponse;
+ });
+ }
+}
+exports.LiteCheckout = LiteCheckout;
+//# sourceMappingURL=liteCheckout.js.map
\ No newline at end of file
diff --git a/types/classes/liteCheckout.js.map b/types/classes/liteCheckout.js.map
new file mode 100644
index 0000000..65a79de
--- /dev/null
+++ b/types/classes/liteCheckout.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"liteCheckout.js","sourceRoot":"","sources":["../../src/classes/liteCheckout.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,4DAAiC;AAYjC,MAAa,YAAY;IAMvB,YAAa,EAAE,MAAM,EAAE,aAAa,EAAE,YAAY,EAA2B;QAC3E,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAEK,yBAAyB,CAAC,WAAmB,EAAE,UAAkB;;YACrE,IAAI,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YAC3B,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YAC9B,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,QAAQ,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACvE,OAAO,QAAQ,CAAC;QAClB,CAAC;KAAA;IACK,WAAW;;YACf,MAAM,WAAW,GAAG,MAAM,KAAK,CAC7B,GAAG,IAAI,CAAC,aAAa,6BAA6B,IAAI,CAAC,YAAY,EAAE,EACrE;gBACE,OAAO,EAAE;oBACP,aAAa,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE;iBAC5C;gBACD,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CACF,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;YAC1C,OAAO,QAAQ,CAAA;QACjB,CAAC;KAAA;IACK,gBAAgB,CAAC,KAAa;;YAClC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,mBAAmB,CAAC;YACrD,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE;iBAC5C;gBACD,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,OAAO,YAAY,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;KAAA;IAEK,WAAW,CAAC,UAAe;;YAC/B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,iBAAiB,CAAC;YACnD,MAAM,IAAI,GAAG,UAAU,CAAC;YACxB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE;iBAC5C;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,OAAO,YAAY,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;KAAA;IAEK,aAAa,CAAC,YAAqC;;YACvD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,oBAAoB,YAAY,CAAC,WAAW,YAAY,CAAC;YAC1F,MAAM,IAAI,GAAG,YAAY,CAAC;YAC1B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE;iBAC5C;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YACH,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAG,GAAG,EAAE,CAAC;gBACpD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,OAAO,YAAY,CAAC;YACtB,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;YACnD,CAAC;QACH,CAAC;KAAA;IAEK,mBAAmB,CAAC,WAAgB;;YACxC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,0BAA0B,CAAC;gBAC5D,MAAM,IAAI,GAAG,WAAW,CAAC;gBACzB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;oBAChC,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE;wBACP,cAAc,EAAE,kBAAkB;wBAClC,aAAa,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE;qBAC5C;oBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;iBAC3B,CAAC,CAAC;gBACH,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBACrD,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;oBAC3C,OAAO,YAAY,CAAC;gBACtB,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;gBACpD,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,KAAK,CAAA;YACb,CAAC;QACH,CAAC;KAAA;IAEK,gBAAgB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAiB;;YAEjE,MAAM,OAAO,GAAG,oBAAO,CAAC,IAAI,CAAC;gBAC3B,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,SAAS;gBACnB,cAAc,EAAE,GAAS,EAAE,gDAAC,OAAA,MAAM,IAAI,CAAC,aAAa,EAAE,CAAA,GAAA;gBACtD,OAAO,EAAE;oBACP,QAAQ,EAAE,oBAAO,CAAC,QAAQ,CAAC,KAAK;oBAChC,GAAG,EAAE,oBAAO,CAAC,GAAG,CAAC,GAAG;iBACrB;aACF,CAAC,CAAC;YAEH,MAAM,gBAAgB,GAAQ,OAAO,CAAC,SAAS,CAC7C,oBAAO,CAAC,aAAa,CAAC,OAAO,CAC9B,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAO,GAAG,EAAE,EAAE;gBACnE,MAAM,qBAAqB,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC;oBAC1D,KAAK,EAAE,OAAO;oBACd,MAAM,EAAE,GAAG;oBACX,IAAI,EAAE,oBAAO,CAAC,WAAW,CAAC,WAAW;iBACtC,CAAC,CAAC;gBACH,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,GAAG,EAAE,GAAG,EAAC,CAAC;YACrD,CAAC,CAAA,CAAC,CAAC,CAAA;YAEH,MAAM,aAAa,GAAmB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;gBACzD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;oBACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;oBACzC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;oBAClB,GAAG,CAAC,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAA;oBAC1B,MAAA,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,0CAAE,WAAW,CAAC,GAAG,CAAC,CAAC;oBACjD,UAAU,CAAC,GAAG,EAAE;wBACd,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,GAAG,EAAE,CAAC,CAAA;wBACvC,WAAW,CAAC,GAAG,EAAE;4BACf,IAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;gCAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gCAC9B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gCACvC,OAAO,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;4BAC3C,CAAC;wBACH,CAAC,EAAE,GAAG,CAAC,CAAA;oBACT,CAAC,EAAE,GAAG,CAAC,CAAA;gBACT,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YAGF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;YAE/C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAa,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;YAEvD,IAAG,SAAS,EAAE,CAAC;gBACb,OAAO,EAAE,KAAK,EAAE,qDAAqD,EAAE,CAAA;YACzE,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC;oBACH,MAAM,4BAA4B,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,CAAC;oBACtE,OAAO,4BAA4B,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAC9D,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAA;oBACnE,OAAO,EAAE,KAAK,EAAE,oDAAoD,EAAE,CAAA;gBACxE,CAAC;YACH,CAAC;QAEH,CAAC;KAAA;IAEK,aAAa;;YACjB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,sBAAsB,EAAE;gBACxE,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,eAAe,EAAE,SAAS,IAAI,CAAC,YAAY,EAAE;iBAC9C;gBACD,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,OAAO,YAAY,CAAC,KAAK,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;KAAA;IAEK,gBAAgB,CAAE,aAAqB,EAAE,KAAa;;YAC1D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,aAAa,iBAAiB,KAAK,EAAE,EAAE;gBAC1E,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,eAAe,EAAE,SAAS,aAAa,EAAE;iBAC1C;gBACD,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;YAEH,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;YAC5C,OAAO,YAAY,CAAC;QACtB,CAAC;KAAA;CAEF;AAjND,oCAiNC"}
\ No newline at end of file
diff --git a/types/helpers/utils.d.ts b/types/helpers/utils.d.ts
new file mode 100644
index 0000000..6cb7417
--- /dev/null
+++ b/types/helpers/utils.d.ts
@@ -0,0 +1,3 @@
+export declare const createObserver: ({ target }: {
+ target: string;
+}) => Promise;
diff --git a/types/helpers/utils.js b/types/helpers/utils.js
new file mode 100644
index 0000000..2daacf1
--- /dev/null
+++ b/types/helpers/utils.js
@@ -0,0 +1,27 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.createObserver = void 0;
+const createObserver = ({ target }) => {
+ return new Promise((resolve, reject) => {
+ let hasChanged = false;
+ const targetNode = document.querySelector(target);
+ const config = { attributes: true, childList: true, subtree: true };
+ const callback = (mutationList, observer) => {
+ for (const mutation of mutationList) {
+ if (mutation.type === "childList") {
+ hasChanged = true;
+ resolve(mutation);
+ }
+ }
+ };
+ const observer = new MutationObserver(callback);
+ observer.observe(targetNode, config);
+ window.setTimeout(() => {
+ if (!hasChanged) {
+ reject("Mounting error");
+ }
+ }, 5000);
+ });
+};
+exports.createObserver = createObserver;
+//# sourceMappingURL=utils.js.map
\ No newline at end of file
diff --git a/types/helpers/utils.js.map b/types/helpers/utils.js.map
new file mode 100644
index 0000000..d26367e
--- /dev/null
+++ b/types/helpers/utils.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/helpers/utils.ts"],"names":[],"mappings":";;;AAAO,MAAM,cAAc,GAAG,CAAC,EAAE,MAAM,EAAsB,EAAgB,EAAE;IAE7E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAErC,IAAI,UAAU,GAAG,KAAK,CAAC;QAGvB,MAAM,UAAU,GAAQ,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAGvD,MAAM,MAAM,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAGpE,MAAM,QAAQ,GAAG,CAAC,YAAiB,EAAE,QAA0B,EAAE,EAAE;YACjE,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,CAAC;gBACpC,IAAI,QAAQ,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBAClC,UAAU,GAAG,IAAI,CAAC;oBAClB,OAAO,CAAC,QAAQ,CAAC,CAAA;gBACnB,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAGF,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAGhD,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAErC,MAAM,CAAC,UAAU,CAAC,GAAE,EAAE;YACpB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,CAAC,gBAAgB,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,EAAE,IAAI,CAAC,CAAC;IAEX,CAAC,CAAC,CAAA;AAEJ,CAAC,CAAA;AApCY,QAAA,cAAc,kBAoC1B"}
\ No newline at end of file
diff --git a/types/index.d.ts b/types/index.d.ts
new file mode 100644
index 0000000..b31dbf3
--- /dev/null
+++ b/types/index.d.ts
@@ -0,0 +1,2 @@
+import { LiteCheckout } from './classes/liteCheckout';
+export { LiteCheckout };
diff --git a/types/index.js b/types/index.js
new file mode 100644
index 0000000..e008097
--- /dev/null
+++ b/types/index.js
@@ -0,0 +1,6 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.LiteCheckout = void 0;
+const liteCheckout_1 = require("./classes/liteCheckout");
+Object.defineProperty(exports, "LiteCheckout", { enumerable: true, get: function () { return liteCheckout_1.LiteCheckout; } });
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/types/index.js.map b/types/index.js.map
new file mode 100644
index 0000000..a0049fd
--- /dev/null
+++ b/types/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yDAAqD;AAGjD,6FAHK,2BAAY,OAGL"}
\ No newline at end of file