tonder-web-sdk 1.11.11 → 1.12.0-beta.0

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,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="PrettierConfiguration">
4
+ <option name="myConfigurationMode" value="MANUAL" />
5
+ </component>
6
+ </project>
@@ -1,25 +1,56 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <project version="4">
3
+ <component name="AutoImportSettings">
4
+ <option name="autoReloadType" value="SELECTIVE" />
5
+ </component>
3
6
  <component name="ChangeListManager">
4
7
  <list default="true" id="37fc62e5-7dd0-4a2e-b68c-304069cdf5bd" name="Changes" comment="">
8
+ <change afterPath="$PROJECT_DIR$/.idea/prettier.xml" afterDir="false" />
9
+ <change afterPath="$PROJECT_DIR$/src/classes/BaseInlineCheckout.js" afterDir="false" />
10
+ <change afterPath="$PROJECT_DIR$/src/classes/LiteInlineCheckout.js" afterDir="false" />
11
+ <change afterPath="$PROJECT_DIR$/src/data/apmApi.js" afterDir="false" />
12
+ <change afterPath="$PROJECT_DIR$/src/data/businessApi.js" afterDir="false" />
13
+ <change afterPath="$PROJECT_DIR$/src/data/cardApi.js" afterDir="false" />
14
+ <change afterPath="$PROJECT_DIR$/src/data/checkoutApi.js" afterDir="false" />
15
+ <change afterPath="$PROJECT_DIR$/src/data/customerApi.js" afterDir="false" />
16
+ <change afterPath="$PROJECT_DIR$/src/data/index.js" afterDir="false" />
17
+ <change afterPath="$PROJECT_DIR$/src/data/openPayApi.js" afterDir="false" />
18
+ <change afterPath="$PROJECT_DIR$/src/data/skyflowApi.js" afterDir="false" />
19
+ <change afterPath="$PROJECT_DIR$/src/shared/constants/paymentMethodAPM.js" afterDir="false" />
20
+ <change afterPath="$PROJECT_DIR$/src/shared/constants/tonderUrl.js" afterDir="false" />
21
+ <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
5
22
  <change beforePath="$PROJECT_DIR$/package-lock.json" beforeDir="false" afterPath="$PROJECT_DIR$/package-lock.json" afterDir="false" />
23
+ <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
6
24
  <change beforePath="$PROJECT_DIR$/src/classes/inlineCheckout.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/classes/inlineCheckout.js" afterDir="false" />
25
+ <change beforePath="$PROJECT_DIR$/src/data/api.js" beforeDir="false" />
26
+ <change beforePath="$PROJECT_DIR$/src/helpers/constants.js" beforeDir="false" />
27
+ <change beforePath="$PROJECT_DIR$/src/helpers/skyflow.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/helpers/skyflow.js" afterDir="false" />
28
+ <change beforePath="$PROJECT_DIR$/src/helpers/utils.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/helpers/utils.js" afterDir="false" />
29
+ <change beforePath="$PROJECT_DIR$/src/index-dev.js" beforeDir="false" afterPath="$PROJECT_DIR$/src/index-dev.js" afterDir="false" />
30
+ <change beforePath="$PROJECT_DIR$/src/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/index.html" afterDir="false" />
7
31
  </list>
8
32
  <option name="SHOW_DIALOG" value="false" />
9
33
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
10
34
  <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
11
35
  <option name="LAST_RESOLUTION" value="IGNORE" />
12
36
  </component>
37
+ <component name="FileTemplateManagerImpl">
38
+ <option name="RECENT_TEMPLATES">
39
+ <list>
40
+ <option value="JavaScript File" />
41
+ </list>
42
+ </option>
43
+ </component>
13
44
  <component name="Git.Settings">
14
45
  <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
15
46
  </component>
16
47
  <component name="MarkdownSettingsMigration">
17
48
  <option name="stateVersion" value="1" />
18
49
  </component>
19
- <component name="ProjectColorInfo"><![CDATA[{
20
- "customColor": "",
21
- "associatedIndex": 2
22
- }]]></component>
50
+ <component name="ProjectColorInfo">{
51
+ &quot;customColor&quot;: &quot;&quot;,
52
+ &quot;associatedIndex&quot;: 2
53
+ }</component>
23
54
  <component name="ProjectId" id="2iy5RvaLleBBnn8yOfQNLpzKK66" />
24
55
  <component name="ProjectViewState">
25
56
  <option name="autoscrollFromSource" value="true" />
@@ -30,19 +61,41 @@
30
61
  </component>
31
62
  <component name="PropertiesComponent"><![CDATA[{
32
63
  "keyToString": {
64
+ "Node.js.index-dev.js.executor": "Run",
33
65
  "RunOnceActivity.OpenProjectViewOnStart": "true",
34
66
  "RunOnceActivity.ShowReadmeOnStart": "true",
35
- "git-widget-placeholder": "Merging TNDR-1140",
67
+ "SHARE_PROJECT_CONFIGURATION_FILES": "true",
68
+ "git-widget-placeholder": "develop",
69
+ "last_opened_file_path": "/Users/davidhernandezalmagro/Desktop/Tonder/tonder-sdk/src/shared/constants",
70
+ "node.js.detected.package.eslint": "true",
71
+ "node.js.detected.package.tslint": "true",
72
+ "node.js.selected.package.eslint": "(autodetect)",
73
+ "node.js.selected.package.tslint": "(autodetect)",
36
74
  "nodejs_package_manager_path": "npm",
75
+ "prettierjs.PrettierConfiguration.Package": "/Users/davidhernandezalmagro/Desktop/Tonder/tonder-sdk/node_modules/prettier",
76
+ "settings.editor.selected.configurable": "settings.javascript.prettier",
77
+ "ts.external.directory.path": "/Applications/WebStorm.app/Contents/plugins/javascript-impl/jsLanguageServicesImpl/external",
37
78
  "vue.rearranger.settings.migration": "true"
38
79
  }
39
80
  }]]></component>
40
- <component name="SharedIndexes">
41
- <attachedChunks>
42
- <set>
43
- <option value="bundled-python-sdk-50da183f06c8-2887949eec09-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-233.13135.95" />
44
- </set>
45
- </attachedChunks>
81
+ <component name="RecentsManager">
82
+ <key name="CopyFile.RECENT_KEYS">
83
+ <recent name="$PROJECT_DIR$/src/shared/constants" />
84
+ </key>
85
+ <key name="MoveFile.RECENT_KEYS">
86
+ <recent name="$PROJECT_DIR$/src/shared/constants" />
87
+ <recent name="$PROJECT_DIR$/src/shared" />
88
+ </key>
89
+ </component>
90
+ <component name="RunManager">
91
+ <configuration name="index-dev.js" type="NodeJSConfigurationType" temporary="true" nameIsGenerated="true" path-to-js-file="$PROJECT_DIR$/src/index-dev.js" working-dir="$PROJECT_DIR$/src">
92
+ <method v="2" />
93
+ </configuration>
94
+ <recent_temporary>
95
+ <list>
96
+ <item itemvalue="Node.js.index-dev.js" />
97
+ </list>
98
+ </recent_temporary>
46
99
  </component>
47
100
  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
48
101
  <component name="TaskManager">
@@ -53,10 +106,42 @@
53
106
  <option name="presentableId" value="Default" />
54
107
  <updated>1720449973301</updated>
55
108
  <workItem from="1720449976262" duration="22000" />
109
+ <workItem from="1723519348652" duration="9602000" />
110
+ <workItem from="1723696656585" duration="1227000" />
111
+ <workItem from="1723697920061" duration="3868000" />
112
+ <workItem from="1723774667217" duration="11739000" />
113
+ <workItem from="1723855727317" duration="20341000" />
114
+ <workItem from="1723952592527" duration="17418000" />
56
115
  </task>
57
116
  <servers />
58
117
  </component>
59
118
  <component name="TypeScriptGeneratedFilesManager">
60
119
  <option name="version" value="3" />
61
120
  </component>
121
+ <component name="Vcs.Log.Tabs.Properties">
122
+ <option name="TAB_STATES">
123
+ <map>
124
+ <entry key="MAIN">
125
+ <value>
126
+ <State />
127
+ </value>
128
+ </entry>
129
+ </map>
130
+ </option>
131
+ </component>
132
+ <component name="XDebuggerManager">
133
+ <breakpoint-manager>
134
+ <breakpoints>
135
+ <line-breakpoint enabled="true" type="javascript">
136
+ <url>file://$PROJECT_DIR$/src/classes/inlineCheckout.js</url>
137
+ <line>151</line>
138
+ <option name="timeStamp" value="1" />
139
+ </line-breakpoint>
140
+ <line-breakpoint enabled="true" type="javascript">
141
+ <url>file://$PROJECT_DIR$/src/shared/constants/paymentMethodAPM.js</url>
142
+ <option name="timeStamp" value="15" />
143
+ </line-breakpoint>
144
+ </breakpoints>
145
+ </breakpoint-manager>
146
+ </component>
62
147
  </project>
package/README.md CHANGED
@@ -138,14 +138,12 @@ const checkoutData = {
138
138
 
139
139
  const apiKey = "4c87c36e697e65ddfe288be0afbe7967ea0ab865";
140
140
  const returnUrl = "http://my-website:8080/checkout"
141
- const successUrl = "http://my-website:8080/success"
142
141
 
143
142
  // if using script tag, it should be initialized like this
144
143
  // new TonderSdk.InlineCheckout
145
144
  const inlineCheckout = new InlineCheckout({
146
145
  apiKey,
147
146
  returnUrl,
148
- successUrl,
149
147
  styles: customStyles
150
148
  });
151
149
 
@@ -179,7 +177,6 @@ const response = await inlineCheckout.payment(checkoutData);
179
177
  | apiKey | string | You can take this from you Tonder Dashboard |
180
178
  | backgroundColor | string | Hex color #000000 |
181
179
  | returnUrl | string | url where the checkout form is mounted (3ds) |
182
- | successUrl | string | |
183
180
  | backgroundColor | string | |
184
181
 
185
182
  ## setPayment params
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tonder-web-sdk",
3
- "version": "1.11.11",
3
+ "version": "1.12.0-beta.0",
4
4
  "description": "tonder sdk for integrations",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -8,6 +8,7 @@
8
8
  "build": "webpack --config webpack.config.js --mode production"
9
9
  },
10
10
  "author": "",
11
+ "types": "types/index.d.ts",
11
12
  "license": "ISC",
12
13
  "dependencies": {
13
14
  "crypto-js": "^4.1.1",
@@ -20,6 +21,7 @@
20
21
  "css-loader": "^6.7.3",
21
22
  "cypress": "^13.6.2",
22
23
  "html-webpack-plugin": "^5.5.3",
24
+ "prettier": "^3.3.3",
23
25
  "style-loader": "^3.3.1",
24
26
  "terser-webpack-plugin": "^5.3.10",
25
27
  "webpack": "^5.75.0",
@@ -3,12 +3,10 @@ export class ThreeDSHandler {
3
3
  payload = null,
4
4
  apiKey,
5
5
  baseUrl,
6
- successUrl
7
6
  }) {
8
7
  this.baseUrl = baseUrl,
9
8
  this.apiKey = apiKey,
10
- this.payload = payload,
11
- this.successUrl = successUrl
9
+ this.payload = payload
12
10
  }
13
11
 
14
12
  saveVerifyTransactionUrl() {
@@ -120,7 +118,6 @@ export class ThreeDSHandler {
120
118
  // TODO: Remove this duplication
121
119
  handleSuccessTransaction(response) {
122
120
  this.removeVerifyTransactionUrl();
123
- // window.location = this.successUrl
124
121
  console.log('Transacción autorizada');
125
122
  return response;
126
123
  }
@@ -0,0 +1,298 @@
1
+ import { ThreeDSHandler } from "./3dsHandler.js";
2
+ import {createOrder, fetchBusiness, getOpenpayDeviceSessionID, registerOrFetchCustomer} from "../data";
3
+ import { TONDER_URL_BY_MODE } from "../shared/constants/tonderUrl";
4
+ import { globalLoader } from "./globalLoader";
5
+ import {createPayment, startCheckoutRouter} from "../data/checkoutApi";
6
+ import {getBrowserInfo, injectMercadoPagoSecurity} from "../helpers/utils";
7
+
8
+ export class BaseInlineCheckout {
9
+ baseUrl = "";
10
+ cartTotal = "0"
11
+ constructor({
12
+ mode = "stage",
13
+ apiKey,
14
+ returnUrl,
15
+ callBack = () => {},
16
+ sdkMode = "full",
17
+ }) {
18
+ this.apiKeyTonder = apiKey;
19
+ this.returnUrl = returnUrl;
20
+ this.callBack = callBack;
21
+ this.mode = mode;
22
+ this.baseUrl = TONDER_URL_BY_MODE[this.mode] || TONDER_URL_BY_MODE["stage"];
23
+ this.abortController = new AbortController();
24
+ this.process3ds = new ThreeDSHandler({
25
+ apiKey: apiKey,
26
+ baseUrl: this.baseUrl,
27
+ });
28
+ this.sdkMode = sdkMode;
29
+ }
30
+
31
+ configureCheckout(data) {
32
+ if ("customer" in data) this.#handleCustomer(data["customer"]);
33
+ }
34
+
35
+ async verify3dsTransaction() {
36
+ globalLoader.show(); // TODO: HOW?
37
+ const result3ds = await this.process3ds.verifyTransactionStatus();
38
+ const resultCheckout = await this.#resumeCheckout(result3ds);
39
+ this.process3ds.setPayload(resultCheckout);
40
+ globalLoader.remove(); // TODO: HOW?
41
+ return this.#handle3dsRedirect(resultCheckout);
42
+ }
43
+
44
+ payment(data) {
45
+ return new Promise(async (resolve, reject) => {
46
+ try {
47
+ this.#handleCustomer(data.customer);
48
+ this._setCartTotal(data.cart?.total);
49
+ this.#setCartItems(data.cart?.items);
50
+ this.#handleMetadata(data);
51
+ this.#handleCurrency(data);
52
+ this.#handleCard(data);
53
+ const response = await this._checkout(data);
54
+ this.process3ds.setPayload(response);
55
+ this.callBack(response);
56
+ const payload = await this.#handle3dsRedirect(response);
57
+ if (payload) {
58
+ resolve(response);
59
+ }
60
+ } catch (error) {
61
+ reject(error);
62
+ }
63
+ });
64
+ }
65
+
66
+ async _initializeCheckout() {
67
+ const { mercado_pago } = await this.#fetchMerchantData();
68
+
69
+ if (!!mercado_pago && !!mercado_pago.active) {
70
+ injectMercadoPagoSecurity();
71
+ }
72
+ }
73
+
74
+ async _getCustomer(customer, signal) {
75
+ return await registerOrFetchCustomer(
76
+ this.baseUrl,
77
+ this.apiKeyTonder,
78
+ customer,
79
+ signal,
80
+ );
81
+ }
82
+
83
+ async _checkout() {
84
+ throw new Error(
85
+ "The #checkout method should be implement in child classes.",
86
+ );
87
+ }
88
+
89
+ _setCartTotal(total) {
90
+ throw new Error(
91
+ "The #setCartTotal method should be implement in child classes.",
92
+ );
93
+ }
94
+
95
+ async _handleCheckout(
96
+ {
97
+ card,
98
+ payment_method,
99
+ customer
100
+ }
101
+ ) {
102
+ const { openpay_keys, reference, business } = this.merchantData;
103
+ const total = Number(this.cartTotal);
104
+
105
+ try {
106
+ let deviceSessionIdTonder;
107
+ if (
108
+ !deviceSessionIdTonder &&
109
+ openpay_keys.merchant_id &&
110
+ openpay_keys.public_key
111
+ ) {
112
+ deviceSessionIdTonder = await getOpenpayDeviceSessionID(
113
+ openpay_keys.merchant_id,
114
+ openpay_keys.public_key,
115
+ this.abortController.signal,
116
+ );
117
+ }
118
+
119
+ const { id, auth_token } = customer;
120
+
121
+ const orderItems = {
122
+ business: this.apiKeyTonder,
123
+ client: auth_token,
124
+ billing_address_id: null,
125
+ shipping_address_id: null,
126
+ amount: total,
127
+ status: "A",
128
+ reference: reference,
129
+ is_oneclick: true,
130
+ items: this.cartItems,
131
+ };
132
+ const jsonResponseOrder = await createOrder(
133
+ this.baseUrl,
134
+ this.apiKeyTonder,
135
+ orderItems,
136
+ );
137
+
138
+ // Create payment
139
+ const now = new Date();
140
+ const dateString = now.toISOString();
141
+
142
+ const paymentItems = {
143
+ business_pk: business.pk,
144
+ client_id: id,
145
+ amount: total,
146
+ date: dateString,
147
+ order_id: jsonResponseOrder.id,
148
+ };
149
+ const jsonResponsePayment = await createPayment(
150
+ this.baseUrl,
151
+ this.apiKeyTonder,
152
+ paymentItems,
153
+ );
154
+
155
+ // Checkout router
156
+ const routerItems = {
157
+ name: this.firstName || "",
158
+ last_name: this.lastName || "",
159
+ email_client: this.email,
160
+ phone_number: this.phone,
161
+ return_url: this.returnUrl,
162
+ id_product: "no_id",
163
+ quantity_product: 1,
164
+ id_ship: "0",
165
+ instance_id_ship: "0",
166
+ amount: total,
167
+ title_ship: "shipping",
168
+ description: "transaction",
169
+ device_session_id: deviceSessionIdTonder ? deviceSessionIdTonder : null,
170
+ token_id: "",
171
+ order_id: jsonResponseOrder.id,
172
+ business_id: business.pk,
173
+ payment_id: jsonResponsePayment.pk,
174
+ source: "sdk",
175
+ metadata: this.metadata,
176
+ browser_info: getBrowserInfo(),
177
+ currency: this.currency,
178
+ ...(!!payment_method ? { payment_method } : { card }),
179
+ ...(typeof MP_DEVICE_SESSION_ID !== "undefined"
180
+ ? { mp_device_session_id: MP_DEVICE_SESSION_ID }
181
+ : {}),
182
+ };
183
+
184
+ const jsonResponseRouter = await startCheckoutRouter(
185
+ this.baseUrl,
186
+ this.apiKeyTonder,
187
+ routerItems,
188
+ );
189
+
190
+ if (jsonResponseRouter) {
191
+ return jsonResponseRouter;
192
+ } else {
193
+ return false;
194
+ }
195
+ } catch (error) {
196
+ console.log(error);
197
+ throw error;
198
+ }
199
+ }
200
+
201
+ async #fetchMerchantData() {
202
+ this.merchantData = await fetchBusiness(
203
+ this.baseUrl,
204
+ this.apiKeyTonder,
205
+ this.abortController.signal,
206
+ );
207
+ return this.merchantData;
208
+ }
209
+
210
+ async #resumeCheckout(response) {
211
+ // Stop the routing process if the transaction is either hard declined or successful
212
+ if (response?.decline?.error_type === "Hard") {
213
+ return response;
214
+ }
215
+
216
+ if (["Success", "Authorized"].includes(response?.transaction_status)) {
217
+ return response;
218
+ }
219
+
220
+ if (response) {
221
+ globalLoader.show();
222
+ const routerItems = {
223
+ checkout_id: response?.checkout?.id,
224
+ };
225
+ try {
226
+ return await startCheckoutRouter(
227
+ this.baseUrl,
228
+ this.apiKeyTonder,
229
+ routerItems,
230
+ );
231
+ } catch (error) {
232
+ // throw error
233
+ } finally {
234
+ globalLoader.remove();
235
+ }
236
+ return response;
237
+ }
238
+ }
239
+
240
+ #handleCustomer(customer) {
241
+ if (!customer) return;
242
+
243
+ this.firstName = customer?.firstName;
244
+ this.lastName = customer?.lastName;
245
+ this.country = customer?.country;
246
+ this.address = customer?.street;
247
+ this.city = customer?.city;
248
+ this.state = customer?.state;
249
+ this.postCode = customer?.postCode;
250
+ this.email = customer?.email;
251
+ this.phone = customer?.phone;
252
+ this.customer = customer;
253
+ }
254
+
255
+ #handleMetadata(data) {
256
+ this.metadata = data?.metadata;
257
+ }
258
+
259
+ #handleCurrency(data) {
260
+ this.currency = data?.currency;
261
+ }
262
+
263
+ #handleCard(data) {
264
+ this.card = data?.card;
265
+ }
266
+
267
+ #setCartItems(items) {
268
+ this.cartItems = items;
269
+ }
270
+
271
+ async #handle3dsRedirect(response) {
272
+ const iframe = response?.next_action?.iframe_resources?.iframe;
273
+
274
+ if (iframe) {
275
+ this.process3ds
276
+ .loadIframe()
277
+ .then(() => {
278
+ //TODO: Check if this will be necessary on the frontend side
279
+ // after some the tests in production, since the 3DS process
280
+ // doesn't works properly on the sandbox environment
281
+ // setTimeout(() => {
282
+ // process3ds.verifyTransactionStatus();
283
+ // }, 10000);
284
+ this.process3ds.verifyTransactionStatus();
285
+ })
286
+ .catch((error) => {
287
+ console.log("Error loading iframe:", error);
288
+ });
289
+ } else {
290
+ const redirectUrl = this.process3ds.getRedirectUrl();
291
+ if (redirectUrl) {
292
+ this.process3ds.redirectToChallenge();
293
+ } else {
294
+ return response;
295
+ }
296
+ }
297
+ }
298
+ }
@@ -0,0 +1,101 @@
1
+ import { BaseInlineCheckout } from "./BaseInlineCheckout";
2
+ import {
3
+ fetchCustomerAPMs,
4
+ fetchCustomerCards,
5
+ saveCustomerCard,
6
+ removeCustomerCard,
7
+ } from "../data";
8
+ import { buildErrorResponseFromCatch } from "../helpers/utils";
9
+ import { getVaultToken } from "../data/skyflowApi";
10
+ import { getSkyflowTokens } from "../helpers/skyflow";
11
+
12
+ export class LiteInlineCheckout extends BaseInlineCheckout {
13
+ constructor({ mode = "stage", apiKey, returnUrl, callBack = () => {} }) {
14
+ super({ mode, apiKey, returnUrl, callBack });
15
+ }
16
+
17
+ async injectCheckout() {
18
+ await this._initializeCheckout();
19
+ }
20
+
21
+ /**
22
+ * Retrieves the list of cards associated with a customer.
23
+ * @param {string} authToken - The customer's authentication token.
24
+ * @param {string} businessId - The business primary key.
25
+ * @returns {Promise<Object>} A promise that resolves with the customer's card data.
26
+ * @public
27
+ */
28
+ async getCustomerCards(authToken, businessId) {
29
+ return await fetchCustomerCards(this.baseUrl, authToken, businessId);
30
+ }
31
+
32
+ /**
33
+ * Saves a card to a customer's account. This method can be used to add a new card
34
+ * or update an existing one.
35
+ * @param {string} authToken - The customer's authentication token.
36
+ * @param {string} businessId - The business primary key.
37
+ * @param {Object} cardData - The card information to be saved.
38
+ * @returns {Promise<Object>} A promise that resolves with the saved card data.
39
+ * @public
40
+ */
41
+ async saveCustomerCard(authToken, businessId, cardData) {
42
+ return await saveCustomerCard(
43
+ this.baseUrl,
44
+ authToken,
45
+ businessId,
46
+ cardData,
47
+ );
48
+ }
49
+
50
+ /**
51
+ * Removes a card from a customer's account.
52
+ * @param {string} authToken - The customer's authentication token.
53
+ * @param {string} skyflowId - The unique identifier of the card to be deleted.
54
+ * @param {string} businessId - The business primary key.
55
+ * @returns {Promise<Object>} A promise that resolves when the card is successfully deleted.
56
+ * @public
57
+ */
58
+ async removeCustomerCard(authToken, skyflowId, businessId) {
59
+ return await removeCustomerCard(
60
+ this.baseUrl,
61
+ authToken,
62
+ skyflowId,
63
+ businessId,
64
+ );
65
+ }
66
+
67
+ /**
68
+ * Retrieves the list of available Alternative Payment Methods (APMs).
69
+ * @returns {Promise<Object>} A promise that resolves with the list of APMs.
70
+ * @public
71
+ */
72
+ async getCustomerAPMs() {
73
+ return await fetchCustomerAPMs(this.baseUrl, this.apiKeyTonder);
74
+ }
75
+
76
+ _setCartTotal(total) {
77
+ this.cartTotal = total;
78
+ }
79
+
80
+ async _checkout({ card, payment_method }) {
81
+ const customer = await this._getCustomer(
82
+ this.customer,
83
+ this.abortController.signal,
84
+ );
85
+ const { vault_id, vault_url } = this.merchantData;
86
+ let skyflowTokens;
87
+ skyflowTokens = await getSkyflowTokens({
88
+ vault_id: vault_id,
89
+ vault_url: vault_url,
90
+ data: card,
91
+ baseUrl: this.baseUrl,
92
+ apiKey: this.apiKeyTonder,
93
+ });
94
+
95
+ return await this._handleCheckout({
96
+ card: skyflowTokens,
97
+ payment_method,
98
+ customer,
99
+ });
100
+ }
101
+ }