@fire-spark/payments-deuna-widget 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -99,9 +99,10 @@ type DeunaWidgetOutcome =
99
99
  by: "user" | "system";
100
100
  };
101
101
  /**
102
- * Implemented once per template with the DEUNA SDK
103
- * (`@deuna/react-native-sdk` or the Web SDK). It opens the widget with the
104
- * given order token and resolves with the first final callback.
102
+ * Implemented once per template with the DEUNA Web SDK (in the page, or in
103
+ * a `react-native-webview` on React Native) or `@deuna/react-native-sdk`.
104
+ * It opens the widget with the given order token and resolves with the
105
+ * first final callback.
105
106
  */
106
107
  type DeunaWidgetBridge = {
107
108
  open(input: DeunaWidgetOpenInput): Promise<DeunaWidgetOutcome>;
@@ -126,6 +127,8 @@ type DeunaOrderState = {
126
127
  order_token: string;
127
128
  status: DeunaPaymentStatus | (string & {});
128
129
  transaction_id?: string | null;
130
+ /** Processor DEUNA charged with (`payment.data.processor`), if reported. */
131
+ processor?: string | null;
129
132
  /** DEUNA `error.code` (core, `DP-`, `EMA-`…) when the payment failed. */
130
133
  error?: {
131
134
  code: string | null;
@@ -160,10 +163,22 @@ type DeunaWidgetOptions = {
160
163
  };
161
164
  /** Processors this method can charge with. */
162
165
  declare const deunaProcessorsFor: (method: DeunaWidgetMethod) => ("card" | "daviplata" | "deuna_wallet" | "mercadopago" | "nequi" | "pse")[];
163
- /** `payments.config.processor`; optional when the method has only one. */
166
+ /**
167
+ * Processors of one payment (same DEUNA credentials): `config.processors`
168
+ * or the legacy `config.processor`; optional when the method has only one.
169
+ * Kept in `DEUNA_PROCESSORS` order.
170
+ */
171
+ declare const resolveDeunaProcessors: (method: DeunaWidgetMethod, config: Record<string, unknown>) => DeunaProcessor[];
172
+ /** @deprecated Use `resolveDeunaProcessors`: first configured processor. */
164
173
  declare const resolveDeunaProcessor: (method: DeunaWidgetMethod, config: Record<string, unknown>) => DeunaProcessor;
165
- /** `paymentMethods` of `initPaymentWidget` for a processor. */
166
- declare const deunaWidgetPaymentMethods: (processor: DeunaProcessor) => DeunaWidgetPaymentMethod[];
174
+ /**
175
+ * `paymentMethods` of `initPaymentWidget`: one entry per widget method, with
176
+ * the DEUNA processors of every configured processor that uses it. One entry
177
+ * opens its form directly; several let the customer choose.
178
+ */
179
+ declare const deunaWidgetPaymentMethods: (processors: DeunaProcessor | readonly DeunaProcessor[]) => DeunaWidgetPaymentMethod[];
180
+ /** Our processor key for the processor DEUNA reports on the order. */
181
+ declare const deunaProcessorFromState: (candidates: readonly DeunaProcessor[], reported: string | null | undefined) => DeunaProcessor | null;
167
182
  /**
168
183
  * DEUNA Payment Widget for every method (card, Nequi, Mercado Pago, Deuna
169
184
  * App Wallet, PSE). Spark tokenizes the DEUNA order with the private key
@@ -300,4 +315,4 @@ declare const deunaStateError: (input: {
300
315
  attempt: number;
301
316
  }) => StandardPaymentError;
302
317
  //#endregion
303
- export { DEUNA_PROCESSORS, DEUNA_PROCESSOR_KEYS, DEUNA_PROVIDER, DEUNA_WIDGET_POLICY, type DeunaCallbackUrls, type DeunaOrderState, type DeunaPaymentStatus, DeunaProcessor, DeunaStatusMapping, type DeunaTokenizeInput, type DeunaTokenizeOutput, type DeunaWidgetApi, type DeunaWidgetBridge, type DeunaWidgetLanguage, type DeunaWidgetMethod, type DeunaWidgetOpenInput, DeunaWidgetOptions, type DeunaWidgetOutcome, type DeunaWidgetPaymentMethod, deunaDeclinedCode, deunaErrors, deunaProcessorsFor, deunaStateError, deunaWidgetPaymentMethods, deunaWidgetPayments, mapDeunaStatus, orderTokenKey, resolveDeunaProcessor };
318
+ export { DEUNA_PROCESSORS, DEUNA_PROCESSOR_KEYS, DEUNA_PROVIDER, DEUNA_WIDGET_POLICY, type DeunaCallbackUrls, type DeunaOrderState, type DeunaPaymentStatus, DeunaProcessor, DeunaStatusMapping, type DeunaTokenizeInput, type DeunaTokenizeOutput, type DeunaWidgetApi, type DeunaWidgetBridge, type DeunaWidgetLanguage, type DeunaWidgetMethod, type DeunaWidgetOpenInput, DeunaWidgetOptions, type DeunaWidgetOutcome, type DeunaWidgetPaymentMethod, deunaDeclinedCode, deunaErrors, deunaProcessorFromState, deunaProcessorsFor, deunaStateError, deunaWidgetPaymentMethods, deunaWidgetPayments, mapDeunaStatus, orderTokenKey, resolveDeunaProcessor, resolveDeunaProcessors };
package/dist/index.js CHANGED
@@ -246,26 +246,60 @@ const deunaProcessorsFor = (method) => {
246
246
  return DEUNA_PROCESSORS[key].method === method;
247
247
  });
248
248
  };
249
- /** `payments.config.processor`; optional when the method has only one. */
250
- const resolveDeunaProcessor = (method, config) => {
249
+ /** `config.processors`, else the legacy single `config.processor`. */
250
+ const configuredValues = (config) => {
251
+ if (Array.isArray(config.processors)) return config.processors;
252
+ return config.processor == null ? [] : [config.processor];
253
+ };
254
+ /**
255
+ * Processors of one payment (same DEUNA credentials): `config.processors`
256
+ * or the legacy `config.processor`; optional when the method has only one.
257
+ * Kept in `DEUNA_PROCESSORS` order.
258
+ */
259
+ const resolveDeunaProcessors = (method, config) => {
251
260
  const allowed = deunaProcessorsFor(method);
252
- const value = config.processor;
253
- const known = allowed.find((key) => key === value);
254
- if (known) return known;
255
- const only = allowed.length === 1 ? allowed[0] : void 0;
256
- if (value == null && only) return only;
257
- const message = `Unsupported DEUNA processor for ${method}: ${String(value)}`;
258
- throw fail("INVALID_REQUEST", message);
261
+ const values = configuredValues(config);
262
+ const unknown = values.find((value) => !allowed.some((key) => key === value));
263
+ if (unknown !== void 0) {
264
+ const message = `Unsupported DEUNA processor for ${method}: ${String(unknown)}`;
265
+ throw fail("INVALID_REQUEST", message);
266
+ }
267
+ const picked = allowed.filter((key) => values.includes(key));
268
+ if (picked.length) return picked;
269
+ if (allowed.length === 1) return allowed;
270
+ throw fail("INVALID_REQUEST", `Missing DEUNA processor for ${method}`);
271
+ };
272
+ /** @deprecated Use `resolveDeunaProcessors`: first configured processor. */
273
+ const resolveDeunaProcessor = (method, config) => {
274
+ return resolveDeunaProcessors(method, config)[0];
275
+ };
276
+ /**
277
+ * `paymentMethods` of `initPaymentWidget`: one entry per widget method, with
278
+ * the DEUNA processors of every configured processor that uses it. One entry
279
+ * opens its form directly; several let the customer choose.
280
+ */
281
+ const deunaWidgetPaymentMethods = (processors) => {
282
+ const list = typeof processors === "string" ? [processors] : processors;
283
+ const entries = [];
284
+ for (const processor of list) {
285
+ const entry = DEUNA_PROCESSORS[processor];
286
+ const found = entries.find((e) => e.paymentMethod === entry.paymentMethod);
287
+ const target = found ?? { paymentMethod: entry.paymentMethod };
288
+ if (!found) entries.push(target);
289
+ if (!entry.processors.length) continue;
290
+ target.processors = [...target.processors ?? [], ...entry.processors];
291
+ }
292
+ return entries;
259
293
  };
260
- /** `paymentMethods` of `initPaymentWidget` for a processor. */
261
- const deunaWidgetPaymentMethods = (processor) => {
262
- const entry = DEUNA_PROCESSORS[processor];
263
- const base = { paymentMethod: entry.paymentMethod };
264
- if (!entry.processors.length) return [base];
265
- return [{
266
- ...base,
267
- processors: [...entry.processors]
268
- }];
294
+ /** Our processor key for the processor DEUNA reports on the order. */
295
+ const deunaProcessorFromState = (candidates, reported) => {
296
+ if (candidates.length === 1) return candidates[0] ?? null;
297
+ if (!reported) return null;
298
+ const value = reported.toLowerCase();
299
+ return candidates.find((key) => {
300
+ const names = DEUNA_PROCESSORS[key].processors;
301
+ return key === value || names.includes(value);
302
+ }) ?? null;
269
303
  };
270
304
  const publicKeyOf = (config) => {
271
305
  const key = config.public_key;
@@ -273,7 +307,7 @@ const publicKeyOf = (config) => {
273
307
  throw fail("INVALID_CREDENTIALS", "Missing DEUNA public_key");
274
308
  };
275
309
  /** Card brand and last 4 are not exposed by the widget: no card details. */
276
- const detailsOf = (charge, reference) => {
310
+ const detailsOf = (charge, processor, reference) => {
277
311
  if (charge.method === "CARD") return null;
278
312
  if (charge.method === "BANK_TRANSFER") return {
279
313
  method: "BANK_TRANSFER",
@@ -281,7 +315,7 @@ const detailsOf = (charge, reference) => {
281
315
  };
282
316
  return {
283
317
  method: "WALLET",
284
- wallet: charge.processor,
318
+ wallet: processor ?? "deuna",
285
319
  reference
286
320
  };
287
321
  };
@@ -290,9 +324,12 @@ const toResult = (ctx, charge, state, base) => {
290
324
  const mapped = mapDeunaStatus(state.status, charge.method);
291
325
  const transactionId = state.transaction_id ?? null;
292
326
  const previous = record(base?.metadata.provider);
327
+ const known = deunaProcessorFromState(charge.processors, state.processor);
328
+ const kept = typeof previous.processor === "string" ? previous.processor : null;
329
+ const processor = known ?? kept;
293
330
  const p1 = {
294
331
  order_token: state.order_token,
295
- processor: charge.processor
332
+ processor
296
333
  };
297
334
  const p2 = {
298
335
  status: state.status,
@@ -314,7 +351,7 @@ const toResult = (ctx, charge, state, base) => {
314
351
  provider
315
352
  };
316
353
  const amount = base?.amount ?? ctx.amount.value;
317
- const details = detailsOf(charge, reference);
354
+ const details = detailsOf(charge, processor, reference);
318
355
  if (mapped.status !== "FAILED") return {
319
356
  status: mapped.status,
320
357
  amount,
@@ -369,7 +406,7 @@ const deunaWidgetPayments = (options) => {
369
406
  const chargeOf = (ctx) => {
370
407
  return {
371
408
  method,
372
- processor: resolveDeunaProcessor(method, ctx.config)
409
+ processors: resolveDeunaProcessors(method, ctx.config)
373
410
  };
374
411
  };
375
412
  const orderState = (ctx, orderToken) => {
@@ -426,7 +463,7 @@ const deunaWidgetPayments = (options) => {
426
463
  ...t3
427
464
  })).order_token;
428
465
  await ctx.storage.set(orderTokenKey(ctx.attemptReference), orderToken);
429
- const paymentMethods = deunaWidgetPaymentMethods(charge.processor);
466
+ const paymentMethods = deunaWidgetPaymentMethods(charge.processors);
430
467
  const o1 = {
431
468
  publicApiKey,
432
469
  environment: ctx.environment,
@@ -456,6 +493,16 @@ const deunaWidgetPayments = (options) => {
456
493
  status: "CANCELLED"
457
494
  };
458
495
  };
496
+ /**
497
+ * A paid DEUNA charge is reversed by Spark with the private key when the
498
+ * order is cancelled or refunded (`server`); DaviPlata has no refund API
499
+ * (`manual`). An unpaid one is only dropped on the device.
500
+ */
501
+ const reversalFor = (result) => {
502
+ if (result.status !== "PAID") return "cancel";
503
+ if (record(result.metadata.provider).processor === "daviplata") return "manual";
504
+ return "server";
505
+ };
459
506
  return {
460
507
  provider: DEUNA_PROVIDER,
461
508
  method,
@@ -463,8 +510,9 @@ const deunaWidgetPayments = (options) => {
463
510
  policy: DEUNA_WIDGET_POLICY,
464
511
  start,
465
512
  query,
466
- cancel
513
+ cancel,
514
+ reversalFor
467
515
  };
468
516
  };
469
517
  //#endregion
470
- export { DEUNA_PROCESSORS, DEUNA_PROCESSOR_KEYS, DEUNA_PROVIDER, DEUNA_WIDGET_POLICY, deunaDeclinedCode, deunaErrors, deunaProcessorsFor, deunaStateError, deunaWidgetPaymentMethods, deunaWidgetPayments, mapDeunaStatus, orderTokenKey, resolveDeunaProcessor };
518
+ export { DEUNA_PROCESSORS, DEUNA_PROCESSOR_KEYS, DEUNA_PROVIDER, DEUNA_WIDGET_POLICY, deunaDeclinedCode, deunaErrors, deunaProcessorFromState, deunaProcessorsFor, deunaStateError, deunaWidgetPaymentMethods, deunaWidgetPayments, mapDeunaStatus, orderTokenKey, resolveDeunaProcessor, resolveDeunaProcessors };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fire-spark/payments-deuna-widget",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Fire Spark DEUNA Payment Widget adapter: cards, Nequi, Mercado Pago, Deuna App Wallet and DaviPlata, and PSE through the DEUNA checkout",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -17,8 +17,8 @@
17
17
  }
18
18
  },
19
19
  "dependencies": {
20
- "@fire-spark/payments": "^0.12.0",
21
- "@fire-spark/types": "^0.12.0"
20
+ "@fire-spark/payments": "^0.12.1",
21
+ "@fire-spark/types": "^0.12.1"
22
22
  },
23
23
  "devDependencies": {
24
24
  "tsdown": "^0.22.14",