@npmtapi/embed 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/README.md +279 -0
- package/dist/chunk-2WNQZXMS.js +61 -0
- package/dist/chunk-2WNQZXMS.js.map +1 -0
- package/dist/index.cjs +87 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +173 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +45 -0
- package/dist/react.d.ts +45 -0
- package/dist/react.js +92 -0
- package/dist/react.js.map +1 -0
- package/dist/types-DmkYbkBI.d.cts +70 -0
- package/dist/types-DmkYbkBI.d.ts +70 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# @npmtapi/embed
|
|
2
|
+
|
|
3
|
+
SDK para integrar el widget de pago de TapiPay en cualquier sitio web o aplicación.
|
|
4
|
+
|
|
5
|
+
<!-- Docs: próximamente en https://docs.tapipay.com/embed -->
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Instalación
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# npm
|
|
13
|
+
npm install @npmtapi/embed
|
|
14
|
+
|
|
15
|
+
# pnpm
|
|
16
|
+
pnpm add @npmtapi/embed
|
|
17
|
+
|
|
18
|
+
# yarn
|
|
19
|
+
yarn add @npmtapi/embed
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Entrypoints
|
|
23
|
+
|
|
24
|
+
| Import | Contenido |
|
|
25
|
+
|--------|-----------|
|
|
26
|
+
| `@npmtapi/embed` | `loadTapipay()` + tipos TypeScript |
|
|
27
|
+
| `@npmtapi/embed/react` | `<TapipayWidget>` + `useTapipay()` |
|
|
28
|
+
|
|
29
|
+
Los tipos están incluidos — no necesitas `@types/tapipay`.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Uso rápido
|
|
34
|
+
|
|
35
|
+
### Script tag (sin bundler)
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<script src="https://app.tapipay.la/embed.js"></script>
|
|
39
|
+
<div id="widget"></div>
|
|
40
|
+
<script>
|
|
41
|
+
tapipay.initialize({
|
|
42
|
+
container: "#widget",
|
|
43
|
+
organization: "acme",
|
|
44
|
+
identifier: "CLI-001"
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
tapipay.on("paymentPending", function(data) {
|
|
48
|
+
console.log("Pago en proceso:", data);
|
|
49
|
+
});
|
|
50
|
+
</script>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Data-attrs (cero JavaScript)
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<script src="https://app.tapipay.la/embed.js"></script>
|
|
57
|
+
|
|
58
|
+
<div
|
|
59
|
+
data-tapipay-widget
|
|
60
|
+
data-organization="acme"
|
|
61
|
+
data-identifier="CLI-001"
|
|
62
|
+
></div>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## React
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
import { TapipayWidget } from "@npmtapi/embed/react";
|
|
71
|
+
|
|
72
|
+
export function PagoPage({ clienteId }: { clienteId: string }) {
|
|
73
|
+
return (
|
|
74
|
+
<TapipayWidget
|
|
75
|
+
organization="acme"
|
|
76
|
+
identifier={clienteId}
|
|
77
|
+
onPending={(data) => console.log("Pago en proceso:", data)}
|
|
78
|
+
onCancelled={() => console.log("Pago cancelado por el usuario")}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Props
|
|
85
|
+
|
|
86
|
+
| Prop | Tipo | Requerido | Descripción |
|
|
87
|
+
|------|------|-----------|-------------|
|
|
88
|
+
| `organization` | `string` | Sí | Alias de la organización en TapiPay |
|
|
89
|
+
| `identifier` | `string` | Sí | Identificador del cliente |
|
|
90
|
+
| `externalRequestId` | `string` | No | ID de deuda a preseleccionar |
|
|
91
|
+
| `selectionStrategy` | `"oldestCreated"` | No | Selecciona automáticamente la deuda pendiente más antigua |
|
|
92
|
+
| `environment` | `'production' \| 'homo'` | No | Entorno del SDK. Por defecto `'production'` |
|
|
93
|
+
| `onPending` | `(data) => void` | No | Callback cuando Yuno redirige al callback (pago en proceso) |
|
|
94
|
+
| `onCancelled` | `() => void` | No | Callback cuando el usuario cierra el popup sin completar el pago |
|
|
95
|
+
| `className` | `string` | No | Clases CSS del contenedor |
|
|
96
|
+
| `style` | `CSSProperties` | No | Estilos inline del contenedor |
|
|
97
|
+
|
|
98
|
+
### Next.js App Router
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
"use client";
|
|
102
|
+
|
|
103
|
+
import { TapipayWidget } from "@npmtapi/embed/react";
|
|
104
|
+
import { useRouter } from "next/navigation";
|
|
105
|
+
|
|
106
|
+
export default function PagarPage() {
|
|
107
|
+
const router = useRouter();
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<TapipayWidget
|
|
111
|
+
organization={process.env.NEXT_PUBLIC_TAPIPAY_ORGANIZATION!}
|
|
112
|
+
identifier="CLI-001"
|
|
113
|
+
onPending={() => router.push("/procesando")}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Vue 3
|
|
122
|
+
|
|
123
|
+
```vue
|
|
124
|
+
<template>
|
|
125
|
+
<div ref="widgetRef"></div>
|
|
126
|
+
</template>
|
|
127
|
+
|
|
128
|
+
<script setup>
|
|
129
|
+
import { loadTapipay } from "@npmtapi/embed";
|
|
130
|
+
import { onMounted, onUnmounted, ref } from "vue";
|
|
131
|
+
|
|
132
|
+
const props = defineProps({ organization: String, identifier: String });
|
|
133
|
+
const widgetRef = ref(null);
|
|
134
|
+
let tapipay = null;
|
|
135
|
+
|
|
136
|
+
onMounted(async () => {
|
|
137
|
+
tapipay = await loadTapipay();
|
|
138
|
+
tapipay.initialize({
|
|
139
|
+
container: widgetRef.value,
|
|
140
|
+
organization: props.organization,
|
|
141
|
+
identifier: props.identifier,
|
|
142
|
+
});
|
|
143
|
+
tapipay.on("paymentPending", (data) => console.log("Pago en proceso:", data));
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
onUnmounted(() => tapipay?.destroy(widgetRef.value));
|
|
147
|
+
</script>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Angular
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { loadTapipay, TapipayInstance } from "@npmtapi/embed";
|
|
156
|
+
import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from "@angular/core";
|
|
157
|
+
|
|
158
|
+
@Component({
|
|
159
|
+
selector: "app-tapipay-widget",
|
|
160
|
+
template: `<div #container></div>`,
|
|
161
|
+
})
|
|
162
|
+
export class TapipayWidgetComponent implements OnInit, OnDestroy {
|
|
163
|
+
@Input() organization!: string;
|
|
164
|
+
@Input() identifier!: string;
|
|
165
|
+
@ViewChild("container", { static: true }) containerRef!: ElementRef<HTMLDivElement>;
|
|
166
|
+
|
|
167
|
+
private tapipay: TapipayInstance | null = null;
|
|
168
|
+
|
|
169
|
+
async ngOnInit() {
|
|
170
|
+
this.tapipay = await loadTapipay();
|
|
171
|
+
this.tapipay.initialize({
|
|
172
|
+
container: this.containerRef.nativeElement,
|
|
173
|
+
organization: this.organization,
|
|
174
|
+
identifier: this.identifier,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
ngOnDestroy() {
|
|
179
|
+
this.tapipay?.destroy(this.containerRef.nativeElement);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Opciones
|
|
187
|
+
|
|
188
|
+
### `loadTapipay(options?)`
|
|
189
|
+
|
|
190
|
+
| Parámetro | Tipo | Requerido | Descripción |
|
|
191
|
+
|-----------|------|-----------|-------------|
|
|
192
|
+
| `environment` | `'production' \| 'homo'` | No | Entorno del SDK a cargar. Por defecto `'production'`. |
|
|
193
|
+
|
|
194
|
+
### `initialize(options)`
|
|
195
|
+
|
|
196
|
+
| Parámetro | Tipo | Requerido | Descripción |
|
|
197
|
+
|-----------|------|-----------|-------------|
|
|
198
|
+
| `container` | `string \| HTMLElement` | Sí | Selector CSS o referencia DOM. Solo para `initialize()`. |
|
|
199
|
+
| `organization` | `string` | Sí | Alias de la organización en TapiPay. |
|
|
200
|
+
| `identifier` | `string` | Sí | Identificador del cliente (DNI, número de cuenta, etc.). |
|
|
201
|
+
| `externalRequestId` | `string` | No | ID externo de una deuda específica a preseleccionar. |
|
|
202
|
+
| `selectionStrategy` | `"oldestCreated"` | No | Selección automática: `"oldestCreated"` elige la deuda pendiente más antigua. |
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Eventos
|
|
207
|
+
|
|
208
|
+
```js
|
|
209
|
+
// Yuno redirigió al callback (pago en proceso)
|
|
210
|
+
tapipay.on("paymentPending", function(data) {
|
|
211
|
+
console.log("Pago en proceso:", data);
|
|
212
|
+
// Mostrar pantalla de "procesando" y esperar webhook
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// El usuario cerró el popup sin completar el pago
|
|
216
|
+
tapipay.on("paymentCancelled", function() {
|
|
217
|
+
console.log("Pago cancelado por el usuario");
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Remover un listener
|
|
221
|
+
tapipay.off("paymentPending", handler);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### `TapipayPaymentPendingEvent`
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
interface TapipayPaymentPendingEvent {
|
|
228
|
+
type: string; // "TAPIPAY_CALLBACK"
|
|
229
|
+
status: "pending";
|
|
230
|
+
data: Record<string, string>; // Parámetros que Yuno haya enviado (pueden estar vacíos)
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### `TapipayPaymentCancelledEvent`
|
|
235
|
+
|
|
236
|
+
```ts
|
|
237
|
+
interface TapipayPaymentCancelledEvent {
|
|
238
|
+
// sin campos adicionales
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Entorno de homologación
|
|
245
|
+
|
|
246
|
+
Para apuntar al entorno de homologación en lugar de producción:
|
|
247
|
+
|
|
248
|
+
### Vía npm (`loadTapipay`)
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
import { loadTapipay } from "@npmtapi/embed";
|
|
252
|
+
|
|
253
|
+
const tapipay = await loadTapipay({ environment: "homo" });
|
|
254
|
+
tapipay.initialize({ container: "#widget", organization: "acme", identifier: "CLI-001" });
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Vía React
|
|
258
|
+
|
|
259
|
+
```tsx
|
|
260
|
+
<TapipayWidget
|
|
261
|
+
environment="homo"
|
|
262
|
+
organization="acme"
|
|
263
|
+
identifier="CLI-001"
|
|
264
|
+
/>
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Vía script tag
|
|
268
|
+
|
|
269
|
+
Apunta directamente al script del entorno deseado:
|
|
270
|
+
|
|
271
|
+
```html
|
|
272
|
+
<!-- Homologación -->
|
|
273
|
+
<script src="https://homo.tapipay.la/embed.js"></script>
|
|
274
|
+
|
|
275
|
+
<!-- Producción -->
|
|
276
|
+
<script src="https://app.tapipay.la/embed.js"></script>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
> **Nota:** No se soporta cargar dos entornos distintos en la misma página, ya que `window.tapipay` es un objeto global compartido.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/loader.ts
|
|
2
|
+
var SDK_URLS = {
|
|
3
|
+
production: "https://app.tapipay.la/embed.js",
|
|
4
|
+
homo: "https://homo.tapipay.la/embed.js"
|
|
5
|
+
};
|
|
6
|
+
var loadPromises = /* @__PURE__ */ new Map();
|
|
7
|
+
function loadTapipay(options) {
|
|
8
|
+
var _a;
|
|
9
|
+
const env = (_a = options == null ? void 0 : options.environment) != null ? _a : "production";
|
|
10
|
+
const SDK_URL = SDK_URLS[env];
|
|
11
|
+
const SCRIPT_ID = `tapipay-embed-sdk-${env}`;
|
|
12
|
+
if (typeof window === "undefined") {
|
|
13
|
+
return Promise.reject(
|
|
14
|
+
new Error("[TapiPay] loadTapipay() requires a browser environment.")
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
if (window.tapipay && !window.tapipay._q) {
|
|
18
|
+
return Promise.resolve(window.tapipay);
|
|
19
|
+
}
|
|
20
|
+
const existing = loadPromises.get(env);
|
|
21
|
+
if (existing) return existing;
|
|
22
|
+
const promise = new Promise((resolve, reject) => {
|
|
23
|
+
const existingScript = document.getElementById(
|
|
24
|
+
SCRIPT_ID
|
|
25
|
+
);
|
|
26
|
+
const onLoad = () => {
|
|
27
|
+
if (window.tapipay) {
|
|
28
|
+
resolve(window.tapipay);
|
|
29
|
+
} else {
|
|
30
|
+
reject(
|
|
31
|
+
new Error(
|
|
32
|
+
"[TapiPay] El script carg\xF3 pero window.tapipay no est\xE1 definido."
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const onError = () => {
|
|
38
|
+
loadPromises.delete(env);
|
|
39
|
+
reject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));
|
|
40
|
+
};
|
|
41
|
+
if (existingScript) {
|
|
42
|
+
existingScript.addEventListener("load", onLoad);
|
|
43
|
+
existingScript.addEventListener("error", onError);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const script = document.createElement("script");
|
|
47
|
+
script.id = SCRIPT_ID;
|
|
48
|
+
script.src = SDK_URL;
|
|
49
|
+
script.async = true;
|
|
50
|
+
script.addEventListener("load", onLoad);
|
|
51
|
+
script.addEventListener("error", onError);
|
|
52
|
+
document.head.appendChild(script);
|
|
53
|
+
});
|
|
54
|
+
loadPromises.set(env, promise);
|
|
55
|
+
return promise;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
loadTapipay
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=chunk-2WNQZXMS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/loader.ts"],"sourcesContent":["import type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n} from \"./types\";\n\nconst SDK_URLS: Record<TapipayEnvironment, string> = {\n\tproduction: \"https://app.tapipay.la/embed.js\",\n\thomo: \"https://homo.tapipay.la/embed.js\",\n};\n\n// Idempotencia por entorno\nconst loadPromises = new Map<TapipayEnvironment, Promise<TapipayInstance>>();\n\n/**\n * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.\n *\n * - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.\n * - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.\n * - Compatible con React Strict Mode (doble mount/unmount).\n *\n * @example\n * // Producción (default)\n * const tapipay = await loadTapipay();\n *\n * // Homologación\n * const tapipay = await loadTapipay({ environment: 'homo' });\n *\n * tapipay.initialize({ container: \"#widget\", organization: \"acme\", identifier: \"CLI-001\" });\n */\nexport function loadTapipay(\n\toptions?: LoadTapipayOptions,\n): Promise<TapipayInstance> {\n\tconst env: TapipayEnvironment = options?.environment ?? \"production\";\n\tconst SDK_URL = SDK_URLS[env];\n\tconst SCRIPT_ID = `tapipay-embed-sdk-${env}`;\n\n\t// SSR guard\n\tif (typeof window === \"undefined\") {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\"[TapiPay] loadTapipay() requires a browser environment.\"),\n\t\t);\n\t}\n\n\t// Ya cargado de forma síncrona (script tag directo)\n\tif (window.tapipay && !window.tapipay._q) {\n\t\treturn Promise.resolve(window.tapipay);\n\t}\n\n\t// Reutilizar promise existente (idempotencia por entorno)\n\tconst existing = loadPromises.get(env);\n\tif (existing) return existing;\n\n\tconst promise = new Promise<TapipayInstance>((resolve, reject) => {\n\t\t// Si ya hay un script inyectado, esperar a que cargue\n\t\tconst existingScript = document.getElementById(\n\t\t\tSCRIPT_ID,\n\t\t) as HTMLScriptElement | null;\n\n\t\tconst onLoad = () => {\n\t\t\tif (window.tapipay) {\n\t\t\t\tresolve(window.tapipay);\n\t\t\t} else {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"[TapiPay] El script cargó pero window.tapipay no está definido.\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onError = () => {\n\t\t\tloadPromises.delete(env);\n\t\t\treject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));\n\t\t};\n\n\t\tif (existingScript) {\n\t\t\texistingScript.addEventListener(\"load\", onLoad);\n\t\t\texistingScript.addEventListener(\"error\", onError);\n\t\t\treturn;\n\t\t}\n\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = SCRIPT_ID;\n\t\tscript.src = SDK_URL;\n\t\tscript.async = true;\n\t\tscript.addEventListener(\"load\", onLoad);\n\t\tscript.addEventListener(\"error\", onError);\n\t\tdocument.head.appendChild(script);\n\t});\n\n\tloadPromises.set(env, promise);\n\treturn promise;\n}\n"],"mappings":";AAMA,IAAM,WAA+C;AAAA,EACpD,YAAY;AAAA,EACZ,MAAM;AACP;AAGA,IAAM,eAAe,oBAAI,IAAkD;AAkBpE,SAAS,YACf,SAC2B;AAhC5B;AAiCC,QAAM,OAA0B,wCAAS,gBAAT,YAAwB;AACxD,QAAM,UAAU,SAAS,GAAG;AAC5B,QAAM,YAAY,qBAAqB,GAAG;AAG1C,MAAI,OAAO,WAAW,aAAa;AAClC,WAAO,QAAQ;AAAA,MACd,IAAI,MAAM,yDAAyD;AAAA,IACpE;AAAA,EACD;AAGA,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,IAAI;AACzC,WAAO,QAAQ,QAAQ,OAAO,OAAO;AAAA,EACtC;AAGA,QAAM,WAAW,aAAa,IAAI,GAAG;AACrC,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,IAAI,QAAyB,CAAC,SAAS,WAAW;AAEjE,UAAM,iBAAiB,SAAS;AAAA,MAC/B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM;AACpB,UAAI,OAAO,SAAS;AACnB,gBAAQ,OAAO,OAAO;AAAA,MACvB,OAAO;AACN;AAAA,UACC,IAAI;AAAA,YACH;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,UAAU,MAAM;AACrB,mBAAa,OAAO,GAAG;AACvB,aAAO,IAAI,MAAM,0CAA0C,OAAO,EAAE,CAAC;AAAA,IACtE;AAEA,QAAI,gBAAgB;AACnB,qBAAe,iBAAiB,QAAQ,MAAM;AAC9C,qBAAe,iBAAiB,SAAS,OAAO;AAChD;AAAA,IACD;AAEA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,KAAK;AACZ,WAAO,MAAM;AACb,WAAO,QAAQ;AACf,WAAO,iBAAiB,QAAQ,MAAM;AACtC,WAAO,iBAAiB,SAAS,OAAO;AACxC,aAAS,KAAK,YAAY,MAAM;AAAA,EACjC,CAAC;AAED,eAAa,IAAI,KAAK,OAAO;AAC7B,SAAO;AACR;","names":[]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
loadTapipay: () => loadTapipay
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/loader.ts
|
|
28
|
+
var SDK_URLS = {
|
|
29
|
+
production: "https://app.tapipay.la/embed.js",
|
|
30
|
+
homo: "https://homo.tapipay.la/embed.js"
|
|
31
|
+
};
|
|
32
|
+
var loadPromises = /* @__PURE__ */ new Map();
|
|
33
|
+
function loadTapipay(options) {
|
|
34
|
+
var _a;
|
|
35
|
+
const env = (_a = options == null ? void 0 : options.environment) != null ? _a : "production";
|
|
36
|
+
const SDK_URL = SDK_URLS[env];
|
|
37
|
+
const SCRIPT_ID = `tapipay-embed-sdk-${env}`;
|
|
38
|
+
if (typeof window === "undefined") {
|
|
39
|
+
return Promise.reject(
|
|
40
|
+
new Error("[TapiPay] loadTapipay() requires a browser environment.")
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (window.tapipay && !window.tapipay._q) {
|
|
44
|
+
return Promise.resolve(window.tapipay);
|
|
45
|
+
}
|
|
46
|
+
const existing = loadPromises.get(env);
|
|
47
|
+
if (existing) return existing;
|
|
48
|
+
const promise = new Promise((resolve, reject) => {
|
|
49
|
+
const existingScript = document.getElementById(
|
|
50
|
+
SCRIPT_ID
|
|
51
|
+
);
|
|
52
|
+
const onLoad = () => {
|
|
53
|
+
if (window.tapipay) {
|
|
54
|
+
resolve(window.tapipay);
|
|
55
|
+
} else {
|
|
56
|
+
reject(
|
|
57
|
+
new Error(
|
|
58
|
+
"[TapiPay] El script carg\xF3 pero window.tapipay no est\xE1 definido."
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const onError = () => {
|
|
64
|
+
loadPromises.delete(env);
|
|
65
|
+
reject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));
|
|
66
|
+
};
|
|
67
|
+
if (existingScript) {
|
|
68
|
+
existingScript.addEventListener("load", onLoad);
|
|
69
|
+
existingScript.addEventListener("error", onError);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const script = document.createElement("script");
|
|
73
|
+
script.id = SCRIPT_ID;
|
|
74
|
+
script.src = SDK_URL;
|
|
75
|
+
script.async = true;
|
|
76
|
+
script.addEventListener("load", onLoad);
|
|
77
|
+
script.addEventListener("error", onError);
|
|
78
|
+
document.head.appendChild(script);
|
|
79
|
+
});
|
|
80
|
+
loadPromises.set(env, promise);
|
|
81
|
+
return promise;
|
|
82
|
+
}
|
|
83
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
84
|
+
0 && (module.exports = {
|
|
85
|
+
loadTapipay
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/loader.ts"],"sourcesContent":["export { loadTapipay } from \"./loader\";\nexport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentPendingEvent,\n} from \"./types\";\n","import type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n} from \"./types\";\n\nconst SDK_URLS: Record<TapipayEnvironment, string> = {\n\tproduction: \"https://app.tapipay.la/embed.js\",\n\thomo: \"https://homo.tapipay.la/embed.js\",\n};\n\n// Idempotencia por entorno\nconst loadPromises = new Map<TapipayEnvironment, Promise<TapipayInstance>>();\n\n/**\n * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.\n *\n * - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.\n * - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.\n * - Compatible con React Strict Mode (doble mount/unmount).\n *\n * @example\n * // Producción (default)\n * const tapipay = await loadTapipay();\n *\n * // Homologación\n * const tapipay = await loadTapipay({ environment: 'homo' });\n *\n * tapipay.initialize({ container: \"#widget\", organization: \"acme\", identifier: \"CLI-001\" });\n */\nexport function loadTapipay(\n\toptions?: LoadTapipayOptions,\n): Promise<TapipayInstance> {\n\tconst env: TapipayEnvironment = options?.environment ?? \"production\";\n\tconst SDK_URL = SDK_URLS[env];\n\tconst SCRIPT_ID = `tapipay-embed-sdk-${env}`;\n\n\t// SSR guard\n\tif (typeof window === \"undefined\") {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\"[TapiPay] loadTapipay() requires a browser environment.\"),\n\t\t);\n\t}\n\n\t// Ya cargado de forma síncrona (script tag directo)\n\tif (window.tapipay && !window.tapipay._q) {\n\t\treturn Promise.resolve(window.tapipay);\n\t}\n\n\t// Reutilizar promise existente (idempotencia por entorno)\n\tconst existing = loadPromises.get(env);\n\tif (existing) return existing;\n\n\tconst promise = new Promise<TapipayInstance>((resolve, reject) => {\n\t\t// Si ya hay un script inyectado, esperar a que cargue\n\t\tconst existingScript = document.getElementById(\n\t\t\tSCRIPT_ID,\n\t\t) as HTMLScriptElement | null;\n\n\t\tconst onLoad = () => {\n\t\t\tif (window.tapipay) {\n\t\t\t\tresolve(window.tapipay);\n\t\t\t} else {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"[TapiPay] El script cargó pero window.tapipay no está definido.\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onError = () => {\n\t\t\tloadPromises.delete(env);\n\t\t\treject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));\n\t\t};\n\n\t\tif (existingScript) {\n\t\t\texistingScript.addEventListener(\"load\", onLoad);\n\t\t\texistingScript.addEventListener(\"error\", onError);\n\t\t\treturn;\n\t\t}\n\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = SCRIPT_ID;\n\t\tscript.src = SDK_URL;\n\t\tscript.async = true;\n\t\tscript.addEventListener(\"load\", onLoad);\n\t\tscript.addEventListener(\"error\", onError);\n\t\tdocument.head.appendChild(script);\n\t});\n\n\tloadPromises.set(env, promise);\n\treturn promise;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMA,IAAM,WAA+C;AAAA,EACpD,YAAY;AAAA,EACZ,MAAM;AACP;AAGA,IAAM,eAAe,oBAAI,IAAkD;AAkBpE,SAAS,YACf,SAC2B;AAhC5B;AAiCC,QAAM,OAA0B,wCAAS,gBAAT,YAAwB;AACxD,QAAM,UAAU,SAAS,GAAG;AAC5B,QAAM,YAAY,qBAAqB,GAAG;AAG1C,MAAI,OAAO,WAAW,aAAa;AAClC,WAAO,QAAQ;AAAA,MACd,IAAI,MAAM,yDAAyD;AAAA,IACpE;AAAA,EACD;AAGA,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,IAAI;AACzC,WAAO,QAAQ,QAAQ,OAAO,OAAO;AAAA,EACtC;AAGA,QAAM,WAAW,aAAa,IAAI,GAAG;AACrC,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,IAAI,QAAyB,CAAC,SAAS,WAAW;AAEjE,UAAM,iBAAiB,SAAS;AAAA,MAC/B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM;AACpB,UAAI,OAAO,SAAS;AACnB,gBAAQ,OAAO,OAAO;AAAA,MACvB,OAAO;AACN;AAAA,UACC,IAAI;AAAA,YACH;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,UAAU,MAAM;AACrB,mBAAa,OAAO,GAAG;AACvB,aAAO,IAAI,MAAM,0CAA0C,OAAO,EAAE,CAAC;AAAA,IACtE;AAEA,QAAI,gBAAgB;AACnB,qBAAe,iBAAiB,QAAQ,MAAM;AAC9C,qBAAe,iBAAiB,SAAS,OAAO;AAChD;AAAA,IACD;AAEA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,KAAK;AACZ,WAAO,MAAM;AACb,WAAO,QAAQ;AACf,WAAO,iBAAiB,QAAQ,MAAM;AACtC,WAAO,iBAAiB,SAAS,OAAO;AACxC,aAAS,KAAK,YAAY,MAAM;AAAA,EACjC,CAAC;AAED,eAAa,IAAI,KAAK,OAAO;AAC7B,SAAO;AACR;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.cjs';
|
|
2
|
+
export { a as TapipayEnvironment, b as TapipayOptions, c as TapipayPaymentCancelledEvent, d as TapipayPaymentPendingEvent } from './types-DmkYbkBI.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.
|
|
6
|
+
*
|
|
7
|
+
* - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.
|
|
8
|
+
* - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.
|
|
9
|
+
* - Compatible con React Strict Mode (doble mount/unmount).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Producción (default)
|
|
13
|
+
* const tapipay = await loadTapipay();
|
|
14
|
+
*
|
|
15
|
+
* // Homologación
|
|
16
|
+
* const tapipay = await loadTapipay({ environment: 'homo' });
|
|
17
|
+
*
|
|
18
|
+
* tapipay.initialize({ container: "#widget", organization: "acme", identifier: "CLI-001" });
|
|
19
|
+
*/
|
|
20
|
+
declare function loadTapipay(options?: LoadTapipayOptions): Promise<TapipayInstance>;
|
|
21
|
+
|
|
22
|
+
export { LoadTapipayOptions, TapipayInstance, loadTapipay };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.js';
|
|
2
|
+
export { a as TapipayEnvironment, b as TapipayOptions, c as TapipayPaymentCancelledEvent, d as TapipayPaymentPendingEvent } from './types-DmkYbkBI.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.
|
|
6
|
+
*
|
|
7
|
+
* - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.
|
|
8
|
+
* - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.
|
|
9
|
+
* - Compatible con React Strict Mode (doble mount/unmount).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Producción (default)
|
|
13
|
+
* const tapipay = await loadTapipay();
|
|
14
|
+
*
|
|
15
|
+
* // Homologación
|
|
16
|
+
* const tapipay = await loadTapipay({ environment: 'homo' });
|
|
17
|
+
*
|
|
18
|
+
* tapipay.initialize({ container: "#widget", organization: "acme", identifier: "CLI-001" });
|
|
19
|
+
*/
|
|
20
|
+
declare function loadTapipay(options?: LoadTapipayOptions): Promise<TapipayInstance>;
|
|
21
|
+
|
|
22
|
+
export { LoadTapipayOptions, TapipayInstance, loadTapipay };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/react.cjs
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/react.tsx
|
|
21
|
+
var react_exports = {};
|
|
22
|
+
__export(react_exports, {
|
|
23
|
+
TapipayWidget: () => TapipayWidget,
|
|
24
|
+
useTapipay: () => useTapipay
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(react_exports);
|
|
27
|
+
var import_react = require("react");
|
|
28
|
+
|
|
29
|
+
// src/loader.ts
|
|
30
|
+
var SDK_URLS = {
|
|
31
|
+
production: "https://app.tapipay.la/embed.js",
|
|
32
|
+
homo: "https://homo.tapipay.la/embed.js"
|
|
33
|
+
};
|
|
34
|
+
var loadPromises = /* @__PURE__ */ new Map();
|
|
35
|
+
function loadTapipay(options) {
|
|
36
|
+
var _a;
|
|
37
|
+
const env = (_a = options == null ? void 0 : options.environment) != null ? _a : "production";
|
|
38
|
+
const SDK_URL = SDK_URLS[env];
|
|
39
|
+
const SCRIPT_ID = `tapipay-embed-sdk-${env}`;
|
|
40
|
+
if (typeof window === "undefined") {
|
|
41
|
+
return Promise.reject(
|
|
42
|
+
new Error("[TapiPay] loadTapipay() requires a browser environment.")
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
if (window.tapipay && !window.tapipay._q) {
|
|
46
|
+
return Promise.resolve(window.tapipay);
|
|
47
|
+
}
|
|
48
|
+
const existing = loadPromises.get(env);
|
|
49
|
+
if (existing) return existing;
|
|
50
|
+
const promise = new Promise((resolve, reject) => {
|
|
51
|
+
const existingScript = document.getElementById(
|
|
52
|
+
SCRIPT_ID
|
|
53
|
+
);
|
|
54
|
+
const onLoad = () => {
|
|
55
|
+
if (window.tapipay) {
|
|
56
|
+
resolve(window.tapipay);
|
|
57
|
+
} else {
|
|
58
|
+
reject(
|
|
59
|
+
new Error(
|
|
60
|
+
"[TapiPay] El script carg\xF3 pero window.tapipay no est\xE1 definido."
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const onError = () => {
|
|
66
|
+
loadPromises.delete(env);
|
|
67
|
+
reject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));
|
|
68
|
+
};
|
|
69
|
+
if (existingScript) {
|
|
70
|
+
existingScript.addEventListener("load", onLoad);
|
|
71
|
+
existingScript.addEventListener("error", onError);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const script = document.createElement("script");
|
|
75
|
+
script.id = SCRIPT_ID;
|
|
76
|
+
script.src = SDK_URL;
|
|
77
|
+
script.async = true;
|
|
78
|
+
script.addEventListener("load", onLoad);
|
|
79
|
+
script.addEventListener("error", onError);
|
|
80
|
+
document.head.appendChild(script);
|
|
81
|
+
});
|
|
82
|
+
loadPromises.set(env, promise);
|
|
83
|
+
return promise;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/react.tsx
|
|
87
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
88
|
+
function useTapipay(options) {
|
|
89
|
+
const [tapipay, setTapipay] = (0, import_react.useState)(null);
|
|
90
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
91
|
+
const environment = options == null ? void 0 : options.environment;
|
|
92
|
+
(0, import_react.useEffect)(() => {
|
|
93
|
+
let cancelled = false;
|
|
94
|
+
loadTapipay({ environment }).then((instance) => {
|
|
95
|
+
if (!cancelled) setTapipay(instance);
|
|
96
|
+
}).catch((err) => {
|
|
97
|
+
if (!cancelled) setError(err);
|
|
98
|
+
});
|
|
99
|
+
return () => {
|
|
100
|
+
cancelled = true;
|
|
101
|
+
};
|
|
102
|
+
}, [environment]);
|
|
103
|
+
return { tapipay, error };
|
|
104
|
+
}
|
|
105
|
+
function TapipayWidget({
|
|
106
|
+
organization,
|
|
107
|
+
identifier,
|
|
108
|
+
externalRequestId,
|
|
109
|
+
selectionStrategy,
|
|
110
|
+
environment,
|
|
111
|
+
onPending,
|
|
112
|
+
onCancelled,
|
|
113
|
+
className,
|
|
114
|
+
style
|
|
115
|
+
}) {
|
|
116
|
+
const containerRef = (0, import_react.useRef)(null);
|
|
117
|
+
const onPendingRef = (0, import_react.useRef)(onPending);
|
|
118
|
+
const onCancelledRef = (0, import_react.useRef)(onCancelled);
|
|
119
|
+
(0, import_react.useEffect)(() => {
|
|
120
|
+
onPendingRef.current = onPending;
|
|
121
|
+
}, [onPending]);
|
|
122
|
+
(0, import_react.useEffect)(() => {
|
|
123
|
+
onCancelledRef.current = onCancelled;
|
|
124
|
+
}, [onCancelled]);
|
|
125
|
+
(0, import_react.useEffect)(() => {
|
|
126
|
+
if (!containerRef.current) return;
|
|
127
|
+
const container = containerRef.current;
|
|
128
|
+
let tapipayInstance = null;
|
|
129
|
+
let cancelled = false;
|
|
130
|
+
const handlePending = (data) => {
|
|
131
|
+
var _a;
|
|
132
|
+
(_a = onPendingRef.current) == null ? void 0 : _a.call(onPendingRef, data);
|
|
133
|
+
};
|
|
134
|
+
const handleCancelled = (data) => {
|
|
135
|
+
var _a;
|
|
136
|
+
(_a = onCancelledRef.current) == null ? void 0 : _a.call(onCancelledRef, data);
|
|
137
|
+
};
|
|
138
|
+
loadTapipay({ environment }).then((instance) => {
|
|
139
|
+
if (cancelled) return;
|
|
140
|
+
tapipayInstance = instance;
|
|
141
|
+
instance.on("paymentPending", handlePending);
|
|
142
|
+
instance.on("paymentCancelled", handleCancelled);
|
|
143
|
+
instance.initialize({
|
|
144
|
+
container,
|
|
145
|
+
organization,
|
|
146
|
+
identifier,
|
|
147
|
+
externalRequestId,
|
|
148
|
+
selectionStrategy
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
return () => {
|
|
152
|
+
cancelled = true;
|
|
153
|
+
if (tapipayInstance) {
|
|
154
|
+
tapipayInstance.off("paymentPending", handlePending);
|
|
155
|
+
tapipayInstance.off("paymentCancelled", handleCancelled);
|
|
156
|
+
tapipayInstance.destroy(container);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}, [
|
|
160
|
+
organization,
|
|
161
|
+
identifier,
|
|
162
|
+
externalRequestId,
|
|
163
|
+
selectionStrategy,
|
|
164
|
+
environment
|
|
165
|
+
]);
|
|
166
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: containerRef, className, style });
|
|
167
|
+
}
|
|
168
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
169
|
+
0 && (module.exports = {
|
|
170
|
+
TapipayWidget,
|
|
171
|
+
useTapipay
|
|
172
|
+
});
|
|
173
|
+
//# sourceMappingURL=react.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx","../src/loader.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { loadTapipay } from \"./loader\";\nimport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentPendingEvent,\n} from \"./types\";\n\n// ─── useTapipay hook ──────────────────────────────────────────────────────────\n\n/**\n * Hook de bajo nivel que carga el SDK y retorna la instancia.\n * Útil cuando necesitas control manual sobre initialize/destroy.\n *\n * @example\n * const { tapipay, error } = useTapipay();\n * const { tapipay, error } = useTapipay({ environment: 'homo' });\n */\nexport function useTapipay(options?: LoadTapipayOptions): {\n\ttapipay: TapipayInstance | null;\n\terror: Error | null;\n} {\n\tconst [tapipay, setTapipay] = useState<TapipayInstance | null>(null);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst environment = options?.environment;\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tloadTapipay({ environment })\n\t\t\t.then((instance) => {\n\t\t\t\tif (!cancelled) setTapipay(instance);\n\t\t\t})\n\t\t\t.catch((err: Error) => {\n\t\t\t\tif (!cancelled) setError(err);\n\t\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [environment]);\n\n\treturn { tapipay, error };\n}\n\n// ─── TapipayWidget component ──────────────────────────────────────────────────\n\nexport interface TapipayWidgetProps extends Omit<TapipayOptions, \"container\"> {\n\t/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */\n\tenvironment?: TapipayEnvironment;\n\t/** Callback invocado cuando Yuno redirige al callback (pago en proceso). */\n\tonPending?: (data: TapipayPaymentPendingEvent) => void;\n\t/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */\n\tonCancelled?: (data: TapipayPaymentCancelledEvent) => void;\n\t/** Clases CSS adicionales para el contenedor del widget. */\n\tclassName?: string;\n\t/** Estilos inline adicionales para el contenedor del widget. */\n\tstyle?: React.CSSProperties;\n}\n\n/**\n * Componente React que encapsula el widget de pago TapiPay.\n *\n * Maneja internamente la carga del SDK, el ciclo de vida del widget\n * y el cleanup al desmontar. Compatible con React Strict Mode.\n *\n * @example\n * <TapipayWidget\n * organization=\"acme\"\n * identifier=\"CLI-001\"\n * externalRequestId=\"FAC-2024-001\"\n * onPending={(data) => console.log(\"Pago en proceso\", data)}\n * onCancelled={() => console.log(\"Pago cancelado por el usuario\")}\n * />\n */\nexport function TapipayWidget({\n\torganization,\n\tidentifier,\n\texternalRequestId,\n\tselectionStrategy,\n\tenvironment,\n\tonPending,\n\tonCancelled,\n\tclassName,\n\tstyle,\n}: TapipayWidgetProps) {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\t// Refs para evitar re-renders innecesarios y closures estáticos en useEffect\n\tconst onPendingRef = useRef(onPending);\n\tconst onCancelledRef = useRef(onCancelled);\n\n\tuseEffect(() => {\n\t\tonPendingRef.current = onPending;\n\t}, [onPending]);\n\n\tuseEffect(() => {\n\t\tonCancelledRef.current = onCancelled;\n\t}, [onCancelled]);\n\n\tuseEffect(() => {\n\t\tif (!containerRef.current) return;\n\t\tconst container = containerRef.current;\n\n\t\tlet tapipayInstance: TapipayInstance | null = null;\n\t\tlet cancelled = false;\n\n\t\tconst handlePending = (data: TapipayPaymentPendingEvent) => {\n\t\t\tonPendingRef.current?.(data);\n\t\t};\n\t\tconst handleCancelled = (data: TapipayPaymentCancelledEvent) => {\n\t\t\tonCancelledRef.current?.(data);\n\t\t};\n\n\t\tloadTapipay({ environment }).then((instance) => {\n\t\t\tif (cancelled) return;\n\t\t\ttapipayInstance = instance;\n\n\t\t\tinstance.on(\"paymentPending\", handlePending);\n\t\t\tinstance.on(\"paymentCancelled\", handleCancelled);\n\n\t\t\tinstance.initialize({\n\t\t\t\tcontainer,\n\t\t\t\torganization,\n\t\t\t\tidentifier,\n\t\t\t\texternalRequestId,\n\t\t\t\tselectionStrategy,\n\t\t\t});\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tif (tapipayInstance) {\n\t\t\t\ttapipayInstance.off(\"paymentPending\", handlePending);\n\t\t\t\ttapipayInstance.off(\"paymentCancelled\", handleCancelled);\n\t\t\t\ttapipayInstance.destroy(container);\n\t\t\t}\n\t\t};\n\t\t// El widget se re-monta si cambian los parámetros de identificación o entorno\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\torganization,\n\t\tidentifier,\n\t\texternalRequestId,\n\t\tselectionStrategy,\n\t\tenvironment,\n\t]);\n\n\treturn <div ref={containerRef} className={className} style={style} />;\n}\n","import type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n} from \"./types\";\n\nconst SDK_URLS: Record<TapipayEnvironment, string> = {\n\tproduction: \"https://app.tapipay.la/embed.js\",\n\thomo: \"https://homo.tapipay.la/embed.js\",\n};\n\n// Idempotencia por entorno\nconst loadPromises = new Map<TapipayEnvironment, Promise<TapipayInstance>>();\n\n/**\n * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.\n *\n * - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.\n * - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.\n * - Compatible con React Strict Mode (doble mount/unmount).\n *\n * @example\n * // Producción (default)\n * const tapipay = await loadTapipay();\n *\n * // Homologación\n * const tapipay = await loadTapipay({ environment: 'homo' });\n *\n * tapipay.initialize({ container: \"#widget\", organization: \"acme\", identifier: \"CLI-001\" });\n */\nexport function loadTapipay(\n\toptions?: LoadTapipayOptions,\n): Promise<TapipayInstance> {\n\tconst env: TapipayEnvironment = options?.environment ?? \"production\";\n\tconst SDK_URL = SDK_URLS[env];\n\tconst SCRIPT_ID = `tapipay-embed-sdk-${env}`;\n\n\t// SSR guard\n\tif (typeof window === \"undefined\") {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\"[TapiPay] loadTapipay() requires a browser environment.\"),\n\t\t);\n\t}\n\n\t// Ya cargado de forma síncrona (script tag directo)\n\tif (window.tapipay && !window.tapipay._q) {\n\t\treturn Promise.resolve(window.tapipay);\n\t}\n\n\t// Reutilizar promise existente (idempotencia por entorno)\n\tconst existing = loadPromises.get(env);\n\tif (existing) return existing;\n\n\tconst promise = new Promise<TapipayInstance>((resolve, reject) => {\n\t\t// Si ya hay un script inyectado, esperar a que cargue\n\t\tconst existingScript = document.getElementById(\n\t\t\tSCRIPT_ID,\n\t\t) as HTMLScriptElement | null;\n\n\t\tconst onLoad = () => {\n\t\t\tif (window.tapipay) {\n\t\t\t\tresolve(window.tapipay);\n\t\t\t} else {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"[TapiPay] El script cargó pero window.tapipay no está definido.\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onError = () => {\n\t\t\tloadPromises.delete(env);\n\t\t\treject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));\n\t\t};\n\n\t\tif (existingScript) {\n\t\t\texistingScript.addEventListener(\"load\", onLoad);\n\t\t\texistingScript.addEventListener(\"error\", onError);\n\t\t\treturn;\n\t\t}\n\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = SCRIPT_ID;\n\t\tscript.src = SDK_URL;\n\t\tscript.async = true;\n\t\tscript.addEventListener(\"load\", onLoad);\n\t\tscript.addEventListener(\"error\", onError);\n\t\tdocument.head.appendChild(script);\n\t});\n\n\tloadPromises.set(env, promise);\n\treturn promise;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4C;;;ACM5C,IAAM,WAA+C;AAAA,EACpD,YAAY;AAAA,EACZ,MAAM;AACP;AAGA,IAAM,eAAe,oBAAI,IAAkD;AAkBpE,SAAS,YACf,SAC2B;AAhC5B;AAiCC,QAAM,OAA0B,wCAAS,gBAAT,YAAwB;AACxD,QAAM,UAAU,SAAS,GAAG;AAC5B,QAAM,YAAY,qBAAqB,GAAG;AAG1C,MAAI,OAAO,WAAW,aAAa;AAClC,WAAO,QAAQ;AAAA,MACd,IAAI,MAAM,yDAAyD;AAAA,IACpE;AAAA,EACD;AAGA,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,IAAI;AACzC,WAAO,QAAQ,QAAQ,OAAO,OAAO;AAAA,EACtC;AAGA,QAAM,WAAW,aAAa,IAAI,GAAG;AACrC,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,IAAI,QAAyB,CAAC,SAAS,WAAW;AAEjE,UAAM,iBAAiB,SAAS;AAAA,MAC/B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM;AACpB,UAAI,OAAO,SAAS;AACnB,gBAAQ,OAAO,OAAO;AAAA,MACvB,OAAO;AACN;AAAA,UACC,IAAI;AAAA,YACH;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,UAAU,MAAM;AACrB,mBAAa,OAAO,GAAG;AACvB,aAAO,IAAI,MAAM,0CAA0C,OAAO,EAAE,CAAC;AAAA,IACtE;AAEA,QAAI,gBAAgB;AACnB,qBAAe,iBAAiB,QAAQ,MAAM;AAC9C,qBAAe,iBAAiB,SAAS,OAAO;AAChD;AAAA,IACD;AAEA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,KAAK;AACZ,WAAO,MAAM;AACb,WAAO,QAAQ;AACf,WAAO,iBAAiB,QAAQ,MAAM;AACtC,WAAO,iBAAiB,SAAS,OAAO;AACxC,aAAS,KAAK,YAAY,MAAM;AAAA,EACjC,CAAC;AAED,eAAa,IAAI,KAAK,OAAO;AAC7B,SAAO;AACR;;;ADuDQ;AA/HD,SAAS,WAAW,SAGzB;AACD,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAiC,IAAI;AACnE,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAuB,IAAI;AACrD,QAAM,cAAc,mCAAS;AAE7B,8BAAU,MAAM;AACf,QAAI,YAAY;AAChB,gBAAY,EAAE,YAAY,CAAC,EACzB,KAAK,CAAC,aAAa;AACnB,UAAI,CAAC,UAAW,YAAW,QAAQ;AAAA,IACpC,CAAC,EACA,MAAM,CAAC,QAAe;AACtB,UAAI,CAAC,UAAW,UAAS,GAAG;AAAA,IAC7B,CAAC;AACF,WAAO,MAAM;AACZ,kBAAY;AAAA,IACb;AAAA,EACD,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO,EAAE,SAAS,MAAM;AACzB;AAgCO,SAAS,cAAc;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAuB;AACtB,QAAM,mBAAe,qBAAuB,IAAI;AAEhD,QAAM,mBAAe,qBAAO,SAAS;AACrC,QAAM,qBAAiB,qBAAO,WAAW;AAEzC,8BAAU,MAAM;AACf,iBAAa,UAAU;AAAA,EACxB,GAAG,CAAC,SAAS,CAAC;AAEd,8BAAU,MAAM;AACf,mBAAe,UAAU;AAAA,EAC1B,GAAG,CAAC,WAAW,CAAC;AAEhB,8BAAU,MAAM;AACf,QAAI,CAAC,aAAa,QAAS;AAC3B,UAAM,YAAY,aAAa;AAE/B,QAAI,kBAA0C;AAC9C,QAAI,YAAY;AAEhB,UAAM,gBAAgB,CAAC,SAAqC;AA3G9D;AA4GG,yBAAa,YAAb,sCAAuB;AAAA,IACxB;AACA,UAAM,kBAAkB,CAAC,SAAuC;AA9GlE;AA+GG,2BAAe,YAAf,wCAAyB;AAAA,IAC1B;AAEA,gBAAY,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa;AAC/C,UAAI,UAAW;AACf,wBAAkB;AAElB,eAAS,GAAG,kBAAkB,aAAa;AAC3C,eAAS,GAAG,oBAAoB,eAAe;AAE/C,eAAS,WAAW;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACZ,kBAAY;AACZ,UAAI,iBAAiB;AACpB,wBAAgB,IAAI,kBAAkB,aAAa;AACnD,wBAAgB,IAAI,oBAAoB,eAAe;AACvD,wBAAgB,QAAQ,SAAS;AAAA,MAClC;AAAA,IACD;AAAA,EAGD,GAAG;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,4CAAC,SAAI,KAAK,cAAc,WAAsB,OAAc;AACpE;","names":[]}
|
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { b as TapipayOptions, a as TapipayEnvironment, d as TapipayPaymentPendingEvent, c as TapipayPaymentCancelledEvent, L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook de bajo nivel que carga el SDK y retorna la instancia.
|
|
6
|
+
* Útil cuando necesitas control manual sobre initialize/destroy.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const { tapipay, error } = useTapipay();
|
|
10
|
+
* const { tapipay, error } = useTapipay({ environment: 'homo' });
|
|
11
|
+
*/
|
|
12
|
+
declare function useTapipay(options?: LoadTapipayOptions): {
|
|
13
|
+
tapipay: TapipayInstance | null;
|
|
14
|
+
error: Error | null;
|
|
15
|
+
};
|
|
16
|
+
interface TapipayWidgetProps extends Omit<TapipayOptions, "container"> {
|
|
17
|
+
/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */
|
|
18
|
+
environment?: TapipayEnvironment;
|
|
19
|
+
/** Callback invocado cuando Yuno redirige al callback (pago en proceso). */
|
|
20
|
+
onPending?: (data: TapipayPaymentPendingEvent) => void;
|
|
21
|
+
/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */
|
|
22
|
+
onCancelled?: (data: TapipayPaymentCancelledEvent) => void;
|
|
23
|
+
/** Clases CSS adicionales para el contenedor del widget. */
|
|
24
|
+
className?: string;
|
|
25
|
+
/** Estilos inline adicionales para el contenedor del widget. */
|
|
26
|
+
style?: React.CSSProperties;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Componente React que encapsula el widget de pago TapiPay.
|
|
30
|
+
*
|
|
31
|
+
* Maneja internamente la carga del SDK, el ciclo de vida del widget
|
|
32
|
+
* y el cleanup al desmontar. Compatible con React Strict Mode.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <TapipayWidget
|
|
36
|
+
* organization="acme"
|
|
37
|
+
* identifier="CLI-001"
|
|
38
|
+
* externalRequestId="FAC-2024-001"
|
|
39
|
+
* onPending={(data) => console.log("Pago en proceso", data)}
|
|
40
|
+
* onCancelled={() => console.log("Pago cancelado por el usuario")}
|
|
41
|
+
* />
|
|
42
|
+
*/
|
|
43
|
+
declare function TapipayWidget({ organization, identifier, externalRequestId, selectionStrategy, environment, onPending, onCancelled, className, style, }: TapipayWidgetProps): react_jsx_runtime.JSX.Element;
|
|
44
|
+
|
|
45
|
+
export { TapipayWidget, type TapipayWidgetProps, useTapipay };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { b as TapipayOptions, a as TapipayEnvironment, d as TapipayPaymentPendingEvent, c as TapipayPaymentCancelledEvent, L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook de bajo nivel que carga el SDK y retorna la instancia.
|
|
6
|
+
* Útil cuando necesitas control manual sobre initialize/destroy.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const { tapipay, error } = useTapipay();
|
|
10
|
+
* const { tapipay, error } = useTapipay({ environment: 'homo' });
|
|
11
|
+
*/
|
|
12
|
+
declare function useTapipay(options?: LoadTapipayOptions): {
|
|
13
|
+
tapipay: TapipayInstance | null;
|
|
14
|
+
error: Error | null;
|
|
15
|
+
};
|
|
16
|
+
interface TapipayWidgetProps extends Omit<TapipayOptions, "container"> {
|
|
17
|
+
/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */
|
|
18
|
+
environment?: TapipayEnvironment;
|
|
19
|
+
/** Callback invocado cuando Yuno redirige al callback (pago en proceso). */
|
|
20
|
+
onPending?: (data: TapipayPaymentPendingEvent) => void;
|
|
21
|
+
/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */
|
|
22
|
+
onCancelled?: (data: TapipayPaymentCancelledEvent) => void;
|
|
23
|
+
/** Clases CSS adicionales para el contenedor del widget. */
|
|
24
|
+
className?: string;
|
|
25
|
+
/** Estilos inline adicionales para el contenedor del widget. */
|
|
26
|
+
style?: React.CSSProperties;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Componente React que encapsula el widget de pago TapiPay.
|
|
30
|
+
*
|
|
31
|
+
* Maneja internamente la carga del SDK, el ciclo de vida del widget
|
|
32
|
+
* y el cleanup al desmontar. Compatible con React Strict Mode.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* <TapipayWidget
|
|
36
|
+
* organization="acme"
|
|
37
|
+
* identifier="CLI-001"
|
|
38
|
+
* externalRequestId="FAC-2024-001"
|
|
39
|
+
* onPending={(data) => console.log("Pago en proceso", data)}
|
|
40
|
+
* onCancelled={() => console.log("Pago cancelado por el usuario")}
|
|
41
|
+
* />
|
|
42
|
+
*/
|
|
43
|
+
declare function TapipayWidget({ organization, identifier, externalRequestId, selectionStrategy, environment, onPending, onCancelled, className, style, }: TapipayWidgetProps): react_jsx_runtime.JSX.Element;
|
|
44
|
+
|
|
45
|
+
export { TapipayWidget, type TapipayWidgetProps, useTapipay };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadTapipay
|
|
3
|
+
} from "./chunk-2WNQZXMS.js";
|
|
4
|
+
|
|
5
|
+
// src/react.tsx
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
function useTapipay(options) {
|
|
9
|
+
const [tapipay, setTapipay] = useState(null);
|
|
10
|
+
const [error, setError] = useState(null);
|
|
11
|
+
const environment = options == null ? void 0 : options.environment;
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
let cancelled = false;
|
|
14
|
+
loadTapipay({ environment }).then((instance) => {
|
|
15
|
+
if (!cancelled) setTapipay(instance);
|
|
16
|
+
}).catch((err) => {
|
|
17
|
+
if (!cancelled) setError(err);
|
|
18
|
+
});
|
|
19
|
+
return () => {
|
|
20
|
+
cancelled = true;
|
|
21
|
+
};
|
|
22
|
+
}, [environment]);
|
|
23
|
+
return { tapipay, error };
|
|
24
|
+
}
|
|
25
|
+
function TapipayWidget({
|
|
26
|
+
organization,
|
|
27
|
+
identifier,
|
|
28
|
+
externalRequestId,
|
|
29
|
+
selectionStrategy,
|
|
30
|
+
environment,
|
|
31
|
+
onPending,
|
|
32
|
+
onCancelled,
|
|
33
|
+
className,
|
|
34
|
+
style
|
|
35
|
+
}) {
|
|
36
|
+
const containerRef = useRef(null);
|
|
37
|
+
const onPendingRef = useRef(onPending);
|
|
38
|
+
const onCancelledRef = useRef(onCancelled);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
onPendingRef.current = onPending;
|
|
41
|
+
}, [onPending]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
onCancelledRef.current = onCancelled;
|
|
44
|
+
}, [onCancelled]);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!containerRef.current) return;
|
|
47
|
+
const container = containerRef.current;
|
|
48
|
+
let tapipayInstance = null;
|
|
49
|
+
let cancelled = false;
|
|
50
|
+
const handlePending = (data) => {
|
|
51
|
+
var _a;
|
|
52
|
+
(_a = onPendingRef.current) == null ? void 0 : _a.call(onPendingRef, data);
|
|
53
|
+
};
|
|
54
|
+
const handleCancelled = (data) => {
|
|
55
|
+
var _a;
|
|
56
|
+
(_a = onCancelledRef.current) == null ? void 0 : _a.call(onCancelledRef, data);
|
|
57
|
+
};
|
|
58
|
+
loadTapipay({ environment }).then((instance) => {
|
|
59
|
+
if (cancelled) return;
|
|
60
|
+
tapipayInstance = instance;
|
|
61
|
+
instance.on("paymentPending", handlePending);
|
|
62
|
+
instance.on("paymentCancelled", handleCancelled);
|
|
63
|
+
instance.initialize({
|
|
64
|
+
container,
|
|
65
|
+
organization,
|
|
66
|
+
identifier,
|
|
67
|
+
externalRequestId,
|
|
68
|
+
selectionStrategy
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
return () => {
|
|
72
|
+
cancelled = true;
|
|
73
|
+
if (tapipayInstance) {
|
|
74
|
+
tapipayInstance.off("paymentPending", handlePending);
|
|
75
|
+
tapipayInstance.off("paymentCancelled", handleCancelled);
|
|
76
|
+
tapipayInstance.destroy(container);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}, [
|
|
80
|
+
organization,
|
|
81
|
+
identifier,
|
|
82
|
+
externalRequestId,
|
|
83
|
+
selectionStrategy,
|
|
84
|
+
environment
|
|
85
|
+
]);
|
|
86
|
+
return /* @__PURE__ */ jsx("div", { ref: containerRef, className, style });
|
|
87
|
+
}
|
|
88
|
+
export {
|
|
89
|
+
TapipayWidget,
|
|
90
|
+
useTapipay
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { loadTapipay } from \"./loader\";\nimport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentPendingEvent,\n} from \"./types\";\n\n// ─── useTapipay hook ──────────────────────────────────────────────────────────\n\n/**\n * Hook de bajo nivel que carga el SDK y retorna la instancia.\n * Útil cuando necesitas control manual sobre initialize/destroy.\n *\n * @example\n * const { tapipay, error } = useTapipay();\n * const { tapipay, error } = useTapipay({ environment: 'homo' });\n */\nexport function useTapipay(options?: LoadTapipayOptions): {\n\ttapipay: TapipayInstance | null;\n\terror: Error | null;\n} {\n\tconst [tapipay, setTapipay] = useState<TapipayInstance | null>(null);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst environment = options?.environment;\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tloadTapipay({ environment })\n\t\t\t.then((instance) => {\n\t\t\t\tif (!cancelled) setTapipay(instance);\n\t\t\t})\n\t\t\t.catch((err: Error) => {\n\t\t\t\tif (!cancelled) setError(err);\n\t\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [environment]);\n\n\treturn { tapipay, error };\n}\n\n// ─── TapipayWidget component ──────────────────────────────────────────────────\n\nexport interface TapipayWidgetProps extends Omit<TapipayOptions, \"container\"> {\n\t/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */\n\tenvironment?: TapipayEnvironment;\n\t/** Callback invocado cuando Yuno redirige al callback (pago en proceso). */\n\tonPending?: (data: TapipayPaymentPendingEvent) => void;\n\t/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */\n\tonCancelled?: (data: TapipayPaymentCancelledEvent) => void;\n\t/** Clases CSS adicionales para el contenedor del widget. */\n\tclassName?: string;\n\t/** Estilos inline adicionales para el contenedor del widget. */\n\tstyle?: React.CSSProperties;\n}\n\n/**\n * Componente React que encapsula el widget de pago TapiPay.\n *\n * Maneja internamente la carga del SDK, el ciclo de vida del widget\n * y el cleanup al desmontar. Compatible con React Strict Mode.\n *\n * @example\n * <TapipayWidget\n * organization=\"acme\"\n * identifier=\"CLI-001\"\n * externalRequestId=\"FAC-2024-001\"\n * onPending={(data) => console.log(\"Pago en proceso\", data)}\n * onCancelled={() => console.log(\"Pago cancelado por el usuario\")}\n * />\n */\nexport function TapipayWidget({\n\torganization,\n\tidentifier,\n\texternalRequestId,\n\tselectionStrategy,\n\tenvironment,\n\tonPending,\n\tonCancelled,\n\tclassName,\n\tstyle,\n}: TapipayWidgetProps) {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\t// Refs para evitar re-renders innecesarios y closures estáticos en useEffect\n\tconst onPendingRef = useRef(onPending);\n\tconst onCancelledRef = useRef(onCancelled);\n\n\tuseEffect(() => {\n\t\tonPendingRef.current = onPending;\n\t}, [onPending]);\n\n\tuseEffect(() => {\n\t\tonCancelledRef.current = onCancelled;\n\t}, [onCancelled]);\n\n\tuseEffect(() => {\n\t\tif (!containerRef.current) return;\n\t\tconst container = containerRef.current;\n\n\t\tlet tapipayInstance: TapipayInstance | null = null;\n\t\tlet cancelled = false;\n\n\t\tconst handlePending = (data: TapipayPaymentPendingEvent) => {\n\t\t\tonPendingRef.current?.(data);\n\t\t};\n\t\tconst handleCancelled = (data: TapipayPaymentCancelledEvent) => {\n\t\t\tonCancelledRef.current?.(data);\n\t\t};\n\n\t\tloadTapipay({ environment }).then((instance) => {\n\t\t\tif (cancelled) return;\n\t\t\ttapipayInstance = instance;\n\n\t\t\tinstance.on(\"paymentPending\", handlePending);\n\t\t\tinstance.on(\"paymentCancelled\", handleCancelled);\n\n\t\t\tinstance.initialize({\n\t\t\t\tcontainer,\n\t\t\t\torganization,\n\t\t\t\tidentifier,\n\t\t\t\texternalRequestId,\n\t\t\t\tselectionStrategy,\n\t\t\t});\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tif (tapipayInstance) {\n\t\t\t\ttapipayInstance.off(\"paymentPending\", handlePending);\n\t\t\t\ttapipayInstance.off(\"paymentCancelled\", handleCancelled);\n\t\t\t\ttapipayInstance.destroy(container);\n\t\t\t}\n\t\t};\n\t\t// El widget se re-monta si cambian los parámetros de identificación o entorno\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\torganization,\n\t\tidentifier,\n\t\texternalRequestId,\n\t\tselectionStrategy,\n\t\tenvironment,\n\t]);\n\n\treturn <div ref={containerRef} className={className} style={style} />;\n}\n"],"mappings":";;;;;AAAA,SAAS,WAAW,QAAQ,gBAAgB;AAoJpC;AA/HD,SAAS,WAAW,SAGzB;AACD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAiC,IAAI;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AACrD,QAAM,cAAc,mCAAS;AAE7B,YAAU,MAAM;AACf,QAAI,YAAY;AAChB,gBAAY,EAAE,YAAY,CAAC,EACzB,KAAK,CAAC,aAAa;AACnB,UAAI,CAAC,UAAW,YAAW,QAAQ;AAAA,IACpC,CAAC,EACA,MAAM,CAAC,QAAe;AACtB,UAAI,CAAC,UAAW,UAAS,GAAG;AAAA,IAC7B,CAAC;AACF,WAAO,MAAM;AACZ,kBAAY;AAAA,IACb;AAAA,EACD,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO,EAAE,SAAS,MAAM;AACzB;AAgCO,SAAS,cAAc;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAuB;AACtB,QAAM,eAAe,OAAuB,IAAI;AAEhD,QAAM,eAAe,OAAO,SAAS;AACrC,QAAM,iBAAiB,OAAO,WAAW;AAEzC,YAAU,MAAM;AACf,iBAAa,UAAU;AAAA,EACxB,GAAG,CAAC,SAAS,CAAC;AAEd,YAAU,MAAM;AACf,mBAAe,UAAU;AAAA,EAC1B,GAAG,CAAC,WAAW,CAAC;AAEhB,YAAU,MAAM;AACf,QAAI,CAAC,aAAa,QAAS;AAC3B,UAAM,YAAY,aAAa;AAE/B,QAAI,kBAA0C;AAC9C,QAAI,YAAY;AAEhB,UAAM,gBAAgB,CAAC,SAAqC;AA3G9D;AA4GG,yBAAa,YAAb,sCAAuB;AAAA,IACxB;AACA,UAAM,kBAAkB,CAAC,SAAuC;AA9GlE;AA+GG,2BAAe,YAAf,wCAAyB;AAAA,IAC1B;AAEA,gBAAY,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa;AAC/C,UAAI,UAAW;AACf,wBAAkB;AAElB,eAAS,GAAG,kBAAkB,aAAa;AAC3C,eAAS,GAAG,oBAAoB,eAAe;AAE/C,eAAS,WAAW;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACZ,kBAAY;AACZ,UAAI,iBAAiB;AACpB,wBAAgB,IAAI,kBAAkB,aAAa;AACnD,wBAAgB,IAAI,oBAAoB,eAAe;AACvD,wBAAgB,QAAQ,SAAS;AAAA,MAClC;AAAA,IACD;AAAA,EAGD,GAAG;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,oBAAC,SAAI,KAAK,cAAc,WAAsB,OAAc;AACpE;","names":[]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entorno de ejecución del SDK.
|
|
3
|
+
* - `'production'`: carga desde https://app.tapipay.la/embed.js (default)
|
|
4
|
+
* - `'homo'`: carga desde https://homo.tapipay.la/embed.js
|
|
5
|
+
*/
|
|
6
|
+
type TapipayEnvironment = "production" | "homo";
|
|
7
|
+
/**
|
|
8
|
+
* Opciones para `loadTapipay()`.
|
|
9
|
+
*/
|
|
10
|
+
interface LoadTapipayOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Entorno a usar. Por defecto `'production'`.
|
|
13
|
+
* Para homologación usar `'homo'`.
|
|
14
|
+
*/
|
|
15
|
+
environment?: TapipayEnvironment;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Opciones requeridas para montar el widget TapiPay.
|
|
19
|
+
*/
|
|
20
|
+
interface TapipayOptions {
|
|
21
|
+
/** Selector CSS o elemento DOM donde se montará el widget. */
|
|
22
|
+
container: string | HTMLElement;
|
|
23
|
+
/** Alias de la Organización configurado en el dashboard de TapiPay (ej. "acme"). Corresponde al campo "Alias" en Configuración → Organización. */
|
|
24
|
+
organization: string;
|
|
25
|
+
/** Identificador del cliente en el sistema del cliente (ej. "CLI-001"). */
|
|
26
|
+
identifier: string;
|
|
27
|
+
/** ID externo de la deuda a preseleccionar (ej. número de factura). */
|
|
28
|
+
externalRequestId?: string;
|
|
29
|
+
/** Estrategia de selección automática de deuda. */
|
|
30
|
+
selectionStrategy?: "oldestCreated";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Payload del evento paymentPending.
|
|
34
|
+
* El usuario completó el flujo de Yuno; el pago está en proceso.
|
|
35
|
+
* El estado real del pago se confirma vía webhooks en el backend.
|
|
36
|
+
*/
|
|
37
|
+
interface TapipayPaymentPendingEvent {
|
|
38
|
+
/** Siempre "TAPIPAY_CALLBACK" */
|
|
39
|
+
type: string;
|
|
40
|
+
/** Estado del pago: siempre "pending" */
|
|
41
|
+
status: "pending";
|
|
42
|
+
/** Parámetros que Yuno haya enviado al callback (pueden estar vacíos) */
|
|
43
|
+
data: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Payload del evento paymentCancelled.
|
|
47
|
+
* El usuario cerró el popup sin completar el flujo de pago.
|
|
48
|
+
*/
|
|
49
|
+
type TapipayPaymentCancelledEvent = {};
|
|
50
|
+
/**
|
|
51
|
+
* Instancia del SDK TapiPay expuesta en window.tapipay y retornada por loadTapipay().
|
|
52
|
+
*/
|
|
53
|
+
interface TapipayInstance {
|
|
54
|
+
initialize(options: TapipayOptions): void;
|
|
55
|
+
destroy(container: string | HTMLElement): void;
|
|
56
|
+
on(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
|
|
57
|
+
on(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
|
|
58
|
+
off(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
|
|
59
|
+
off(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
|
|
60
|
+
off(event: string, handler: (...args: unknown[]) => unknown): void;
|
|
61
|
+
/** Cola interna usada por el stub antes de que cargue el SDK real. */
|
|
62
|
+
_q?: [string, unknown[]][];
|
|
63
|
+
}
|
|
64
|
+
declare global {
|
|
65
|
+
interface Window {
|
|
66
|
+
tapipay?: TapipayInstance;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type { LoadTapipayOptions as L, TapipayInstance as T, TapipayEnvironment as a, TapipayOptions as b, TapipayPaymentCancelledEvent as c, TapipayPaymentPendingEvent as d };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entorno de ejecución del SDK.
|
|
3
|
+
* - `'production'`: carga desde https://app.tapipay.la/embed.js (default)
|
|
4
|
+
* - `'homo'`: carga desde https://homo.tapipay.la/embed.js
|
|
5
|
+
*/
|
|
6
|
+
type TapipayEnvironment = "production" | "homo";
|
|
7
|
+
/**
|
|
8
|
+
* Opciones para `loadTapipay()`.
|
|
9
|
+
*/
|
|
10
|
+
interface LoadTapipayOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Entorno a usar. Por defecto `'production'`.
|
|
13
|
+
* Para homologación usar `'homo'`.
|
|
14
|
+
*/
|
|
15
|
+
environment?: TapipayEnvironment;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Opciones requeridas para montar el widget TapiPay.
|
|
19
|
+
*/
|
|
20
|
+
interface TapipayOptions {
|
|
21
|
+
/** Selector CSS o elemento DOM donde se montará el widget. */
|
|
22
|
+
container: string | HTMLElement;
|
|
23
|
+
/** Alias de la Organización configurado en el dashboard de TapiPay (ej. "acme"). Corresponde al campo "Alias" en Configuración → Organización. */
|
|
24
|
+
organization: string;
|
|
25
|
+
/** Identificador del cliente en el sistema del cliente (ej. "CLI-001"). */
|
|
26
|
+
identifier: string;
|
|
27
|
+
/** ID externo de la deuda a preseleccionar (ej. número de factura). */
|
|
28
|
+
externalRequestId?: string;
|
|
29
|
+
/** Estrategia de selección automática de deuda. */
|
|
30
|
+
selectionStrategy?: "oldestCreated";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Payload del evento paymentPending.
|
|
34
|
+
* El usuario completó el flujo de Yuno; el pago está en proceso.
|
|
35
|
+
* El estado real del pago se confirma vía webhooks en el backend.
|
|
36
|
+
*/
|
|
37
|
+
interface TapipayPaymentPendingEvent {
|
|
38
|
+
/** Siempre "TAPIPAY_CALLBACK" */
|
|
39
|
+
type: string;
|
|
40
|
+
/** Estado del pago: siempre "pending" */
|
|
41
|
+
status: "pending";
|
|
42
|
+
/** Parámetros que Yuno haya enviado al callback (pueden estar vacíos) */
|
|
43
|
+
data: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Payload del evento paymentCancelled.
|
|
47
|
+
* El usuario cerró el popup sin completar el flujo de pago.
|
|
48
|
+
*/
|
|
49
|
+
type TapipayPaymentCancelledEvent = {};
|
|
50
|
+
/**
|
|
51
|
+
* Instancia del SDK TapiPay expuesta en window.tapipay y retornada por loadTapipay().
|
|
52
|
+
*/
|
|
53
|
+
interface TapipayInstance {
|
|
54
|
+
initialize(options: TapipayOptions): void;
|
|
55
|
+
destroy(container: string | HTMLElement): void;
|
|
56
|
+
on(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
|
|
57
|
+
on(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
|
|
58
|
+
off(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
|
|
59
|
+
off(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
|
|
60
|
+
off(event: string, handler: (...args: unknown[]) => unknown): void;
|
|
61
|
+
/** Cola interna usada por el stub antes de que cargue el SDK real. */
|
|
62
|
+
_q?: [string, unknown[]][];
|
|
63
|
+
}
|
|
64
|
+
declare global {
|
|
65
|
+
interface Window {
|
|
66
|
+
tapipay?: TapipayInstance;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type { LoadTapipayOptions as L, TapipayInstance as T, TapipayEnvironment as a, TapipayOptions as b, TapipayPaymentCancelledEvent as c, TapipayPaymentPendingEvent as d };
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@npmtapi/embed",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "TapiPay Embed SDK — carga y controla el widget de pago embebido",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.cjs"
|
|
11
|
+
},
|
|
12
|
+
"./react": {
|
|
13
|
+
"types": "./dist/react.d.ts",
|
|
14
|
+
"import": "./dist/react.js",
|
|
15
|
+
"require": "./dist/react.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"dev": "tsup --watch",
|
|
24
|
+
"prepublishOnly": "pnpm build"
|
|
25
|
+
},
|
|
26
|
+
"author": "tapipay",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"react": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/react": "^18.0.0",
|
|
40
|
+
"react": "^18.0.0",
|
|
41
|
+
"tsup": "^8.0.0",
|
|
42
|
+
"typescript": "^5.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|