> ## Documentation Index
> Fetch the complete documentation index at: https://firespark.cloud/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# DEUNA

> Cobra tarjetas, Nequi, Mercado Pago, Deuna App Wallet, DaviPlata y PSE con el Payment Widget de DEUNA y @fire-spark/payments-deuna-widget.

DEUNA (deuna.com) es un orquestador de pagos. Fire spark cobra todos los métodos de DEUNA con su **Payment Widget**: el widget de DEUNA cobra, Fire spark crea la orden en DEUNA con tu llave privada, y el estado que Fire spark lee de DEUNA es el que cuenta.

| | |
| - | - |
| Países | Ecuador (tarjeta, Deuna App Wallet), Colombia (tarjeta, Nequi, DaviPlata, Mercado Pago, PSE) |
| Monedas | La moneda del pedido (USD en Ecuador, COP en Colombia) |
| Estado | Disponible (beta) |
| Paquete | `@fire-spark/payments-deuna-widget` |

| Método | Procesador (`processor`) | Qué hace el cliente |
| - | - | - |
| Tarjeta (`CARD`) | `card` | Escribe la tarjeta en el formulario de DEUNA |
| Billetera (`WALLET`) | `nequi` | Aprueba una notificación en la app de Nequi |
| Billetera (`WALLET`) | `mercadopago` | Paga en Mercado Pago (navegador seguro) |
| Billetera (`WALLET`) | `deuna_wallet` | Escanea un QR o escribe un código de 6 dígitos en la app Deuna! |
| Billetera (`WALLET`) | `daviplata` | Escribe su número de documento y el código que DaviPlata envía a su celular (vale 3 min) |
| Transferencia (`BANK_TRANSFER`) | `pse` | Paga en su banco por PSE |

## Requisitos

* Una cuenta de comercio en DEUNA con los procesadores que necesites activos, y sus llaves de API **pública** y **privada** por entorno (sandbox y producción están separados).
* El SDK de DEUNA en tu canal: `@deuna/react-native-sdk` (React Native 0.73+, Expo SDK 50+ con development build) o el Web SDK de DEUNA. Fire spark no lo incluye; tu canal abre el widget.
* Procesadores configurados para capturar al autorizar. El flujo por widget no tiene un paso de captura aparte.

## Activarlo

1. En el dashboard, abre tu comercio, ve a **Payments** y crea un pago con el proveedor **DEUNA** y el método que necesites (`CARD`, `WALLET` o `BANK_TRANSFER`).
2. En **Connection Settings**, completa:

| Campo | Clave | Secreto | Notas |
| - | - | - | - |
| Public key | `public_key` | No | Se envía al canal para abrir el widget |
| Private key | `private_key` | Sí | Queda en la API de Fire spark; nunca llega a los canales |
| Webhook signature | `webhook_signature` | Sí | Secreto con el que DEUNA firma `X-Signature`. Opcional, ver [Webhooks](#webhooks) |
| Store code | `store_code` | No | Tu código de tienda en DEUNA, si tienes varias |
| Processor | `processor` | No | Obligatorio en `WALLET`: `nequi`, `mercadopago`, `deuna_wallet` o `daviplata` |

3. En el DEUNA Admin, configura la URL del webhook `https://<host-de-tu-api>/api/webhooks/payments/deuna` en cada entorno.

## Usarlo en el SDK

```bash theme={null}
pnpm add @fire-spark/payments-deuna-widget @deuna/react-native-sdk react-native-webview
```

Tu canal implementa un **bridge** pequeño que abre el widget de DEUNA y resuelve con el primer callback final. El adaptador hace el resto: pide a Fire spark el token de la orden DEUNA, abre el widget con el bridge y confirma el estado.

```typescript theme={null}
import { createDeunaWidgetApi } from "@fire-spark/storefront";
import { deunaWidgetPayments } from "@fire-spark/payments-deuna-widget";
import type { DeunaWidgetBridge } from "@fire-spark/payments-deuna-widget";

// Un bridge por app, sobre la instancia del SDK de DEUNA que montas una vez.
const bridge: DeunaWidgetBridge = {
  open: input => {
    return new Promise(resolve => {
      const close = () => deunaSDK.close();
      input.signal.addEventListener("abort", () => {
        close();
        resolve({ type: "closed", by: "system" });
      });
      deunaSDK.initPaymentWidget({
        orderToken: input.orderToken,
        paymentMethods: input.paymentMethods,
        language: input.language,
        callbacks: {
          onSuccess: order => {
            close();
            resolve({ type: "success", order });
          },
          onPending: order => resolve({ type: "pending", order }),
          onExpired: () => resolve({ type: "expired" }),
          onError: error => {
            close();
            const code = error?.metadata?.code ?? null;
            resolve({ type: "error", code, errorType: error?.type ?? null });
          },
          onClosed: action => {
            resolve({ type: "closed", by: action === "userAction" ? "user" : "system" });
          }
        }
      });
    });
  }
};

const api = createDeunaWidgetApi(httpOptions);

order.setPaymentAdapters([
  deunaWidgetPayments({ method: "CARD", bridge, api }),
  deunaWidgetPayments({
    method: "WALLET",
    bridge,
    api,
    // Deep links de vuelta a la app después de Mercado Pago o PSE.
    callbackUrls: { on_success: "myapp://deuna/success", on_failed: "myapp://deuna/failed" }
  }),
  deunaWidgetPayments({ method: "BANK_TRANSFER", bridge, api })
]);

const result = await order.payIntent({ payment: deunaPayment });
```

Inicializa el SDK de DEUNA con `publicApiKey: payment.config.public_key` y el entorno del pago. Para Mercado Pago en React Native, pasa un `InAppBrowserAdapter` (`@deuna/react-native-in-app-browser`) al inicializar el SDK de DEUNA. En web, carga el Web SDK de DEUNA desde su CDN e implementa el mismo bridge con `DeunaSDK.initPaymentWidget`.

`payIntent({ payment })` crea un tender real. Para dividir DEUNA con otro método, llama a `order.setTenders` con una asignación y luego a `payIntent()`. Ver [Usar pagos en el SDK](https://firespark.cloud/docs/es/guides/payments/use-payments-in-the-sdk.md).

### Qué pasa con cada callback del widget

| Widget | Tender |
| - | - |
| `onSuccess` | `PAID` cuando Fire spark lee `processed`, `authorized` o `captured`; sigue `PENDING` mientras DEUNA procesa |
| `onPending` | `PENDING`; el SDK consulta el estado hasta que sea final o venza la solicitud |
| `onExpired` | `FAILED` con `WALLET_EXPIRED` |
| `onError` | `FAILED` con el código de la tabla de abajo |
| `onClosed` (cliente) | `PAID` si el pago ya pasó; si no, `FAILED` con `CANCELLED_BY_USER` |

## Endpoints del storefront

El adaptador los llama con `createDeunaWidgetApi`. Usan la sesión del storefront.

| Endpoint | Qué hace |
| - | - |
| `POST /api/storefront/v1/payments/deuna/{payment_id}/tokenize` | Crea la orden DEUNA de un intento de pago y devuelve `{ order_token, order_id }`. El monto sale del tender, nunca de la solicitud. |
| `GET /api/storefront/v1/payments/deuna/{payment_id}/orders/{order_token}` | Devuelve `{ order_token, status, transaction_id, error }` de una orden DEUNA del cliente. |

## Qué ve el cliente

El widget de DEUNA, en español por defecto (`language: "es"`). La metadata del resultado incluye `attempt_reference` y `provider` (`order_token`, `processor`, `status`, `transaction_id`). Los `details` de billetera registran el procesador y la referencia de DEUNA; los de tarjeta no traen datos de la tarjeta. No hay voucher.

## Webhooks

`POST /api/webhooks/payments/deuna` actualiza el tender cuando DEUNA avisa un cambio de estado. Con **Webhook signature** configurado, `X-Signature` debe ser el HMAC-SHA256 en Base64 del body crudo con ese secreto; si no, el aviso se rechaza (`401`). Fire spark siempre relee la orden en DEUNA con tu llave privada antes de cambiar el tender, así que un aviso sin firma solo cuenta cuando DEUNA lo confirma.

## Reembolsos

Fire spark no reembolsa pagos DEUNA. El reverso de un tender DEUNA pagado queda para revisión manual: reembólsalo desde el DEUNA Admin. DaviPlata no admite reembolsos por DEUNA: el reintegro se pide a DaviPlata de forma manual.

## Errores comunes

| Código Spark | Código del proveedor | Qué hacer |
| - | - | - |
| `CARD_DECLINED` | `PAYMENT_DECLINED`, `denied` (tarjeta) | Pide otra tarjeta u otro método |
| `WALLET_REJECTED` | `PAYMENT_DECLINED`, `PAYMENT_FAILED`, `denied` | Pide otro método |
| `WALLET_EXPIRED` | `expired`, `DP-4562` | El push, QR o código venció. Empieza de nuevo |
| `INSUFFICIENT_FUNDS` | `DP-9000` | Pide otro método |
| `INVALID_CREDENTIALS` | `AUTHENTICATION_FAILED` | Revisa las llaves y su entorno en Connection Settings |
| `PROVIDER_UNAVAILABLE` | `INITIALIZATION_FAILED`, `RATE_LIMIT_EXCEEDED`, `PROVIDER_UNAVAILABLE`, `DP-4200`, `DP-4504` | Reintentable. Vuelve a intentar |
| `CANCELLED_BY_USER` | — | El cliente cerró el widget antes de pagar |
| `AMBIGUOUS` | `IDEMPOTENCY_CONFLICT`, estado desconocido | Queda para revisión. Revisa la orden en el DEUNA Admin |

## Compatibilidad

| `@fire-spark/payments-deuna-widget` | Proveedor | `@fire-spark/payments` |
| - | - | - |
| 0.10.0 | DEUNA API v2, `@deuna/react-native-sdk` 2.1.10 | Misma versión |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.