@monkeyplus/payscope 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/dist/THIRD-PARTY-LICENSES.md +41 -0
- package/dist/_chunks/auth.d.mts +707 -0
- package/dist/_chunks/database.mjs +831 -0
- package/dist/_chunks/db.d.mts +7100 -0
- package/dist/_chunks/index.d.mts +178 -0
- package/dist/_chunks/lib.mjs +3073 -0
- package/dist/_chunks/libs/better-call.d.mts +478 -0
- package/dist/_chunks/libs/postgres.d.mts +1 -0
- package/dist/_chunks/rolldown-runtime.mjs +11 -0
- package/dist/server/db.d.mts +2 -0
- package/dist/server/db.mjs +108 -0
- package/dist/server/env.d.mts +21 -0
- package/dist/server/env.mjs +22 -0
- package/dist/server/lib.d.mts +362 -0
- package/dist/server/lib.mjs +2 -0
- package/dist/server/router.d.mts +1218 -0
- package/dist/server/router.mjs +1157 -0
- package/dist/server/schemas/auth.d.mts +2 -0
- package/dist/server/schemas/auth.mjs +62 -0
- package/package.json +58 -0
- package/storefront/Readme.md +0 -0
- package/storefront/auth.ts +29 -0
- package/storefront/cart/ResumeCart.vue +217 -0
- package/storefront/cart/ResumeCartSelect.vue +32 -0
- package/storefront/cart/ShoppinCart.vue +100 -0
- package/storefront/cart/ShoppinCartItem.vue +99 -0
- package/storefront/checkout/App.vue +36 -0
- package/storefront/checkout/AppCart.vue +72 -0
- package/storefront/checkout/AppCartDiscount.vue +74 -0
- package/storefront/checkout/AppCartTotals.vue +72 -0
- package/storefront/checkout/AppLoading.vue +55 -0
- package/storefront/checkout/composables.ts +28 -0
- package/storefront/checkout/constants.ts +0 -0
- package/storefront/checkout/main.ts +11 -0
- package/storefront/checkout/pages/Address/Address.vue +95 -0
- package/storefront/checkout/pages/Info/Info.vue +94 -0
- package/storefront/checkout/pages/Info/InfoUser.vue +38 -0
- package/storefront/checkout/pages/Pay/Pay.vue +115 -0
- package/storefront/checkout/pages/Pay/Providers/BancoEconomico/BancoEconomico.vue +9 -0
- package/storefront/checkout/pages/Pay/Providers/Cybersource/Cybersource.vue +9 -0
- package/storefront/checkout/pages/Pay/Providers/Datafast/Datafast.vue +9 -0
- package/storefront/checkout/pages/Pay/Providers/Multipago/Multipago.vue +9 -0
- package/storefront/checkout/pages/Pay/Providers/Pagomedios/Pagomedios.vue +93 -0
- package/storefront/checkout/pages/Pay/Providers/Pagomedios/composable.ts +23 -0
- package/storefront/checkout/pages/Pay/Providers/Paypal/Paypal.vue +168 -0
- package/storefront/checkout/pages/Pay/Providers/Paypal/composable.ts +33 -0
- package/storefront/checkout/pages/Pay/Providers/Placetopay/Placetopay.vue +9 -0
- package/storefront/checkout/pages/Pay/Providers/Wabi/Wabi.vue +9 -0
- package/storefront/checkout/pages/Pay/Providers/composable.ts +30 -0
- package/storefront/checkout/pages/Payment/Payment.vue +19 -0
- package/storefront/checkout/pages/Payment/PaymentStatus.vue +187 -0
- package/storefront/checkout/pages/Payment/PaymentStatusDetail.vue +77 -0
- package/storefront/checkout/pages/Payment/composable.ts +81 -0
- package/storefront/checkout/pages/Shipping/Shipping.vue +67 -0
- package/storefront/checkout/pages/StepInfo.vue +37 -0
- package/storefront/checkout/router.ts +59 -0
- package/storefront/index.ts +3 -0
- package/storefront/login/App.vue +9 -0
- package/storefront/login/main.ts +10 -0
- package/storefront/login/pages/SignIn/Login.vue +82 -0
- package/storefront/login/pages/SignUp/SignUp.vue +99 -0
- package/storefront/login/router.ts +15 -0
- package/storefront/product/AddProduct.vue +303 -0
- package/storefront/product/AddProductNumber.vue +62 -0
- package/storefront/product/AddProductVariant.vue +66 -0
- package/storefront/profile/App.vue +88 -0
- package/storefront/profile/main.ts +10 -0
- package/storefront/profile/pages/Addresses/Addresses.vue +79 -0
- package/storefront/profile/pages/Addresses/AddressesForm.vue +95 -0
- package/storefront/profile/pages/Addresses/AddressesModal.vue +24 -0
- package/storefront/profile/pages/Buys/Buys.vue +8 -0
- package/storefront/profile/pages/Me/Me.vue +15 -0
- package/storefront/profile/pages/Me/MeBilling.vue +79 -0
- package/storefront/profile/pages/Me/MeBillingForm.vue +66 -0
- package/storefront/profile/pages/Me/MeBillingModal.vue +24 -0
- package/storefront/profile/pages/Me/MeInfo.vue +75 -0
- package/storefront/profile/pages/Me/MePassword.vue +53 -0
- package/storefront/profile/pages/Me/MeSubscriptions.vue +15 -0
- package/storefront/profile/pages/Returns/Returns.vue +8 -0
- package/storefront/profile/pages/Whislist/Whislist.vue +8 -0
- package/storefront/profile/router.ts +32 -0
- package/storefront/stores.ts +320 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { inject, ref } from 'vue';
|
|
3
|
+
import { useSession } from '../../../../../auth';
|
|
4
|
+
import { useCheckoutStore } from '../../../../../stores';
|
|
5
|
+
import { usePayment } from '../composable';
|
|
6
|
+
import { usePagomedios } from './composable';
|
|
7
|
+
|
|
8
|
+
const checkout = useCheckoutStore();
|
|
9
|
+
|
|
10
|
+
const { transactionId, provider, paymentPending } = usePayment();
|
|
11
|
+
const { user } = useSession();
|
|
12
|
+
|
|
13
|
+
const { onPrepare } = usePagomedios({
|
|
14
|
+
transactionId,
|
|
15
|
+
provider,
|
|
16
|
+
});
|
|
17
|
+
const srcdoc = ref('');
|
|
18
|
+
const loading = ref(false);
|
|
19
|
+
// const route = useRoute()
|
|
20
|
+
const getExtras = inject('payExtras', () => undefined);
|
|
21
|
+
async function sendPay(): Promise<void> {
|
|
22
|
+
try {
|
|
23
|
+
if (!checkout?.billing?.id) {
|
|
24
|
+
// eslint-disable-next-line no-alert
|
|
25
|
+
alert('Por favor ingresa los datos de facturación');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (!checkout?.address?.id) {
|
|
29
|
+
// eslint-disable-next-line no-alert
|
|
30
|
+
alert('Por favor ingresa los datos de envio');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
document.getElementById('buy-page')?.classList.add('opacity-40');
|
|
34
|
+
loading.value = true;
|
|
35
|
+
const { iframe } = await onPrepare({
|
|
36
|
+
user: user.value,
|
|
37
|
+
customer: user.value,
|
|
38
|
+
extras: getExtras(),
|
|
39
|
+
});
|
|
40
|
+
location.href = iframe as any;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// eslint-disable-next-line no-alert
|
|
44
|
+
alert('Error al procesar el pago, por favor intente nuevamente. Revisa que esten ingresados los datos de envio y facturación correctamente.');
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
loading.value = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// srcdoc.value = iframe;
|
|
51
|
+
// loading.value = false;
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<div class="pt-3">
|
|
57
|
+
<div class="px-5 py-10 rounded-lg bg-gray-50">
|
|
58
|
+
<div class="text-center">
|
|
59
|
+
<div class="max-w-360px mx-auto py-6">
|
|
60
|
+
<div class="text-lg">
|
|
61
|
+
Este método de pago cuenta con el respaldo de <a href="https://pagomedios.com/" target="_blank" class="underline">
|
|
62
|
+
Pagomedios
|
|
63
|
+
</a>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="flex space-x-3 justify-center py-6 text-gray-700 text-4xl">
|
|
66
|
+
<i-fa-brands-cc-mastercard />
|
|
67
|
+
<i-cib-visa />
|
|
68
|
+
<i-fa-brands-cc-amex />
|
|
69
|
+
<i-fa-brands-cc-diners-club />
|
|
70
|
+
<i-fa-brands-cc-discover />
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div v-if="transactionId && srcdoc" :key="srcdoc" class="py-3 h-470px">
|
|
74
|
+
<iframe class="w-full h-full" :src="srcdoc" frameborder="0" />
|
|
75
|
+
</div>
|
|
76
|
+
<DialogQuestions>
|
|
77
|
+
<template #active="{ onActive }">
|
|
78
|
+
<EButton @click="onActive">
|
|
79
|
+
Preguntas frecuentes
|
|
80
|
+
</EButton>
|
|
81
|
+
</template>
|
|
82
|
+
</DialogQuestions>
|
|
83
|
+
|
|
84
|
+
<div />
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="pt-3 text-center">
|
|
88
|
+
<UButton :loading="paymentPending || loading" type="primary" class="h-12 bg-eprimary text-econtrast px-5 rounded-lg shadow" @click="sendPay">
|
|
89
|
+
Continuar y Pagar
|
|
90
|
+
</UButton>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ofetch } from 'ofetch';
|
|
2
|
+
import { useLinkPayment } from '../composable';
|
|
3
|
+
|
|
4
|
+
export function usePagomedios({ endpointPrepare, provider, transactionId }: DatafastOptions) {
|
|
5
|
+
//
|
|
6
|
+
|
|
7
|
+
// console.log(identifyState);
|
|
8
|
+
const { basePath } = useLinkPayment();
|
|
9
|
+
|
|
10
|
+
const onPrepare = async (body: any): Promise<any> => {
|
|
11
|
+
const data = await ofetch(endpointPrepare || `/${basePath}/prepare/pagomedios`, {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
body: {
|
|
14
|
+
...body,
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
});
|
|
18
|
+
transactionId.value = data.uid;
|
|
19
|
+
provider.value = 'pagomedios';
|
|
20
|
+
return data;
|
|
21
|
+
};
|
|
22
|
+
return { onPrepare };
|
|
23
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed, inject, onMounted, ref } from 'vue';
|
|
3
|
+
import { useRoute } from 'vue-router';
|
|
4
|
+
import { useSession } from '../../../../../auth';
|
|
5
|
+
import { useCheckoutStore } from '../../../../../stores';
|
|
6
|
+
import { usePayment } from '../composable';
|
|
7
|
+
import { usePaypal } from './composable';
|
|
8
|
+
|
|
9
|
+
;
|
|
10
|
+
|
|
11
|
+
const { checkout } = useCheckoutStore();
|
|
12
|
+
const { user } = useSession();
|
|
13
|
+
const route = useRoute();
|
|
14
|
+
const omitBilling = inject('omitBilling', false);
|
|
15
|
+
|
|
16
|
+
// const { payments } = useConfigs();
|
|
17
|
+
const payments = {
|
|
18
|
+
paypal: {
|
|
19
|
+
iframe: true,
|
|
20
|
+
currency: 'BOB',
|
|
21
|
+
intent: 'CAPTURE',
|
|
22
|
+
brandName: 'E-Monkey',
|
|
23
|
+
locale: 'es_BO',
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
const paypalOptions = computed(() => payments?.paypay || {});
|
|
27
|
+
|
|
28
|
+
const { transactionId, provider, paymentPending } = usePayment();
|
|
29
|
+
const { onPrepare, sendPay } = usePaypal({
|
|
30
|
+
transactionId,
|
|
31
|
+
provider,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const loading = ref(false);
|
|
35
|
+
const capturing = ref(false);
|
|
36
|
+
const iframeUrl = ref('');
|
|
37
|
+
|
|
38
|
+
const usingIframe = computed(() => !!paypalOptions.value?.iframe);
|
|
39
|
+
|
|
40
|
+
function getCurrentCallbackUrl(): string {
|
|
41
|
+
return `${location.origin}${location.pathname}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function buildStatusUrl(uid: string, id?: string): string {
|
|
45
|
+
const params = new URLSearchParams();
|
|
46
|
+
params.set('provider', 'paypal');
|
|
47
|
+
params.set('uid', uid);
|
|
48
|
+
if (id)
|
|
49
|
+
params.set('id', id);
|
|
50
|
+
|
|
51
|
+
return `${location.pathname}?${params.toString()}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function captureFromReturn(token: string, payerId?: string): Promise<void> {
|
|
55
|
+
if (!transactionId.value || capturing.value)
|
|
56
|
+
return;
|
|
57
|
+
|
|
58
|
+
capturing.value = true;
|
|
59
|
+
try {
|
|
60
|
+
const response = await sendPay(transactionId.value, {
|
|
61
|
+
orderID: token,
|
|
62
|
+
payerID: payerId,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
location.replace(buildStatusUrl(transactionId.value, response?.id || token));
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error(error);
|
|
69
|
+
// eslint-disable-next-line no-alert
|
|
70
|
+
alert('No fue posible confirmar el pago con PayPal. Intenta nuevamente.');
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
capturing.value = false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function startPay(): Promise<void> {
|
|
78
|
+
if (!checkout?.billing?.id && !omitBilling)
|
|
79
|
+
return alert('Debes seleccionar unos datos de facturacion.');
|
|
80
|
+
|
|
81
|
+
document.getElementById('buy-page')?.classList.add('opacity-40');
|
|
82
|
+
loading.value = true;
|
|
83
|
+
try {
|
|
84
|
+
const callbackUrl = getCurrentCallbackUrl();
|
|
85
|
+
const data = await onPrepare({
|
|
86
|
+
user: user.value,
|
|
87
|
+
customer: user.value,
|
|
88
|
+
returnUrl: callbackUrl,
|
|
89
|
+
cancelUrl: callbackUrl,
|
|
90
|
+
currency: paypalOptions.value?.currency,
|
|
91
|
+
intent: paypalOptions.value?.intent,
|
|
92
|
+
brandName: paypalOptions.value?.brandName,
|
|
93
|
+
locale: paypalOptions.value?.locale,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const approveUrl = data?.iframe?.approveUrl || data?.approveUrl;
|
|
97
|
+
if (!approveUrl) {
|
|
98
|
+
// eslint-disable-next-line no-alert
|
|
99
|
+
alert('PayPal no devolvio una URL de aprobacion.');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (usingIframe.value) {
|
|
104
|
+
iframeUrl.value = approveUrl;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
location.href = approveUrl;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
// eslint-disable-next-line no-alert
|
|
112
|
+
alert('No fue posible iniciar PayPal. Intenta nuevamente.');
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
loading.value = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
onMounted(() => {
|
|
120
|
+
const token = `${route.query.token || ''}`;
|
|
121
|
+
const payerId = `${route.query.PayerID || route.query.payerId || ''}`;
|
|
122
|
+
|
|
123
|
+
if (token && transactionId.value)
|
|
124
|
+
captureFromReturn(token, payerId || undefined);
|
|
125
|
+
});
|
|
126
|
+
</script>
|
|
127
|
+
|
|
128
|
+
<template>
|
|
129
|
+
<div class="pt-3">
|
|
130
|
+
<div class="px-5 py-10 rounded-lg bg-gray-50">
|
|
131
|
+
<div class="text-center">
|
|
132
|
+
<div class="max-w-420px mx-auto py-6">
|
|
133
|
+
<div class="text-lg">
|
|
134
|
+
Paga de forma segura con PayPal.
|
|
135
|
+
</div>
|
|
136
|
+
<div class="flex space-x-3 justify-center py-6 text-[#003087] text-4xl">
|
|
137
|
+
<i-fa-brands-paypal />
|
|
138
|
+
<i-cib-cc-paypal />
|
|
139
|
+
</div>
|
|
140
|
+
<p class="text-sm text-gray-600">
|
|
141
|
+
Al continuar seras redirigido para aprobar el pago en PayPal y luego volver al checkout.
|
|
142
|
+
</p>
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<div v-if="iframeUrl" class="py-3 h-[640px] border rounded-lg overflow-hidden bg-white">
|
|
146
|
+
<iframe class="w-full h-full" :src="iframeUrl" frameborder="0" />
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<!-- -->
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div class="pt-3 text-center space-y-2">
|
|
154
|
+
<UButton
|
|
155
|
+
:disabled="paymentPending || loading || capturing"
|
|
156
|
+
:loading="loading || capturing"
|
|
157
|
+
size="xl"
|
|
158
|
+
|
|
159
|
+
@click="startPay"
|
|
160
|
+
>
|
|
161
|
+
Continuar con PayPal
|
|
162
|
+
</UButton>
|
|
163
|
+
<a v-if="iframeUrl" :href="iframeUrl" class="text-sm underline text-eprimary" target="_blank" rel="noopener noreferrer">
|
|
164
|
+
Abrir PayPal en una nueva ventana
|
|
165
|
+
</a>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
</template>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ofetch } from 'ofetch';
|
|
2
|
+
import { useLinkPayment } from '../composable';
|
|
3
|
+
|
|
4
|
+
export function usePaypal({ endpointPrepare, provider, transactionId }: DatafastOptions) {
|
|
5
|
+
// const extra = inject('extraPrepare', {}) as any;
|
|
6
|
+
// const identifyState = inject('authorizer-state', {}) as AuthorizerState;
|
|
7
|
+
const { basePath } = useLinkPayment();
|
|
8
|
+
|
|
9
|
+
const onPrepare = async (body: any): Promise<any> => {
|
|
10
|
+
const data = await ofetch(endpointPrepare || `/${basePath}/prepare/paypal`, {
|
|
11
|
+
method: 'POST',
|
|
12
|
+
body: {
|
|
13
|
+
...body,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
transactionId.value = data.uid;
|
|
17
|
+
provider.value = 'paypal';
|
|
18
|
+
return data;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const sendPay = async (uid: string, body: any = {}) => {
|
|
22
|
+
const data = await ofetch(`/${basePath}/pay/paypal?uid=${uid}&redirect=0`, {
|
|
23
|
+
method: 'POST',
|
|
24
|
+
body: {
|
|
25
|
+
...body,
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
});
|
|
29
|
+
return data;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return { onPrepare, sendPay };
|
|
33
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Ref } from 'vue';
|
|
2
|
+
import { useLocalStorage } from '@vueuse/core';
|
|
3
|
+
import { ofetch } from 'ofetch';
|
|
4
|
+
import { inject } from 'vue';
|
|
5
|
+
|
|
6
|
+
export function useLinkPayment() {
|
|
7
|
+
// const isLinkPayment = inject('isLinkPayment', false);
|
|
8
|
+
const storePath = inject('storePath', '');
|
|
9
|
+
const basePath = `payment${storePath}`;
|
|
10
|
+
return { basePath };
|
|
11
|
+
}
|
|
12
|
+
export function usePayment() {
|
|
13
|
+
const transactionId = useLocalStorage('eTransaction', '');
|
|
14
|
+
const provider = useLocalStorage('ePayment', '');
|
|
15
|
+
const { basePath } = useLinkPayment();
|
|
16
|
+
|
|
17
|
+
const getState = async (namespace?: string) => {
|
|
18
|
+
const data = await ofetch(`/${basePath}/verify/${provider.value}`, {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
body: {
|
|
21
|
+
uid: transactionId.value,
|
|
22
|
+
namespace,
|
|
23
|
+
},
|
|
24
|
+
params: { override: true },
|
|
25
|
+
});
|
|
26
|
+
return data;
|
|
27
|
+
};
|
|
28
|
+
const paymentPending = inject('paymentPending', undefined) as unknown as Ref<boolean> | undefined;
|
|
29
|
+
return { getState, transactionId, provider, paymentPending };
|
|
30
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { onBeforeMount } from 'vue';
|
|
3
|
+
import { useState } from './composable';
|
|
4
|
+
import PaymentStatus from './PaymentStatus.vue';
|
|
5
|
+
|
|
6
|
+
const { getState, status, response, uid, provider } = useState();
|
|
7
|
+
|
|
8
|
+
onBeforeMount(() => {
|
|
9
|
+
getState();
|
|
10
|
+
});
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<div>
|
|
15
|
+
<PaymentStatus
|
|
16
|
+
:status="status" :response="(response as any)" :uid="uid!"
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import AppStatus from './PaymentStatusDetail.vue';
|
|
3
|
+
|
|
4
|
+
defineProps({
|
|
5
|
+
status: {
|
|
6
|
+
type: String,
|
|
7
|
+
default: 'loading',
|
|
8
|
+
},
|
|
9
|
+
uid: {
|
|
10
|
+
type: String,
|
|
11
|
+
},
|
|
12
|
+
response: Object,
|
|
13
|
+
loading: Boolean,
|
|
14
|
+
});
|
|
15
|
+
function onBack(): void {
|
|
16
|
+
// history.replaceState()
|
|
17
|
+
sessionStorage.removeItem('ePayment');
|
|
18
|
+
sessionStorage.removeItem('eQuery');
|
|
19
|
+
localStorage.removeItem('ePayment');
|
|
20
|
+
localStorage.removeItem('eQuery');
|
|
21
|
+
history.go(-1);
|
|
22
|
+
}
|
|
23
|
+
function onEnd() {
|
|
24
|
+
//
|
|
25
|
+
sessionStorage.removeItem('eCustomer');
|
|
26
|
+
sessionStorage.removeItem('eQuery');
|
|
27
|
+
sessionStorage.removeItem('ePayment');
|
|
28
|
+
localStorage.removeItem('eCustomer');
|
|
29
|
+
localStorage.removeItem('eQuery');
|
|
30
|
+
localStorage.removeItem('ePayment');
|
|
31
|
+
// location.replace('/profile/');
|
|
32
|
+
const el = document.createElement('a');
|
|
33
|
+
|
|
34
|
+
el.href = '/storefront/checkout/end';
|
|
35
|
+
el.click();
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div class="w-full min-h-[60vh] flex items-center justify-center py-6 px-4">
|
|
41
|
+
<div class="w-full max-w-xl text-center">
|
|
42
|
+
|
|
43
|
+
<!-- 1. ESTADO: LOADING / VERIFICANDO PAGO -->
|
|
44
|
+
<div v-if="status === 'loading'" class="flex flex-col items-center py-8">
|
|
45
|
+
<div class="relative flex items-center justify-center mb-8">
|
|
46
|
+
<!-- Anillos pulsantes en color Indigo -->
|
|
47
|
+
<div class="absolute inset-0 rounded-full bg-indigo-500/20 animate-ping" style="animation-duration: 2.5s;"></div>
|
|
48
|
+
<div class="absolute inset-[-1.5rem] rounded-full bg-indigo-500/10 animate-pulse" style="animation-duration: 3s;"></div>
|
|
49
|
+
|
|
50
|
+
<!-- Icono central -->
|
|
51
|
+
<div class="relative z-10 w-24 h-24 bg-gradient-to-br from-indigo-400 to-indigo-600 rounded-full flex items-center justify-center shadow-lg shadow-indigo-500/30">
|
|
52
|
+
<i-mdi-clock-outline class="text-white text-5xl" />
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<h2 class="text-2xl font-bold text-gray-800 tracking-tight mb-2">
|
|
57
|
+
Verificando tu pago
|
|
58
|
+
</h2>
|
|
59
|
+
<p class="text-sm text-gray-500 max-w-sm mx-auto mb-8 leading-relaxed">
|
|
60
|
+
Estamos confirmando la transacción con tu entidad bancaria. Por favor, no cierres ni recargues esta página.
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
<!-- Barra de progreso -->
|
|
64
|
+
<div class="w-64 h-1.5 bg-gray-100 rounded-full overflow-hidden relative border border-gray-200/30">
|
|
65
|
+
<div class="absolute top-0 left-0 h-full bg-gradient-to-r from-indigo-400 to-indigo-600 rounded-full animate-progress"></div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<!-- 2. ESTADO: PENDING / PAGO EN PROCESO -->
|
|
70
|
+
<div v-else-if="status === 'pending'" class="flex flex-col items-center py-8">
|
|
71
|
+
<div class="relative flex items-center justify-center mb-8">
|
|
72
|
+
<!-- Anillos pulsantes en color Ámbar -->
|
|
73
|
+
<div class="absolute inset-0 rounded-full bg-amber-500/20 animate-ping" style="animation-duration: 2.5s;"></div>
|
|
74
|
+
<div class="absolute inset-[-1.5rem] rounded-full bg-amber-500/10 animate-pulse" style="animation-duration: 3s;"></div>
|
|
75
|
+
|
|
76
|
+
<!-- Icono central -->
|
|
77
|
+
<div class="relative z-10 w-24 h-24 bg-gradient-to-br from-amber-400 to-amber-600 rounded-full flex items-center justify-center shadow-lg shadow-amber-500/30 animate-pulse">
|
|
78
|
+
<i-mdi-clock-outline class="text-white text-5xl animate-spin-slow" />
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<h2 class="text-2xl font-bold text-gray-800 tracking-tight mb-2">
|
|
83
|
+
Pago en proceso
|
|
84
|
+
</h2>
|
|
85
|
+
<p class="text-sm text-gray-500 max-w-sm mx-auto mb-6 leading-relaxed">
|
|
86
|
+
Tu pago está siendo procesado por el proveedor de servicios. Esto puede tomar unos segundos.
|
|
87
|
+
</p>
|
|
88
|
+
|
|
89
|
+
<AppStatus :uid="uid!" :response="response" />
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<!-- 3. ESTADO: SUCCESS / COMPRA CONFIRMADA -->
|
|
93
|
+
<div v-else-if="status === 'success'" class="flex flex-col items-center py-8">
|
|
94
|
+
<div class="relative flex items-center justify-center mb-8">
|
|
95
|
+
<!-- Anillos pulsantes en color Esmeralda -->
|
|
96
|
+
<div class="absolute inset-0 rounded-full bg-emerald-500/20 animate-ping" style="animation-duration: 2.5s;"></div>
|
|
97
|
+
<div class="absolute inset-[-1.5rem] rounded-full bg-emerald-500/10 animate-pulse" style="animation-duration: 3s;"></div>
|
|
98
|
+
|
|
99
|
+
<!-- Icono central -->
|
|
100
|
+
<div class="relative z-10 w-24 h-24 bg-gradient-to-br from-emerald-400 to-emerald-600 rounded-full flex items-center justify-center shadow-lg shadow-emerald-500/30">
|
|
101
|
+
<i-mdi-check-circle class="text-white text-5xl" />
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<span class="text-xs font-bold px-4 py-1.5 bg-emerald-50 text-emerald-600 border border-emerald-100 rounded-full uppercase tracking-wider mb-3">
|
|
106
|
+
Compra Confirmada
|
|
107
|
+
</span>
|
|
108
|
+
|
|
109
|
+
<h2 class="text-3xl font-extrabold text-gray-900 tracking-tight mb-2">
|
|
110
|
+
¡Gracias por tu compra!
|
|
111
|
+
</h2>
|
|
112
|
+
<p class="text-sm text-gray-500 max-w-sm mx-auto mb-6 leading-relaxed">
|
|
113
|
+
Tu transacción se completó con éxito. Hemos enviado un correo con el comprobante de pago.
|
|
114
|
+
</p>
|
|
115
|
+
|
|
116
|
+
<AppStatus :uid="uid!" :response="response" />
|
|
117
|
+
|
|
118
|
+
<div class="pt-8">
|
|
119
|
+
<button
|
|
120
|
+
class="bg-gradient-to-r from-emerald-500 to-emerald-600 hover:from-emerald-600 hover:to-emerald-700 text-white font-bold px-8 py-3.5 rounded-xl uppercase tracking-wider text-xs shadow-lg shadow-emerald-500/20 hover:shadow-xl hover:shadow-emerald-500/30 transition-all duration-300 transform hover:-translate-y-0.5 active:translate-y-0"
|
|
121
|
+
@click="onEnd"
|
|
122
|
+
>
|
|
123
|
+
Finalizar
|
|
124
|
+
</button>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<!-- 4. ESTADO: FAILURE / PAGO RECHAZADO -->
|
|
129
|
+
<div v-else-if="status === 'failure'" class="flex flex-col items-center py-8">
|
|
130
|
+
<div class="relative flex items-center justify-center mb-8">
|
|
131
|
+
<!-- Anillos pulsantes en color Rojo/Rosa -->
|
|
132
|
+
<div class="absolute inset-0 rounded-full bg-rose-500/20 animate-ping" style="animation-duration: 2.5s;"></div>
|
|
133
|
+
<div class="absolute inset-[-1.5rem] rounded-full bg-rose-500/10 animate-pulse" style="animation-duration: 3s;"></div>
|
|
134
|
+
|
|
135
|
+
<!-- Icono central -->
|
|
136
|
+
<div class="relative z-10 w-24 h-24 bg-gradient-to-br from-rose-400 to-rose-600 rounded-full flex items-center justify-center shadow-lg shadow-rose-500/30">
|
|
137
|
+
<i-mdi-close-circle class="text-white text-5xl" />
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<span class="text-xs font-bold px-4 py-1.5 bg-rose-50 text-rose-600 border border-rose-100 rounded-full uppercase tracking-wider mb-3">
|
|
142
|
+
Pago Rechazado
|
|
143
|
+
</span>
|
|
144
|
+
|
|
145
|
+
<h2 class="text-2xl font-bold text-gray-800 tracking-tight mb-2">
|
|
146
|
+
Inconveniente con tu pago
|
|
147
|
+
</h2>
|
|
148
|
+
<p class="text-sm text-gray-500 max-w-sm mx-auto mb-6 leading-relaxed">
|
|
149
|
+
Tuvimos un inconveniente al procesar tu método de pago. Por favor, verifica tus datos e inténtalo nuevamente.
|
|
150
|
+
</p>
|
|
151
|
+
|
|
152
|
+
<AppStatus :uid="uid!" :response="response" />
|
|
153
|
+
|
|
154
|
+
<div class="pt-8">
|
|
155
|
+
<button
|
|
156
|
+
class="bg-gradient-to-r from-slate-800 to-slate-900 hover:from-slate-900 hover:to-slate-950 text-white font-bold px-8 py-3.5 rounded-xl uppercase tracking-wider text-xs shadow-md hover:shadow-lg transition-all duration-300 transform hover:-translate-y-0.5 active:translate-y-0"
|
|
157
|
+
@click="onBack"
|
|
158
|
+
>
|
|
159
|
+
Reintentar Pago
|
|
160
|
+
</button>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</template>
|
|
167
|
+
|
|
168
|
+
<style scoped>
|
|
169
|
+
.animate-progress {
|
|
170
|
+
width: 40%;
|
|
171
|
+
animation: progress-bar 1.5s ease-in-out infinite alternate;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.animate-spin-slow {
|
|
175
|
+
animation: spin 8s linear infinite;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@keyframes progress-bar {
|
|
179
|
+
0% { transform: translateX(-50%); }
|
|
180
|
+
100% { transform: translateX(200%); }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@keyframes spin {
|
|
184
|
+
from { transform: rotate(0deg); }
|
|
185
|
+
to { transform: rotate(360deg); }
|
|
186
|
+
}
|
|
187
|
+
</style>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
|
|
4
|
+
const props = defineProps({
|
|
5
|
+
uid: null,
|
|
6
|
+
response: {
|
|
7
|
+
type: Object,
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const details = computed(() => {
|
|
12
|
+
return {
|
|
13
|
+
message: props.response?.details?.messages?.es,
|
|
14
|
+
code: props.response?.details?.code,
|
|
15
|
+
description: props.response?.details?.description,
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<div class="w-full max-w-md mx-auto px-4 mt-6">
|
|
22
|
+
<div
|
|
23
|
+
class="bg-white/80 backdrop-blur-md border border-gray-100 shadow-xl shadow-slate-100/50 rounded-2xl p-5 text-left transition-all duration-300 hover:shadow-2xl hover:shadow-slate-100/80"
|
|
24
|
+
>
|
|
25
|
+
<!-- Header de la tarjeta de transacción -->
|
|
26
|
+
<div class="flex items-center space-x-2 pb-4 mb-4 border-b border-gray-100">
|
|
27
|
+
<i-mdi-receipt-text-outline class="text-gray-400 text-xl" />
|
|
28
|
+
<span class="text-xs font-semibold text-gray-400 uppercase tracking-wider">
|
|
29
|
+
Detalles de la Transacción
|
|
30
|
+
</span>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<!-- Filas de datos -->
|
|
34
|
+
<div class="space-y-4">
|
|
35
|
+
<!-- Transacción ID -->
|
|
36
|
+
<div v-if="uid" class="flex justify-between items-center text-sm">
|
|
37
|
+
<span class="text-gray-500 font-medium">Transacción ID</span>
|
|
38
|
+
<span class="font-mono text-gray-800 bg-gray-50 px-2.5 py-1 rounded-md border border-gray-100 text-xs font-semibold select-all">
|
|
39
|
+
#{{ uid }}
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<!-- Referencia de Pago -->
|
|
44
|
+
<div v-if="response?.id" class="flex justify-between items-center text-sm">
|
|
45
|
+
<span class="text-gray-500 font-medium">Referencia de Pago</span>
|
|
46
|
+
<span class="font-mono text-gray-800 bg-gray-50 px-2.5 py-1 rounded-md border border-gray-100 text-xs font-semibold select-all">
|
|
47
|
+
{{ response.id }}
|
|
48
|
+
</span>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<!-- Mensaje / Detalles del Proveedor -->
|
|
52
|
+
<div
|
|
53
|
+
v-if="details.message || details.description"
|
|
54
|
+
class="pt-3 mt-3 border-t border-dashed border-gray-100 space-y-1.5"
|
|
55
|
+
>
|
|
56
|
+
<div v-if="details.message" class="text-sm font-semibold text-gray-700">
|
|
57
|
+
{{ details.message }}
|
|
58
|
+
</div>
|
|
59
|
+
<div v-if="details.description" class="text-xs text-gray-400 leading-relaxed max-w-sm">
|
|
60
|
+
{{ details.description }}
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<!-- Código de Respuesta / Razón -->
|
|
65
|
+
<div
|
|
66
|
+
v-if="details.code"
|
|
67
|
+
class="flex items-center space-x-1.5 bg-amber-50/50 border border-amber-100/50 rounded-lg p-2.5 mt-2"
|
|
68
|
+
>
|
|
69
|
+
<i-mdi-information-outline class="text-amber-500 text-base flex-shrink-0" />
|
|
70
|
+
<span class="text-xs text-amber-800 font-medium">
|
|
71
|
+
Razón del estado: <code class="font-bold select-all">{{ details.code }}</code>
|
|
72
|
+
</span>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|