@skrigueztep/sdk-booking 1.0.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.
- package/LICENSE +27 -0
- package/README.md +105 -0
- package/dist/SDKBooking.d.ts +31 -0
- package/dist/errors/SDKError.d.ts +4 -0
- package/dist/errors/SubscriptionError.d.ts +4 -0
- package/dist/errors/ValidationError.d.ts +4 -0
- package/dist/favicon.svg +1 -0
- package/dist/icons.svg +24 -0
- package/dist/index.d.ts +2 -0
- package/dist/sdk-booking.js +188 -0
- package/dist/sdk-booking.umd.cjs +1 -0
- package/dist/types/index.d.ts +47 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Copyright (c) 2026 Israel Olvera
|
|
2
|
+
|
|
3
|
+
Todos los derechos reservados.
|
|
4
|
+
|
|
5
|
+
Este software y su código fuente asociado son propiedad exclusiva de Israel Olvera.
|
|
6
|
+
Se concede permiso limitado para utilizar este software únicamente como parte del
|
|
7
|
+
sistema de reservas para el cual fue diseñado, sujeto a las siguientes condiciones:
|
|
8
|
+
|
|
9
|
+
1. El software solo puede ser utilizado por personas o entidades con una cuenta
|
|
10
|
+
activa y autorizada en el sistema de reservas.
|
|
11
|
+
|
|
12
|
+
2. No está permitido redistribuir, modificar, realizar ingeniería inversa, o
|
|
13
|
+
utilizar el código fuente para crear obras derivadas sin autorización explícita
|
|
14
|
+
por escrito del titular de los derechos.
|
|
15
|
+
|
|
16
|
+
3. No está permitido utilizar este software en sistemas que compitan directa o
|
|
17
|
+
indirectamente con el sistema de reservas original.
|
|
18
|
+
|
|
19
|
+
4. Esta licencia no otorga ningún derecho de propiedad sobre el software. El
|
|
20
|
+
titular de los derechos se reserva todos los derechos no otorgados expresamente.
|
|
21
|
+
|
|
22
|
+
EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O
|
|
23
|
+
IMPLÍCITA, INCLUYENDO PERO NO LIMITADO A GARANTÍAS DE COMERCIABILIDAD,
|
|
24
|
+
ADECUACIÓN PARA UN PROPÓSITO PARTICULAR Y NO INFRACCIÓN. EN NINGÚN CASO EL
|
|
25
|
+
TITULAR DE LOS DERECHOS SERÁ RESPONSABLE POR RECLAMACIONES, DAÑOS U OTRAS
|
|
26
|
+
RESPONSABILIDADES, YA SEA EN UNA ACCIÓN CONTRACTUAL, EXTRACONTRACTUAL O DE OTRA
|
|
27
|
+
ÍNDOLE, DERIVADAS DE O EN CONEXIÓN CON EL SOFTWARE O SU USO.
|
package/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# @israel-olvera/sdk-booking
|
|
2
|
+
|
|
3
|
+
SDK de integración para el sistema de reservas. Permite a aplicaciones externas
|
|
4
|
+
crear reservas y procesar pagos a través de CLIP mediante API tokens.
|
|
5
|
+
|
|
6
|
+
## Requisitos
|
|
7
|
+
|
|
8
|
+
- Node.js 18+
|
|
9
|
+
- Navegador moderno (para integración con CLIP SDK)
|
|
10
|
+
|
|
11
|
+
## Instalación
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @israel-olvera/sdk-booking
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Uso rápido
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { SDKBooking } from '@israel-olvera/sdk-booking';
|
|
21
|
+
|
|
22
|
+
const sdk = new SDKBooking('TU_API_TOKEN', 'https://tu-backend.com');
|
|
23
|
+
|
|
24
|
+
sdk.create(
|
|
25
|
+
{
|
|
26
|
+
titulo: 'Reserva de prueba',
|
|
27
|
+
fecha_inicio: '2026-05-10T10:00:00Z',
|
|
28
|
+
fecha_fin: '2026-05-10T12:00:00Z',
|
|
29
|
+
nombre_cliente: 'Juan Pérez',
|
|
30
|
+
cliente_email: 'juan@ejemplo.com',
|
|
31
|
+
cliente_telefono: '5512345678',
|
|
32
|
+
costo: 500,
|
|
33
|
+
},
|
|
34
|
+
'https://miapp.com',
|
|
35
|
+
'checkout-container'
|
|
36
|
+
).catch(console.error);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API
|
|
40
|
+
|
|
41
|
+
### `SDKBooking(apiKey, baseUrl)`
|
|
42
|
+
|
|
43
|
+
Crea una instancia del SDK.
|
|
44
|
+
|
|
45
|
+
| Parámetro | Tipo | Descripción |
|
|
46
|
+
|-----------|------|-------------|
|
|
47
|
+
| `apiKey` | `string` | API token generado desde el panel de administración |
|
|
48
|
+
| `baseUrl` | `string` | URL base del backend (ej. `https://api.misistema.com`) |
|
|
49
|
+
|
|
50
|
+
### `create(data, domain, containerId): Promise<void>`
|
|
51
|
+
|
|
52
|
+
Crea una reserva y gestiona el pago según el tipo de suscripción.
|
|
53
|
+
|
|
54
|
+
| Parámetro | Tipo | Descripción |
|
|
55
|
+
|-----------|------|-------------|
|
|
56
|
+
| `data` | `ReservationInput` | Datos de la reserva |
|
|
57
|
+
| `domain` | `string` | Dominio de origen (debe coincidir con el permitido en el API token) |
|
|
58
|
+
| `containerId` | `string` | ID del contenedor DOM donde se renderizará el formulario de pago |
|
|
59
|
+
|
|
60
|
+
### `ReservationInput`
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
interface ReservationInput {
|
|
64
|
+
titulo: string;
|
|
65
|
+
descripcion?: string | object;
|
|
66
|
+
fecha_inicio: string;
|
|
67
|
+
fecha_fin: string;
|
|
68
|
+
nombre_cliente: string;
|
|
69
|
+
cliente_email: string;
|
|
70
|
+
cliente_telefono: string;
|
|
71
|
+
costo?: number;
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Clases de error
|
|
76
|
+
|
|
77
|
+
| Clase | Código HTTP | Descripción |
|
|
78
|
+
|-------|-------------|-------------|
|
|
79
|
+
| `SDKError` | variable | Error genérico del SDK |
|
|
80
|
+
| `SubscriptionError` | 403 | Error relacionado con la suscripción |
|
|
81
|
+
| `ValidationError` | 400 | Error de validación de campos |
|
|
82
|
+
|
|
83
|
+
## Manejo de errores
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { SDKBooking, ValidationError, SubscriptionError } from '@israel-olvera/sdk-booking';
|
|
87
|
+
|
|
88
|
+
const sdk = new SDKBooking(token, baseUrl);
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
await sdk.create(data, domain, containerId);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
if (e instanceof ValidationError) {
|
|
94
|
+
console.error('Datos inválidos:', e.message);
|
|
95
|
+
} else if (e instanceof SubscriptionError) {
|
|
96
|
+
console.error('Problema de suscripción:', e.message);
|
|
97
|
+
} else {
|
|
98
|
+
console.error('Error:', e.message);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Licencia
|
|
104
|
+
|
|
105
|
+
Este proyecto está bajo una licencia propietaria. Consulta el archivo [LICENSE](./LICENSE) para más información.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { SDKError } from './errors/SDKError.js';
|
|
2
|
+
import { SubscriptionError } from './errors/SubscriptionError.js';
|
|
3
|
+
import { ValidationError } from './errors/ValidationError.js';
|
|
4
|
+
import { Reservation, ReservationInput, SubscriptionStatus, SubscriptionType, ProcessPaymentResponse } from './types/index.js';
|
|
5
|
+
export { SDKError, SubscriptionError, ValidationError };
|
|
6
|
+
export type { Reservation, ReservationInput, SubscriptionStatus, SubscriptionType, ProcessPaymentResponse };
|
|
7
|
+
declare global {
|
|
8
|
+
interface Window {
|
|
9
|
+
ClipSDK: new (publicKey: string) => {
|
|
10
|
+
element: {
|
|
11
|
+
create: (type: string, options: {
|
|
12
|
+
locale: string;
|
|
13
|
+
}) => {
|
|
14
|
+
mount: (selector: string) => void;
|
|
15
|
+
cardToken: () => Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export declare class SDKBooking {
|
|
24
|
+
private apiKey;
|
|
25
|
+
private baseUrl;
|
|
26
|
+
private api;
|
|
27
|
+
constructor(apiKey: string, baseUrl: string);
|
|
28
|
+
create(data: ReservationInput, domain: string, containerId: string): Promise<void>;
|
|
29
|
+
private handlePayPerUse;
|
|
30
|
+
private loadClipSDK;
|
|
31
|
+
}
|
package/dist/favicon.svg
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="46" fill="none" viewBox="0 0 48 46"><path fill="#863bff" d="M25.946 44.938c-.664.845-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.287c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.497 0-3.578-1.842-3.578H1.237c-.92 0-1.456-1.04-.92-1.788L10.013.474c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.579 1.842 3.579h11.377c.943 0 1.473 1.088.89 1.83L25.947 44.94z" style="fill:#863bff;fill:color(display-p3 .5252 .23 1);fill-opacity:1"/><mask id="a" width="48" height="46" x="0" y="0" maskUnits="userSpaceOnUse" style="mask-type:alpha"><path fill="#000" d="M25.842 44.938c-.664.844-2.021.375-2.021-.698V33.937a2.26 2.26 0 0 0-2.262-2.262H10.183c-.92 0-1.456-1.04-.92-1.788l7.48-10.471c1.07-1.498 0-3.579-1.842-3.579H1.133c-.92 0-1.456-1.04-.92-1.787L9.91.473c.214-.297.556-.474.92-.474h28.894c.92 0 1.456 1.04.92 1.788l-7.48 10.471c-1.07 1.498 0 3.578 1.842 3.578h11.377c.943 0 1.473 1.088.89 1.832L25.843 44.94z" style="fill:#000;fill-opacity:1"/></mask><g mask="url(#a)"><g filter="url(#b)"><ellipse cx="5.508" cy="14.704" fill="#ede6ff" rx="5.508" ry="14.704" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -4.47 31.516)"/></g><g filter="url(#c)"><ellipse cx="10.399" cy="29.851" fill="#ede6ff" rx="10.399" ry="29.851" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -39.328 7.883)"/></g><g filter="url(#d)"><ellipse cx="5.508" cy="30.487" fill="#7e14ff" rx="5.508" ry="30.487" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -25.913 -14.639)scale(1 -1)"/></g><g filter="url(#e)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.814 -32.644 -3.334)scale(1 -1)"/></g><g filter="url(#f)"><ellipse cx="5.508" cy="30.599" fill="#7e14ff" rx="5.508" ry="30.599" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="matrix(.00324 1 1 -.00324 -34.34 30.47)"/></g><g filter="url(#g)"><ellipse cx="14.072" cy="22.078" fill="#ede6ff" rx="14.072" ry="22.078" style="fill:#ede6ff;fill:color(display-p3 .9275 .9033 1);fill-opacity:1" transform="rotate(93.35 24.506 48.493)scale(-1 1)"/></g><g filter="url(#h)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#i)"><ellipse cx="3.47" cy="21.501" fill="#7e14ff" rx="3.47" ry="21.501" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(89.009 28.708 47.59)scale(-1 1)"/></g><g filter="url(#j)"><ellipse cx=".387" cy="8.972" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(39.51 .387 8.972)"/></g><g filter="url(#k)"><ellipse cx="47.523" cy="-6.092" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 47.523 -6.092)"/></g><g filter="url(#l)"><ellipse cx="41.412" cy="6.333" fill="#47bfff" rx="5.971" ry="9.665" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 41.412 6.333)"/></g><g filter="url(#m)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#n)"><ellipse cx="-1.879" cy="38.332" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 -1.88 38.332)"/></g><g filter="url(#o)"><ellipse cx="35.651" cy="29.907" fill="#7e14ff" rx="4.407" ry="29.108" style="fill:#7e14ff;fill:color(display-p3 .4922 .0767 1);fill-opacity:1" transform="rotate(37.892 35.651 29.907)"/></g><g filter="url(#p)"><ellipse cx="38.418" cy="32.4" fill="#47bfff" rx="5.971" ry="15.297" style="fill:#47bfff;fill:color(display-p3 .2799 .748 1);fill-opacity:1" transform="rotate(37.892 38.418 32.4)"/></g></g><defs><filter id="b" width="60.045" height="41.654" x="-19.77" y="16.149" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="c" width="90.34" height="51.437" x="-54.613" y="-7.533" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="d" width="79.355" height="29.4" x="-49.64" y="2.03" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="e" width="79.579" height="29.4" x="-45.045" y="20.029" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="f" width="79.579" height="29.4" x="-43.513" y="21.178" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="g" width="74.749" height="58.852" x="15.756" y="-17.901" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="7.659"/></filter><filter id="h" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="i" width="61.377" height="25.362" x="23.548" y="2.284" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="j" width="56.045" height="63.649" x="-27.636" y="-22.853" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="k" width="54.814" height="64.646" x="20.116" y="-38.415" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="l" width="33.541" height="35.313" x="24.641" y="-11.323" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="m" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="n" width="54.814" height="64.646" x="-29.286" y="6.009" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="o" width="54.814" height="64.646" x="8.244" y="-2.416" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter><filter id="p" width="39.409" height="43.623" x="18.713" y="10.588" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feGaussianBlur result="effect1_foregroundBlur_2002_17158" stdDeviation="4.596"/></filter></defs></svg>
|
package/dist/icons.svg
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<symbol id="bluesky-icon" viewBox="0 0 16 17">
|
|
3
|
+
<g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
|
|
4
|
+
<defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
|
|
5
|
+
</symbol>
|
|
6
|
+
<symbol id="discord-icon" viewBox="0 0 20 19">
|
|
7
|
+
<path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
|
|
8
|
+
</symbol>
|
|
9
|
+
<symbol id="documentation-icon" viewBox="0 0 21 20">
|
|
10
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
|
|
11
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
|
|
12
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
|
|
13
|
+
</symbol>
|
|
14
|
+
<symbol id="github-icon" viewBox="0 0 19 19">
|
|
15
|
+
<path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
|
|
16
|
+
</symbol>
|
|
17
|
+
<symbol id="social-icon" viewBox="0 0 20 20">
|
|
18
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
|
|
19
|
+
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
|
|
20
|
+
</symbol>
|
|
21
|
+
<symbol id="x-icon" viewBox="0 0 19 19">
|
|
22
|
+
<path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
|
|
23
|
+
</symbol>
|
|
24
|
+
</svg>
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
//#region src/errors/SDKError.ts
|
|
2
|
+
var e = class extends Error {
|
|
3
|
+
constructor(e, t) {
|
|
4
|
+
super(e), this.code = t, this.name = "SDKError";
|
|
5
|
+
}
|
|
6
|
+
}, t = class extends e {
|
|
7
|
+
constructor(e) {
|
|
8
|
+
super(e, 403), this.name = "SubscriptionError";
|
|
9
|
+
}
|
|
10
|
+
}, n = class extends e {
|
|
11
|
+
constructor(e) {
|
|
12
|
+
super(e, 400), this.name = "ValidationError";
|
|
13
|
+
}
|
|
14
|
+
}, r = class {
|
|
15
|
+
static insertPaymentForm(t, n) {
|
|
16
|
+
let r = document.getElementById(t);
|
|
17
|
+
if (!r) throw new e(`Container with id "${t}" not found`, 400);
|
|
18
|
+
let i = r.firstElementChild;
|
|
19
|
+
i && (i.style.display = "none");
|
|
20
|
+
let a = document.createElement("form");
|
|
21
|
+
a.id = "payment-form", a.style.maxWidth = "42rem", a.style.display = "flex", a.style.flexDirection = "column", a.style.gap = "1.5rem", a.style.borderRadius = "0.75rem", a.style.backgroundColor = "#ffffff", a.style.padding = "1.5rem";
|
|
22
|
+
let o = document.createElement("h3");
|
|
23
|
+
o.textContent = "Datos de pago", o.style.fontSize = "1.125rem", o.style.fontWeight = "500", o.style.color = "#111827";
|
|
24
|
+
let s = document.createElement("div");
|
|
25
|
+
s.id = "checkout";
|
|
26
|
+
let c = document.createElement("p");
|
|
27
|
+
c.style.fontSize = "1.125rem", c.style.fontWeight = "500", c.style.color = "#111827", c.textContent = "Total a pagar: ";
|
|
28
|
+
let l = document.createElement("span");
|
|
29
|
+
l.style.color = "#6366f1", l.textContent = `$${n.toFixed(2)} MXN`, c.appendChild(l);
|
|
30
|
+
let u = document.createElement("button");
|
|
31
|
+
u.id = "submit", u.type = "submit", u.textContent = "Pagar", u.style.width = "100%", u.style.cursor = "pointer", u.style.borderRadius = "0.75rem", u.style.backgroundColor = "#020617", u.style.color = "#ffffff", u.style.border = "2px solid #e5e7eb", u.style.padding = "0.5rem 0.75rem", u.style.transition = "all 0.2s ease", u.addEventListener("mouseover", () => {
|
|
32
|
+
u.style.borderColor = "#9ca3af", u.style.boxShadow = "0 4px 6px rgba(0,0,0,0.1)";
|
|
33
|
+
}), u.addEventListener("mouseout", () => {
|
|
34
|
+
u.style.borderColor = "#e5e7eb", u.style.boxShadow = "none";
|
|
35
|
+
});
|
|
36
|
+
let d = document.createElement("p");
|
|
37
|
+
d.id = "cardTokenId", a.appendChild(o), a.appendChild(s), a.appendChild(c), a.appendChild(u), a.appendChild(d), r.appendChild(a);
|
|
38
|
+
}
|
|
39
|
+
static handlePaymentSuccess(e) {
|
|
40
|
+
let t = document.getElementById("payment-form");
|
|
41
|
+
if (t) {
|
|
42
|
+
t.children[1].remove(), t.style.maxWidth = "42rem", t.style.margin = "0 auto", t.style.display = "flex", t.style.flexDirection = "column", t.style.gap = "1.5rem", t.style.backgroundColor = "#ffffff", t.style.padding = "1.5rem", t.style.borderRadius = "0.75rem", t.style.textAlign = "center";
|
|
43
|
+
let n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
44
|
+
n.setAttribute("fill", "none"), n.setAttribute("stroke", "currentColor"), n.setAttribute("viewBox", "0 0 24 24"), n.style.margin = "0 auto", n.style.height = "4rem", n.style.width = "4rem", n.style.color = "#22c55e";
|
|
45
|
+
let r = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
46
|
+
r.setAttribute("stroke-linecap", "round"), r.setAttribute("stroke-linejoin", "round"), r.setAttribute("stroke-width", "2"), r.setAttribute("d", "M5 13l4 4L19 7"), n.appendChild(r);
|
|
47
|
+
let i = document.createElement("h3");
|
|
48
|
+
i.textContent = "Pago procesado correctamente", i.style.fontSize = "1.125rem", i.style.fontWeight = "500", i.style.color = "#111827";
|
|
49
|
+
let a = document.createElement("p");
|
|
50
|
+
a.textContent = `Tu reserva ha sido creada con ID: ${e.id}`, a.style.color = "#4b5563", t.appendChild(n), t.appendChild(i), t.appendChild(a);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
static handlePaymentError(e) {
|
|
54
|
+
let t = document.getElementById("payment-form");
|
|
55
|
+
if (t) {
|
|
56
|
+
t.children[1].remove(), t.style.maxWidth = "42rem", t.style.margin = "0 auto", t.style.display = "flex", t.style.flexDirection = "column", t.style.gap = "1.5rem", t.style.backgroundColor = "#ffffff", t.style.padding = "1.5rem", t.style.borderRadius = "0.75rem", t.style.textAlign = "center";
|
|
57
|
+
let n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
58
|
+
n.setAttribute("fill", "none"), n.setAttribute("stroke", "currentColor"), n.setAttribute("viewBox", "0 0 24 24"), n.style.margin = "0 auto", n.style.height = "4rem", n.style.width = "4rem", n.style.color = "#ef4444";
|
|
59
|
+
let r = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
60
|
+
r.setAttribute("stroke-linecap", "round"), r.setAttribute("stroke-linejoin", "round"), r.setAttribute("stroke-width", "2"), r.setAttribute("d", "M6 18L18 6M6 6l12 12"), n.appendChild(r);
|
|
61
|
+
let i = document.createElement("h3");
|
|
62
|
+
i.textContent = "Error en el pago", i.style.fontSize = "1.125rem", i.style.fontWeight = "500", i.style.color = "#111827";
|
|
63
|
+
let a = document.createElement("p");
|
|
64
|
+
a.textContent = e.message, a.style.color = "#4b5563", t.appendChild(n), t.appendChild(i), t.appendChild(a);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}, i = class {
|
|
68
|
+
apiKey;
|
|
69
|
+
baseUrl;
|
|
70
|
+
constructor(e, t) {
|
|
71
|
+
this.apiKey = e, this.baseUrl = t;
|
|
72
|
+
}
|
|
73
|
+
async create(n) {
|
|
74
|
+
let r = await fetch(`${this.baseUrl}/api/subscriptions/active`, { headers: {
|
|
75
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
76
|
+
Origin: n
|
|
77
|
+
} });
|
|
78
|
+
if (!r.ok) throw r.status === 404 ? new t("No active subscription found") : new e("Failed to validate subscription", r.status);
|
|
79
|
+
return r.json();
|
|
80
|
+
}
|
|
81
|
+
async getKey(e) {
|
|
82
|
+
let t = await fetch(`${this.baseUrl}/api/reservation-payments/public-key`, { headers: {
|
|
83
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
Origin: e
|
|
86
|
+
} });
|
|
87
|
+
if (!t.ok) {
|
|
88
|
+
let e = await t.json().catch(() => ({}));
|
|
89
|
+
throw Error(e.error ?? "Error al obtener clave pública");
|
|
90
|
+
}
|
|
91
|
+
return t.json();
|
|
92
|
+
}
|
|
93
|
+
async processPayment(t, n, r, i) {
|
|
94
|
+
let a = await fetch(`${this.baseUrl}/api/reservation-payments/token`, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers: {
|
|
97
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
98
|
+
"Content-Type": "application/json"
|
|
99
|
+
},
|
|
100
|
+
body: JSON.stringify({
|
|
101
|
+
reservationId: t,
|
|
102
|
+
cardToken: n,
|
|
103
|
+
amount: r,
|
|
104
|
+
customerEmail: i
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
if (!a.ok) throw new e((await a.json().catch(() => ({}))).message || "Failed to process payment", a.status);
|
|
108
|
+
return a.json();
|
|
109
|
+
}
|
|
110
|
+
async createReservationDirect(t, r) {
|
|
111
|
+
let i = [];
|
|
112
|
+
if ((!t.titulo || typeof t.titulo != "string") && i.push("titulo es requerido"), (!t.fecha_inicio || typeof t.fecha_inicio != "string") && i.push("fecha_inicio es requerido"), (!t.fecha_fin || typeof t.fecha_fin != "string") && i.push("fecha_fin es requerido"), (!t.nombre_cliente || typeof t.nombre_cliente != "string") && i.push("nombre_cliente es requerido"), (!t.cliente_email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t.cliente_email)) && i.push("cliente_email es requerido o formato inválido"), (!t.cliente_telefono || !/^[0-9]{10,15}$/.test(t.cliente_telefono)) && i.push("cliente_telefono es requerido (10-15 dígitos)"), i.length > 0) throw new n(i.join("; "));
|
|
113
|
+
let a = await fetch(`${this.baseUrl}/api/reservations/create`, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: {
|
|
116
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
Origin: r
|
|
119
|
+
},
|
|
120
|
+
body: JSON.stringify(t)
|
|
121
|
+
});
|
|
122
|
+
if (!a.ok) throw new e((await a.json().catch(() => ({}))).message || "Failed to create reservation", a.status);
|
|
123
|
+
return a.json();
|
|
124
|
+
}
|
|
125
|
+
}, a = class {
|
|
126
|
+
apiKey;
|
|
127
|
+
baseUrl;
|
|
128
|
+
api;
|
|
129
|
+
constructor(e, t) {
|
|
130
|
+
this.apiKey = e, this.baseUrl = t, this.api = new i(this.apiKey, this.baseUrl);
|
|
131
|
+
}
|
|
132
|
+
async create(e, n, r) {
|
|
133
|
+
try {
|
|
134
|
+
let i = await this.api.create(n);
|
|
135
|
+
if (i.status !== "ACTIVE") throw new t(`Subscription is ${i.status}`);
|
|
136
|
+
i.type === "PAY_PER_USE" ? this.handlePayPerUse(e, n, r) : this.api.createReservationDirect(e, n);
|
|
137
|
+
} catch (e) {
|
|
138
|
+
console.log(e);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
async handlePayPerUse(e, t, n) {
|
|
142
|
+
return r.insertPaymentForm(n, 50), await this.loadClipSDK(e, t), new Promise(() => {});
|
|
143
|
+
}
|
|
144
|
+
async loadClipSDK(e, t) {
|
|
145
|
+
return new Promise((n, i) => {
|
|
146
|
+
let a = document.createElement("script");
|
|
147
|
+
a.src = "https://sdk.clip.mx/js/clip-sdk.js", a.onload = async () => {
|
|
148
|
+
try {
|
|
149
|
+
let { publicKey: i } = await this.api.getKey(t), a = new window.ClipSDK(i || "YOUR_PUBLIC_KEY").element.create("Card", { locale: "es" });
|
|
150
|
+
a.mount("checkout"), document.querySelector("#payment-form")?.addEventListener("submit", async (n) => {
|
|
151
|
+
n.preventDefault();
|
|
152
|
+
try {
|
|
153
|
+
let n = (await a.cardToken()).id, i = await this.api.createReservationDirect(e, t), o = i.id;
|
|
154
|
+
if (!o) {
|
|
155
|
+
r.handlePaymentError(/* @__PURE__ */ Error("Error al crear intento de pago"));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
let s = await this.api.processPayment(o, n, 50, "");
|
|
159
|
+
if (s.threeDsRequired && s.threeDsExternalUrl) window.location.href = s.threeDsExternalUrl;
|
|
160
|
+
else if (s.status === "approved") r.handlePaymentSuccess(i);
|
|
161
|
+
else throw Error(s.statusDetail?.message || "Pago rechazado");
|
|
162
|
+
} catch (e) {
|
|
163
|
+
let t = e;
|
|
164
|
+
switch (t.code) {
|
|
165
|
+
case "CL2200":
|
|
166
|
+
case "CL2290":
|
|
167
|
+
r.handlePaymentError(Error(t.message || "Error en el pago"));
|
|
168
|
+
break;
|
|
169
|
+
case "AI1300":
|
|
170
|
+
r.handlePaymentError(Error(t.message || "Error en el pago"));
|
|
171
|
+
break;
|
|
172
|
+
default:
|
|
173
|
+
r.handlePaymentError(Error(t.message || "Error al procesar el pago"));
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}), n();
|
|
178
|
+
} catch (e) {
|
|
179
|
+
r.handlePaymentError(/* @__PURE__ */ Error("Error al cargar el SDK de Clip")), i(e);
|
|
180
|
+
}
|
|
181
|
+
}, a.onerror = () => {
|
|
182
|
+
r.handlePaymentError(/* @__PURE__ */ Error("Error al cargar el SDK de Clip")), i(/* @__PURE__ */ Error("Error al cargar el SDK de Clip"));
|
|
183
|
+
}, document.head.appendChild(a);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
//#endregion
|
|
188
|
+
export { a as SDKBooking, e as SDKError, t as SubscriptionError, n as ValidationError };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.SDKBooking={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class extends Error{constructor(e,t){super(e),this.code=t,this.name=`SDKError`}},n=class extends t{constructor(e){super(e,403),this.name=`SubscriptionError`}},r=class extends t{constructor(e){super(e,400),this.name=`ValidationError`}},i=class{static insertPaymentForm(e,n){let r=document.getElementById(e);if(!r)throw new t(`Container with id "${e}" not found`,400);let i=r.firstElementChild;i&&(i.style.display=`none`);let a=document.createElement(`form`);a.id=`payment-form`,a.style.maxWidth=`42rem`,a.style.display=`flex`,a.style.flexDirection=`column`,a.style.gap=`1.5rem`,a.style.borderRadius=`0.75rem`,a.style.backgroundColor=`#ffffff`,a.style.padding=`1.5rem`;let o=document.createElement(`h3`);o.textContent=`Datos de pago`,o.style.fontSize=`1.125rem`,o.style.fontWeight=`500`,o.style.color=`#111827`;let s=document.createElement(`div`);s.id=`checkout`;let c=document.createElement(`p`);c.style.fontSize=`1.125rem`,c.style.fontWeight=`500`,c.style.color=`#111827`,c.textContent=`Total a pagar: `;let l=document.createElement(`span`);l.style.color=`#6366f1`,l.textContent=`$${n.toFixed(2)} MXN`,c.appendChild(l);let u=document.createElement(`button`);u.id=`submit`,u.type=`submit`,u.textContent=`Pagar`,u.style.width=`100%`,u.style.cursor=`pointer`,u.style.borderRadius=`0.75rem`,u.style.backgroundColor=`#020617`,u.style.color=`#ffffff`,u.style.border=`2px solid #e5e7eb`,u.style.padding=`0.5rem 0.75rem`,u.style.transition=`all 0.2s ease`,u.addEventListener(`mouseover`,()=>{u.style.borderColor=`#9ca3af`,u.style.boxShadow=`0 4px 6px rgba(0,0,0,0.1)`}),u.addEventListener(`mouseout`,()=>{u.style.borderColor=`#e5e7eb`,u.style.boxShadow=`none`});let d=document.createElement(`p`);d.id=`cardTokenId`,a.appendChild(o),a.appendChild(s),a.appendChild(c),a.appendChild(u),a.appendChild(d),r.appendChild(a)}static handlePaymentSuccess(e){let t=document.getElementById(`payment-form`);if(t){t.children[1].remove(),t.style.maxWidth=`42rem`,t.style.margin=`0 auto`,t.style.display=`flex`,t.style.flexDirection=`column`,t.style.gap=`1.5rem`,t.style.backgroundColor=`#ffffff`,t.style.padding=`1.5rem`,t.style.borderRadius=`0.75rem`,t.style.textAlign=`center`;let n=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);n.setAttribute(`fill`,`none`),n.setAttribute(`stroke`,`currentColor`),n.setAttribute(`viewBox`,`0 0 24 24`),n.style.margin=`0 auto`,n.style.height=`4rem`,n.style.width=`4rem`,n.style.color=`#22c55e`;let r=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);r.setAttribute(`stroke-linecap`,`round`),r.setAttribute(`stroke-linejoin`,`round`),r.setAttribute(`stroke-width`,`2`),r.setAttribute(`d`,`M5 13l4 4L19 7`),n.appendChild(r);let i=document.createElement(`h3`);i.textContent=`Pago procesado correctamente`,i.style.fontSize=`1.125rem`,i.style.fontWeight=`500`,i.style.color=`#111827`;let a=document.createElement(`p`);a.textContent=`Tu reserva ha sido creada con ID: ${e.id}`,a.style.color=`#4b5563`,t.appendChild(n),t.appendChild(i),t.appendChild(a)}}static handlePaymentError(e){let t=document.getElementById(`payment-form`);if(t){t.children[1].remove(),t.style.maxWidth=`42rem`,t.style.margin=`0 auto`,t.style.display=`flex`,t.style.flexDirection=`column`,t.style.gap=`1.5rem`,t.style.backgroundColor=`#ffffff`,t.style.padding=`1.5rem`,t.style.borderRadius=`0.75rem`,t.style.textAlign=`center`;let n=document.createElementNS(`http://www.w3.org/2000/svg`,`svg`);n.setAttribute(`fill`,`none`),n.setAttribute(`stroke`,`currentColor`),n.setAttribute(`viewBox`,`0 0 24 24`),n.style.margin=`0 auto`,n.style.height=`4rem`,n.style.width=`4rem`,n.style.color=`#ef4444`;let r=document.createElementNS(`http://www.w3.org/2000/svg`,`path`);r.setAttribute(`stroke-linecap`,`round`),r.setAttribute(`stroke-linejoin`,`round`),r.setAttribute(`stroke-width`,`2`),r.setAttribute(`d`,`M6 18L18 6M6 6l12 12`),n.appendChild(r);let i=document.createElement(`h3`);i.textContent=`Error en el pago`,i.style.fontSize=`1.125rem`,i.style.fontWeight=`500`,i.style.color=`#111827`;let a=document.createElement(`p`);a.textContent=e.message,a.style.color=`#4b5563`,t.appendChild(n),t.appendChild(i),t.appendChild(a)}}},a=class{apiKey;baseUrl;constructor(e,t){this.apiKey=e,this.baseUrl=t}async create(e){let r=await fetch(`${this.baseUrl}/api/subscriptions/active`,{headers:{Authorization:`Bearer ${this.apiKey}`,Origin:e}});if(!r.ok)throw r.status===404?new n(`No active subscription found`):new t(`Failed to validate subscription`,r.status);return r.json()}async getKey(e){let t=await fetch(`${this.baseUrl}/api/reservation-payments/public-key`,{headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":`application/json`,Origin:e}});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.error??`Error al obtener clave pública`)}return t.json()}async processPayment(e,n,r,i){let a=await fetch(`${this.baseUrl}/api/reservation-payments/token`,{method:`POST`,headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify({reservationId:e,cardToken:n,amount:r,customerEmail:i})});if(!a.ok)throw new t((await a.json().catch(()=>({}))).message||`Failed to process payment`,a.status);return a.json()}async createReservationDirect(e,n){let i=[];if((!e.titulo||typeof e.titulo!=`string`)&&i.push(`titulo es requerido`),(!e.fecha_inicio||typeof e.fecha_inicio!=`string`)&&i.push(`fecha_inicio es requerido`),(!e.fecha_fin||typeof e.fecha_fin!=`string`)&&i.push(`fecha_fin es requerido`),(!e.nombre_cliente||typeof e.nombre_cliente!=`string`)&&i.push(`nombre_cliente es requerido`),(!e.cliente_email||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.cliente_email))&&i.push(`cliente_email es requerido o formato inválido`),(!e.cliente_telefono||!/^[0-9]{10,15}$/.test(e.cliente_telefono))&&i.push(`cliente_telefono es requerido (10-15 dígitos)`),i.length>0)throw new r(i.join(`; `));let a=await fetch(`${this.baseUrl}/api/reservations/create`,{method:`POST`,headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":`application/json`,Origin:n},body:JSON.stringify(e)});if(!a.ok)throw new t((await a.json().catch(()=>({}))).message||`Failed to create reservation`,a.status);return a.json()}};e.SDKBooking=class{apiKey;baseUrl;api;constructor(e,t){this.apiKey=e,this.baseUrl=t,this.api=new a(this.apiKey,this.baseUrl)}async create(e,t,r){try{let i=await this.api.create(t);if(i.status!==`ACTIVE`)throw new n(`Subscription is ${i.status}`);i.type===`PAY_PER_USE`?this.handlePayPerUse(e,t,r):this.api.createReservationDirect(e,t)}catch(e){console.log(e)}}async handlePayPerUse(e,t,n){return i.insertPaymentForm(n,50),await this.loadClipSDK(e,t),new Promise(()=>{})}async loadClipSDK(e,t){return new Promise((n,r)=>{let a=document.createElement(`script`);a.src=`https://sdk.clip.mx/js/clip-sdk.js`,a.onload=async()=>{try{let{publicKey:r}=await this.api.getKey(t),a=new window.ClipSDK(r||`YOUR_PUBLIC_KEY`).element.create(`Card`,{locale:`es`});a.mount(`checkout`),document.querySelector(`#payment-form`)?.addEventListener(`submit`,async n=>{n.preventDefault();try{let n=(await a.cardToken()).id,r=await this.api.createReservationDirect(e,t),o=r.id;if(!o){i.handlePaymentError(Error(`Error al crear intento de pago`));return}let s=await this.api.processPayment(o,n,50,``);if(s.threeDsRequired&&s.threeDsExternalUrl)window.location.href=s.threeDsExternalUrl;else if(s.status===`approved`)i.handlePaymentSuccess(r);else throw Error(s.statusDetail?.message||`Pago rechazado`)}catch(e){let t=e;switch(t.code){case`CL2200`:case`CL2290`:i.handlePaymentError(Error(t.message||`Error en el pago`));break;case`AI1300`:i.handlePaymentError(Error(t.message||`Error en el pago`));break;default:i.handlePaymentError(Error(t.message||`Error al procesar el pago`));break}}}),n()}catch(e){i.handlePaymentError(Error(`Error al cargar el SDK de Clip`)),r(e)}},a.onerror=()=>{i.handlePaymentError(Error(`Error al cargar el SDK de Clip`)),r(Error(`Error al cargar el SDK de Clip`))},document.head.appendChild(a)})}},e.SDKError=t,e.SubscriptionError=n,e.ValidationError=r});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface ReservationInput {
|
|
2
|
+
titulo: string;
|
|
3
|
+
descripcion?: string | object;
|
|
4
|
+
fecha_inicio: string;
|
|
5
|
+
fecha_fin: string;
|
|
6
|
+
nombre_cliente: string;
|
|
7
|
+
cliente_email: string;
|
|
8
|
+
cliente_telefono: string;
|
|
9
|
+
costo?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Reservation {
|
|
12
|
+
id: string;
|
|
13
|
+
titulo: string;
|
|
14
|
+
descripcion?: string | object;
|
|
15
|
+
fecha_inicio: string;
|
|
16
|
+
fecha_fin: string;
|
|
17
|
+
nombre_cliente: string;
|
|
18
|
+
costo: number;
|
|
19
|
+
estado: string;
|
|
20
|
+
userId: string;
|
|
21
|
+
createdAt: string;
|
|
22
|
+
updatedAt: string;
|
|
23
|
+
}
|
|
24
|
+
export type SubscriptionType = 'PAY_PER_USE' | 'MONTHLY' | 'ANNUAL';
|
|
25
|
+
export interface SubscriptionStatus {
|
|
26
|
+
status: 'PENDING' | 'ACTIVE' | 'EXPIRED' | 'CANCELLED';
|
|
27
|
+
type: SubscriptionType;
|
|
28
|
+
endDate: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ProcessPaymentResponse {
|
|
31
|
+
paymentId: string;
|
|
32
|
+
clipPaymentId: string;
|
|
33
|
+
status: string;
|
|
34
|
+
statusDetail: {
|
|
35
|
+
code: string;
|
|
36
|
+
message: string;
|
|
37
|
+
};
|
|
38
|
+
threeDsRequired: boolean;
|
|
39
|
+
threeDsExternalUrl?: string;
|
|
40
|
+
amount: number;
|
|
41
|
+
currency: string;
|
|
42
|
+
paymentRecord: {
|
|
43
|
+
id: string;
|
|
44
|
+
status: string;
|
|
45
|
+
createdAt: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skrigueztep/sdk-booking",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/sdk-booking.umd.cjs",
|
|
6
|
+
"module": "./dist/sdk-booking.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"private": false,
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/sdk-booking.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "vite",
|
|
20
|
+
"build": "vite build",
|
|
21
|
+
"preview": "vite preview",
|
|
22
|
+
"link": "npm run build && npm link --force"
|
|
23
|
+
},
|
|
24
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://gitlab.com/Skrigueztep/booking-system.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"email": "contact@israel-olvera.com"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public",
|
|
34
|
+
"@skrigueztep:registry": "https://registry.npmjs.org/"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"typescript": "~5.9.3",
|
|
38
|
+
"vite": "^8.0.1",
|
|
39
|
+
"vite-plugin-dts": "^4.5.4"
|
|
40
|
+
}
|
|
41
|
+
}
|