@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.
Files changed (82) hide show
  1. package/dist/THIRD-PARTY-LICENSES.md +41 -0
  2. package/dist/_chunks/auth.d.mts +707 -0
  3. package/dist/_chunks/database.mjs +831 -0
  4. package/dist/_chunks/db.d.mts +7100 -0
  5. package/dist/_chunks/index.d.mts +178 -0
  6. package/dist/_chunks/lib.mjs +3073 -0
  7. package/dist/_chunks/libs/better-call.d.mts +478 -0
  8. package/dist/_chunks/libs/postgres.d.mts +1 -0
  9. package/dist/_chunks/rolldown-runtime.mjs +11 -0
  10. package/dist/server/db.d.mts +2 -0
  11. package/dist/server/db.mjs +108 -0
  12. package/dist/server/env.d.mts +21 -0
  13. package/dist/server/env.mjs +22 -0
  14. package/dist/server/lib.d.mts +362 -0
  15. package/dist/server/lib.mjs +2 -0
  16. package/dist/server/router.d.mts +1218 -0
  17. package/dist/server/router.mjs +1157 -0
  18. package/dist/server/schemas/auth.d.mts +2 -0
  19. package/dist/server/schemas/auth.mjs +62 -0
  20. package/package.json +58 -0
  21. package/storefront/Readme.md +0 -0
  22. package/storefront/auth.ts +29 -0
  23. package/storefront/cart/ResumeCart.vue +217 -0
  24. package/storefront/cart/ResumeCartSelect.vue +32 -0
  25. package/storefront/cart/ShoppinCart.vue +100 -0
  26. package/storefront/cart/ShoppinCartItem.vue +99 -0
  27. package/storefront/checkout/App.vue +36 -0
  28. package/storefront/checkout/AppCart.vue +72 -0
  29. package/storefront/checkout/AppCartDiscount.vue +74 -0
  30. package/storefront/checkout/AppCartTotals.vue +72 -0
  31. package/storefront/checkout/AppLoading.vue +55 -0
  32. package/storefront/checkout/composables.ts +28 -0
  33. package/storefront/checkout/constants.ts +0 -0
  34. package/storefront/checkout/main.ts +11 -0
  35. package/storefront/checkout/pages/Address/Address.vue +95 -0
  36. package/storefront/checkout/pages/Info/Info.vue +94 -0
  37. package/storefront/checkout/pages/Info/InfoUser.vue +38 -0
  38. package/storefront/checkout/pages/Pay/Pay.vue +115 -0
  39. package/storefront/checkout/pages/Pay/Providers/BancoEconomico/BancoEconomico.vue +9 -0
  40. package/storefront/checkout/pages/Pay/Providers/Cybersource/Cybersource.vue +9 -0
  41. package/storefront/checkout/pages/Pay/Providers/Datafast/Datafast.vue +9 -0
  42. package/storefront/checkout/pages/Pay/Providers/Multipago/Multipago.vue +9 -0
  43. package/storefront/checkout/pages/Pay/Providers/Pagomedios/Pagomedios.vue +93 -0
  44. package/storefront/checkout/pages/Pay/Providers/Pagomedios/composable.ts +23 -0
  45. package/storefront/checkout/pages/Pay/Providers/Paypal/Paypal.vue +168 -0
  46. package/storefront/checkout/pages/Pay/Providers/Paypal/composable.ts +33 -0
  47. package/storefront/checkout/pages/Pay/Providers/Placetopay/Placetopay.vue +9 -0
  48. package/storefront/checkout/pages/Pay/Providers/Wabi/Wabi.vue +9 -0
  49. package/storefront/checkout/pages/Pay/Providers/composable.ts +30 -0
  50. package/storefront/checkout/pages/Payment/Payment.vue +19 -0
  51. package/storefront/checkout/pages/Payment/PaymentStatus.vue +187 -0
  52. package/storefront/checkout/pages/Payment/PaymentStatusDetail.vue +77 -0
  53. package/storefront/checkout/pages/Payment/composable.ts +81 -0
  54. package/storefront/checkout/pages/Shipping/Shipping.vue +67 -0
  55. package/storefront/checkout/pages/StepInfo.vue +37 -0
  56. package/storefront/checkout/router.ts +59 -0
  57. package/storefront/index.ts +3 -0
  58. package/storefront/login/App.vue +9 -0
  59. package/storefront/login/main.ts +10 -0
  60. package/storefront/login/pages/SignIn/Login.vue +82 -0
  61. package/storefront/login/pages/SignUp/SignUp.vue +99 -0
  62. package/storefront/login/router.ts +15 -0
  63. package/storefront/product/AddProduct.vue +303 -0
  64. package/storefront/product/AddProductNumber.vue +62 -0
  65. package/storefront/product/AddProductVariant.vue +66 -0
  66. package/storefront/profile/App.vue +88 -0
  67. package/storefront/profile/main.ts +10 -0
  68. package/storefront/profile/pages/Addresses/Addresses.vue +79 -0
  69. package/storefront/profile/pages/Addresses/AddressesForm.vue +95 -0
  70. package/storefront/profile/pages/Addresses/AddressesModal.vue +24 -0
  71. package/storefront/profile/pages/Buys/Buys.vue +8 -0
  72. package/storefront/profile/pages/Me/Me.vue +15 -0
  73. package/storefront/profile/pages/Me/MeBilling.vue +79 -0
  74. package/storefront/profile/pages/Me/MeBillingForm.vue +66 -0
  75. package/storefront/profile/pages/Me/MeBillingModal.vue +24 -0
  76. package/storefront/profile/pages/Me/MeInfo.vue +75 -0
  77. package/storefront/profile/pages/Me/MePassword.vue +53 -0
  78. package/storefront/profile/pages/Me/MeSubscriptions.vue +15 -0
  79. package/storefront/profile/pages/Returns/Returns.vue +8 -0
  80. package/storefront/profile/pages/Whislist/Whislist.vue +8 -0
  81. package/storefront/profile/router.ts +32 -0
  82. package/storefront/stores.ts +320 -0
@@ -0,0 +1,3073 @@
1
+ import { checkouts, refunds, sessions, transactions } from "./database.mjs";
2
+ import { eq } from "drizzle-orm";
3
+ import { ofetch } from "ofetch";
4
+ import dayjs from "dayjs";
5
+ import { createError } from "h3";
6
+ import { Buffer } from "node:buffer";
7
+ import crypto from "node:crypto";
8
+ import qs from "qs";
9
+ import { joinURL } from "ufo";
10
+ function roundNum(v, r = 2) {
11
+ return Number(Number(v).toFixed(r));
12
+ }
13
+ function calcPercentaje(value, percentaje, hasInclude) {
14
+ const val = +value;
15
+ const per = +percentaje;
16
+ if (hasInclude) return roundNum(val * per / (100 + per));
17
+ else return roundNum(val / 100 * per);
18
+ }
19
+ function calcDiscount(amount, discount) {
20
+ if ("percent" in discount) return {
21
+ amount: calcPercentaje(amount, discount.percent),
22
+ percent: +discount.percent
23
+ };
24
+ else return { amount: +discount.amount };
25
+ }
26
+ const sum = (arr) => arr.reduce((a, b) => a + b, 0);
27
+ const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);
28
+ function groupBy(fn, arr) {
29
+ return arr.reduce((acc, value) => {
30
+ const key = fn(value);
31
+ if (!acc[key]) acc[key] = [];
32
+ acc[key].push(value);
33
+ return acc;
34
+ }, {});
35
+ }
36
+ function calcAmount(_itemDiscount, _parentDiscount, taxIncluded) {
37
+ return (price) => {
38
+ if (!taxIncluded) {
39
+ const itemDiscount = calcDiscount(price, _itemDiscount);
40
+ const parentDiscount = calcDiscount(price - itemDiscount.amount, _parentDiscount);
41
+ const unitBase = price - (itemDiscount.amount + parentDiscount.amount);
42
+ return {
43
+ price,
44
+ discounts: {
45
+ itemDiscount,
46
+ parentDiscount
47
+ },
48
+ unitAmount: unitBase,
49
+ unitBase
50
+ };
51
+ } else {
52
+ const parentDiscount = calcDiscount(price, _parentDiscount);
53
+ const itemDiscount = calcDiscount(price - parentDiscount.amount, _itemDiscount);
54
+ return {
55
+ price,
56
+ discounts: {
57
+ itemDiscount,
58
+ parentDiscount
59
+ },
60
+ unitAmount: price - (itemDiscount.amount + parentDiscount.amount),
61
+ unitBase: 0
62
+ };
63
+ }
64
+ };
65
+ }
66
+ function calcTax(unitBase, quantity, taxtIncluded = false) {
67
+ return (tax) => {
68
+ const amount = calcPercentaje(unitBase, tax.value, taxtIncluded);
69
+ const base = taxtIncluded ? unitBase - amount : unitBase;
70
+ return {
71
+ amount,
72
+ totalAmount: amount * quantity,
73
+ base,
74
+ totalBase: base * quantity,
75
+ ...tax
76
+ };
77
+ };
78
+ }
79
+ function calcSingleItem(parentDiscount) {
80
+ return (item) => {
81
+ const firstTaxes = item.taxes.filter((tax) => tax.beforeTaxes === true);
82
+ const latestTaxes = item.taxes.filter((tax) => !tax.beforeTaxes);
83
+ const quantity = +item.quantity;
84
+ if (!item.taxIncluded) {
85
+ const amounts = calcAmount(item.discount, parentDiscount)(+item.price);
86
+ const _firstTaxes = firstTaxes.map((i) => calcTax(i.excludeDiscount ? amounts.price : amounts.unitBase, quantity)(i));
87
+ const firstTotalTaxes = sum(_firstTaxes.map((v) => v.amount));
88
+ const base2 = amounts.unitBase + firstTotalTaxes;
89
+ const _latestTaxes = latestTaxes.map(calcTax(base2, quantity));
90
+ return {
91
+ id: item.id,
92
+ title: item.title,
93
+ taxIncluded: item.taxIncluded,
94
+ item: amounts,
95
+ taxes: [..._firstTaxes, ..._latestTaxes],
96
+ quantity: +item.quantity,
97
+ product: item.product,
98
+ variant: item.variant,
99
+ discountAllocations: item.discountAllocations
100
+ };
101
+ } else {
102
+ const amounts = calcAmount(item.discount, parentDiscount, true)(+item.price);
103
+ const UNIT_AMOUNT = +amounts.unitAmount;
104
+ const _latestTaxes = latestTaxes.map(calcTax(UNIT_AMOUNT, quantity, item.taxIncluded));
105
+ const latestTotalTaxes = sum(_latestTaxes.map((tax) => tax.amount));
106
+ const unitTaxBase = +UNIT_AMOUNT - latestTotalTaxes;
107
+ const _firstTaxes = firstTaxes.map(calcTax(unitTaxBase, quantity, item.taxIncluded));
108
+ const UNIT_BASE = unitTaxBase - sum(_firstTaxes.map((tax) => tax.amount));
109
+ const taxes = [..._firstTaxes, ..._latestTaxes];
110
+ amounts.unitBase = UNIT_BASE;
111
+ amounts.total = amounts.unitBase * quantity + taxes.reduce((acc, tax) => acc + tax.totalAmount, 0);
112
+ return {
113
+ id: item.id,
114
+ title: item.title,
115
+ taxIncluded: item.taxIncluded,
116
+ item: amounts,
117
+ quantity: +item.quantity,
118
+ taxes,
119
+ product: item.product,
120
+ variant: item.variant,
121
+ discountAllocations: item.discountAllocations
122
+ };
123
+ }
124
+ };
125
+ }
126
+ function calcItems(items, parentDiscount = { amount: 0 }) {
127
+ return items.map(calcSingleItem(parentDiscount));
128
+ }
129
+ function buildInvoice(items) {
130
+ const base = sum(items.map((item) => item.item.unitBase * item.quantity));
131
+ const lineItemsSubtotalPrice = sum(items.filter((item) => !["_envio"].includes(item.id)).map((item) => item.item.price * item.quantity));
132
+ const shipping = sum(items.filter((item) => ["_envio"].includes(item.id)).map((item) => item.item.price * item.quantity));
133
+ const imp = groupBy((tax) => {
134
+ return `${tax.type.code}_${tax.code}`;
135
+ }, flatten(items.map((item) => item.taxes)));
136
+ const _taxes = Object.values(imp).map((taxes) => {
137
+ let base = 0;
138
+ let value = 0;
139
+ const type = taxes[0].type.code;
140
+ const title = taxes[0].type.name;
141
+ const code = taxes[0].code;
142
+ const rate = +taxes[0].value;
143
+ for (const iterator of taxes) {
144
+ base += +iterator.totalBase;
145
+ value += +iterator.totalAmount;
146
+ }
147
+ return {
148
+ type,
149
+ code,
150
+ base,
151
+ value,
152
+ rate,
153
+ title
154
+ };
155
+ });
156
+ return {
157
+ total: base + sum(_taxes.map((tax) => tax.value)),
158
+ totalTax: sum(_taxes.map((t) => t.value)),
159
+ base,
160
+ items,
161
+ taxes: _taxes,
162
+ lineItemsSubtotalPrice,
163
+ shipping
164
+ };
165
+ }
166
+ function omit(keys, obj = {}) {
167
+ const result = {};
168
+ for (const key in obj) if (!keys.includes(key)) result[key] = obj[key];
169
+ return result;
170
+ }
171
+ function createCheckout({ graphql }) {
172
+ return async (_items, opts) => {
173
+ const { shipping: totalShipping, ...inv } = buildInvoice(calcItems(_items));
174
+ const _checkout = {
175
+ ...omit(["lineItemsSubtotalPrice"], inv),
176
+ ...opts,
177
+ totalShipping
178
+ };
179
+ return await graphql.checkout.create(_checkout);
180
+ };
181
+ }
182
+ function readCheckout({ graphql }) {
183
+ return async (id) => {
184
+ return await graphql.checkout.findByPk(id);
185
+ };
186
+ }
187
+ function associateCheckout({ graphql }) {
188
+ return async (id, sessionId, data) => {
189
+ return await graphql.checkout.updateByPk(id, {
190
+ ...data,
191
+ sessionId
192
+ });
193
+ };
194
+ }
195
+ function useCheckout({ graphql }) {
196
+ return {
197
+ create: createCheckout({ graphql }),
198
+ read: readCheckout({ graphql }),
199
+ associate: associateCheckout({ graphql })
200
+ };
201
+ }
202
+ var CustomError = class CustomError extends Error {
203
+ httpStatusCode;
204
+ date;
205
+ constructor({ message, statusCode = 500 }) {
206
+ super(message);
207
+ if (Error.captureStackTrace) Error.captureStackTrace(this, CustomError);
208
+ this.name = "CustomError";
209
+ this.httpStatusCode = statusCode;
210
+ this.date = /* @__PURE__ */ new Date();
211
+ }
212
+ };
213
+ function assertTransactionProvider(provider, transactionProvider) {
214
+ if (provider !== transactionProvider) throw new CustomError({
215
+ message: `Provider ${provider} does not match transaction provider ${transactionProvider}`,
216
+ statusCode: 400
217
+ });
218
+ }
219
+ function postPreparePayment({ transaction, providers, tasks }) {
220
+ return async (provider, body, options) => {
221
+ const _provider = providers[provider];
222
+ if (!_provider) throw new CustomError({
223
+ message: `Provider ${provider} dont exist`,
224
+ statusCode: 400
225
+ });
226
+ const _transaction = await transaction.read(body.transactionId);
227
+ assertTransactionProvider(provider, _transaction.provider);
228
+ if (!_provider.postPrepare) throw new CustomError({
229
+ message: `Postprocess ${provider} dont exist`,
230
+ statusCode: 400
231
+ });
232
+ const r = await _provider.postPrepare(_transaction.id, _transaction, {
233
+ ...options,
234
+ body
235
+ });
236
+ await transaction.updateState({
237
+ id: _transaction.id,
238
+ details: {},
239
+ extras: {
240
+ ..._transaction.extras,
241
+ ...r.extras
242
+ },
243
+ status: "created",
244
+ ref: `${r.id}`
245
+ }).catch((e) => {
246
+ console.error("Error updating transaction state:", e);
247
+ throw e;
248
+ });
249
+ return {
250
+ ...r,
251
+ uid: _transaction.id
252
+ };
253
+ };
254
+ }
255
+ function preparePayment({ transaction, providers, tasks }) {
256
+ return async (provider, body, options) => {
257
+ const _provider = providers[provider];
258
+ if (!_provider) throw new CustomError({
259
+ message: `Provider ${provider} dont exist`,
260
+ statusCode: 400
261
+ });
262
+ const _transaction = await transaction.create({
263
+ ...body,
264
+ provider
265
+ });
266
+ const r = await _provider.prepare(_transaction.id, _transaction, options);
267
+ await transaction.updateState({
268
+ id: _transaction.id,
269
+ details: {},
270
+ extras: r.extras || void 0,
271
+ status: "created",
272
+ ref: `${r.id}`
273
+ });
274
+ await tasks.addJob("updateStatus", {
275
+ id: _transaction.id,
276
+ payload: { status: "created" },
277
+ sonda: r.sonda ? {
278
+ uid: _transaction.id,
279
+ verify: _transaction.endpoints.verify,
280
+ expiredAt: typeof r.sonda === "number" ? r.sonda : void 0
281
+ } : void 0
282
+ }, { queueName: `t-${_transaction.id}` }).catch((error) => {
283
+ console.warn("Could not enqueue updateStatus on prepare:", error);
284
+ });
285
+ return {
286
+ ...r,
287
+ uid: _transaction.id
288
+ };
289
+ };
290
+ }
291
+ function payPayment({ providers, transaction, tasks }) {
292
+ return async (provider, params) => {
293
+ const _provider = providers[provider];
294
+ if (!_provider) throw new CustomError({
295
+ message: `Provider ${provider} dont exist`,
296
+ statusCode: 400
297
+ });
298
+ const _transaction = await transaction.read(params.uid);
299
+ assertTransactionProvider(provider, _transaction.provider);
300
+ if (_transaction.status !== "created") return {
301
+ id: _transaction.ref || "",
302
+ uid: _transaction.id,
303
+ status: _transaction.status,
304
+ body: _transaction.details,
305
+ message: {
306
+ failure: "Transacción rechazada",
307
+ pending: "Transacción pendiente",
308
+ refund: "Transacción reembolsada",
309
+ success: "Transacción aprobada"
310
+ }[_transaction.status] || "Transacción iniciada"
311
+ };
312
+ await transaction.updateState({
313
+ id: params.uid,
314
+ status: "pending",
315
+ details: {}
316
+ });
317
+ const state = await _provider.sendPay(params, {
318
+ uid: params.uid,
319
+ transaction: _transaction,
320
+ tasks
321
+ });
322
+ await tasks.addJob("updateStatus", {
323
+ id: params.uid,
324
+ payload: {
325
+ status: state.status,
326
+ details: state.body,
327
+ ref: state.id
328
+ },
329
+ sonda: state.sonda ? {
330
+ uid: params.uid,
331
+ verify: _transaction.endpoints.verify,
332
+ expiredAt: typeof state.sonda === "number" ? state.sonda : void 0
333
+ } : void 0
334
+ }, { queueName: `t-${params.uid}` }).catch(async (error) => {
335
+ console.warn("Could not enqueue updateStatus after pay, writing fallback state:", error);
336
+ await transaction.updateState({
337
+ id: params.uid,
338
+ status: state.status,
339
+ details: state.body,
340
+ ref: state.id
341
+ }).catch((fallbackError) => {
342
+ console.error("Could not write fallback state after pay:", fallbackError);
343
+ });
344
+ });
345
+ return state;
346
+ };
347
+ }
348
+ function verifyPayment({ providers, transaction }) {
349
+ return async (provider, uid, override) => {
350
+ const _provider = providers[provider];
351
+ if (!_provider) throw new CustomError({
352
+ message: `Provider ${provider} dont exist`,
353
+ statusCode: 400
354
+ });
355
+ const _transaction = await transaction.read(uid);
356
+ assertTransactionProvider(provider, _transaction.provider);
357
+ const totalTax = _transaction?.checkout?.taxes?.reduce((acc, tax) => acc + tax.value, 0);
358
+ const state = await _provider.verify({
359
+ uid,
360
+ transaction: _transaction,
361
+ override
362
+ });
363
+ return {
364
+ ...state,
365
+ transaction: {
366
+ ...state.transaction,
367
+ total: _transaction?.checkout?.total,
368
+ totalTax,
369
+ shipping: _transaction?.checkout?.shippingType?.price,
370
+ discount: _transaction?.checkout.discount,
371
+ items: _transaction?.checkout?.items?.map((item) => ({
372
+ item_id: item.id,
373
+ item_name: item.title,
374
+ price: item.variant?.price,
375
+ quantity: item.quantity
376
+ })).filter((el) => !el.item_id.startsWith("_"))
377
+ }
378
+ };
379
+ };
380
+ }
381
+ function webhookPayment({ providers, transaction, tasks }) {
382
+ return async (provider, uid, body) => {
383
+ const _provider = providers[provider];
384
+ if (!_provider) throw new CustomError({
385
+ message: `Provider ${provider} dont exist`,
386
+ statusCode: 400
387
+ });
388
+ const _transaction = await transaction.read(uid);
389
+ const state = await _provider.webhook(body, {});
390
+ if (state && state.status) await tasks.addJob("updateStatus", {
391
+ id: _transaction.id,
392
+ payload: { status: state?.status || "pending" },
393
+ sonda: void 0
394
+ }, { queueName: `t-${_transaction.id}` });
395
+ return {
396
+ message: state ? "Webhook approved" : "Webhook not approved",
397
+ body,
398
+ id: _transaction.ref || "",
399
+ uid,
400
+ status: state?.status
401
+ };
402
+ };
403
+ }
404
+ function refundPayment({ providers, transaction }) {
405
+ return async (provider, uid, options) => {
406
+ const _provider = providers[provider];
407
+ if (!_provider) throw new CustomError({
408
+ message: `Provider ${provider} dont exist`,
409
+ statusCode: 400
410
+ });
411
+ const _transaction = await transaction.read(uid);
412
+ assertTransactionProvider(provider, _transaction.provider);
413
+ if (_transaction.ref && !_transaction.refunds.totalCount) {
414
+ const totalAmount = Number(_transaction.checkout.total || 0);
415
+ const requestedAmount = Number(options?.amount || 0);
416
+ const refundAmount = requestedAmount > 0 && requestedAmount < totalAmount ? requestedAmount : totalAmount;
417
+ const details = await _provider.refund(_transaction.ref, refundAmount, options);
418
+ await transaction.refund({
419
+ id: uid,
420
+ details
421
+ });
422
+ await transaction.updateState({
423
+ id: uid,
424
+ status: "refund",
425
+ details: void 0
426
+ }).catch((e) => {
427
+ console.warn("Error updating transaction state:", e);
428
+ });
429
+ return {
430
+ message: "Refund aproved",
431
+ payload: details
432
+ };
433
+ } else {
434
+ if (_transaction.refunds.totalCount) return { message: "Esta transacción ya fue reversada" };
435
+ return { message: " Esta transacción no tiene ref" };
436
+ }
437
+ };
438
+ }
439
+ function usePayment(ctx) {
440
+ return {
441
+ pay: payPayment(ctx),
442
+ prepare: preparePayment(ctx),
443
+ verify: verifyPayment(ctx),
444
+ refund: refundPayment(ctx),
445
+ postPrepare: postPreparePayment(ctx),
446
+ webhook: webhookPayment(ctx)
447
+ };
448
+ }
449
+ function createSession$1({ secret, graphql, storeId }) {
450
+ return async (opts) => {
451
+ const _session = {
452
+ hash: opts.hash || `${secret}${storeId}${opts.email}`,
453
+ email: opts.email,
454
+ storeId,
455
+ identification: opts.identification,
456
+ customer: opts.customer
457
+ };
458
+ return await graphql.session.create(_session);
459
+ };
460
+ }
461
+ function verifySession(secret, storeId) {
462
+ return async (opts, hash) => {
463
+ return true;
464
+ };
465
+ }
466
+ function useSession({ graphql, secret, storeId }) {
467
+ return {
468
+ create: createSession$1({
469
+ secret,
470
+ graphql,
471
+ storeId
472
+ }),
473
+ verify: verifySession(secret, storeId)
474
+ };
475
+ }
476
+ function createTransaction({ graphql, storeId }) {
477
+ return async (payload) => {
478
+ return await graphql.transaction.create({
479
+ ...payload,
480
+ storeId
481
+ });
482
+ };
483
+ }
484
+ function readTransaction({ graphql }) {
485
+ return async (id) => {
486
+ return await graphql.transaction.findByPk(id);
487
+ };
488
+ }
489
+ function updateStateTransaction({ graphql }) {
490
+ return async ({ id, status, details, ref, extras }) => {
491
+ return await graphql.transaction.updateByPk(id, {
492
+ status,
493
+ details,
494
+ ref,
495
+ extras
496
+ });
497
+ };
498
+ }
499
+ function refundTransaction({ graphql }) {
500
+ return async ({ id, details }) => {
501
+ return await graphql.refunds.create({
502
+ transactionId: id,
503
+ details
504
+ });
505
+ };
506
+ }
507
+ function useTransaction({ graphql, storeId }) {
508
+ return {
509
+ create: createTransaction({
510
+ graphql,
511
+ storeId
512
+ }),
513
+ read: readTransaction({ graphql }),
514
+ updateState: updateStateTransaction({ graphql }),
515
+ refund: refundTransaction({ graphql })
516
+ };
517
+ }
518
+ function useTasks({ endpoint, headers }) {
519
+ const addJob = async (identifier, payload, spec) => {
520
+ await ofetch(endpoint, {
521
+ method: "POST",
522
+ body: {
523
+ task: identifier,
524
+ payload,
525
+ spec
526
+ },
527
+ headers
528
+ });
529
+ };
530
+ return { addJob };
531
+ }
532
+ const createPayment = (opts) => {
533
+ const graphql = opts.graphql;
534
+ const checkout = useCheckout({ graphql });
535
+ const session = useSession({
536
+ graphql,
537
+ secret: opts.secret,
538
+ storeId: opts.storeId
539
+ });
540
+ const transaction = useTransaction({
541
+ graphql,
542
+ storeId: opts.storeId
543
+ });
544
+ const tasks = useTasks({
545
+ endpoint: opts.tasks.url,
546
+ headers: opts.tasks.headers
547
+ });
548
+ const payment = usePayment({
549
+ transaction,
550
+ providers: opts.providers,
551
+ tasks
552
+ });
553
+ const getStore = async () => {
554
+ return graphql.stores.findByPk(opts.storeId);
555
+ };
556
+ return {
557
+ session,
558
+ checkout,
559
+ payment,
560
+ transaction,
561
+ providers: Object.keys(opts.providers),
562
+ _providers: opts.providers,
563
+ $graphql: graphql,
564
+ $tasks: tasks,
565
+ getStore
566
+ };
567
+ };
568
+ const codes$6 = {
569
+ 0: {
570
+ status: "pending",
571
+ messages: { es: "Orden de pago creada" }
572
+ },
573
+ 1: {
574
+ status: "success",
575
+ messages: { es: "Pago aprobado" }
576
+ },
577
+ 9: {
578
+ status: "refund",
579
+ messages: { es: "Pago anulado" }
580
+ }
581
+ };
582
+ function normalizeStatus$4(data) {
583
+ const code = codes$6[data.statusQrCode];
584
+ if (!code) return {
585
+ status: "pending",
586
+ code: String(data.statusQrCode || "??"),
587
+ description: data?.message || "unknow code",
588
+ messages: { es: "Codigo desconocido" }
589
+ };
590
+ return {
591
+ ...code,
592
+ description: data.message,
593
+ code: String(data.statusQrCode)
594
+ };
595
+ }
596
+ function verifyError$1(body) {
597
+ if (body.responseCode !== 0) throw createError({
598
+ cause: body.message,
599
+ message: body.message,
600
+ data: { ...body }
601
+ });
602
+ }
603
+ const createBancoEconomico = ({ endpoint, credentials, ...globalOptions }) => {
604
+ const api = ofetch.create({ baseURL: endpoint });
605
+ const encryt = async (text) => {
606
+ return await api("/api/authentication/encrypt", {
607
+ method: "GET",
608
+ params: {
609
+ text,
610
+ aesKey: globalOptions.aesKey
611
+ }
612
+ }).catch((e) => {
613
+ console.error("Error en encriptación:", e.response);
614
+ throw e;
615
+ });
616
+ };
617
+ const getAuth = async () => {
618
+ const password = await encryt(credentials.password);
619
+ const auth = await api("/api/authentication/authenticate", {
620
+ method: "POST",
621
+ body: {
622
+ userName: credentials.userName,
623
+ password
624
+ }
625
+ }).catch((e) => {
626
+ console.error("Error en encriptación:", e.response);
627
+ throw e;
628
+ });
629
+ verifyError$1(auth);
630
+ return auth;
631
+ };
632
+ return {
633
+ methods: {},
634
+ prepare: async (uid, transaction) => {
635
+ const { token } = await getAuth();
636
+ if (!token) throw new Error("No se pudo obtener el token de autenticación");
637
+ const accountCredit = await encryt(globalOptions.accountCredit);
638
+ const r = await api("/api/qrsimple/generateQR", {
639
+ method: "POST",
640
+ body: {
641
+ transactionId: transaction.id,
642
+ accountCredit,
643
+ currency: "BOB",
644
+ description: transaction.description || "Generacion de QR-Ecommerce",
645
+ amount: Number(transaction.checkout.total).toFixed(2),
646
+ dueDate: dayjs().add(1, "day").format("YYYY-MM-DD"),
647
+ singleUse: true,
648
+ modifyAmount: false,
649
+ branchCode: globalOptions.branchCode || "E0001"
650
+ },
651
+ headers: { Authorization: `Bearer ${token}` }
652
+ }).catch((e) => {
653
+ console.error("Error al crear el QR:", e);
654
+ throw e;
655
+ });
656
+ verifyError$1(r);
657
+ return {
658
+ id: r.qrId,
659
+ checkout: transaction.checkout,
660
+ ...r,
661
+ sonda: dayjs().add(1, "day").valueOf()
662
+ };
663
+ },
664
+ sendPay: async ({ uid }, { transaction }) => {
665
+ const { token } = await getAuth();
666
+ const r = await api(`/api/qrsimple/v2/statusQr/${transaction.ref}`, {
667
+ method: "GET",
668
+ headers: { Authorization: `Bearer ${token}` }
669
+ });
670
+ verifyError$1(r);
671
+ const details = normalizeStatus$4(r);
672
+ return {
673
+ id: transaction.ref,
674
+ uid,
675
+ status: details.status,
676
+ body: r,
677
+ message: details.description || details.messages?.es || "",
678
+ sonda: details.status !== "success" ? dayjs().add(28, "hours").valueOf() : false
679
+ };
680
+ },
681
+ verify: async ({ transaction }) => {
682
+ const { token } = await getAuth();
683
+ const r = await api(`/api/qrsimple/v2/statusQr/${transaction.ref}`, {
684
+ method: "GET",
685
+ headers: { Authorization: `Bearer ${token}` }
686
+ });
687
+ verifyError$1(r);
688
+ const details = normalizeStatus$4(r);
689
+ return {
690
+ id: transaction.ref,
691
+ status: details.status,
692
+ responseRaw: r,
693
+ details,
694
+ customer: transaction.session.customer || {},
695
+ payments: {
696
+ current: {},
697
+ history: []
698
+ },
699
+ uid: transaction.id,
700
+ transaction: {
701
+ provider: transaction.provider,
702
+ status: transaction.status,
703
+ responseTasks: transaction.responseTasks,
704
+ payloadTasks: { success: transaction.tasks.success?.map((el) => {
705
+ return el.payload;
706
+ }) }
707
+ }
708
+ };
709
+ },
710
+ refund: async () => {
711
+ return {};
712
+ }
713
+ };
714
+ };
715
+ const codes$5 = {
716
+ 1: {
717
+ status: "pending",
718
+ messages: { es: "Orden de pago creada" }
719
+ },
720
+ 2: {
721
+ status: "success",
722
+ messages: { es: "Pago aprobad" }
723
+ },
724
+ 3: {
725
+ status: "refund",
726
+ messages: { es: "Pago anulado" }
727
+ }
728
+ };
729
+ function normalizeStatus$3(data) {
730
+ const code = codes$5[data.orderState];
731
+ if (!code) return {
732
+ status: "pending",
733
+ code: data.result || "??",
734
+ description: data?.message || "unknow code",
735
+ messages: { es: "Codigo desconocido" }
736
+ };
737
+ return {
738
+ ...code,
739
+ description: data.message,
740
+ code: data.result
741
+ };
742
+ }
743
+ function verifyError(body) {
744
+ if (body.result !== "COD000") throw createError({
745
+ cause: body.message,
746
+ message: body.message,
747
+ data: { ...body }
748
+ });
749
+ }
750
+ const createBancoGanadero = ({ endpoint, apiKey, credentials }) => {
751
+ const api = ofetch.create({ baseURL: endpoint });
752
+ const getAuth = async () => {
753
+ const auth = await api("/ws-servicio-codigo-qr-empresas/enterprise/service/v1/qrcode/access", {
754
+ method: "POST",
755
+ body: credentials,
756
+ headers: { "x-api-key": apiKey }
757
+ });
758
+ verifyError(auth);
759
+ return auth;
760
+ };
761
+ return {
762
+ methods: {
763
+ login: async (body) => {
764
+ return {
765
+ result: "",
766
+ message: "",
767
+ token: ""
768
+ };
769
+ },
770
+ payments: async (body) => {
771
+ return {
772
+ result: "",
773
+ message: ""
774
+ };
775
+ }
776
+ },
777
+ prepare: async (uid, transaction) => {
778
+ const { token } = await getAuth();
779
+ if (!token) throw new Error("No se pudo obtener el token de autenticación");
780
+ const r = await api("/ws-servicio-codigo-qr-empresas/service/v1/qrcode/collections", {
781
+ method: "POST",
782
+ body: {
783
+ accountReference: "CUENTA_QR_BOB",
784
+ amount: transaction.checkout.total,
785
+ apiKey,
786
+ currency: "BOB",
787
+ userName: credentials.userName,
788
+ expirationDate: dayjs().add(1, "day").format("DDMMYYYY"),
789
+ reference: transaction.id,
790
+ transactionId: transaction.id,
791
+ singleUse: 1
792
+ },
793
+ headers: { Authorization: `Bearer ${token}` }
794
+ }).catch((e) => {
795
+ console.error("Error al crear el QR:", e);
796
+ throw e;
797
+ });
798
+ verifyError(r);
799
+ return {
800
+ id: r.qrId,
801
+ checkout: transaction.checkout,
802
+ ...r,
803
+ sonda: dayjs().add(1, "day").valueOf()
804
+ };
805
+ },
806
+ sendPay: async ({ uid }, { transaction }) => {
807
+ const { token } = await getAuth();
808
+ const r = await api("/ws-servicio-codigo-qr-empresas/service/v1/qrcode/status", {
809
+ body: {
810
+ qrId: transaction.ref,
811
+ userName: credentials.userName,
812
+ apiKey
813
+ },
814
+ method: "POST",
815
+ headers: { Authorization: `Bearer ${token}` }
816
+ });
817
+ verifyError(r);
818
+ const details = normalizeStatus$3(r);
819
+ return {
820
+ id: transaction.ref,
821
+ uid,
822
+ status: details.status,
823
+ body: r,
824
+ message: details.description || details.messages?.es || "",
825
+ sonda: details.status !== "success" ? dayjs().add(1, "day").valueOf() : false
826
+ };
827
+ },
828
+ verify: async ({ transaction }) => {
829
+ const { token } = await getAuth();
830
+ const r = await api("/ws-servicio-codigo-qr-empresas/service/v1/qrcode/status", {
831
+ body: {
832
+ qrId: transaction.ref,
833
+ userName: credentials.userName,
834
+ apiKey
835
+ },
836
+ method: "POST",
837
+ headers: { Authorization: `Bearer ${token}` }
838
+ });
839
+ verifyError(r);
840
+ const details = normalizeStatus$3(r);
841
+ return {
842
+ id: transaction.ref,
843
+ status: details.status,
844
+ responseRaw: r,
845
+ details,
846
+ customer: transaction.session.customer || {},
847
+ payments: {
848
+ current: {},
849
+ history: []
850
+ },
851
+ uid: transaction.id,
852
+ transaction: {
853
+ provider: transaction.provider,
854
+ status: transaction.status,
855
+ responseTasks: transaction.responseTasks,
856
+ payloadTasks: { success: transaction.tasks.success?.map((el) => {
857
+ return el.payload;
858
+ }) }
859
+ }
860
+ };
861
+ },
862
+ refund: async () => {
863
+ return {};
864
+ }
865
+ };
866
+ };
867
+ function computeHttpSignature(config, headerHash) {
868
+ let sig = "keyid=\"${keyid}\", algorithm=\"${algorithm}\", headers=\"${headers}\", signature=\"${signature}\"";
869
+ let signingBase = "";
870
+ config.headers.forEach((h) => {
871
+ if (signingBase !== "") signingBase += "\n";
872
+ signingBase += `${h.toLowerCase()}: ${headerHash[h]}`;
873
+ });
874
+ let hash;
875
+ const secret = Buffer.from(config.secretkey, "base64");
876
+ if (config.algorithm === "HmacSHA256" || config.algorithm === "SHA256withRSA") hash = crypto.createHmac("sha256", secret).update(signingBase).digest();
877
+ else throw new Error(`Unsupported algorithm: ${config.algorithm}`);
878
+ const signatureOptions = {
879
+ keyid: config.keyid,
880
+ algorithm: config.algorithm,
881
+ headers: config.headers,
882
+ signature: hash.toString("base64")
883
+ };
884
+ Object.keys(signatureOptions).forEach((key) => {
885
+ const pattern = `\${${key}}`;
886
+ const value = Array.isArray(signatureOptions[key]) ? signatureOptions[key].join(" ") : signatureOptions[key];
887
+ sig = sig.replace(pattern, value);
888
+ });
889
+ return sig;
890
+ }
891
+ function generateSignatureHeaders(request, environment) {
892
+ const curDate = (/* @__PURE__ */ new Date()).toUTCString();
893
+ const targetUrl = request.url.trim().replace(/^https?:\/\/[^/]+\//, "/");
894
+ const method = request.method.toLowerCase();
895
+ const computedDigest = `SHA-256=${crypto.createHash("sha256").update(request.data).digest().toString("base64")}`;
896
+ const postHeaderHash = {
897
+ "host": environment.host,
898
+ "date": curDate,
899
+ "(request-target)": `${method} ${targetUrl}`,
900
+ "digest": computedDigest,
901
+ "v-c-merchant-id": environment.merchantId
902
+ };
903
+ const getHeaderHash = {
904
+ "host": environment.host,
905
+ "date": curDate,
906
+ "(request-target)": `${method} ${targetUrl}`,
907
+ "v-c-merchant-id": environment.merchantId
908
+ };
909
+ const postConfig = {
910
+ algorithm: "HmacSHA256",
911
+ keyid: environment.keyId,
912
+ secretkey: environment.secretkey,
913
+ headers: [
914
+ "host",
915
+ "date",
916
+ "(request-target)",
917
+ "digest",
918
+ "v-c-merchant-id"
919
+ ]
920
+ };
921
+ const getConfig = {
922
+ algorithm: "HmacSHA256",
923
+ keyid: environment.keyId,
924
+ secretkey: environment.secretkey,
925
+ headers: [
926
+ "host",
927
+ "date",
928
+ "(request-target)",
929
+ "v-c-merchant-id"
930
+ ]
931
+ };
932
+ let config;
933
+ let headerHash;
934
+ if ([
935
+ "post",
936
+ "put",
937
+ "patch"
938
+ ].includes(method)) {
939
+ config = postConfig;
940
+ headerHash = postHeaderHash;
941
+ } else if (["get", "delete"].includes(method)) {
942
+ config = getConfig;
943
+ headerHash = getHeaderHash;
944
+ } else throw new Error(`Unsupported HTTP method: ${method}`);
945
+ return {
946
+ sig: computeHttpSignature(config, headerHash),
947
+ computedDigest,
948
+ curDate,
949
+ targetUrl,
950
+ signingBase: Object.values(headerHash).join("\n"),
951
+ method
952
+ };
953
+ }
954
+ async function setupAuthentication(api, { card, clientReferenceInformation, buyerInformation }) {
955
+ console.log(buyerInformation);
956
+ return await api("/risk/v1/authentication-setups", {
957
+ method: "POST",
958
+ body: {
959
+ clientReferenceInformation,
960
+ buyerInformation,
961
+ paymentInformation: { card }
962
+ }
963
+ });
964
+ }
965
+ const createCybersource = ({ hostEndpoint, keyId, secretkey, merchantId }) => {
966
+ const api = ofetch.create({
967
+ baseURL: `https://${hostEndpoint}`,
968
+ onRequest({ request, options }) {
969
+ const h = generateSignatureHeaders({
970
+ url: `https://${hostEndpoint}${request}`,
971
+ method: options.method,
972
+ data: JSON.stringify(options.body || {})
973
+ }, {
974
+ host: hostEndpoint,
975
+ merchantId,
976
+ keyId,
977
+ secretkey
978
+ });
979
+ options.headers.append("v-c-merchant-id", merchantId);
980
+ options.headers.append("Date", h.curDate);
981
+ options.headers.append("Host", hostEndpoint);
982
+ if (!["get", "delete"].includes(h.method)) options.headers.append("Digest", h.computedDigest);
983
+ options.headers.append("Signature", h.sig);
984
+ options.headers.append("Accept", "*/*");
985
+ options.headers.append("Content-Type", "application/json");
986
+ }
987
+ });
988
+ return {
989
+ methods: { recurrent: async (body) => {
990
+ return await api("/pts/v2/payments", {
991
+ method: "POST",
992
+ body: {
993
+ clientReferenceInformation: { code: body.code },
994
+ processingInformation: {
995
+ commerceIndicator: "recurring",
996
+ capture: true,
997
+ authorizationOptions: {
998
+ ignoreAvsResult: false,
999
+ declineAvsFlags: null,
1000
+ ignoreCvResult: false,
1001
+ initiator: {
1002
+ type: "merchant",
1003
+ credentialStoredOnFile: null,
1004
+ merchantInitiatedTransaction: {
1005
+ reason: body.reason || "1",
1006
+ previousTransactionId: body.previousTransactionId
1007
+ }
1008
+ },
1009
+ billPayment: null
1010
+ },
1011
+ captureOptions: null
1012
+ },
1013
+ paymentInformation: { customer: { customerId: body.customerId } },
1014
+ instrumentIdentifier: { id: body.instrumentIdentifierId },
1015
+ orderInformation: {
1016
+ amountDetails: {
1017
+ totalAmount: body.totalAmount,
1018
+ currency: body.currency || "BOB"
1019
+ },
1020
+ billTo: {
1021
+ firstName: body.firstName || "",
1022
+ lastName: body.lastName || ""
1023
+ },
1024
+ shipTo: null
1025
+ },
1026
+ buyerInformation: null,
1027
+ recipientInformation: null,
1028
+ deviceInformation: { hostName: null }
1029
+ }
1030
+ });
1031
+ } },
1032
+ prepare: async (uid, transaction, options) => {
1033
+ const { card } = options;
1034
+ if (!card) throw new Error("Card information is required for Cybersource prepare");
1035
+ const r = await setupAuthentication(api, {
1036
+ card,
1037
+ clientReferenceInformation: { code: transaction.id },
1038
+ buyerInformation: {
1039
+ merchantCustomerID: transaction.session.identification,
1040
+ email: transaction.session.email
1041
+ }
1042
+ });
1043
+ return {
1044
+ id: r.id,
1045
+ iframe: r,
1046
+ extras: { setup: r }
1047
+ };
1048
+ },
1049
+ postPrepare: async (uid, transaction, options) => {
1050
+ const { card, body, transactionMode, returnUrl, deviceInformation, merchantDefinedInformation } = options;
1051
+ if (!card) throw new Error("Card information is required for Cybersource prepare");
1052
+ let iframe = {};
1053
+ const extras = {};
1054
+ const orderInformation = {
1055
+ amountDetails: {
1056
+ currency: transaction.checkout.billingInfo.currency || "BOB",
1057
+ totalAmount: transaction.checkout.total
1058
+ },
1059
+ billTo: {
1060
+ address1: transaction.checkout.billingInfo.address1 || "Zona sur",
1061
+ address2: transaction.checkout.billingInfo.address2 || "Calacoto",
1062
+ administrativeArea: transaction.checkout.billingInfo.administrativeArea || null,
1063
+ country: transaction.checkout.billingInfo.country || "BO",
1064
+ locality: transaction.checkout.billingInfo.locality || "La Paz",
1065
+ firstName: transaction.checkout.billingInfo.firstName || "Ivan",
1066
+ lastName: transaction.checkout.billingInfo.lastName || "Olguin",
1067
+ phoneNumber: transaction.checkout.billingInfo.phone || "N/A",
1068
+ email: transaction.checkout.billingInfo.email || "N/A",
1069
+ postalCode: transaction.checkout.billingInfo.postalCode || "94105"
1070
+ }
1071
+ };
1072
+ if (body.referenceId) {
1073
+ const payload = {
1074
+ clientReferenceInformation: { code: transaction.id },
1075
+ orderInformation,
1076
+ paymentInformation: { card },
1077
+ consumerAuthenticationInformation: {
1078
+ returnUrl: `${returnUrl}/payment/cybersource/return`,
1079
+ transactionMode: transactionMode || "S",
1080
+ referenceId: body.referenceId
1081
+ },
1082
+ buyerInformation: {
1083
+ merchantCustomerID: transaction.session.identification,
1084
+ email: transaction.session.email
1085
+ }
1086
+ };
1087
+ if (deviceInformation) payload.deviceInformation = {
1088
+ ...deviceInformation,
1089
+ phoneNumber: transaction.checkout.billingInfo.phone || "",
1090
+ email: transaction.checkout.billingInfo.email || "",
1091
+ firstName: transaction.checkout.billingInfo.firstName || "N/A",
1092
+ lastName: transaction.checkout.billingInfo.lastName || "N/A"
1093
+ };
1094
+ if (merchantDefinedInformation) payload.merchantDefinedInformation = merchantDefinedInformation || [];
1095
+ console.log("Request:", "/risk/v1/authentications ::", payload);
1096
+ iframe = await api("/risk/v1/authentications", {
1097
+ method: "POST",
1098
+ body: payload
1099
+ }).catch((e) => {
1100
+ console.error("Error in Cybersource authentication:", e);
1101
+ throw e;
1102
+ });
1103
+ extras.enrollment = iframe;
1104
+ }
1105
+ if (body.authenticationTransactionId) {
1106
+ const payload = {
1107
+ buyerInformation: {
1108
+ merchantCustomerID: transaction.session.identification,
1109
+ email: transaction.session.email
1110
+ },
1111
+ clientReferenceInformation: { code: transaction.id },
1112
+ orderInformation,
1113
+ paymentInformation: { card },
1114
+ consumerAuthenticationInformation: { authenticationTransactionId: body.authenticationTransactionId }
1115
+ };
1116
+ if (deviceInformation) payload.deviceInformation = {
1117
+ ...deviceInformation,
1118
+ phoneNumber: transaction.checkout.billingInfo.phone || "",
1119
+ email: transaction.checkout.billingInfo.email || "",
1120
+ firstName: transaction.checkout.billingInfo.firstName || "N/A",
1121
+ lastName: transaction.checkout.billingInfo.lastName || "N/A"
1122
+ };
1123
+ if (merchantDefinedInformation) payload.merchantDefinedInformation = merchantDefinedInformation || [];
1124
+ console.log("Request:", "/risk/v1/authentication-results ::", payload);
1125
+ iframe = await api("/risk/v1/authentication-results", {
1126
+ method: "POST",
1127
+ body: payload
1128
+ });
1129
+ extras.authentication = iframe;
1130
+ }
1131
+ return {
1132
+ id: transaction.ref,
1133
+ iframe,
1134
+ extras
1135
+ };
1136
+ },
1137
+ sendPay: async ({ uid, body }, { transaction }) => {
1138
+ const { card, consumer, processingInformation, deviceInformation, merchantDefinedInformation } = body;
1139
+ if (!card) throw new Error("Card information is required for Cybersource prepare");
1140
+ const orderInformation = {
1141
+ amountDetails: {
1142
+ currency: transaction.checkout.billingInfo.currency || "BOB",
1143
+ totalAmount: transaction.checkout.total
1144
+ },
1145
+ billTo: {
1146
+ address1: transaction.checkout.billingInfo.address1 || "Zona sur",
1147
+ address2: transaction.checkout.billingInfo.address2 || "Colacoto",
1148
+ administrativeArea: transaction.checkout.billingInfo.administrativeArea || null,
1149
+ country: transaction.checkout.billingInfo.country || "BO",
1150
+ locality: transaction.checkout.billingInfo.locality || "La Paz",
1151
+ firstName: transaction.checkout.billingInfo.firstName || "Ival",
1152
+ lastName: transaction.checkout.billingInfo.lastName || "Olguin",
1153
+ phoneNumber: transaction.checkout.billingInfo.phone || "N/A",
1154
+ email: transaction.checkout.billingInfo.email || "N/A",
1155
+ postalCode: transaction.checkout.billingInfo.postalCode || "94105"
1156
+ }
1157
+ };
1158
+ const payload = {
1159
+ clientReferenceInformation: { code: transaction.id },
1160
+ buyerInformation: {
1161
+ merchantCustomerID: transaction.session.identification,
1162
+ email: transaction.session.email
1163
+ },
1164
+ orderInformation,
1165
+ paymentInformation: { card },
1166
+ processingInformation,
1167
+ consumerAuthenticationInformation: consumer,
1168
+ deviceInformation: {},
1169
+ merchantDefinedInformation: []
1170
+ };
1171
+ if (deviceInformation) payload.deviceInformation = {
1172
+ ...deviceInformation,
1173
+ phoneNumber: transaction.checkout.billingInfo.phone || "",
1174
+ email: transaction.checkout.billingInfo.email || "",
1175
+ firstName: transaction.checkout.billingInfo.firstName || "N/A",
1176
+ lastName: transaction.checkout.billingInfo.lastName || "N/A"
1177
+ };
1178
+ if (merchantDefinedInformation) payload.merchantDefinedInformation = merchantDefinedInformation || [];
1179
+ console.log("Request:", "/pts/v2/payments::", payload);
1180
+ const r = await api("/pts/v2/payments", {
1181
+ method: "POST",
1182
+ body: payload
1183
+ });
1184
+ console.log("Response:", "/pts/v2/payments::", r);
1185
+ let status = "pending";
1186
+ if (r.status === "AUTHORIZED") status = "success";
1187
+ if (["DECLINED", "CANCELLED"].includes(r.status)) status = "failure";
1188
+ if (r.status === "PENDING") status = "pending";
1189
+ return {
1190
+ id: r.id,
1191
+ uid,
1192
+ status,
1193
+ body: r,
1194
+ message: ""
1195
+ };
1196
+ },
1197
+ verify: async ({ uid, transaction }) => {
1198
+ const self = transaction.details._links?.self?.href;
1199
+ let reason = "";
1200
+ let message = "";
1201
+ let msg = "Estado desconocido";
1202
+ if (self) {
1203
+ const r = await api(self, { method: "GET" });
1204
+ reason = r.statusInformation?.reason || "";
1205
+ message = r.statusInformation?.message || "";
1206
+ }
1207
+ if (reason === "Success") msg = "Pago exitoso";
1208
+ if (reason === "Declined") msg = "Pago declinado";
1209
+ else if (reason === "Cancelled") msg = "Pago cancelado";
1210
+ else if (reason === "Pending") msg = "Pago pendiente";
1211
+ else if (reason === "Error") msg = "Error en el pago";
1212
+ return {
1213
+ id: transaction.id,
1214
+ status: transaction.status,
1215
+ details: {
1216
+ messages: { es: msg },
1217
+ status: transaction.status,
1218
+ code: reason,
1219
+ description: message
1220
+ },
1221
+ payments: {
1222
+ current: {},
1223
+ history: []
1224
+ },
1225
+ responseRaw: transaction.details,
1226
+ uid,
1227
+ customer: transaction.session.customer,
1228
+ transaction: {
1229
+ provider: transaction.provider,
1230
+ status: transaction.status
1231
+ }
1232
+ };
1233
+ },
1234
+ refund: async () => {
1235
+ return {};
1236
+ }
1237
+ };
1238
+ };
1239
+ function createBodyDatafast(uid, { checkout, session, ip }, credentials) {
1240
+ const amount = (+`${checkout.total}`).toFixed(2);
1241
+ const sCountryCode = checkout.shippingInfo?.countryCode;
1242
+ const bCountryCode = checkout.billingInfo?.countryCode || sCountryCode;
1243
+ if (+`${credentials.fase}` === 1) return [
1244
+ `entityId=${credentials.entityId}`,
1245
+ "amount=12.00",
1246
+ "currency=USD",
1247
+ "paymentType=DB"
1248
+ ].join("&");
1249
+ if (!session.email || !session.identification || !ip) throw new Error("Missing required session fields");
1250
+ const body = {
1251
+ entityId: credentials.entityId,
1252
+ merchantTransactionId: uid,
1253
+ amount: `${amount}`,
1254
+ currency: "USD",
1255
+ paymentType: "DB",
1256
+ shipping: {
1257
+ street1: checkout.shippingInfo?.address || "NA",
1258
+ country: sCountryCode || "EC"
1259
+ },
1260
+ billing: {
1261
+ street1: checkout.billingInfo?.address || checkout.shippingInfo?.address || "NA",
1262
+ country: bCountryCode || "EC"
1263
+ },
1264
+ customer: {
1265
+ email: session.email,
1266
+ identificationDocType: "IDCARD",
1267
+ identificationDocId: session.identification,
1268
+ givenName: session.customer.givenName,
1269
+ middleName: session.customer.middleName || "NA",
1270
+ surname: session.customer.surname,
1271
+ ip,
1272
+ merchantCustomerId: session.customer.id,
1273
+ phone: session.customer.phone || "0999999999"
1274
+ }
1275
+ };
1276
+ const itemsStr = checkout.items.map((el, ix) => {
1277
+ return [
1278
+ `cart.items[${ix}].name=${encodeURIComponent(el.title)}`,
1279
+ `cart.items[${ix}].description=${encodeURIComponent(`Description:${el.title}`)}`,
1280
+ `cart.items[${ix}].price=${encodeURIComponent(Number(`${el.item.unitAmount}`).toFixed(2))}`,
1281
+ `cart.items[${ix}].quantity=${encodeURIComponent(el.quantity)}`
1282
+ ].join("&");
1283
+ }).join("&");
1284
+ const base0 = checkout.taxes.find((el) => el.code === "0")?.base || 0;
1285
+ const baseIVA = checkout.taxes.find((el) => el.code === credentials.codeIva || "4")?.base || 0;
1286
+ const taxIVA = checkout.taxes.find((el) => el.code === credentials.codeIva || "4")?.value || 0;
1287
+ const cp = {
1288
+ "customParameters[SHOPPER_MID]": credentials.mid,
1289
+ "customParameters[SHOPPER_TID]": credentials.tid,
1290
+ "customParameters[SHOPPER_ECI]": "0103910",
1291
+ "customParameters[SHOPPER_PSERV]": "17913101",
1292
+ "customParameters[SHOPPER_VAL_BASE0]": base0?.toFixed(2),
1293
+ "customParameters[SHOPPER_VAL_BASEIMP]": baseIVA?.toFixed(2),
1294
+ "customParameters[SHOPPER_VAL_IVA]": taxIVA?.toFixed(2),
1295
+ "customParameters[SHOPPER_VERSIONDF]": "2"
1296
+ };
1297
+ const str = [
1298
+ qs.stringify(body, { allowDots: true }),
1299
+ itemsStr,
1300
+ Object.entries(cp).map(([key, value]) => {
1301
+ return `${key}=${value}`;
1302
+ }).join("&"),
1303
+ `risk.parameters[USER_DATA2]=${credentials.nameEcommerce}`
1304
+ ];
1305
+ if (+`${credentials.fase}` !== 3) str.push("testMode=EXTERNAL");
1306
+ return str.join("&");
1307
+ }
1308
+ function numberOfInstallments(installments = []) {
1309
+ const option = (value, index) => `<option value="${value}" ${index === 0 ? "selected" : ""}>${value} meses</option>`;
1310
+ const disabled = installments.length > 1 ? "" : "disabled";
1311
+ const display = "inline-block";
1312
+ return installments.length ? `
1313
+ <div class="wpwl-label wpwl-label-custom" style="display:${display}">
1314
+ Diferido:
1315
+ </div>
1316
+ <div class="wpwl-wrapper wpwl-wrapper-custom" style="display:${display}">
1317
+ <select name="recurring.numberOfInstallments" ${disabled}>
1318
+ ${installments.map(option).join(" ")}
1319
+ </select>
1320
+ </div>
1321
+ ` : "";
1322
+ }
1323
+ const dicCreditTypes = {
1324
+ "00": "Transacción corriente",
1325
+ "01": "Diferido corriente",
1326
+ "02": "Diferido con Interés",
1327
+ "03": "Diferido sin Interés",
1328
+ "07": "Diferido con Interés + Meses de Gracia",
1329
+ "09": "Diferido sin Interés + Meses de Gracia",
1330
+ "21": "Diferido Plus",
1331
+ "22": "Diferido"
1332
+ };
1333
+ function creditType(options = false) {
1334
+ let selectOptions = [];
1335
+ const option = ([key], index) => `<option value="${key}" ${index === 0 ? "selected" : ""}>${dicCreditTypes[key]}</option>`;
1336
+ if (typeof options === "boolean") {
1337
+ if (!options) return "";
1338
+ selectOptions = Object.entries(dicCreditTypes).sort(([keyA], [keyB]) => +keyA - +keyB).map(option);
1339
+ } else selectOptions = Object.entries(options).filter(([, value]) => {
1340
+ return value;
1341
+ }).sort(([keyA], [keyB]) => +keyA - +keyB).map(option);
1342
+ const display = "inline-block";
1343
+ const disabled = selectOptions.length > 1 ? "" : "disabled";
1344
+ return selectOptions ? ` <div
1345
+ class="wpwl-wrapper wpwl-wrapper-custom"
1346
+ style="display:${display};padding-left: 10px;padding-bottom: 15px;"
1347
+ >
1348
+ Tipo de crédito:
1349
+ <select name="customParameters[SHOPPER_TIPOCREDITO]" style="max-width: 190px;" ${disabled}>
1350
+ ${selectOptions.join(" ")}
1351
+ </select>
1352
+ </div>` : "";
1353
+ }
1354
+ function loadIframe(siteUrl, credentials) {
1355
+ return (checkoutId, endpoint = `${siteUrl || ""}/payment/pay/datafast`, searchParams = {}, options) => {
1356
+ const _searchParams = Object.entries(searchParams).map(([key, value]) => `${key}=${value}`).join("&");
1357
+ const brands = options.brands?.join(" ")?.trim();
1358
+ const scriptInstallments = (element) => element ? `
1359
+ const nI = document.createElement('div');
1360
+ nI.style.display='inline-block';
1361
+ nI.innerHTML = '${element.replace(/\n/g, " ")}';
1362
+ document.querySelector('form.wpwl-form-card .wpwl-button').before(nI);
1363
+ ` : "";
1364
+ const scriptTypeCredits = (element) => element ? `
1365
+ const tC = document.createElement('div');
1366
+ tC.style.display='inline-block';
1367
+ tC.innerHTML = '${element.replace(/\n/g, " ")}';
1368
+ document.querySelector('form.wpwl-form-card .wpwl-button').before(tC);
1369
+ ` : "";
1370
+ const installments = numberOfInstallments(options.installments);
1371
+ const typeCredits = creditType(options.typeCredits);
1372
+ const addLogo = options.logo ? `const Br = document.createElement('div');
1373
+ Br.innerHTML ='<br/><img src="https://www.datafast.com.ec/images/verified.png" style="display:block;margin:0 auto; width:100%"><br/>';
1374
+ document.querySelector('form.wpwl-form-card .wpwl-button').before(Br);` : "";
1375
+ return `
1376
+ <style>
1377
+ body {
1378
+ font-family: sans-serif;
1379
+ }
1380
+ .wpwl-form-card {
1381
+ background-image: none;
1382
+ }
1383
+ </style>
1384
+
1385
+ ${`
1386
+ <script type="text/javascript">
1387
+ var wpwlOptions = {
1388
+ locale: 'es',
1389
+ labels: {
1390
+ cvv: 'CVV',
1391
+ cardHolder: "Nombre(Igual que en la tarjeta)"
1392
+ },
1393
+ onReady: function () {
1394
+ ${scriptInstallments(installments)}
1395
+ ${scriptTypeCredits(typeCredits)}
1396
+ ${addLogo}
1397
+ },
1398
+ onBeforeSubmitCard: function () {
1399
+ console.log('validate')
1400
+ if (document.querySelector('.wpwl-control-cardHolder').value === '') {
1401
+ const ch = document.querySelector('.wpwl-control-cardHolder');
1402
+ ch.classList.add('wpwl-has-error');
1403
+ const er = document.createElement('div');
1404
+ er.classList.add('wpwl-hint');
1405
+ er.classList.add('wpwl-hint-cardHolderError');
1406
+
1407
+ er.innerHTML = 'Campo requerido';
1408
+ ch.after(er);
1409
+ const btp = document.querySelector('.wpwl-button-pay');
1410
+ btp.classList.add('wpwl-button-error');
1411
+ btp.setAttribute('disabled', 'disabled');
1412
+ return false
1413
+ } else {
1414
+ return true;
1415
+ }
1416
+ },
1417
+ };
1418
+ <\/script>
1419
+ `}
1420
+ <form
1421
+ action="${endpoint}?${_searchParams}"
1422
+ class="paymentWidgets"
1423
+ data-brands="${brands || "VISA MASTER DISCOVER AMEX DINERS"}"
1424
+ ></form>
1425
+ <script src='${credentials.endpoint || "https://test.oppwa.com/v1"}/paymentWidgets.js?checkoutId=${checkoutId}'><\/script>
1426
+ `;
1427
+ };
1428
+ }
1429
+ const codes$4 = {
1430
+ "000.000.000": {
1431
+ status: "success",
1432
+ description: "Transaction succeeded",
1433
+ messages: { es: "Transacción aprobada" }
1434
+ },
1435
+ "000.100.110": {
1436
+ status: "success",
1437
+ description: "Request successfully processed in Merchant in Integrator Test Mode",
1438
+ messages: { es: "Transacción aprobada" }
1439
+ },
1440
+ "000.100.112": {
1441
+ status: "success",
1442
+ description: "",
1443
+ messages: { es: "Transacción aprobada" }
1444
+ },
1445
+ "000.000.100": {
1446
+ status: "success",
1447
+ description: "",
1448
+ messages: { es: "Transacción aprobada" }
1449
+ },
1450
+ "000.200.100": {
1451
+ status: "success",
1452
+ description: "successfully created checkout",
1453
+ messages: { es: "Creación del id (checkoutId) de manera exitosa" }
1454
+ },
1455
+ "600.200.201": {
1456
+ status: "failure",
1457
+ description: "Channel/Merchant not configured for this payment method",
1458
+ messages: { es: "MID o TID mal configurado" }
1459
+ },
1460
+ "800.110.100": {
1461
+ status: "failure",
1462
+ description: "Duplicate transaction",
1463
+ messages: { es: "Envio de transacción duplicado" }
1464
+ },
1465
+ "200.100.101": {
1466
+ status: "pending",
1467
+ description: "invalid Request Message. No valid XML. XML must be url-encoded! maybe it contains a not encoded ampersand or something similar.",
1468
+ messages: { es: "Cédula de identidad, teléfono entre otro. Si todo está bien, entonces se debe revisar el campo Response, si tiene el valor de 05" },
1469
+ pendingAction: (body) => {
1470
+ return body.resultDetails.Response === "05" ? "pending" : "failure";
1471
+ }
1472
+ },
1473
+ "200.100.103": {
1474
+ status: "failure",
1475
+ description: "Invalid Request Message. The request contains structural errors",
1476
+ messages: { es: "Mensaje invalido. Verifique los datos enviados" }
1477
+ },
1478
+ "800.100.171": {
1479
+ status: "failure",
1480
+ description: "Transaction declined (pick up card)",
1481
+ messages: { es: "Pick up: Retenga y llame" }
1482
+ },
1483
+ "700.300.700": {
1484
+ status: "failure",
1485
+ description: "referenced tx can not be reversed",
1486
+ messages: { es: "Reverso declinado" }
1487
+ },
1488
+ "800.100.174": {
1489
+ status: "failure",
1490
+ description: "transaction declined (invalid amount)",
1491
+ messages: { es: "Mondo invalido" }
1492
+ },
1493
+ "800.100.151": {
1494
+ status: "failure",
1495
+ description: "transaction declined (invalid card)",
1496
+ messages: { es: "Tarjeta de crédito inválida" }
1497
+ },
1498
+ "800.100.402": {
1499
+ status: "failure",
1500
+ description: "cc/bank account holder not valid",
1501
+ messages: { es: "No such issuer. Omisión de nombre de tarjetahabiente." }
1502
+ },
1503
+ "800.100.190": {
1504
+ status: "failure",
1505
+ description: "transaction declined (invalid configuration data)",
1506
+ messages: { es: "Transacción declinada por el banco: 1: tipo de crédito que no autorizada 2: Tarjeta no autodizada 3: Banco funora de red " }
1507
+ },
1508
+ "800.100.152": {
1509
+ status: "failure",
1510
+ description: "Authorization Error (95) transaction declined by authorization system",
1511
+ messages: { es: "La transacción fue rechazada por el banco" }
1512
+ },
1513
+ "800.100.197": {
1514
+ status: "failure",
1515
+ description: "transaction declined (registration cancelled externally)",
1516
+ messages: { es: "Transacción cancelada por el cliente" }
1517
+ },
1518
+ "800.100.176": {
1519
+ status: "failure",
1520
+ description: "transaction declined (account temporarily not available. Please try again later)",
1521
+ messages: { es: "Transacción rechazada: cuenta temporalmente no disponible, porfavor intente mas tarde" }
1522
+ },
1523
+ "100.400.311": {
1524
+ status: "failure",
1525
+ description: "transaction declined (format error)",
1526
+ messages: { es: " Error de formato" }
1527
+ },
1528
+ "100.100.100": {
1529
+ status: "failure",
1530
+ description: "request contains no creditcard, bank account number or bank name",
1531
+ messages: { es: "No se envió datos de la tarjeta" }
1532
+ },
1533
+ "800.100.165": {
1534
+ status: "failure",
1535
+ description: "transaction declined (card lost)",
1536
+ messages: { es: "Tarjeta reportada como perdida" }
1537
+ },
1538
+ "800.100.159": {
1539
+ status: "failure",
1540
+ description: "transaction declined (stolen card)",
1541
+ messages: { es: "Tarjeta reportada como sustraída" }
1542
+ },
1543
+ "800.100.155": {
1544
+ status: "failure",
1545
+ description: "transaction declined (amount exceeds credit)",
1546
+ messages: { es: "Fondos insuficientes" }
1547
+ },
1548
+ "100.100.400": {
1549
+ status: "failure",
1550
+ description: "request contains no cc/bank account holder",
1551
+ messages: { es: "Se envía vacío el cardholder" }
1552
+ },
1553
+ "100.100.303": {
1554
+ status: "failure",
1555
+ description: "Card Expired",
1556
+ messages: { es: "Tarjeta expirada" }
1557
+ },
1558
+ "800.100.170": {
1559
+ status: "failure",
1560
+ description: "transaction declined (transaction not permitted)",
1561
+ messages: { es: "Tarjeta de débito que no puede realizar compras por internet." }
1562
+ },
1563
+ "100.550.310": {
1564
+ status: "failure",
1565
+ description: "amount exceeds limit for the registered account",
1566
+ messages: { es: "Monto excede el cupo" }
1567
+ },
1568
+ "800.100.168": {
1569
+ status: "failure",
1570
+ description: "transaction declined (restricted card)",
1571
+ messages: { es: "Tarjeta restringida, cliente debe llamar al banco." }
1572
+ },
1573
+ "800.100.179": {
1574
+ status: "failure",
1575
+ description: "transaction declined (exceed withdrawal count limit)",
1576
+ messages: { es: "Maximo transacciones permitidas" }
1577
+ },
1578
+ "100.100.402": {
1579
+ status: "failure",
1580
+ description: "cc/bank account holder not valid",
1581
+ messages: { es: "Cardholder inválido, puede ser que tenga caracteres especiales" }
1582
+ },
1583
+ "600.200.100": {
1584
+ status: "failure",
1585
+ description: "invalid Payment Method",
1586
+ messages: { es: "Modalidad invalida" }
1587
+ },
1588
+ "700.100.200": {
1589
+ status: "failure",
1590
+ description: "non matching reference amount",
1591
+ messages: { es: "Verifique interés" }
1592
+ },
1593
+ "700.400.200": {
1594
+ status: "failure",
1595
+ description: "cannot refund",
1596
+ messages: { es: "Se intentó anular una transacción que ya había sido anulada previamente" }
1597
+ },
1598
+ "800.100.157": {
1599
+ status: "failure",
1600
+ description: "transaction declined (wrong expiry date)",
1601
+ messages: { es: "transaction declined (wrong expiry Vigencia de la tarjeta errada" }
1602
+ },
1603
+ "800.100.501": {
1604
+ status: "failure",
1605
+ description: "Card holder has advised his bank to stop all recurring payments for this merchant",
1606
+ messages: { es: "Establecimiento cancelado" }
1607
+ },
1608
+ "800.100.100": {
1609
+ status: "failure",
1610
+ description: "transaction declined for unknown reason",
1611
+ messages: { es: "1.La tarjeta tiene problemas por lo que el cliente debe llamar al Banco. 2.Transacción con una tarjeta de débito que no tiene autorizado compras por internet." }
1612
+ },
1613
+ "800.300.500": {
1614
+ status: "failure",
1615
+ description: "transaction temporary blacklisted (too many tries invalid CVV)",
1616
+ messages: { es: "La tarjeta se encuentra en lista negra debido a múltiples intentos de transacciones con CVV errado, se libera después de 48 horas." }
1617
+ },
1618
+ "800.300.501": {
1619
+ status: "failure",
1620
+ description: "transaction temporary blacklisted (too many tries invalid expire date)",
1621
+ messages: { es: "La tarjeta se encuentra en lista negra debido a múltiples intentos de transacciones con fecha de caducidad errada, se libera después de 48 horas." }
1622
+ },
1623
+ "900.100.201": {
1624
+ status: "pending",
1625
+ description: "error on the external gateway (bank)",
1626
+ messages: { es: "Se ha perdido la conexión con el Gateway de Pagos," }
1627
+ },
1628
+ "900.100.100": {
1629
+ status: "pending",
1630
+ description: "unexpected communication error with connector/acquirer",
1631
+ messages: { es: "Se ha perdido la conexión con el banco, intentar luego de unos minutos." }
1632
+ },
1633
+ "900.100.300": {
1634
+ status: "pending",
1635
+ description: "no response from connector/acquirer [uncertain result]",
1636
+ messages: { es: "Existió una desconexión en el instante de la transacción," }
1637
+ },
1638
+ "800.100.199": {
1639
+ status: "failure",
1640
+ description: "transaction declined (invalid tax number)",
1641
+ messages: { es: "Mensaje emitido cuando se ha calculado mal los impuestos, la base 0% + la base 12% + valor del IVA debe ser igual al monto que se envía." }
1642
+ },
1643
+ "600.200.500": {
1644
+ status: "failure",
1645
+ description: "Invalid payment data. You are not configured for this currency or sub type (country or brand)",
1646
+ messages: { es: "Mensaje emitido cuando no se ha asignado una marca de tarjeta para transaccionar." }
1647
+ },
1648
+ "800.100.156": {
1649
+ status: "failure",
1650
+ description: "transaction declined (format error)",
1651
+ messages: { es: "Depende del valor del código en el campo Response" }
1652
+ },
1653
+ "800.100.162": {
1654
+ status: "failure",
1655
+ description: "Transaction declined (limit exceeded)",
1656
+ messages: { es: "La tarjeta tiene un límite en el monto en compras, aún teniendo cupo." }
1657
+ },
1658
+ "100.100.101": {
1659
+ status: "failure",
1660
+ description: "invalid creditcard, bank account number or bank name",
1661
+ messages: { es: "Tarjeta de crédito inválida" }
1662
+ },
1663
+ "100.700.801": {
1664
+ status: "failure",
1665
+ description: "identity contains no or invalid identification value",
1666
+ messages: { es: "Se está enviando un campo mal, ya sea en el nombre o en su valor, el técnico debe revisar internamente." }
1667
+ },
1668
+ "100.400.147": {
1669
+ status: "failure",
1670
+ description: "Payment void and transaction denied by ReD Shield",
1671
+ messages: { es: "La transacción infringió una regla antifraude. Estas reglas fueron definidas por el comercio al momento de firmar." }
1672
+ },
1673
+ "100.400.149": {
1674
+ status: "failure",
1675
+ description: "Payment void and transaction denied by ReD Shield",
1676
+ messages: { es: "La transacción infringió una regla antifraude. Estas reglas fueron definidas por el comercio al momento de firmar." }
1677
+ },
1678
+ "100.400.325": {
1679
+ status: "failure",
1680
+ description: "External risk system not available",
1681
+ messages: { es: "Si este mensaje se presenta en muchas transacciones entonces el comercio debe comunicarse con Datafast de manera inmediata." }
1682
+ },
1683
+ "100.380.401": {
1684
+ status: "failure",
1685
+ description: "User Authentication Failed. (3DSecure Error)",
1686
+ messages: { es: "El código ingresado por el tarjetahabiente es incorrecto." }
1687
+ },
1688
+ "100.380.501": {
1689
+ status: "failure",
1690
+ description: "User Authentication Error (risk management transaction timeout)",
1691
+ messages: { es: "El tarjetahabiente no digitó el código enviado por el banco dentro del tiempo establecido." }
1692
+ },
1693
+ "100.396.103": {
1694
+ status: "failure",
1695
+ description: "Previously pending transaction timed out (Error in asynchronous workflow)",
1696
+ messages: { es: "El tarjetahabiente no digitó el código enviado por el banco dentro del tiempo establecido para tarjetas" }
1697
+ },
1698
+ "100.390.108": {
1699
+ status: "failure",
1700
+ description: "Transaction rejected because merchant not participating in 3DSecure program (3DSecure Error)",
1701
+ messages: { es: "Error de configuración en el canal." }
1702
+ },
1703
+ "100.390.112": {
1704
+ status: "failure",
1705
+ description: "Technical Error in 3D system (3DSecure Error)",
1706
+ messages: { es: "Error de configuración en el canal." }
1707
+ }
1708
+ };
1709
+ function handleControlCodes$1(body) {
1710
+ const code = codes$4[body.result.code];
1711
+ if (!code) return {
1712
+ status: "pending",
1713
+ code: body.result.code,
1714
+ description: "unknow code",
1715
+ messages: { es: "Codigo desconocido" }
1716
+ };
1717
+ return {
1718
+ ...code,
1719
+ code: body.result.code
1720
+ };
1721
+ }
1722
+ function sendPay({ credentials }) {
1723
+ return async ({ id }, { uid }) => {
1724
+ const body = await ofetch(`${credentials.endpoint}/checkouts/${id}/payment?entityId=${credentials.entityId}`, { headers: { Authorization: `Bearer ${credentials.token}` } });
1725
+ const state = handleControlCodes$1(body);
1726
+ return {
1727
+ id: body.id,
1728
+ uid,
1729
+ status: state.status,
1730
+ message: state.messages.es,
1731
+ body
1732
+ };
1733
+ };
1734
+ }
1735
+ const createDatafast = (options) => {
1736
+ const { credentials, urlSite } = options;
1737
+ return {
1738
+ methods: {},
1739
+ prepare: async (uid, transaction, options = {}) => {
1740
+ const data = createBodyDatafast(uid, transaction, credentials);
1741
+ if (options?.fake) return data;
1742
+ const r = await ofetch(`${credentials.endpoint}/checkouts`, {
1743
+ method: "POST",
1744
+ body: data,
1745
+ headers: {
1746
+ "Content-Type": "application/x-www-form-urlencoded",
1747
+ "Content-Length": `${data.length}`,
1748
+ "Authorization": `Bearer ${credentials.token}`
1749
+ }
1750
+ });
1751
+ const iframe = loadIframe(urlSite, credentials)(r.id, options.endpoint, {
1752
+ ...options?.searchParams,
1753
+ uid: transaction.id
1754
+ }, { ...options?.iframe });
1755
+ return {
1756
+ id: r.id,
1757
+ ...r,
1758
+ iframe
1759
+ };
1760
+ },
1761
+ sendPay: sendPay({ credentials }),
1762
+ verify: async ({ uid, transaction }) => {
1763
+ const r = await ofetch(`${credentials.endpoint}/query?entityId=${credentials.entityId}&merchantTransactionId=${uid}`, { headers: { Authorization: `Bearer ${credentials.token}` } });
1764
+ const payments = r.payments || [];
1765
+ const history = payments.filter((el) => el.paymentType !== "RF");
1766
+ const refunds = payments.filter((el) => el.paymentType === "RF");
1767
+ const last = payments[payments.length - 1];
1768
+ const h = handleControlCodes$1(last);
1769
+ return {
1770
+ id: last.id,
1771
+ status: h.status,
1772
+ details: h,
1773
+ payments: {
1774
+ current: history[history.length - 1],
1775
+ history,
1776
+ refunds
1777
+ },
1778
+ responseRaw: r,
1779
+ uid,
1780
+ customer: payments[0]?.customer,
1781
+ transaction: {
1782
+ provider: transaction.provider,
1783
+ status: transaction.status
1784
+ }
1785
+ };
1786
+ },
1787
+ refund: async (ref, amount, options = {}) => {
1788
+ return await ofetch(`${credentials.endpoint}/payments/${ref}`, {
1789
+ method: "POST",
1790
+ body: `entityId=${credentials.entityId}&paymentType=RF&amount=${Number(`${amount}`).toFixed(2)}&currency=${options.currency || "USD"}${+credentials.fase !== 3 ? "&testMode=EXTERNAL" : ""}`,
1791
+ headers: {
1792
+ "Content-Type": "application/x-www-form-urlencoded",
1793
+ "Authorization": `Bearer ${credentials.token}`
1794
+ }
1795
+ });
1796
+ }
1797
+ };
1798
+ };
1799
+ function createBodyMultipago$1(uid, { session, checkout }, options) {
1800
+ return {
1801
+ service: { code: options.code },
1802
+ payment_data: {
1803
+ item_selecteds: checkout.items.map((item) => {
1804
+ return {
1805
+ id: item.id || 34,
1806
+ description: `${item.title}`,
1807
+ quantity: `${item.quantity}`,
1808
+ unitary_price: `${item.item.unitAmount}`
1809
+ };
1810
+ }),
1811
+ payment_receiver: {
1812
+ id_local: null,
1813
+ name: null,
1814
+ ci: null,
1815
+ account_type: null,
1816
+ account_num: null,
1817
+ bank: null
1818
+ },
1819
+ url_confirm: `${options.urlReturn}&status=success`,
1820
+ url_fail: `${options.urlReturn}&status=failure`,
1821
+ button_label_ok: "OK",
1822
+ color: "",
1823
+ font: ""
1824
+ },
1825
+ client: {
1826
+ name: session.customer.givenName,
1827
+ last_name: session.customer.surname,
1828
+ ci: session.identification,
1829
+ phone: session.customer.phone || "",
1830
+ email: session.email,
1831
+ business_name: session.customer?.extras?.businessName || "",
1832
+ nit: session.customer?.extras?.nit || ""
1833
+ }
1834
+ };
1835
+ }
1836
+ const codes$3 = {
1837
+ pendiente: {
1838
+ status: "created",
1839
+ messages: { es: "Orden de pago creada" }
1840
+ },
1841
+ pediente: {
1842
+ status: "created",
1843
+ messages: { es: "Orden de pago creada" }
1844
+ },
1845
+ confirmada: {
1846
+ status: "success",
1847
+ messages: { es: "Pago aprobada" }
1848
+ },
1849
+ cancelada: {
1850
+ status: "failure",
1851
+ messages: { es: "Transacción cancelada" }
1852
+ },
1853
+ error: {
1854
+ status: "failure",
1855
+ messages: { es: "Sesión de transacción expirada" }
1856
+ },
1857
+ revertido: {
1858
+ status: "refund",
1859
+ messages: { es: "Transaccíon reversada" }
1860
+ },
1861
+ reservado: {
1862
+ status: "pending",
1863
+ messages: { es: "Pago pendiente" }
1864
+ }
1865
+ };
1866
+ function normalizeStatus$2({ data }) {
1867
+ const code = codes$3[data.status_order.toLowerCase().trim()];
1868
+ if (!code) return {
1869
+ status: "pending",
1870
+ code: data.status_order || "??",
1871
+ description: data?.detail?.payment_response || "unknow code",
1872
+ messages: { es: "Codigo desconocido" }
1873
+ };
1874
+ return {
1875
+ ...code,
1876
+ description: data?.detail?.payment_response,
1877
+ code: data.status_order
1878
+ };
1879
+ }
1880
+ const createMultipagos = ({ credentials, serviceCode, urlReturn }) => {
1881
+ const getToken = async () => {
1882
+ const token = await ofetch(joinURL(credentials.endpoint, "/api/v2/get_token"), {
1883
+ method: "post",
1884
+ body: {
1885
+ provider: credentials.provider,
1886
+ uid: credentials.uid
1887
+ }
1888
+ });
1889
+ if (token.status !== "OK") throw token;
1890
+ return token;
1891
+ };
1892
+ const createPayOrder = async (token, body) => {
1893
+ return await ofetch(joinURL(credentials.endpoint, "/api/v2/external_services/payorders"), {
1894
+ method: "post",
1895
+ headers: { Authorization: token.data },
1896
+ body
1897
+ });
1898
+ };
1899
+ return {
1900
+ prepare: async (uid, transaction, options) => {
1901
+ const order = await createPayOrder(await getToken(), createBodyMultipago$1(uid, transaction, {
1902
+ code: serviceCode,
1903
+ urlReturn: `${urlReturn}?uid=${uid}&provider=multipago&${Object.entries(options?.params || {}).map(([key, value]) => `${key}=${value}`).join("&")}`
1904
+ }));
1905
+ return {
1906
+ id: `${order.data.pay_order.pay_order_number}`,
1907
+ iframe: order.data.url_to_pay,
1908
+ order: order.data.pay_order,
1909
+ sonda: dayjs().add(1, "day").valueOf()
1910
+ };
1911
+ },
1912
+ sendPay: async ({ uid }, { transaction }) => {
1913
+ const token = await getToken();
1914
+ const r = await ofetch(`${credentials.endpoint}/api/v2/getPayOrderByNumber`, {
1915
+ method: "post",
1916
+ body: { pay_order_number: transaction.ref },
1917
+ headers: { Authorization: token.data }
1918
+ });
1919
+ const details = normalizeStatus$2(r);
1920
+ return {
1921
+ id: transaction.ref,
1922
+ uid,
1923
+ status: details.status,
1924
+ body: r,
1925
+ message: details.description || details.messages?.es || "",
1926
+ sonda: details.status !== "success" ? dayjs().add(1, "day").valueOf() : false
1927
+ };
1928
+ },
1929
+ verify: async ({ transaction }) => {
1930
+ const token = await getToken();
1931
+ const r = await ofetch(`${credentials.endpoint}/api/v2/getPayOrderByNumber`, {
1932
+ method: "post",
1933
+ body: { pay_order_number: transaction.ref },
1934
+ headers: { Authorization: token.data }
1935
+ });
1936
+ const details = normalizeStatus$2(r);
1937
+ return {
1938
+ id: transaction.ref,
1939
+ status: details.status,
1940
+ responseRaw: r,
1941
+ details,
1942
+ customer: transaction.session.customer || {},
1943
+ payments: {
1944
+ current: {},
1945
+ history: []
1946
+ },
1947
+ uid: transaction.id,
1948
+ transaction: {
1949
+ provider: transaction.provider,
1950
+ status: transaction.status,
1951
+ responseTasks: transaction.responseTasks,
1952
+ payloadTasks: { success: transaction.tasks.success?.map((el) => {
1953
+ return el.payload;
1954
+ }) }
1955
+ }
1956
+ };
1957
+ },
1958
+ refund: async () => {
1959
+ return {};
1960
+ },
1961
+ methods: {}
1962
+ };
1963
+ };
1964
+ function createBodyMultipago(_uid, { session, checkout, id }, options) {
1965
+ const base0 = checkout.taxes.find((el) => el.code === "0")?.base || 0;
1966
+ let baseIVA = checkout.taxes.find((el) => el.code === "4")?.base || 0;
1967
+ const taxIVA = checkout.taxes.find((el) => el.code === "4")?.value || 0;
1968
+ console.log(checkout.taxes, session);
1969
+ if (!session.email || !session.identification || !checkout.total) throw new Error("Missing required session fields: email, identification, or checkout total");
1970
+ if (!base0 && !baseIVA && !taxIVA) baseIVA = +(checkout.total || 0);
1971
+ const document_type = session.identification.length === 10 ? "05" : "04";
1972
+ const description = `Compra en ecommerce ${options.storeName || ""}, transacción N°${id}`;
1973
+ return {
1974
+ integration: true,
1975
+ third: {
1976
+ name: [session.customer.givenName, session.customer.surname].join(" "),
1977
+ document_type,
1978
+ document: session.identification,
1979
+ phones: session.customer.billingInfo?.phone || session.customer.phone || "",
1980
+ email: session.email,
1981
+ type: "Individual",
1982
+ address: session.customer.billingInfo?.address || session.customer.address || "No disponible"
1983
+ },
1984
+ generate_invoice: 0,
1985
+ description,
1986
+ amount: +(checkout.total || 0),
1987
+ amount_with_tax: +base0,
1988
+ amount_without_tax: +baseIVA,
1989
+ tax_value: +taxIVA,
1990
+ settings: [],
1991
+ notify_url: options.urlReturn,
1992
+ has_cash: 0,
1993
+ has_cards: 1
1994
+ };
1995
+ }
1996
+ const codes$2 = {
1997
+ 0: {
1998
+ status: "created",
1999
+ messages: { es: "Orden de pago creada" }
2000
+ },
2001
+ 1: {
2002
+ status: "success",
2003
+ messages: { es: "Pago aprobada" }
2004
+ },
2005
+ 2: {
2006
+ status: "failure",
2007
+ messages: { es: "Transacción rechazada" }
2008
+ },
2009
+ 3: {
2010
+ status: "refund",
2011
+ messages: { es: "Transaccíon reversada" }
2012
+ }
2013
+ };
2014
+ function normalizeStatus$1({ data }) {
2015
+ const payment = data[0];
2016
+ const code = codes$2[payment.status];
2017
+ if (!code) return {
2018
+ status: "pending",
2019
+ code: payment.reference || "??",
2020
+ description: payment.description || "unknow code",
2021
+ messages: { es: "Codigo desconocido" }
2022
+ };
2023
+ return {
2024
+ ...code,
2025
+ description: payment.description,
2026
+ code: payment.reference
2027
+ };
2028
+ }
2029
+ const createPagomedios = ({ credentials, urlReturn, nameEcommerce }) => {
2030
+ const getToken = async () => {
2031
+ return `Bearer ${credentials.token}`;
2032
+ };
2033
+ const createPayOrder = async (token, body) => {
2034
+ console.log(joinURL(credentials.endpoint, "/pagomedios/v2/payment-request"), token, body);
2035
+ try {
2036
+ return await ofetch(joinURL(credentials.endpoint, "/pagomedios/v2/payment-requests"), {
2037
+ method: "post",
2038
+ headers: { Authorization: token },
2039
+ body
2040
+ });
2041
+ } catch (error) {
2042
+ console.error(error);
2043
+ console.error(error?.response?._data?.data);
2044
+ throw error;
2045
+ }
2046
+ };
2047
+ return {
2048
+ prepare: async (uid, transaction, options) => {
2049
+ const token = await getToken();
2050
+ let returnUrl = `${urlReturn}?uid=${uid}&provider=pagomedios&${Object.entries(options?.params || {}).map(([key, value]) => `${key}=${value}`).join("&")}`;
2051
+ returnUrl = returnUrl.replace("{{storeId}}", `${transaction.session.store.id}`);
2052
+ const order = await createPayOrder(token, createBodyMultipago(uid, transaction, {
2053
+ urlReturn: returnUrl,
2054
+ storeName: nameEcommerce
2055
+ }));
2056
+ return {
2057
+ id: `${order.data.token}`,
2058
+ iframe: order.data.url,
2059
+ sonda: dayjs().add(30, "minutes").valueOf()
2060
+ };
2061
+ },
2062
+ sendPay: async ({ uid }, { transaction }) => {
2063
+ const token = await getToken();
2064
+ const r = await ofetch(`${credentials.endpoint}/pagomedios/v2/payment-requests`, {
2065
+ method: "get",
2066
+ query: { uuid: transaction.ref },
2067
+ headers: { Authorization: token }
2068
+ });
2069
+ const details = normalizeStatus$1(r);
2070
+ return {
2071
+ id: transaction.ref,
2072
+ uid,
2073
+ status: details.status,
2074
+ body: r,
2075
+ message: details.description || details.messages?.es || "",
2076
+ sonda: details.status !== "success" ? dayjs().add(1, "day").valueOf() : false
2077
+ };
2078
+ },
2079
+ verify: async ({ transaction }) => {
2080
+ const token = await getToken();
2081
+ const r = await ofetch(`${credentials.endpoint}/pagomedios/v2/payment-requests`, {
2082
+ method: "get",
2083
+ query: { uuid: transaction.ref },
2084
+ headers: { Authorization: token }
2085
+ });
2086
+ const details = normalizeStatus$1(r);
2087
+ return {
2088
+ id: transaction.ref,
2089
+ status: details.status,
2090
+ responseRaw: r,
2091
+ details,
2092
+ customer: transaction.session.customer || {},
2093
+ payments: {
2094
+ current: {},
2095
+ history: []
2096
+ },
2097
+ uid: transaction.id,
2098
+ transaction: {
2099
+ provider: transaction.provider,
2100
+ status: transaction.status,
2101
+ responseTasks: transaction.responseTasks,
2102
+ payloadTasks: { success: transaction.tasks.success?.map((el) => {
2103
+ return el.payload;
2104
+ }) }
2105
+ }
2106
+ };
2107
+ },
2108
+ refund: async () => {
2109
+ return {};
2110
+ },
2111
+ methods: {}
2112
+ };
2113
+ };
2114
+ function createAuthToken(credentials) {
2115
+ return () => {
2116
+ const { code, key } = credentials;
2117
+ const hash = crypto.createHash("sha256");
2118
+ const timestamp = Math.floor(Date.now() / 1e3);
2119
+ const uniqueToken = `${key}${timestamp}`;
2120
+ hash.update(uniqueToken);
2121
+ const uniqueHash = hash.digest("hex");
2122
+ return Buffer.from(`${code};${timestamp};${uniqueHash}`).toString("base64");
2123
+ };
2124
+ }
2125
+ function createPmzPayload(uid, { checkout, session, ip }, options) {
2126
+ const base12 = checkout.taxes.find((el) => el.code === "2")?.base || 0;
2127
+ const tax12 = checkout.taxes.find((el) => el.code === "2")?.value || 0;
2128
+ return {
2129
+ order: {
2130
+ amount: +checkout.total,
2131
+ taxable_amount: +base12,
2132
+ dev_reference: uid,
2133
+ description: "Buy in ecommerce",
2134
+ vat: tax12,
2135
+ tax_percentage: base12 === 0 ? 0 : 12
2136
+ },
2137
+ user: {
2138
+ email: session.email || "",
2139
+ id: session.customer.id,
2140
+ ip_address: ip || "",
2141
+ phone: session.customer.phone
2142
+ },
2143
+ card: options.card
2144
+ };
2145
+ }
2146
+ function getAllCards(auth) {
2147
+ return async (uid) => {
2148
+ const res = auth();
2149
+ return await ofetch("v2/card/list", {
2150
+ baseURL: res.endpoint,
2151
+ query: { uid },
2152
+ headers: {
2153
+ "Content-Type": "application/json",
2154
+ "Auth-Token": res.authToken
2155
+ }
2156
+ }).catch((err) => {
2157
+ console.error(err?.response?.body);
2158
+ throw err;
2159
+ });
2160
+ };
2161
+ }
2162
+ function deleteCard(auth) {
2163
+ return async (body) => {
2164
+ const res = auth();
2165
+ return await ofetch("v2/card/delete/", {
2166
+ method: "POST",
2167
+ baseURL: res.endpoint,
2168
+ body,
2169
+ headers: { "Auth-Token": res.authToken }
2170
+ });
2171
+ };
2172
+ }
2173
+ function debitWithToken(auth) {
2174
+ return async (body) => {
2175
+ const res = auth();
2176
+ return await ofetch("v2/transaction/debit/", {
2177
+ method: "POST",
2178
+ baseURL: res.endpoint,
2179
+ body,
2180
+ headers: { "Auth-Token": res.authToken }
2181
+ });
2182
+ };
2183
+ }
2184
+ function verify(auth) {
2185
+ return async (body, moreInfo) => {
2186
+ const res = auth();
2187
+ return await ofetch("v2/transaction/verify/", {
2188
+ method: "POST",
2189
+ baseURL: res.endpoint,
2190
+ body: {
2191
+ ...body,
2192
+ more_info: moreInfo
2193
+ },
2194
+ headers: { "Auth-Token": res.authToken }
2195
+ });
2196
+ };
2197
+ }
2198
+ function refund(auth) {
2199
+ return async (body, moreInfo) => {
2200
+ const res = auth();
2201
+ return await ofetch("v2/transaction/refund/", {
2202
+ method: "POST",
2203
+ baseURL: res.endpoint,
2204
+ body: {
2205
+ ...body,
2206
+ more_info: moreInfo
2207
+ },
2208
+ headers: { "Auth-Token": res.authToken }
2209
+ });
2210
+ };
2211
+ }
2212
+ function transactionInfo(auth) {
2213
+ return async (id) => {
2214
+ const res = auth();
2215
+ return await ofetch(`v2/transaction/${id}`, {
2216
+ baseURL: res.endpoint,
2217
+ headers: {
2218
+ "Auth-Token": res.authToken,
2219
+ "Content-Type": "application/json"
2220
+ }
2221
+ });
2222
+ };
2223
+ }
2224
+ const createPaymentez = (options) => {
2225
+ const URL_PROD = "https://ccapi.paymentez.com";
2226
+ const URL_STG = "https://ccapi-stg.paymentez.com";
2227
+ const URL_DEV = "http://localhost:3658";
2228
+ const isProduction = options.mode === "production";
2229
+ const getAuth = () => {
2230
+ const endpoint = isProduction ? URL_PROD : options.mode === "staging" ? URL_STG : URL_DEV;
2231
+ return {
2232
+ authToken: createAuthToken(options.credentials)(),
2233
+ endpoint
2234
+ };
2235
+ };
2236
+ const methods = {
2237
+ debitWithToken: debitWithToken(getAuth),
2238
+ deleteCard: deleteCard(getAuth),
2239
+ getAllCards: getAllCards(getAuth),
2240
+ refund: refund(getAuth),
2241
+ transactionInfo: transactionInfo(getAuth),
2242
+ verify: verify(getAuth)
2243
+ };
2244
+ return {
2245
+ prepare: async () => {
2246
+ return { id: "" };
2247
+ },
2248
+ sendPay: async ({ uid, card }, { transaction }) => {
2249
+ const body = createPmzPayload(uid, transaction, { card: { token: card } });
2250
+ try {
2251
+ const response = await debitWithToken(getAuth)(body);
2252
+ return {
2253
+ id: response.transaction.id,
2254
+ uid,
2255
+ status: response.transaction.status,
2256
+ body: response.transaction,
2257
+ message: response.transaction.message
2258
+ };
2259
+ } catch (error) {
2260
+ console.error(error.response.body);
2261
+ throw error;
2262
+ }
2263
+ },
2264
+ verify: async ({ transaction }) => {
2265
+ const r = await methods.transactionInfo(transaction.ref);
2266
+ return {
2267
+ id: transaction.ref,
2268
+ status: r.transaction.status,
2269
+ customer: {},
2270
+ details: {
2271
+ messages: { es: r.transaction.message },
2272
+ status: r.transaction.status,
2273
+ code: `${r.transaction.status_detail}`
2274
+ },
2275
+ payments: {
2276
+ current: {},
2277
+ history: []
2278
+ },
2279
+ uid: transaction.id,
2280
+ responseRaw: r.transaction,
2281
+ transaction: {
2282
+ provider: transaction.provider,
2283
+ status: transaction.status
2284
+ }
2285
+ };
2286
+ },
2287
+ refund: async () => {
2288
+ return {};
2289
+ },
2290
+ methods
2291
+ };
2292
+ };
2293
+ function resolveBaseUrl(mode) {
2294
+ return mode === "production" ? "https://api-m.paypal.com" : "https://api-m.sandbox.paypal.com";
2295
+ }
2296
+ function createBasicAuthorization(credentials) {
2297
+ return Buffer.from(`${credentials.clientId}:${credentials.clientSecret}`).toString("base64");
2298
+ }
2299
+ function normalizeMoney(value) {
2300
+ const amount = Number(value);
2301
+ if (!Number.isFinite(amount)) return "0.00";
2302
+ return amount.toFixed(2);
2303
+ }
2304
+ function resolveCurrency(transaction, options) {
2305
+ return `${options?.currency || transaction?.checkout?.billingInfo?.currency || transaction?.checkout?.shippingInfo?.currency || "USD"}`.toUpperCase();
2306
+ }
2307
+ function buildOrderBody(uid, transaction, options = {}, currencyCode) {
2308
+ const amount = normalizeMoney(transaction?.checkout?.total || 0);
2309
+ const intent = options.intent || "CAPTURE";
2310
+ const application_context = {};
2311
+ const queryParams = `?uid=${uid}&intent=${intent}&provider=${options.provider || "paypal"}`;
2312
+ if (options.returnUrl) application_context.return_url = options.returnUrl + queryParams;
2313
+ if (options.cancelUrl) application_context.cancel_url = options.cancelUrl + queryParams;
2314
+ if (options.brandName) application_context.brand_name = options.brandName;
2315
+ if (options.locale) application_context.locale = options.locale;
2316
+ if (options.landingPage) application_context.landing_page = options.landingPage;
2317
+ if (options.userAction) application_context.user_action = options.userAction;
2318
+ const body = {
2319
+ intent,
2320
+ purchase_units: [{
2321
+ reference_id: String(uid),
2322
+ description: transaction?.description || void 0,
2323
+ amount: {
2324
+ currency_code: currencyCode,
2325
+ value: amount
2326
+ }
2327
+ }]
2328
+ };
2329
+ if (Object.keys(application_context).length) body.application_context = application_context;
2330
+ return body;
2331
+ }
2332
+ function extractApproveUrl(order) {
2333
+ return (order?.links || []).find((link) => link?.rel === "approve")?.href;
2334
+ }
2335
+ const orderCodes = {
2336
+ CREATED: {
2337
+ status: "created",
2338
+ messages: { es: "Orden creada" }
2339
+ },
2340
+ SAVED: {
2341
+ status: "created",
2342
+ messages: { es: "Orden guardada" }
2343
+ },
2344
+ APPROVED: {
2345
+ status: "pending",
2346
+ messages: { es: "Orden aprobada por el comprador" }
2347
+ },
2348
+ PAYER_ACTION_REQUIRED: {
2349
+ status: "pending",
2350
+ messages: { es: "Se requiere accion del comprador" }
2351
+ },
2352
+ COMPLETED: {
2353
+ status: "success",
2354
+ messages: { es: "Orden completada" }
2355
+ },
2356
+ VOIDED: {
2357
+ status: "failure",
2358
+ messages: { es: "Orden anulada" }
2359
+ },
2360
+ CANCELLED: {
2361
+ status: "failure",
2362
+ messages: { es: "Orden cancelada" }
2363
+ },
2364
+ PENDING: {
2365
+ status: "pending",
2366
+ messages: { es: "Orden pendiente" }
2367
+ }
2368
+ };
2369
+ const captureCodes = {
2370
+ COMPLETED: {
2371
+ status: "success",
2372
+ messages: { es: "Pago capturado" }
2373
+ },
2374
+ PARTIALLY_REFUNDED: {
2375
+ status: "refund",
2376
+ messages: { es: "Pago parcialmente reversado" }
2377
+ },
2378
+ REFUNDED: {
2379
+ status: "refund",
2380
+ messages: { es: "Pago reversado" }
2381
+ },
2382
+ PENDING: {
2383
+ status: "pending",
2384
+ messages: { es: "Pago pendiente" }
2385
+ },
2386
+ DECLINED: {
2387
+ status: "failure",
2388
+ messages: { es: "Pago rechazado" }
2389
+ },
2390
+ FAILED: {
2391
+ status: "failure",
2392
+ messages: { es: "Pago fallido" }
2393
+ }
2394
+ };
2395
+ const refundCodes = {
2396
+ COMPLETED: {
2397
+ status: "refund",
2398
+ messages: { es: "Reverso completado" }
2399
+ },
2400
+ PENDING: {
2401
+ status: "pending",
2402
+ messages: { es: "Reverso pendiente" }
2403
+ },
2404
+ FAILED: {
2405
+ status: "failure",
2406
+ messages: { es: "Reverso fallido" }
2407
+ },
2408
+ CANCELLED: {
2409
+ status: "failure",
2410
+ messages: { es: "Reverso cancelado" }
2411
+ }
2412
+ };
2413
+ function handlePayPalStatus(status, kind = "order") {
2414
+ const normalized = `${status || ""}`.toUpperCase();
2415
+ const details = (kind === "capture" ? captureCodes : kind === "refund" ? refundCodes : orderCodes)[normalized];
2416
+ if (!details) return {
2417
+ status: "pending",
2418
+ code: normalized || "UNKNOWN",
2419
+ description: "Unknown PayPal status",
2420
+ messages: { es: "Estado desconocido de PayPal" }
2421
+ };
2422
+ return {
2423
+ ...details,
2424
+ code: normalized,
2425
+ description: `PayPal status ${normalized}`
2426
+ };
2427
+ }
2428
+ const createPayPal = (options) => {
2429
+ const baseURL = resolveBaseUrl(options.mode);
2430
+ const api = ofetch.create({ baseURL });
2431
+ const getAccessToken = async () => {
2432
+ const response = await api("/v1/oauth2/token", {
2433
+ method: "POST",
2434
+ body: "grant_type=client_credentials",
2435
+ headers: {
2436
+ "Authorization": `Basic ${createBasicAuthorization(options.credentials)}`,
2437
+ "Content-Type": "application/x-www-form-urlencoded"
2438
+ }
2439
+ });
2440
+ if (!response?.access_token) throw new Error("PayPal access token not received");
2441
+ return response.access_token;
2442
+ };
2443
+ const request = async (url, opts = {}) => {
2444
+ const accessToken = await getAccessToken();
2445
+ return await api(url, {
2446
+ ...opts,
2447
+ headers: {
2448
+ ...opts.headers || {},
2449
+ Authorization: `Bearer ${accessToken}`
2450
+ }
2451
+ }).catch((err) => {
2452
+ console.error("error", err.response.data || err.response?._data);
2453
+ throw err;
2454
+ });
2455
+ };
2456
+ const methods = {
2457
+ getAccessToken,
2458
+ createOrder: (body) => request("/v2/checkout/orders", {
2459
+ method: "POST",
2460
+ body,
2461
+ headers: { Prefer: "return=representation" }
2462
+ }),
2463
+ captureOrder: (orderId, body = {}) => request(`/v2/checkout/orders/${orderId}/capture`, {
2464
+ method: "POST",
2465
+ body,
2466
+ headers: { Prefer: "return=representation" }
2467
+ }),
2468
+ getOrder: (orderId) => request(`/v2/checkout/orders/${orderId}`, { method: "GET" }),
2469
+ getCapture: (captureId) => request(`/v2/payments/captures/${captureId}`, { method: "GET" }),
2470
+ refundCapture: (captureId, body = {}) => request(`/v2/payments/captures/${captureId}/refund`, {
2471
+ method: "POST",
2472
+ body,
2473
+ headers: { Prefer: "return=representation" }
2474
+ })
2475
+ };
2476
+ return {
2477
+ methods,
2478
+ prepare: async (uid, transaction, prepareOptions = {}) => {
2479
+ const body = buildOrderBody(uid, transaction, prepareOptions, resolveCurrency(transaction, prepareOptions));
2480
+ const order = await methods.createOrder(body);
2481
+ const approveUrl = extractApproveUrl(order);
2482
+ return {
2483
+ id: order.id,
2484
+ iframe: {
2485
+ approveUrl,
2486
+ orderId: order.id,
2487
+ status: order.status,
2488
+ links: order.links || []
2489
+ },
2490
+ extras: {
2491
+ orderId: order.id,
2492
+ approveUrl
2493
+ }
2494
+ };
2495
+ },
2496
+ sendPay: async (params, { transaction }) => {
2497
+ console.log(params);
2498
+ const orderId = `${params?.orderID || params?.orderId || params?.id || transaction.ref || ""}`;
2499
+ if (!orderId) throw new Error("PayPal order id is required to capture payment");
2500
+ const captureResult = await methods.captureOrder(orderId, params?.captureBody || {});
2501
+ console.log("captureResult", captureResult, orderId);
2502
+ const captures = captureResult?.purchase_units?.flatMap((unit) => unit?.payments?.captures || []) || [];
2503
+ const currentCapture = captures[captures.length - 1] || captureResult;
2504
+ const details = handlePayPalStatus(currentCapture?.status || captureResult?.status, "capture");
2505
+ return {
2506
+ id: currentCapture?.id || orderId,
2507
+ uid: params.uid,
2508
+ status: details.status,
2509
+ body: captureResult,
2510
+ message: details.messages.es
2511
+ };
2512
+ },
2513
+ verify: async ({ uid, transaction }) => {
2514
+ let responseRaw;
2515
+ let kind = "capture";
2516
+ try {
2517
+ responseRaw = await methods.getCapture(transaction.ref);
2518
+ } catch {
2519
+ kind = "order";
2520
+ responseRaw = await methods.getOrder(transaction.ref);
2521
+ }
2522
+ const captures = kind === "order" ? responseRaw?.purchase_units?.flatMap((unit) => unit?.payments?.captures || []) || [] : [responseRaw];
2523
+ const current = captures[captures.length - 1] || responseRaw;
2524
+ const statusDetails = handlePayPalStatus(current?.status || responseRaw?.status, captures.length ? "capture" : "order");
2525
+ return {
2526
+ id: current?.id || responseRaw?.id || transaction.ref,
2527
+ status: statusDetails.status,
2528
+ details: statusDetails,
2529
+ customer: responseRaw?.payer || transaction?.session?.customer || {},
2530
+ payments: {
2531
+ current,
2532
+ history: captures.length ? captures : [responseRaw],
2533
+ refunds: current?.status === "REFUNDED" || current?.status === "PARTIALLY_REFUNDED" ? [current] : []
2534
+ },
2535
+ responseRaw,
2536
+ uid,
2537
+ transaction: {
2538
+ provider: transaction.provider,
2539
+ status: transaction.status
2540
+ }
2541
+ };
2542
+ },
2543
+ refund: async (ref, amount, options = {}) => {
2544
+ const payload = {};
2545
+ const numericAmount = Number(options?.amount || amount);
2546
+ if (numericAmount > 0) payload.amount = {
2547
+ value: normalizeMoney(numericAmount),
2548
+ currency_code: `${options?.currency || "USD"}`.toUpperCase()
2549
+ };
2550
+ if (options?.noteToPayer) payload.note_to_payer = options.noteToPayer;
2551
+ const refundResult = await methods.refundCapture(ref, payload);
2552
+ const details = handlePayPalStatus(refundResult?.status, "refund");
2553
+ return {
2554
+ ...refundResult,
2555
+ status: details.status,
2556
+ details
2557
+ };
2558
+ }
2559
+ };
2560
+ };
2561
+ const codes$1 = {
2562
+ APPROVED: {
2563
+ status: "success",
2564
+ messages: { es: "Transacción aprobada" }
2565
+ },
2566
+ APPROVED_PARTIAL: {
2567
+ status: "success",
2568
+ messages: { es: "Transacción aprobada parcialmente" }
2569
+ },
2570
+ FAILED: {
2571
+ status: "failure",
2572
+ messages: { es: "Transacción rechazada" }
2573
+ },
2574
+ PARTIAL_EXPIRED: {
2575
+ status: "failure",
2576
+ messages: { es: "Sesión de transacción expirada" }
2577
+ },
2578
+ PENDING: {
2579
+ status: "pending",
2580
+ messages: { es: "Transacción pendiente" }
2581
+ },
2582
+ PENDING_VALIDATION: {
2583
+ status: "pending",
2584
+ messages: { es: "Transacción pendiente de validación" }
2585
+ },
2586
+ REFUNDED: {
2587
+ status: "refund",
2588
+ messages: { es: "Transacción reversada" }
2589
+ },
2590
+ REJECTED: {
2591
+ status: "failure",
2592
+ messages: { es: "Transacción rechazada" }
2593
+ },
2594
+ OK: {
2595
+ status: "pending",
2596
+ messages: { es: "Transacción pendiente" }
2597
+ }
2598
+ };
2599
+ function handleControlCodes(body, lastPayment) {
2600
+ const current = lastPayment;
2601
+ const code = codes$1[current?.status || body.status];
2602
+ if (!code) return {
2603
+ status: "pending",
2604
+ code: current?.reason || body.reason,
2605
+ description: "unknow code",
2606
+ messages: { es: "Codigo desconocido" }
2607
+ };
2608
+ return {
2609
+ ...code,
2610
+ code: current?.reason || body.reason,
2611
+ description: current?.message || body.message
2612
+ };
2613
+ }
2614
+ function verifySignatureV1(secretKey) {
2615
+ return (payload) => {
2616
+ const { signature, internalReference, status } = payload;
2617
+ const base = `${internalReference || payload.requestId}${status.status}${status.date}${secretKey}`;
2618
+ return signature === crypto.createHash("sha1").update(base).digest("hex");
2619
+ };
2620
+ }
2621
+ function createSession(secretKey, login, expiration) {
2622
+ return () => {
2623
+ const seed = dayjs().format();
2624
+ const nonce = crypto.randomBytes(16).toString("hex");
2625
+ const nonce64 = Buffer.from(nonce).toString("base64");
2626
+ const tranKey = `${nonce}${seed}${secretKey}`;
2627
+ return {
2628
+ auth: {
2629
+ login,
2630
+ seed,
2631
+ nonce: nonce64,
2632
+ tranKey: crypto.createHash("sha1").update(tranKey).digest("base64")
2633
+ },
2634
+ expiration: dayjs().add(expiration, "minutes").format()
2635
+ };
2636
+ };
2637
+ }
2638
+ const createPlaceToPay = (options) => {
2639
+ const { credentials, endpoint, urlReturn } = options;
2640
+ const getSession = createSession(credentials.secretKey, credentials.login, 15);
2641
+ return {
2642
+ prepare: async (uid, transaction, options) => {
2643
+ const baseSession = getSession();
2644
+ const { checkout, session, ip, extras } = transaction;
2645
+ const buyer = {
2646
+ documentType: session.customer.documentType || "CI",
2647
+ name: session.customer.givenName,
2648
+ surname: session.customer.surname,
2649
+ document: session.identification,
2650
+ email: session.email,
2651
+ mobile: session.customer.phone
2652
+ };
2653
+ const returnUrl = `${urlReturn}?uid=${uid}&provider=ptp&${Object.entries(options?.params || {}).map(([key, value]) => `${key}=${value}`).join("&")}`;
2654
+ const type = options.params?.type === "subscription" ? "subscription" : "payment";
2655
+ const body = {
2656
+ ...baseSession,
2657
+ buyer,
2658
+ returnUrl,
2659
+ ipAddress: ip,
2660
+ userAgent: "eMonkey Sandbox"
2661
+ };
2662
+ if (type === "payment") {
2663
+ const baseIVA = checkout.taxes.find((el) => el.code === "4")?.base || 0;
2664
+ const taxIVA = checkout.taxes.find((el) => el.code === "4")?.value || 0;
2665
+ body.payment = {
2666
+ reference: uid,
2667
+ description: transaction.description || "Compra comercio electronico",
2668
+ amount: {
2669
+ currency: "USD",
2670
+ total: checkout.total,
2671
+ taxes: [{
2672
+ kind: "valueAddedTax",
2673
+ amount: taxIVA,
2674
+ base: baseIVA
2675
+ }]
2676
+ }
2677
+ };
2678
+ }
2679
+ if (type === "subscription") {
2680
+ body.subscription = {
2681
+ reference: uid,
2682
+ description: transaction.description || "Suscripción comercio electronico"
2683
+ };
2684
+ body.skipResult = true;
2685
+ }
2686
+ let theEndpoint = `${endpoint}/api/session`;
2687
+ if (extras?.instrument) {
2688
+ body.instrument = extras.instrument;
2689
+ body.payment.reference = extras?.reference || uid;
2690
+ body.payer = body.buyer;
2691
+ theEndpoint = `${endpoint}/api/collect`;
2692
+ }
2693
+ const r = await ofetch(theEndpoint, {
2694
+ method: "POST",
2695
+ body
2696
+ }).catch((err) => {
2697
+ console.error(err);
2698
+ throw err;
2699
+ });
2700
+ let responsePay;
2701
+ if (extras?.instrument) {
2702
+ const details = handleControlCodes(r.status, void 0);
2703
+ responsePay = {
2704
+ id: transaction.ref,
2705
+ uid,
2706
+ status: details.status,
2707
+ body: r,
2708
+ message: details.messages.es,
2709
+ sonda: true
2710
+ };
2711
+ }
2712
+ return {
2713
+ id: r.requestId,
2714
+ ...r,
2715
+ responsePay,
2716
+ sonda: true
2717
+ };
2718
+ },
2719
+ sendPay: async ({ uid }, { transaction }) => {
2720
+ const { auth } = getSession();
2721
+ const body = { auth };
2722
+ const r = await ofetch(`${endpoint}/api/session/${transaction.ref}`, {
2723
+ method: "POST",
2724
+ body
2725
+ });
2726
+ const details = handleControlCodes(r.status, void 0);
2727
+ return {
2728
+ id: transaction.ref,
2729
+ uid,
2730
+ status: details.status,
2731
+ body: r,
2732
+ message: details.messages.es,
2733
+ sonda: true
2734
+ };
2735
+ },
2736
+ verify: async ({ transaction, override }) => {
2737
+ const { auth } = getSession();
2738
+ const body = { auth };
2739
+ const r = await ofetch(`${endpoint}/api/session/${transaction.ref}`, {
2740
+ method: "POST",
2741
+ body
2742
+ });
2743
+ const expiration = r.request.expiration;
2744
+ if (dayjs(expiration).diff(dayjs().format()) < 0) override = true;
2745
+ const history = r.payment || [];
2746
+ const current = history?.[0];
2747
+ const details = handleControlCodes(r.status, override ? current?.status : void 0);
2748
+ return {
2749
+ id: transaction.ref,
2750
+ status: details.status,
2751
+ details,
2752
+ customer: r.request?.buyer,
2753
+ payments: {
2754
+ current,
2755
+ history
2756
+ },
2757
+ responseRaw: r,
2758
+ uid: transaction.id,
2759
+ transaction: {
2760
+ provider: transaction.provider,
2761
+ status: transaction.status
2762
+ }
2763
+ };
2764
+ },
2765
+ refund: async (ref, amount, opts) => {
2766
+ const _amount = opts?.amount || 0;
2767
+ const { auth } = getSession();
2768
+ const body = { auth };
2769
+ const { internalReference } = ((await ofetch(`${endpoint}/api/session/${ref}`, {
2770
+ method: "POST",
2771
+ body
2772
+ })).payment || [])?.[0];
2773
+ const totalAmount = _amount && _amount < amount ? _amount : amount;
2774
+ console.log("Refunding", {
2775
+ ref,
2776
+ amount: totalAmount,
2777
+ internalReference
2778
+ });
2779
+ return { ...await ofetch(`${endpoint}/api/reverse`, {
2780
+ method: "POST",
2781
+ body: {
2782
+ auth,
2783
+ internalReference,
2784
+ amount: totalAmount
2785
+ }
2786
+ }) };
2787
+ },
2788
+ webhook: async (body) => {
2789
+ if (!verifySignatureV1(credentials.secretKey)(body)) return false;
2790
+ return { status: handleControlCodes(body.status).status };
2791
+ },
2792
+ methods: {
2793
+ subscription: () => {},
2794
+ deleteToken: (body) => {
2795
+ const { auth } = getSession();
2796
+ return ofetch(`${endpoint}/api/instrument/invalidate`, {
2797
+ method: "POST",
2798
+ body: {
2799
+ auth,
2800
+ ...body
2801
+ }
2802
+ });
2803
+ }
2804
+ }
2805
+ };
2806
+ };
2807
+ const createTransference = () => {
2808
+ return {
2809
+ methods: {},
2810
+ prepare: async (uid, transaction) => {
2811
+ const r = { id: Date.now() };
2812
+ return {
2813
+ id: transaction.id,
2814
+ ...r
2815
+ };
2816
+ },
2817
+ sendPay: async ({ uid }, { transaction }) => {
2818
+ return {
2819
+ id: transaction.ref,
2820
+ uid,
2821
+ status: "success",
2822
+ body: {},
2823
+ message: ""
2824
+ };
2825
+ },
2826
+ verify: async ({ uid, transaction }) => {
2827
+ return {
2828
+ id: transaction.id,
2829
+ status: transaction.status,
2830
+ details: {
2831
+ messages: { es: "Orden creada" },
2832
+ status: "success"
2833
+ },
2834
+ payments: {
2835
+ current: {},
2836
+ history: []
2837
+ },
2838
+ responseRaw: {},
2839
+ uid,
2840
+ customer: transaction.session.customer,
2841
+ transaction: {
2842
+ provider: transaction.provider,
2843
+ status: transaction.status
2844
+ }
2845
+ };
2846
+ },
2847
+ refund: async () => {
2848
+ return {};
2849
+ }
2850
+ };
2851
+ };
2852
+ const codes = {
2853
+ Pending: {
2854
+ status: "pending",
2855
+ messages: { es: "La orden se encuentra a la espera del pago" }
2856
+ },
2857
+ Paid: {
2858
+ status: "success",
2859
+ messages: { es: " Orden confirmada con pago recibido" }
2860
+ },
2861
+ Completed: {
2862
+ status: "success",
2863
+ messages: { es: " Orden confirmada con pago completado" }
2864
+ },
2865
+ Cancelling: {
2866
+ status: "failure",
2867
+ messages: { es: "Pago en estado cancelado por procesos internos o a solicitud" }
2868
+ },
2869
+ Refund: {
2870
+ status: "refund",
2871
+ messages: { es: "Pago anulado" }
2872
+ }
2873
+ };
2874
+ function normalizeStatus(data) {
2875
+ const code = codes[data.order_payments[0].payment_status];
2876
+ if (!code) return {
2877
+ status: "pending",
2878
+ code: "??",
2879
+ description: "unknow code",
2880
+ messages: { es: "Codigo desconocido" }
2881
+ };
2882
+ return {
2883
+ ...code,
2884
+ description: code.messages.es,
2885
+ code: code.code || "??"
2886
+ };
2887
+ }
2888
+ const createWabi = (opts) => {
2889
+ const { credentials, endpoint } = opts;
2890
+ const api = ofetch.create({ baseURL: endpoint });
2891
+ const getAuth = async () => {
2892
+ return await api("/generateToken", {
2893
+ method: "POST",
2894
+ body: credentials
2895
+ });
2896
+ };
2897
+ return {
2898
+ methods: {},
2899
+ prepare: async (uid, { checkout, session }) => {
2900
+ const { token } = await getAuth();
2901
+ if (!token) throw new Error("No se pudo obtener el token de autenticación");
2902
+ const r = await api("/create", {
2903
+ method: "POST",
2904
+ body: {
2905
+ agency_id: opts.agency,
2906
+ plattform_id: opts.platform,
2907
+ latitude: "",
2908
+ longitude: "",
2909
+ ip_mac: "",
2910
+ type_transaction: "1",
2911
+ user_id: opts.userId || "",
2912
+ amount: {
2913
+ currency: "Bs",
2914
+ value: Number(checkout.total)
2915
+ },
2916
+ payment_method: { type: "QR" },
2917
+ order_payments: [{
2918
+ description: checkout.items[0].title || "DEPOSITO BOLIVIANOS",
2919
+ service_code: opts.serviceCode,
2920
+ debtor_first_name: session.customer.givenName,
2921
+ debtor_last_name: session.customer.surname,
2922
+ debtor_phone: session.customer.phone || "",
2923
+ debtor_ci_code: session.identification,
2924
+ invoice_name: "",
2925
+ invoice_type: "",
2926
+ invoice_document_number: "",
2927
+ additional_data: opts.callbackUrl ? `{"callbackUrl":"${opts.callbackUrl}"}` : void 0,
2928
+ amount: {
2929
+ currency: "Bs",
2930
+ value: Number(checkout.total)
2931
+ },
2932
+ items: checkout.items.map((item) => {
2933
+ return {
2934
+ description: item.title,
2935
+ unit_price: item.item.unitAmount,
2936
+ cuf: "",
2937
+ invoice_number: "",
2938
+ type: "1",
2939
+ additional_data: {},
2940
+ additional_billable: {}
2941
+ };
2942
+ })
2943
+ }],
2944
+ customer_payer: {
2945
+ first_name: session.customer.givenName,
2946
+ last_name: session.customer.surname,
2947
+ email: session.email,
2948
+ phone: session.customer.phone || "",
2949
+ document: {
2950
+ document_type: "",
2951
+ business_name: "",
2952
+ document_number: ""
2953
+ }
2954
+ }
2955
+ },
2956
+ headers: { Authorization: `Bearer ${token}` }
2957
+ }).catch((e) => {
2958
+ console.error("Error al crear el QR:", e);
2959
+ throw e;
2960
+ });
2961
+ if (!r) throw new Error("No se recibió respuesta del proveedor Wabi");
2962
+ return {
2963
+ ...r,
2964
+ extras: r.order_payments?.[0] || {},
2965
+ sonda: dayjs().add(1, "day").valueOf()
2966
+ };
2967
+ },
2968
+ sendPay: async ({ uid }, { transaction }) => {
2969
+ const { token } = await getAuth();
2970
+ const r = await api(`/status/${transaction.ref}`, {
2971
+ method: "GET",
2972
+ headers: { Authorization: `Bearer ${token}` }
2973
+ });
2974
+ const details = normalizeStatus(r);
2975
+ return {
2976
+ id: transaction.ref,
2977
+ uid,
2978
+ status: details.status,
2979
+ body: r,
2980
+ message: details.description || details.messages?.es || "",
2981
+ sonda: details.status !== "success" ? dayjs().add(1, "day").valueOf() : false
2982
+ };
2983
+ },
2984
+ verify: async ({ transaction }) => {
2985
+ const { token } = await getAuth();
2986
+ const r = await api(`/status/${transaction.ref}`, {
2987
+ method: "GET",
2988
+ headers: { Authorization: `Bearer ${token}` }
2989
+ });
2990
+ const details = normalizeStatus(r);
2991
+ return {
2992
+ id: transaction.ref,
2993
+ status: details.status,
2994
+ responseRaw: r,
2995
+ details,
2996
+ customer: transaction.session.customer || {},
2997
+ payments: {
2998
+ current: {},
2999
+ history: []
3000
+ },
3001
+ uid: transaction.id,
3002
+ transaction: {
3003
+ provider: transaction.provider,
3004
+ status: transaction.status,
3005
+ responseTasks: transaction.responseTasks,
3006
+ payloadTasks: { success: transaction.tasks.success?.map((el) => {
3007
+ return el.payload;
3008
+ }) }
3009
+ }
3010
+ };
3011
+ },
3012
+ refund: async () => {
3013
+ return {};
3014
+ }
3015
+ };
3016
+ };
3017
+ function createGraphql(db) {
3018
+ return {
3019
+ stores: { findByPk: async (id) => {
3020
+ return await db.query.stores.findFirst({ where: { id } });
3021
+ } },
3022
+ checkout: {
3023
+ create: async (data) => {
3024
+ return (await db.insert(checkouts).values(data).returning())[0];
3025
+ },
3026
+ findByPk: async (id) => {
3027
+ return await db.query.checkouts.findFirst({ where: { id } });
3028
+ },
3029
+ updateByPk: async (id, data) => {
3030
+ return (await db.update(checkouts).set(data).where(eq(checkouts.id, id)).returning())[0];
3031
+ }
3032
+ },
3033
+ session: { create: async (data) => {
3034
+ return (await db.insert(sessions).values(data).returning())[0];
3035
+ } },
3036
+ transaction: {
3037
+ create: async (data) => {
3038
+ const items = await db.insert(transactions).values(data).returning({ id: transactions.id });
3039
+ return await db.query.transactions.findFirst({
3040
+ where: { id: items[0].id },
3041
+ with: {
3042
+ checkout: true,
3043
+ session: { with: { store: { columns: {
3044
+ id: true,
3045
+ name: true,
3046
+ endpoint: true
3047
+ } } } }
3048
+ }
3049
+ });
3050
+ },
3051
+ findByPk: async (id) => {
3052
+ return await db.query.transactions.findFirst({
3053
+ where: { id },
3054
+ with: {
3055
+ checkout: true,
3056
+ session: { with: { store: { columns: {
3057
+ id: true,
3058
+ name: true,
3059
+ endpoint: true
3060
+ } } } }
3061
+ }
3062
+ });
3063
+ },
3064
+ updateByPk: async (id, data) => {
3065
+ return (await db.update(transactions).set(data).where(eq(transactions.id, id)).returning())[0];
3066
+ }
3067
+ },
3068
+ refunds: { create: async (data) => {
3069
+ return (await db.insert(refunds).values(data).returning())[0];
3070
+ } }
3071
+ };
3072
+ }
3073
+ export { CustomError, createBancoEconomico, createBancoGanadero, createCybersource, createDatafast, createGraphql, createMultipagos, createPagomedios, createPayPal, createPayment, createPaymentez, createPlaceToPay, createTransference, createWabi, useTasks };