@tonder.io/ionic-full-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,40 @@
1
+ export type Customer = {
2
+ firstName: string;
3
+ lastName: string;
4
+ country: string;
5
+ street: string;
6
+ city: string;
7
+ state: string;
8
+ postCode: string;
9
+ email: string;
10
+ phone: string;
11
+ };
12
+ export type Business = {
13
+ vault_id: string;
14
+ vault_url: string;
15
+ openpay_keys: {
16
+ merchant_id: string;
17
+ public_key: string;
18
+ };
19
+ reference: string;
20
+ business: {
21
+ pk: string;
22
+ };
23
+ };
24
+ export type OrderItem = {
25
+ description: string;
26
+ quantity: number;
27
+ price_unit: number;
28
+ discount: number;
29
+ taxes: number;
30
+ product_reference: number;
31
+ name: string;
32
+ amount_total: number;
33
+ };
34
+ export type PaymentData = {
35
+ customer: Customer;
36
+ cart: {
37
+ total: string | number;
38
+ items: OrderItem[];
39
+ };
40
+ };
@@ -0,0 +1,40 @@
1
+ export type Customer = {
2
+ firstName: string;
3
+ lastName: string;
4
+ country: string;
5
+ street: string;
6
+ city: string;
7
+ state: string;
8
+ postCode: string;
9
+ email: string;
10
+ phone: string;
11
+ };
12
+ export type Business = {
13
+ vault_id: string;
14
+ vault_url: string;
15
+ openpay_keys: {
16
+ merchant_id: string;
17
+ public_key: string;
18
+ };
19
+ reference: string;
20
+ business: {
21
+ pk: string;
22
+ };
23
+ };
24
+ export type OrderItem = {
25
+ description: string;
26
+ quantity: number;
27
+ price_unit: number;
28
+ discount: number;
29
+ taxes: number;
30
+ product_reference: number;
31
+ name: string;
32
+ amount_total: number;
33
+ };
34
+ export type PaymentData = {
35
+ customer: Customer;
36
+ cart: {
37
+ total: string | number;
38
+ items: OrderItem[];
39
+ };
40
+ };
@@ -0,0 +1,39 @@
1
+ type SkyflowRecord = {
2
+ method: string;
3
+ quorum?: boolean;
4
+ tableName: string;
5
+ fields?: {
6
+ [key: string]: string;
7
+ };
8
+ ID?: string;
9
+ tokenization?: boolean;
10
+ batchID?: string;
11
+ redaction?: "DEFAULT" | "REDACTED" | "MASKED" | "PLAIN_TEXT";
12
+ downloadURL?: boolean;
13
+ upsert?: string;
14
+ tokens?: {
15
+ [key: string]: string;
16
+ };
17
+ };
18
+ export type VaultRequest = {
19
+ records: SkyflowRecord[];
20
+ continueOnError?: boolean;
21
+ byot?: "DISABLE" | "ENABLE" | "ENABLE_STRICT";
22
+ };
23
+ export type TokensRequest = {
24
+ baseUrl: string;
25
+ vault_id: string;
26
+ vault_url: string;
27
+ apiKey: string;
28
+ signal: AbortSignal;
29
+ data: {
30
+ [key: string]: any;
31
+ };
32
+ };
33
+ export type TokensResponse = {
34
+ vaultID: string;
35
+ responses: {
36
+ [key: string]: string;
37
+ }[];
38
+ };
39
+ export {};
@@ -0,0 +1,39 @@
1
+ type SkyflowRecord = {
2
+ method: string;
3
+ quorum?: boolean;
4
+ tableName: string;
5
+ fields?: {
6
+ [key: string]: string;
7
+ };
8
+ ID?: string;
9
+ tokenization?: boolean;
10
+ batchID?: string;
11
+ redaction?: "DEFAULT" | "REDACTED" | "MASKED" | "PLAIN_TEXT";
12
+ downloadURL?: boolean;
13
+ upsert?: string;
14
+ tokens?: {
15
+ [key: string]: string;
16
+ };
17
+ };
18
+ export type VaultRequest = {
19
+ records: SkyflowRecord[];
20
+ continueOnError?: boolean;
21
+ byot?: "DISABLE" | "ENABLE" | "ENABLE_STRICT";
22
+ };
23
+ export type TokensRequest = {
24
+ baseUrl: string;
25
+ vault_id: string;
26
+ vault_url: string;
27
+ apiKey: string;
28
+ signal: AbortSignal;
29
+ data: {
30
+ [key: string]: any;
31
+ };
32
+ };
33
+ export type TokensResponse = {
34
+ vaultID: string;
35
+ responses: {
36
+ [key: string]: string;
37
+ }[];
38
+ };
39
+ export {};
@@ -0,0 +1,50 @@
1
+ import { Checkout } from './classes/checkout'
2
+ export {
3
+ Checkout,
4
+ }
5
+
6
+ const config = {
7
+ url: "http://localhost:8081/#/",
8
+ apiKey: "e0f89d5328398b93634f56ba06c9474ec9388d5e",
9
+ type: "payment",
10
+ backgroundColor: "#F34616",
11
+ color: "#F3F7F6"
12
+ }
13
+ const tonderCheckout = new Checkout(config)
14
+ const params = {
15
+ shippingCost: "129.99",
16
+ email: "fuentesc91@gmail.com"
17
+ }
18
+ tonderCheckout.setOrder(params)
19
+
20
+ let products = {products: [
21
+ {
22
+ name: 'first product',
23
+ price_unit: 120.99,
24
+ quantity: 1
25
+ },
26
+ {
27
+ name: 'second product',
28
+ price_unit: 12.99,
29
+ }
30
+ ]}
31
+
32
+ tonderCheckout.setOrder(products)
33
+
34
+ products = {products: [
35
+ {
36
+ name: 'first product',
37
+ price_unit: 120.99,
38
+ quantity: 3
39
+ },
40
+ {
41
+ name: 'second product',
42
+ price_unit: 12.99,
43
+ }
44
+ ]}
45
+
46
+ tonderCheckout.setOrder(products)
47
+
48
+ console.log(tonderCheckout.getUrlParams())
49
+
50
+ tonderCheckout.mountButton({ buttonText: 'Proceder al pago' })
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@tonder.io/ionic-full-sdk",
3
+ "version": "0.0.1",
4
+ "description": "Tonder ionic full SDK",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.js",
7
+ "scripts": {
8
+ "build": "tsc -noEmit && rollup --config"
9
+ },
10
+ "author": "",
11
+ "license": "ISC",
12
+ "dependencies": {
13
+ "@tonder.io/ionic-lite-sdk": "^0.0.6",
14
+ "crypto-js": "^4.1.1",
15
+ "skyflow-js": "^1.34.1"
16
+ },
17
+ "devDependencies": {
18
+ "@rollup/plugin-terser": "^0.4.4",
19
+ "@rollup/plugin-typescript": "^11.1.6",
20
+ "@types/crypto-js": "^4.2.2",
21
+ "@types/node": "^20.11.5",
22
+ "cypress": "^13.6.2",
23
+ "rollup": "^4.9.6",
24
+ "ts-loader": "^9.5.1",
25
+ "typescript": "^5.3.3"
26
+ }
27
+ }
@@ -0,0 +1,15 @@
1
+ const typescript = require('@rollup/plugin-typescript');
2
+ const terser = require('@rollup/plugin-terser');
3
+
4
+ module.exports = {
5
+ input: './src/index.ts',
6
+ output: {
7
+ dir: 'dist',
8
+ format: 'es',
9
+ plugins: [terser()]
10
+ },
11
+ plugins: [
12
+ typescript()
13
+ ],
14
+ external: ["skyflow-js", "crypto-js", "@tonder.io/ionic-lite-sdk"]
15
+ };
@@ -0,0 +1,103 @@
1
+ type ThreeDSHandlerContructor = {
2
+ payload?: any,
3
+ apiKey?: string,
4
+ baseUrl?: string,
5
+ successUrl?: Location | string
6
+ }
7
+
8
+ export class ThreeDSHandler {
9
+
10
+ baseUrl?: string
11
+ apiKey?: string
12
+ payload?: any
13
+ successUrl?: Location | string
14
+
15
+ constructor({
16
+ payload = null,
17
+ apiKey,
18
+ baseUrl,
19
+ successUrl
20
+ }: ThreeDSHandlerContructor) {
21
+ this.baseUrl = baseUrl,
22
+ this.apiKey = apiKey,
23
+ this.payload = payload,
24
+ this.successUrl = successUrl
25
+ }
26
+
27
+ saveVerifyTransactionUrl() {
28
+ const url = this.payload?.next_action?.redirect_to_url?.verify_transaction_status_url
29
+ if (url) {
30
+ localStorage.setItem("verify_transaction_status_url", url)
31
+ }
32
+ }
33
+
34
+ removeVerifyTransactionUrl() {
35
+ localStorage.removeItem("verify_transaction_status_url")
36
+ }
37
+
38
+ getVerifyTransactionUrl() {
39
+ return localStorage.getItem("verify_transaction_status_url")
40
+ }
41
+
42
+ redirectTo3DS() {
43
+ const url = this.payload?.next_action?.redirect_to_url?.url
44
+ if (url) {
45
+ this.saveVerifyTransactionUrl()
46
+ window.open('@tonder/ionic-full-sdk://', '_system')
47
+ // window.open(url, '_blank');
48
+ return true
49
+ } else {
50
+ console.log('No redirection found');
51
+ return false
52
+ }
53
+ }
54
+
55
+ // Returns an object
56
+ // https://example.com/?name=John&age=30&city=NewYork
57
+ // { name: "John", age: "30", city: "NewYork" }
58
+ getURLParameters() {
59
+ const parameters: any = {};
60
+ const urlParams: any = new URLSearchParams(window.location.search);
61
+
62
+ for (const [key, value] of urlParams) {
63
+ parameters[key] = value;
64
+ }
65
+
66
+ return parameters;
67
+ }
68
+
69
+ async verifyTransactionStatus() {
70
+ const verifyUrl = this.getVerifyTransactionUrl();
71
+
72
+ if (verifyUrl) {
73
+ const url = `${this.baseUrl}${verifyUrl}`;
74
+ try {
75
+ const response = await fetch(url, {
76
+ method: "GET",
77
+ headers: {
78
+ "Content-Type": "application/json",
79
+ Authorization: `Token ${this.apiKey}`,
80
+ },
81
+ // body: JSON.stringify(data),
82
+ });
83
+
84
+ if (response.status === 200) {
85
+ this.removeVerifyTransactionUrl();
86
+ //@ts-ignore
87
+ window.location = this.successUrl
88
+ console.log('La transacción se verificó con éxito.');
89
+ return response;
90
+ } else {
91
+ console.error('La verificación de la transacción falló.');
92
+ return null;
93
+ }
94
+ } catch (error) {
95
+ console.error('Error al verificar la transacción:', error);
96
+ return error;
97
+ }
98
+ } else {
99
+ console.log('No verify_transaction_status_url found');
100
+ return null;
101
+ }
102
+ }
103
+ }
@@ -0,0 +1,148 @@
1
+ import { AES } from "crypto-js";
2
+
3
+ type CheckoutType = {
4
+ apiKey?: string,
5
+ type: string,
6
+ backgroundColor: string,
7
+ color: string,
8
+ cb: (params?: any)=> void,
9
+ url: string,
10
+ }
11
+
12
+ export class Checkout {
13
+
14
+ url: string
15
+ apiKey?: string
16
+ type: string
17
+ backgroundColor: string
18
+ color: string
19
+ params: string
20
+ order: any
21
+ buttonText: string
22
+ cb: (params: any) => void
23
+ tonderButton: any
24
+
25
+ constructor({
26
+ apiKey,
27
+ type = "payment",
28
+ backgroundColor="#141414",
29
+ color="#EBEBEB",
30
+ cb=()=>{},
31
+ url="http://checkout.tonder.io/#/"
32
+ }: CheckoutType) {
33
+ this.url = url
34
+ this.apiKey = apiKey
35
+ this.type = type
36
+ this.backgroundColor = backgroundColor
37
+ this.color = color
38
+ this.params = ""
39
+ this.order = {}
40
+ this.buttonText = "Proceder al pago"
41
+ this.cb = cb
42
+
43
+ window.addEventListener("message", this.receiveMessage.bind(this), false);
44
+ }
45
+ generateButton = (buttonText: string) => {
46
+ this.buttonText = buttonText ? buttonText : this.buttonText
47
+ this.tonderButton = document.createElement('button');
48
+ this.tonderButton.innerHTML = this.buttonText;
49
+ this.stylishButton(this.tonderButton)
50
+ this.tonderButton.onclick = this.openCheckout
51
+ }
52
+ getButton = ({ buttonText }: { buttonText: string }) => {
53
+ this.generateButton(buttonText)
54
+ return this.tonderButton
55
+ }
56
+ mountButton = ({ buttonText }: { buttonText: string }) => {
57
+ this.generateButton(buttonText)
58
+ const entryPoint: HTMLElement | null = document.getElementById("tonder-checkout")
59
+ try {
60
+ if(entryPoint) {
61
+ entryPoint.innerHTML = ""
62
+ entryPoint.append(this.tonderButton)
63
+ }
64
+ } catch(error) {
65
+ console.error(error)
66
+ }
67
+ }
68
+ stylishButton = (element: HTMLElement) => {
69
+ element.style.backgroundColor = this.backgroundColor
70
+ element.style.color = this.color
71
+ element.style.display = 'flex'
72
+ element.style.justifyContent = 'center'
73
+ element.style.border = 'none'
74
+ element.style.padding = '1rem'
75
+ element.style.borderRadius = '10px'
76
+ element.style.fontSize = '1rem'
77
+ element.style.width = '100%'
78
+ element.style.boxShadow = '0 3px 6px 0 rgba(0,0,0,0.16)'
79
+ }
80
+ setOrder = ({ products, email, shippingCost }: { products: any, email: string, shippingCost: string }) => {
81
+ let _order: any = {}
82
+ if (products) _order.products = products
83
+ if (email) _order.email = email
84
+ if (shippingCost) _order.shippingCost = shippingCost
85
+ this.order = {...this.order, ..._order}
86
+ return this.order
87
+ }
88
+ openTabListener = (tab: any, button: HTMLButtonElement) => {
89
+ const tabInterval = setInterval(() => {
90
+ if (tab.closed) {
91
+ clearInterval(tabInterval);
92
+ button.disabled = false
93
+ button.innerHTML = this.buttonText
94
+ }
95
+ }, 500)
96
+ }
97
+ openCheckout = () => {
98
+ const queryString = this.getUrlParams()
99
+ const encrypted = AES.encrypt(queryString, 'url-params-encrypt').toString()
100
+ const encodedURL = encodeURIComponent(encrypted);
101
+ this.params = "?" + encodedURL;
102
+ const newWindow = window.open(this.url + this.params, '_blank', `width=1200,height=$800,left=0,top=0`);
103
+ this.tonderButton.disabled = true
104
+ this.tonderButton.innerHTML = `
105
+ <div class="loader"></div>
106
+ <style>
107
+ .loader {
108
+ border: 4px solid ${this.color};
109
+ border-radius: 50%;
110
+ border-top: 4px solid ${this.backgroundColor};
111
+ width: 0.625rem;
112
+ height: 0.625rem;
113
+ -webkit-animation: spin 2s linear infinite; /* Safari */
114
+ animation: spin 2s linear infinite;
115
+ }
116
+
117
+ /* Safari */
118
+ @-webkit-keyframes spin {
119
+ 0% { -webkit-transform: rotate(0deg); }
120
+ 100% { -webkit-transform: rotate(360deg); }
121
+ }
122
+
123
+ @keyframes spin {
124
+ 0% { transform: rotate(0deg); }
125
+ 100% { transform: rotate(360deg); }
126
+ }
127
+ </style>
128
+ `
129
+ this.openTabListener(newWindow, this.tonderButton)
130
+ }
131
+ getUrlParams = () => {
132
+ const params = { apiKey: this.apiKey, ...this.order, type: this.type}
133
+ if (params.products) {
134
+ params.products = JSON.stringify(params.products)
135
+ }
136
+ const queryString = new URLSearchParams(params).toString();
137
+ return queryString
138
+ }
139
+ receiveMessage(event: any) {
140
+ // Parse data if it is possible, in case of error it will return the raw data.
141
+ try {
142
+ const data = JSON.parse(event.data)
143
+ this.cb(data)
144
+ } catch(error) {
145
+ this.cb(event.data)
146
+ }
147
+ }
148
+ }