# Crear una venta

La venta es la transacción en la que los fondos se autorizan y capturan en una sola operación. Este es el flujo más común para venta minorista y servicios inmediatos, donde el pago se procesa instantáneamente.

Esta guía te explica cómo procesar una transacción de venta completa usando el SDK de Get Mini, desde la creación del DTO de pago hasta el manejo del resultado de la autorización.

## Requisitos

Antes de comenzar, asegúrate de tener:

- **SDK inicializado** con entorno y licencia a través de `CommonUtils`
- **Configuración de comercio** de un inicio de sesión exitoso (`DatosLoginResponseDTO`)
- **PIN pad conectado** e inicializado (recibió `PinpadConfig` de `onInitFinished`)
- **Delegados implementados**: `RedsysBTPinpadPaymentDelegate` para manejar resultados de transacciones

<Callout type="note">

Completa [Inicializar el SDK](/es/get-mini/android-sdk/guides/initialize-sdk-lifecycle) e [Inicio Rápido: Tu Primera Venta](/es/get-mini/ios-sdk/first-steps/ios-sdk-quickstart) antes de proceder.

</Callout>

## Proceso de pago

### Paso 1: Crear el DTO de pago

Prepara los datos de la transacción usando `PagoDTO`. El importe debe especificarse en céntimos (multiplicar por 100):

```
// Importar vía Bridging Header: PagoDTO.h
func createPaymentData() -> PagoDTO {
    let amount: Float = 15.50  // Importe en unidades de moneda

    let pagoDTO = PagoDTO(
        valor: Int(amount * 100),        // Convertir a céntimos: 1550
        mMoneda: 978,                    // Código ISO 4217 (978 = EUR)
        nFactura: "SALE\(Int.random(in: 1000...9999))",  // ID de orden único
        email: "",                       // Email del cliente opcional
        tlfCliente: "",                  // Teléfono del cliente opcional
        datosPropietarios: ""            // Datos de comercio personalizados opcionales
    )

    return pagoDTO
}
```

| Parámetro | Tipo | Descripción |
| :---- | :---- | :---- |
| `valor` | Int | Importe de transacción en céntimos (ej., 1550 para €15.50) |
| `mMoneda` | Int | Código de moneda ISO 4217 (978 = EUR, 840 = USD) |
| `nFactura` | String | Número de orden/factura único (caracteres alfanuméricos; no admite "ñ"/"Ñ") |
| `email` | String | Email del cliente para el ticket (opcional) |
| `tlfCliente` | String | Número de teléfono del cliente (opcional) |
| `datosPropietarios` | String | Datos de comercio personalizados (opcional) |

<Callout type="warning">

Siempre convierte importes a céntimos para asegurar precisión. Para €15.50, usa `1550` como el valor.

</Callout>

### Paso 2: Ejecutar el pago

Llama a `payWithPinpadBluetooth` con el dispositivo conectado, datos del comercio, configuración del PIN pad y DTO de pago:

```
// Importar vía Bridging Header: RedsysPinpadManager.h, MerchanDTO.h
func executePayment() {
    guard let config = pinpadConfig else {
        print("PIN pad no inicializado")
        return
    }

    // Crear MerchanDTO con campos requeridos de la respuesta de login
    let merchantDTO = MerchanDTO()
    merchantDTO.fuc = "999008881"
    merchantDTO.fucExtendido = "999008881"  // Usualmente igual que FUC
    merchantDTO.terminal = "001"
    merchantDTO.password = "merchant_pass"  // Contraseña del login

    // Crear DTO de pago
    let pagoDTO = createPaymentData()

    // Ejecutar pago
    pinpadManager.payWithPinpadBluetooth(
        selectedDevice,
        merchan: merchantDTO,
        config: config,
        andPagoDTO: pagoDTO,
        withDelegate: self
    )
}
```

Cuando llamas a `payWithPinpadBluetooth`, el SDK:
1. **Solicita** al cliente que presente su tarjeta (Insertar, Deslizar o Tocar)
2. **Lee** los datos de la tarjeta vía el método seleccionado
3. **Solicita entrada de PIN** si es requerido
4. **Procesa** los datos de la tarjeta de forma segura
5. **Envía** la solicitud de autorización a los servidores de TPV PC
6. **Devuelve** el resultado vía callbacks del delegado

### Paso 3: Manejar resultados de transacción

El SDK entrega resultados a través de los callbacks de `RedsysBTPinpadPaymentDelegate`.

**Manejo de Éxito**

```
func onPaymentFinished(_ result: RespuestaTransaccionDTO!, orError error: Error!) {
    if let transaction = result, error == nil {
        // Transacción exitosa - autorizada y capturada
        print("Venta Exitosa!")
        print("Código de Autorización: \(transaction.codigoAutorizacion ?? "N/A")")

        // Guardar detalles de la transacción
        saveTransaction(
            authCode: transaction.codigoRespuesta ?? "",
            orderId: transaction.pedido ?? "",
            amount: transaction.importe ?? ""
        )

        // Verificar si se requiere firma (transacciones sin PIN)
        // Nota: AutenticadoPorPin es una propiedad BOOL de Objective-C
        if !transaction.autenticadoPorPin {
            captureCustomerSignature(for: transaction)
        }

        // Mostrar mensaje de éxito
        showSuccessAlert()
    } else {
        // Transacción fallida
        handlePaymentError(error)
    }
}
```

**Actualizaciones de Progreso**

```
func onPaymentProcess(_ result: Any!, orError error: Error!) {
    // Llamado durante el procesamiento para actualizaciones de UI
    print("Pago en progreso...")
    updateProgressIndicator()
}
```

**Manejo de Errores**

```
func handlePaymentError(_ error: Error?) {
    print("Pago fallido: \(error?.localizedDescription ?? "Error desconocido")")

    // Mostrar mensaje de error amigable al usuario
    showErrorAlert(message: "Transacción rechazada. Por favor intente de nuevo.")

    // Registrar error para soporte
    logTransactionError(error)
}
```

## Consideraciones clave

A diferencia de las preautorizaciones, en una venta los fondos se autorizan y capturan inmediatamente.

### Formateo de importes

Siempre convierte importes decimales a céntimos para el campo `PagoDTO.valor`:

| Importe a Mostrar | valor (céntimos) | Cálculo |
| :---- | :---- | :---- |
| €10.50 | 1050 | 10.50 × 100 |
| €100.00 | 10000 | 100.00 × 100 |
| \$25.99 | 2599 | 25.99 × 100 |

### IDs de orden únicos

El campo `nFactura` debe ser único para cada transacción. Genera IDs usando marcas de tiempo, UUIDs o números secuenciales para prevenir problemas de seguimiento de orden duplicados.

### Gestión de firma

Para transacciones donde `autenticadoPorPin == false`, capturar una firma digital es obligatorio para cumplir con los requisitos legales. La propiedad BOOL `autenticadoPorPin` indica si se usó autenticación por PIN. Consulta el proceso de envío de firma en [Ciclo de Vida de la Transacción](/es/get-mini/ios-sdk/core-concepts/ios-lifecycle#phase-4-finalization--signature).

## Mejores prácticas

**Prevenir Transacciones Duplicadas**

Deshabilita los botones de pago mientras `onPaymentProcess` esté activo para prevenir múltiples intentos de pago simultáneos:

```
func executePayment() {
    payButton.isEnabled = false
    // Ejecutar pago...
}

func onPaymentFinished(_ result: RespuestaTransaccionDTO!, orError error: Error!) {
    payButton.isEnabled = true  // Rehabilitar después de completar
    // Manejar resultado...
}
```

**Guardar Datos de Transacción**

Siempre guarda los códigos de autorización inmediatamente tras el éxito. Necesitarás estos para devoluciones y conciliación.

**Proporcionar Retroalimentación Clara**

Actualiza tu UI durante `onPaymentProcess` para mostrar a los clientes que el procesamiento está ocurriendo. Muestra mensajes claros de éxito o error basados en el resultado final.

## Solución de Problemas

**Tiempo de Espera de Transacción**

Si el pago agota el tiempo de espera esperando la presentación de la tarjeta, asegúrate de que el PIN pad esté encendido y mostrando el aviso de listo. Verifica la estabilidad de la conexión Bluetooth.

**Transacciones Rechazadas**

Los rechazos de tarjeta ocurren a nivel del banco emisor. Muestra el motivo del rechazo a los clientes y ofrece reintentar con una tarjeta o método de pago diferente.

**Firma Requerida pero No Capturada**

Si `autenticadoPorPin == false`, debes capturar y enviar una firma usando `envioFirmaDigitalizada`. Consulta [Seguridad y licencias](/es/get-mini/ios-sdk/core-concepts/security-pci#firma-como-alternativa-de-seguridad) para detalles.

## Próximos pasos

Explora funcionalidades de pago adicionales:

* [Crear un pago preautorizado](/es/get-mini/ios-sdk/guides/preauth-payments-ios) - Reservar fondos para captura posterior
* [Ciclo de Vida de la Transacción](/es/get-mini/ios-sdk/core-concepts/ios-lifecycle) - Entender el flujo de pago completo
* [Seguridad y licencias](/es/get-mini/ios-sdk/core-concepts/security-pci) - Aprender sobre seguridad de pagos