@tonder.io/ionic-lite-sdk 0.0.26-beta → 0.0.29-beta
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.
- package/README.md +78 -0
- package/dist/classes/liteCheckout.d.ts +2 -1
- package/dist/helpers/utils.d.ts +9 -3
- package/dist/index.js +1 -1
- package/dist/types/requests.d.ts +24 -0
- package/package.json +1 -1
- package/src/classes/liteCheckout.ts +123 -1
- package/src/helpers/utils.ts +12 -37
- package/src/types/requests.ts +25 -0
- package/tests/methods/startCheckoutRouterFull.test.ts +139 -0
- package/tests/utils/mockClasses.ts +51 -1
package/README.md
CHANGED
|
@@ -437,6 +437,84 @@ const jsonResponseRouter = await liteCheckout.startCheckoutRouter(
|
|
|
437
437
|
|
|
438
438
|
## Take actions on base to the checkout router response
|
|
439
439
|
|
|
440
|
+
# Checkout router full
|
|
441
|
+
|
|
442
|
+
<font size="4">This method integrate the create order, create payment and checkout router methods into one method, the info required to this method is:</font>
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
|
|
446
|
+
const returnUrl = "http://localhost:8100/payment/success";
|
|
447
|
+
|
|
448
|
+
let checkoutData = {
|
|
449
|
+
customer: {
|
|
450
|
+
name: "Jhon",
|
|
451
|
+
lastname: "Doe",
|
|
452
|
+
email: "john.c.calhoun@examplepetstore.com",
|
|
453
|
+
phone: "+58452258525"
|
|
454
|
+
},
|
|
455
|
+
order: {
|
|
456
|
+
items: [
|
|
457
|
+
{
|
|
458
|
+
description: "Test product description",
|
|
459
|
+
quantity: 1,
|
|
460
|
+
price_unit: 25,
|
|
461
|
+
discount: 1,
|
|
462
|
+
taxes: 12,
|
|
463
|
+
product_reference: 89456123,
|
|
464
|
+
name: "Test product",
|
|
465
|
+
amount_total: 25
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
},
|
|
469
|
+
return_url: returnUrl,
|
|
470
|
+
total: 25,
|
|
471
|
+
isSandbox: true,
|
|
472
|
+
metadata: {},
|
|
473
|
+
currency: "MXN",
|
|
474
|
+
skyflowTokens: {
|
|
475
|
+
cardholder_name: "",
|
|
476
|
+
card_number: "",
|
|
477
|
+
expiration_year: "",
|
|
478
|
+
expiration_month: "",
|
|
479
|
+
cvv: "",
|
|
480
|
+
skyflow_id: ""
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
<font size="4">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</font>
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
|
|
490
|
+
const merchantData: any = await liteCheckout.getBusiness();
|
|
491
|
+
|
|
492
|
+
const { vault_id, vault_url } = merchantData;
|
|
493
|
+
|
|
494
|
+
const skyflowFields = {
|
|
495
|
+
card_number: this.paymentForm.value.cardNumber,
|
|
496
|
+
cvv: this.paymentForm.value.cvv,
|
|
497
|
+
expiration_month: this.paymentForm.value.month,
|
|
498
|
+
expiration_year: this.paymentForm.value.expirationYear,
|
|
499
|
+
cardholder_name: this.paymentForm.value.name
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const skyflowTokens = await liteCheckout.getSkyflowTokens({
|
|
503
|
+
vault_id: vault_id,
|
|
504
|
+
vault_url: vault_url,
|
|
505
|
+
data: skyflowFields
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
checkoutData.skyflowTokens = skyflowTokens;
|
|
509
|
+
|
|
510
|
+
const jsonResponseRouter: any = await liteCheckout.startCheckoutRouterFull(
|
|
511
|
+
checkoutData
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
<font size="4">The response is the same to the startCheckoutRouter method. Take actions on base to the checkout router response</font>
|
|
517
|
+
|
|
440
518
|
# Customer Cards(Register)
|
|
441
519
|
|
|
442
520
|
## Register customer card
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CollectContainer from "skyflow-js/types/core/external/collect/collect-container";
|
|
2
|
-
import { CreateOrderRequest, CreatePaymentRequest, RegisterCustomerCardRequest, StartCheckoutRequest, TokensRequest } from "../types/requests";
|
|
2
|
+
import { CreateOrderRequest, CreatePaymentRequest, RegisterCustomerCardRequest, StartCheckoutRequest, TokensRequest, StartCheckoutFullRequest } from "../types/requests";
|
|
3
3
|
import { GetBusinessResponse, CustomerRegisterResponse, CreateOrderResponse, CreatePaymentResponse, StartCheckoutResponse, GetCustomerCardsResponse, RegisterCustomerCardResponse } from "../types/responses";
|
|
4
4
|
import { ErrorResponse } from "./errorResponse";
|
|
5
5
|
declare global {
|
|
@@ -23,6 +23,7 @@ export declare class LiteCheckout implements LiteCheckoutConstructor {
|
|
|
23
23
|
createOrder(orderItems: CreateOrderRequest): Promise<CreateOrderResponse | ErrorResponse>;
|
|
24
24
|
createPayment(paymentItems: CreatePaymentRequest): Promise<CreatePaymentResponse | ErrorResponse>;
|
|
25
25
|
startCheckoutRouter(routerData: StartCheckoutRequest): Promise<StartCheckoutResponse | ErrorResponse>;
|
|
26
|
+
startCheckoutRouterFull(routerFullData: StartCheckoutFullRequest): Promise<StartCheckoutResponse | ErrorResponse>;
|
|
26
27
|
getSkyflowTokens({ vault_id, vault_url, data, }: TokensRequest): Promise<any | ErrorResponse>;
|
|
27
28
|
getVaultToken(): Promise<string>;
|
|
28
29
|
getFieldsPromise(data: any, collectContainer: CollectContainer): Promise<Promise<boolean>[]>;
|
package/dist/helpers/utils.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export declare const getBrowserInfo: () => {
|
|
2
|
+
javascript_enabled: boolean;
|
|
3
|
+
time_zone: number;
|
|
4
|
+
language: string;
|
|
5
|
+
color_depth: number | null;
|
|
6
|
+
screen_width: number | null;
|
|
7
|
+
screen_height: number | null;
|
|
8
|
+
user_agent: string;
|
|
9
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"skyflow-js";function t(e,t,
|
|
1
|
+
import e from"skyflow-js";function t(e,t,i,r){return new(i||(i=Promise))((function(o,n){function s(e){try{a(r.next(e))}catch(e){n(e)}}function d(e){try{a(r.throw(e))}catch(e){n(e)}}function a(e){var t;e.done?o(e.value):(t=e.value,t instanceof i?t:new i((function(e){e(t)}))).then(s,d)}a((r=r.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class i{constructor({code:e,body:t,name:i,message:r,stack:o}){this.code=e,this.body=t,this.name=i,this.message=r,this.stack=o}}class r{constructor({signal:e,baseUrlTonder:t,apiKeyTonder:i}){this.baseUrlTonder=t,this.signal=e,this.apiKeyTonder=i}getOpenpayDeviceSessionID(e,i,r){return t(this,void 0,void 0,(function*(){try{let t=yield window.OpenPay;return t.setId(e),t.setApiKey(i),t.setSandboxMode(r),yield t.deviceData.setup({signal:this.signal})}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}getBusiness(){return t(this,void 0,void 0,(function*(){try{const e=yield fetch(`${this.baseUrlTonder}/api/v1/payments/business/${this.apiKeyTonder}`,{headers:{Authorization:`Token ${this.apiKeyTonder}`},signal:this.signal});if(e.ok)return yield e.json();throw yield this.buildErrorResponse(e)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}customerRegister(e){return t(this,void 0,void 0,(function*(){try{const t=`${this.baseUrlTonder}/api/v1/customer/`,i={email:e},r=yield fetch(t,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Token ${this.apiKeyTonder}`},signal:this.signal,body:JSON.stringify(i)});if(r.ok)return yield r.json();throw yield this.buildErrorResponse(r)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}createOrder(e){return t(this,void 0,void 0,(function*(){try{const t=`${this.baseUrlTonder}/api/v1/orders/`,i=e,r=yield fetch(t,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Token ${this.apiKeyTonder}`},body:JSON.stringify(i)});if(r.ok)return yield r.json();throw yield this.buildErrorResponse(r)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}createPayment(e){return t(this,void 0,void 0,(function*(){try{const t=`${this.baseUrlTonder}/api/v1/business/${e.business_pk}/payments/`,i=e,r=yield fetch(t,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Token ${this.apiKeyTonder}`},body:JSON.stringify(i)});if(r.ok)return yield r.json();throw yield this.buildErrorResponse(r)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}startCheckoutRouter(e){return t(this,void 0,void 0,(function*(){try{const t=`${this.baseUrlTonder}/api/v1/checkout-router/`,i=e,r=yield fetch(t,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Token ${this.apiKeyTonder}`},body:JSON.stringify(i)});if(r.ok)return yield r.json();throw yield this.buildErrorResponse(r)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}startCheckoutRouterFull(e){return t(this,void 0,void 0,(function*(){try{const{order:t,total:r,customer:o,skyflowTokens:n,return_url:s,isSandbox:d,metadata:a,currency:l}=e,h=yield this.getBusiness(),c=yield this.customerRegister(o.email);if(c&&"auth_token"in c&&h&&"reference"in h){const e={business:this.apiKeyTonder,client:c.auth_token,billing_address_id:null,shipping_address_id:null,amount:r,reference:h.reference,is_oneclick:!0,items:t.items},u=yield this.createOrder(e),y=(new Date).toISOString();if("id"in u&&"id"in c&&"business"in h){const e={business_pk:h.business.pk,amount:r,date:y,order_id:u.id,client_id:c.id},t=yield this.createPayment(e);let i;const{openpay_keys:p,business:m}=h;p.merchant_id&&p.public_key&&(i=yield this.getOpenpayDeviceSessionID(p.merchant_id,p.public_key,d));const v={card:n,name:n.cardholder_name,last_name:o.lastname,email_client:o.email,phone_number:o.phone,return_url:s,id_product:"no_id",quantity_product:1,id_ship:"0",instance_id_ship:"0",amount:r,title_ship:"shipping",description:"transaction",device_session_id:i||null,token_id:"",order_id:"id"in u&&u.id,business_id:m.pk,payment_id:"pk"in t&&t.pk,source:"sdk",metadata:a,browser_info:{javascript_enabled:!0,time_zone:(new Date).getTimezoneOffset(),language:navigator.language||"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,user_agent:navigator.userAgent},currency:l};return yield this.startCheckoutRouter(v)}throw new i({code:"500",body:u,name:"Keys error",message:"Order response errors"})}throw new i({code:"500",body:h,name:"Keys error",message:"Merchant or customer reposne errors"})}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}getSkyflowTokens({vault_id:i,vault_url:r,data:o}){return t(this,void 0,void 0,(function*(){const n=e.init({vaultID:i,vaultURL:r,getBearerToken:()=>t(this,void 0,void 0,(function*(){return yield this.getVaultToken()})),options:{logLevel:e.LogLevel.ERROR,env:e.Env.DEV}}).container(e.ContainerType.COLLECT),s=yield this.getFieldsPromise(o,n);if((yield Promise.all(s)).some((e=>!e)))throw this.buildErrorResponseFromCatch(Error("Ocurrió un error al montar los campos de la tarjeta"));try{const e=yield n.collect();if(e)return e.records[0].fields;throw this.buildErrorResponseFromCatch(Error("Por favor, verifica todos los campos de tu tarjeta"))}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}getVaultToken(){var e;return t(this,void 0,void 0,(function*(){try{const t=yield fetch(`${this.baseUrlTonder}/api/v1/vault-token/`,{method:"GET",headers:{Authorization:`Token ${this.apiKeyTonder}`},signal:this.signal});if(t.ok)return null===(e=yield t.json())||void 0===e?void 0:e.token;throw new Error(`HTTPCODE: ${t.status}`)}catch(e){throw new Error(`Failed to retrieve bearer token; ${"string"==typeof e?e:e.message}`)}}))}getFieldsPromise(e,i){return t(this,void 0,void 0,(function*(){const t=yield this.getFields(e,i);return t?t.map((t=>new Promise((i=>{var r;const o=document.createElement("div");o.hidden=!0,o.id=`id-${t.key}`,null===(r=document.querySelector("body"))||void 0===r||r.appendChild(o),setTimeout((()=>{t.element.mount(`#id-${t.key}`),setInterval((()=>{if(t.element.isMounted()){const r=e[t.key];return t.element.update({value:r}),i(t.element.isMounted())}}),120)}),120)})))):[]}))}registerCustomerCard(e,i){return t(this,void 0,void 0,(function*(){try{const t=yield fetch(`${this.baseUrlTonder}/api/v1/cards/`,{method:"POST",headers:{Authorization:`Token ${e}`,"Content-Type":"application/json"},signal:this.signal,body:JSON.stringify(i)});if(t.ok)return yield t.json();throw yield this.buildErrorResponse(t)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}getCustomerCards(e,i=""){return t(this,void 0,void 0,(function*(){try{const t=yield fetch(`${this.baseUrlTonder}/api/v1/cards/${i}`,{method:"GET",headers:{Authorization:`Token ${e}`,"Content-Type":"application/json"},signal:this.signal});if(t.ok)return yield t.json();throw yield this.buildErrorResponse(t)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}deleteCustomerCard(e,i=""){return t(this,void 0,void 0,(function*(){try{const t=yield fetch(`${this.baseUrlTonder}/api/v1/cards/${i}`,{method:"DELETE",headers:{Authorization:`Token ${e}`,"Content-Type":"application/json"},signal:this.signal});if(t.ok)return!0;throw yield this.buildErrorResponse(t)}catch(e){throw this.buildErrorResponseFromCatch(e)}}))}buildErrorResponseFromCatch(e){return new i({code:(null==e?void 0:e.status)?e.status:e.code,body:null==e?void 0:e.body,name:e?"string"==typeof e?"catch":e.name:"Error",message:e?"string"==typeof e?e:e.message:"Error",stack:"string"==typeof e?void 0:e.stack})}buildErrorResponse(e,r=void 0){return t(this,void 0,void 0,(function*(){let t,o,n="Error";e&&"json"in e&&(t=yield null==e?void 0:e.json()),e&&"status"in e&&(o=e.status.toString()),e&&"text"in e&&(n=yield e.text());return new i({code:o,body:t,name:o,message:n,stack:r})}))}getFields(i,r){return t(this,void 0,void 0,(function*(){return yield Promise.all(Object.keys(i).map((i=>t(this,void 0,void 0,(function*(){return{element:yield r.create({table:"cards",column:i,type:e.ElementType.INPUT_FIELD}),key:i}})))))}))}}export{r as LiteCheckout};
|
package/dist/types/requests.d.ts
CHANGED
|
@@ -57,3 +57,27 @@ export type TokensRequest = {
|
|
|
57
57
|
[key: string]: any;
|
|
58
58
|
};
|
|
59
59
|
};
|
|
60
|
+
export type StartCheckoutFullRequest = {
|
|
61
|
+
order: {
|
|
62
|
+
items: OrderItem[];
|
|
63
|
+
};
|
|
64
|
+
total: number;
|
|
65
|
+
customer: {
|
|
66
|
+
name: string;
|
|
67
|
+
lastname: string;
|
|
68
|
+
email: string;
|
|
69
|
+
phone: string;
|
|
70
|
+
};
|
|
71
|
+
skyflowTokens: {
|
|
72
|
+
cardholder_name: string;
|
|
73
|
+
card_number: string;
|
|
74
|
+
cvv: string;
|
|
75
|
+
expiration_year: string;
|
|
76
|
+
expiration_month: string;
|
|
77
|
+
skyflow_id: string;
|
|
78
|
+
};
|
|
79
|
+
return_url: string;
|
|
80
|
+
isSandbox: boolean;
|
|
81
|
+
metadata: any;
|
|
82
|
+
currency: string;
|
|
83
|
+
};
|
package/package.json
CHANGED
|
@@ -2,9 +2,10 @@ import Skyflow from "skyflow-js";
|
|
|
2
2
|
import CollectContainer from "skyflow-js/types/core/external/collect/collect-container";
|
|
3
3
|
import CollectElement from "skyflow-js/types/core/external/collect/collect-element";
|
|
4
4
|
import { Business } from "../types/commons";
|
|
5
|
-
import { CreateOrderRequest, CreatePaymentRequest, RegisterCustomerCardRequest, StartCheckoutRequest, TokensRequest } from "../types/requests";
|
|
5
|
+
import { CreateOrderRequest, CreatePaymentRequest, RegisterCustomerCardRequest, StartCheckoutRequest, TokensRequest, StartCheckoutFullRequest } from "../types/requests";
|
|
6
6
|
import { GetBusinessResponse, CustomerRegisterResponse, CreateOrderResponse, CreatePaymentResponse, StartCheckoutResponse, GetVaultTokenResponse, IErrorResponse, GetCustomerCardsResponse, RegisterCustomerCardResponse } from "../types/responses";
|
|
7
7
|
import { ErrorResponse } from "./errorResponse";
|
|
8
|
+
import { getBrowserInfo } from "../helpers/utils";
|
|
8
9
|
|
|
9
10
|
declare global {
|
|
10
11
|
interface Window {
|
|
@@ -149,6 +150,127 @@ export class LiteCheckout implements LiteCheckoutConstructor {
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
|
|
153
|
+
async startCheckoutRouterFull(routerFullData: StartCheckoutFullRequest): Promise<StartCheckoutResponse | ErrorResponse> {
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
|
|
157
|
+
const {
|
|
158
|
+
order,
|
|
159
|
+
total,
|
|
160
|
+
customer,
|
|
161
|
+
skyflowTokens,
|
|
162
|
+
return_url,
|
|
163
|
+
isSandbox,
|
|
164
|
+
metadata,
|
|
165
|
+
currency
|
|
166
|
+
} = routerFullData;
|
|
167
|
+
|
|
168
|
+
const merchantResult = await this.getBusiness();
|
|
169
|
+
|
|
170
|
+
const customerResult : CustomerRegisterResponse | ErrorResponse = await this.customerRegister(customer.email);
|
|
171
|
+
|
|
172
|
+
if(customerResult && "auth_token" in customerResult && merchantResult && "reference" in merchantResult) {
|
|
173
|
+
|
|
174
|
+
const orderData: CreateOrderRequest = {
|
|
175
|
+
business: this.apiKeyTonder,
|
|
176
|
+
client: customerResult.auth_token,
|
|
177
|
+
billing_address_id: null,
|
|
178
|
+
shipping_address_id: null,
|
|
179
|
+
amount: total,
|
|
180
|
+
reference: merchantResult.reference,
|
|
181
|
+
is_oneclick: true,
|
|
182
|
+
items: order.items,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const orderResult = await this.createOrder(orderData);
|
|
186
|
+
|
|
187
|
+
const now = new Date();
|
|
188
|
+
|
|
189
|
+
const dateString = now.toISOString();
|
|
190
|
+
|
|
191
|
+
if("id" in orderResult && "id" in customerResult && "business" in merchantResult) {
|
|
192
|
+
|
|
193
|
+
const paymentItems: CreatePaymentRequest = {
|
|
194
|
+
business_pk: merchantResult.business.pk,
|
|
195
|
+
amount: total,
|
|
196
|
+
date: dateString,
|
|
197
|
+
order_id: orderResult.id,
|
|
198
|
+
client_id: customerResult.id
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const paymentResult = await this.createPayment(
|
|
202
|
+
paymentItems
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
let deviceSessionIdTonder: any;
|
|
206
|
+
|
|
207
|
+
const { openpay_keys, business } = merchantResult
|
|
208
|
+
|
|
209
|
+
if (openpay_keys.merchant_id && openpay_keys.public_key) {
|
|
210
|
+
deviceSessionIdTonder = await this.getOpenpayDeviceSessionID(
|
|
211
|
+
openpay_keys.merchant_id,
|
|
212
|
+
openpay_keys.public_key,
|
|
213
|
+
isSandbox
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const routerItems: StartCheckoutRequest = {
|
|
218
|
+
card: skyflowTokens,
|
|
219
|
+
name: skyflowTokens.cardholder_name,
|
|
220
|
+
last_name: customer.lastname,
|
|
221
|
+
email_client: customer.email,
|
|
222
|
+
phone_number: customer.phone,
|
|
223
|
+
return_url: return_url,
|
|
224
|
+
id_product: "no_id",
|
|
225
|
+
quantity_product: 1,
|
|
226
|
+
id_ship: "0",
|
|
227
|
+
instance_id_ship: "0",
|
|
228
|
+
amount: total,
|
|
229
|
+
title_ship: "shipping",
|
|
230
|
+
description: "transaction",
|
|
231
|
+
device_session_id: deviceSessionIdTonder ? deviceSessionIdTonder : null,
|
|
232
|
+
token_id: "",
|
|
233
|
+
order_id: ("id" in orderResult) && orderResult.id,
|
|
234
|
+
business_id: business.pk,
|
|
235
|
+
payment_id: ("pk" in paymentResult) && paymentResult.pk,
|
|
236
|
+
source: 'sdk',
|
|
237
|
+
metadata: metadata,
|
|
238
|
+
browser_info: getBrowserInfo(),
|
|
239
|
+
currency: currency
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const checkoutResult = await this.startCheckoutRouter(routerItems);
|
|
243
|
+
|
|
244
|
+
return checkoutResult;
|
|
245
|
+
|
|
246
|
+
} else {
|
|
247
|
+
|
|
248
|
+
throw new ErrorResponse({
|
|
249
|
+
code: "500",
|
|
250
|
+
body: orderResult as any,
|
|
251
|
+
name: "Keys error",
|
|
252
|
+
message: "Order response errors"
|
|
253
|
+
} as IErrorResponse)
|
|
254
|
+
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
} else {
|
|
258
|
+
|
|
259
|
+
throw new ErrorResponse({
|
|
260
|
+
code: "500",
|
|
261
|
+
body: merchantResult as any,
|
|
262
|
+
name: "Keys error",
|
|
263
|
+
message: "Merchant or customer reposne errors"
|
|
264
|
+
} as IErrorResponse)
|
|
265
|
+
|
|
266
|
+
}
|
|
267
|
+
} catch (e) {
|
|
268
|
+
|
|
269
|
+
throw this.buildErrorResponseFromCatch(e);
|
|
270
|
+
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
152
274
|
async getSkyflowTokens({
|
|
153
275
|
vault_id,
|
|
154
276
|
vault_url,
|
package/src/helpers/utils.ts
CHANGED
|
@@ -1,37 +1,12 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// Callback function to execute when mutations are observed
|
|
14
|
-
const callback = (mutationList: any, observer: MutationObserver) => {
|
|
15
|
-
for (const mutation of mutationList) {
|
|
16
|
-
if (mutation.type === "childList") {
|
|
17
|
-
hasChanged = true;
|
|
18
|
-
resolve(mutation)
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// Create an observer instance linked to the callback function
|
|
24
|
-
const observer = new MutationObserver(callback);
|
|
25
|
-
|
|
26
|
-
// Start observing the target node for configured mutations
|
|
27
|
-
observer.observe(targetNode, config);
|
|
28
|
-
|
|
29
|
-
window.setTimeout(() => {
|
|
30
|
-
if (!hasChanged) {
|
|
31
|
-
reject("Mounting error");
|
|
32
|
-
}
|
|
33
|
-
}, 5000);
|
|
34
|
-
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
}
|
|
1
|
+
export const getBrowserInfo = () => {
|
|
2
|
+
const browserInfo = {
|
|
3
|
+
javascript_enabled: true, // Assumed since JavaScript is running
|
|
4
|
+
time_zone: new Date().getTimezoneOffset(),
|
|
5
|
+
language: navigator.language || 'en-US', // Fallback to 'en-US'
|
|
6
|
+
color_depth: window.screen ? window.screen.colorDepth : null,
|
|
7
|
+
screen_width: window.screen ? window.screen.width * window.devicePixelRatio || window.screen.width : null,
|
|
8
|
+
screen_height: window.screen ? window.screen.height * window.devicePixelRatio || window.screen.height : null,
|
|
9
|
+
user_agent: navigator.userAgent,
|
|
10
|
+
};
|
|
11
|
+
return browserInfo;
|
|
12
|
+
}
|
package/src/types/requests.ts
CHANGED
|
@@ -62,4 +62,29 @@ export type TokensRequest = {
|
|
|
62
62
|
data: {
|
|
63
63
|
[key: string]: any;
|
|
64
64
|
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type StartCheckoutFullRequest = {
|
|
68
|
+
order: {
|
|
69
|
+
items: OrderItem[];
|
|
70
|
+
};
|
|
71
|
+
total: number;
|
|
72
|
+
customer: {
|
|
73
|
+
name: string;
|
|
74
|
+
lastname: string;
|
|
75
|
+
email: string;
|
|
76
|
+
phone: string;
|
|
77
|
+
};
|
|
78
|
+
skyflowTokens: {
|
|
79
|
+
cardholder_name: string;
|
|
80
|
+
card_number: string;
|
|
81
|
+
cvv: string;
|
|
82
|
+
expiration_year: string;
|
|
83
|
+
expiration_month: string;
|
|
84
|
+
skyflow_id: string;
|
|
85
|
+
};
|
|
86
|
+
return_url: string;
|
|
87
|
+
isSandbox: boolean;
|
|
88
|
+
metadata: any;
|
|
89
|
+
currency: string;
|
|
65
90
|
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import "../utils/defaultMock";
|
|
2
|
+
import { LiteCheckout } from "../../src";
|
|
3
|
+
import { ErrorResponse } from "../../src/classes/errorResponse";
|
|
4
|
+
import { LiteCheckoutConstructor } from "../../src/classes/liteCheckout";
|
|
5
|
+
import { IErrorResponse } from "../../src/types/responses";
|
|
6
|
+
import { constructorFields } from "../utils/defaultMock";
|
|
7
|
+
import { StartCheckoutResponseClass, StartCheckoutFullRequestClass, BusinessClass, CustomerRegisterClass, OrderResponseClass, CreatePaymentResponseClass } from "../utils/mockClasses";
|
|
8
|
+
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
OpenPay: any;
|
|
12
|
+
Skyflow: any;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("startCheckoutRouterFull", () => {
|
|
17
|
+
let checkoutConstructor: LiteCheckoutConstructor,
|
|
18
|
+
liteCheckout: LiteCheckout,
|
|
19
|
+
fetchSpy: jest.SpyInstance,
|
|
20
|
+
liteCheckoutSpy: jest.SpyInstance;
|
|
21
|
+
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
window.fetch = jest.fn();
|
|
24
|
+
|
|
25
|
+
checkoutConstructor = {
|
|
26
|
+
...constructorFields,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
liteCheckout = new LiteCheckout(constructorFields);
|
|
30
|
+
|
|
31
|
+
fetchSpy = jest.spyOn(global, "fetch");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterEach(() => {
|
|
35
|
+
jest.restoreAllMocks();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("startCheckoutRouterFull success", async () => {
|
|
39
|
+
|
|
40
|
+
liteCheckout.getBusiness = jest
|
|
41
|
+
.fn()
|
|
42
|
+
.mockImplementation(() => Promise.resolve({ ...new BusinessClass().mockObject }));
|
|
43
|
+
|
|
44
|
+
liteCheckout.customerRegister = jest
|
|
45
|
+
.fn()
|
|
46
|
+
.mockImplementation(() => Promise.resolve({ ...new CustomerRegisterClass().mockObject }));
|
|
47
|
+
|
|
48
|
+
liteCheckout.createOrder = jest
|
|
49
|
+
.fn()
|
|
50
|
+
.mockImplementation(() => Promise.resolve({ ...new OrderResponseClass().mockObject }));
|
|
51
|
+
|
|
52
|
+
liteCheckout.createPayment = jest
|
|
53
|
+
.fn()
|
|
54
|
+
.mockImplementation(() => Promise.resolve({ ...new CreatePaymentResponseClass().mockObject }));
|
|
55
|
+
|
|
56
|
+
liteCheckoutSpy = jest.spyOn(liteCheckout, "startCheckoutRouterFull");
|
|
57
|
+
|
|
58
|
+
fetchSpy.mockImplementation(() =>
|
|
59
|
+
Promise.resolve({
|
|
60
|
+
json: () => Promise.resolve([{ ...new StartCheckoutResponseClass() }]),
|
|
61
|
+
ok: true,
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const response = await liteCheckout.startCheckoutRouterFull({ ...new StartCheckoutFullRequestClass().mockObject, });
|
|
66
|
+
|
|
67
|
+
expect(response).toStrictEqual([{ ...new StartCheckoutResponseClass() }]);
|
|
68
|
+
expect(liteCheckoutSpy).toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("startCheckoutRouterFull empty", async () => {
|
|
72
|
+
liteCheckoutSpy = jest.spyOn(liteCheckout, "startCheckoutRouterFull");
|
|
73
|
+
|
|
74
|
+
fetchSpy.mockImplementation(() =>
|
|
75
|
+
Promise.resolve({
|
|
76
|
+
json: () => Promise.resolve(),
|
|
77
|
+
ok: true,
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
let error: ErrorResponse;
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const response = (await liteCheckout.startCheckoutRouterFull({
|
|
85
|
+
...new StartCheckoutFullRequestClass().mockObject,
|
|
86
|
+
})) as IErrorResponse;
|
|
87
|
+
} catch (e: any) {
|
|
88
|
+
error = e;
|
|
89
|
+
expect(error.code).toStrictEqual("500");
|
|
90
|
+
expect(error).toBeInstanceOf(ErrorResponse);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("startCheckoutRouterFull errorResponse", async () => {
|
|
96
|
+
liteCheckoutSpy = jest.spyOn(liteCheckout, "startCheckoutRouterFull");
|
|
97
|
+
|
|
98
|
+
fetchSpy.mockImplementation(() =>
|
|
99
|
+
Promise.resolve({
|
|
100
|
+
json: () => Promise.resolve(),
|
|
101
|
+
ok: false,
|
|
102
|
+
status: 400,
|
|
103
|
+
})
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
let error: ErrorResponse;
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const response = (await liteCheckout.startCheckoutRouterFull({
|
|
110
|
+
...new StartCheckoutFullRequestClass(),
|
|
111
|
+
})) as IErrorResponse;
|
|
112
|
+
} catch (e: any) {
|
|
113
|
+
error = e;
|
|
114
|
+
expect(error.code).toStrictEqual("400");
|
|
115
|
+
expect(error).toBeInstanceOf(ErrorResponse);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("startCheckoutRouterFull errorCatch", async () => {
|
|
120
|
+
liteCheckoutSpy = jest.spyOn(liteCheckout, "startCheckoutRouterFull");
|
|
121
|
+
|
|
122
|
+
fetchSpy.mockRejectedValue("error");
|
|
123
|
+
|
|
124
|
+
let error: ErrorResponse;
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const response = (await liteCheckout.startCheckoutRouterFull({
|
|
128
|
+
...new StartCheckoutFullRequestClass(),
|
|
129
|
+
})) as IErrorResponse;
|
|
130
|
+
} catch (e: any) {
|
|
131
|
+
error = e;
|
|
132
|
+
expect(error.message).toStrictEqual("error");
|
|
133
|
+
expect(error.name).toStrictEqual("catch");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
expect(liteCheckoutSpy).toHaveBeenCalled();
|
|
137
|
+
expect(liteCheckoutSpy).rejects.toThrow();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -4,7 +4,8 @@ import {
|
|
|
4
4
|
CreatePaymentRequest,
|
|
5
5
|
RegisterCustomerCardRequest,
|
|
6
6
|
StartCheckoutRequest,
|
|
7
|
-
TokensRequest
|
|
7
|
+
TokensRequest,
|
|
8
|
+
StartCheckoutFullRequest
|
|
8
9
|
} from "../../src/types/requests";
|
|
9
10
|
import {
|
|
10
11
|
CreateOrderResponse,
|
|
@@ -499,6 +500,55 @@ export class StartCheckoutResponseClass implements StartCheckoutResponse {
|
|
|
499
500
|
}
|
|
500
501
|
}
|
|
501
502
|
|
|
503
|
+
export class StartCheckoutFullRequestClass implements StartCheckoutFullRequest {
|
|
504
|
+
order!: { items: OrderItem[]; };
|
|
505
|
+
return_url!: string;
|
|
506
|
+
total!: number;
|
|
507
|
+
skyflowTokens!: { cardholder_name: string; card_number: string; cvv: string; expiration_year: string; expiration_month: string; skyflow_id: string; };
|
|
508
|
+
customer!: { name: string; lastname: string; email: string; phone: string; };
|
|
509
|
+
isSandbox!: boolean;
|
|
510
|
+
currency!: string;
|
|
511
|
+
metadata!: any;
|
|
512
|
+
|
|
513
|
+
get mockObject(): StartCheckoutFullRequest {
|
|
514
|
+
return {
|
|
515
|
+
order: {
|
|
516
|
+
items: [
|
|
517
|
+
{
|
|
518
|
+
description: "string",
|
|
519
|
+
quantity: 25,
|
|
520
|
+
price_unit: 25,
|
|
521
|
+
discount: 0,
|
|
522
|
+
taxes: 0,
|
|
523
|
+
product_reference: 25,
|
|
524
|
+
name: "Product text",
|
|
525
|
+
amount_total: 25
|
|
526
|
+
}
|
|
527
|
+
]
|
|
528
|
+
},
|
|
529
|
+
return_url: "string",
|
|
530
|
+
total: 25,
|
|
531
|
+
skyflowTokens: {
|
|
532
|
+
cardholder_name: "string",
|
|
533
|
+
card_number: "string",
|
|
534
|
+
cvv: "string",
|
|
535
|
+
expiration_year: "string",
|
|
536
|
+
expiration_month: "string",
|
|
537
|
+
skyflow_id: "string",
|
|
538
|
+
},
|
|
539
|
+
customer: {
|
|
540
|
+
name: "string",
|
|
541
|
+
lastname: "string",
|
|
542
|
+
email: "string",
|
|
543
|
+
phone: "string",
|
|
544
|
+
},
|
|
545
|
+
isSandbox: true,
|
|
546
|
+
currency: "MXN",
|
|
547
|
+
metadata: null
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
502
552
|
export class TokensRequestClass implements TokensRequest {
|
|
503
553
|
vault_id!: string;
|
|
504
554
|
vault_url!: string;
|