# Create a Single-Step Payment

A single-step payment (or "Direct Sale") is a transaction where funds are authorized and captured in one operation. This is the most common flow for retail and immediate services, where payment is processed instantly.

This guide walks you through processing a complete sale transaction using the Get Mini SDK, from creating the payment DTO to handling the authorization result.

## Requirements

Before you begin, ensure you have:

- **SDK initialized** with environment and license via `CommonUtils`
- **Merchant configuration** from successful login (`DatosLoginResponseDTO`)
- **PIN pad connected** and initialized (received `PinpadConfig` from `onInitFinished`)
- **Delegates implemented**: `RedsysBTPinpadPaymentDelegate` to handle transaction results

<Callout type="note">

Complete [Initialize the SDK](/en/get-mini/android-sdk/guides/initialize-sdk-lifecycle) and [Quick Start: Your First Sale](/en/get-mini/ios-sdk/first-steps/ios-sdk-quickstart) before proceeding.

</Callout>

## Payment Process

### Step 1: Create the Payment DTO

Prepare the transaction data using `PagoDTO`. The amount must be specified in cents (multiply by 100):

```
// Import via Bridging Header: PagoDTO.h
func createPaymentData() -> PagoDTO {
    let amount: Float = 15.50  // Amount in currency units

    let pagoDTO = PagoDTO(
        valor: Int(amount * 100),        // Convert to cents: 1550
        mMoneda: 978,                    // ISO 4217 code (978 = EUR)
        nFactura: "SALE\(Int.random(in: 1000...9999))",  // Unique order ID
        email: "",                       // Optional customer email
        tlfCliente: "",                  // Optional customer phone
        datosPropietarios: ""            // Optional custom data
    )

    return pagoDTO
}
```

| Parameter | Type | Description |
| :---- | :---- | :---- |
| `valor` | Int | Transaction amount in cents (e.g., 1550 for €15.50) |
| `mMoneda` | Int | ISO 4217 currency code (978 = EUR, 840 = USD) |
| `nFactura` | String | Unique order/invoice number (max 12 characters) |
| `email` | String | Customer email for receipt (optional) |
| `tlfCliente` | String | Customer phone number (optional) |
| `datosPropietarios` | String | Custom merchant data (optional) |

<Callout type="warning">

Always convert amounts to cents to ensure precision. For €15.50, use `1550` as the valor.

</Callout>

### Step 2: Execute the Payment

Call `payWithPinpadBluetooth` with the connected device, merchant data, PIN pad configuration, and payment DTO:

```
// Import via Bridging Header: RedsysPinpadManager.h, MerchanDTO.h
func executePayment() {
    guard let config = pinpadConfig else {
        print("PinPad not initialized")
        return
    }

    // Create MerchanDTO with required fields from login response
    let merchantDTO = MerchanDTO()
    merchantDTO.fuc = "999008881"
    merchantDTO.fucExtendido = "999008881"  // Usually same as FUC
    merchantDTO.terminal = "001"
    merchantDTO.password = "merchant_pass"  // Password from login

    // Create payment DTO
    let pagoDTO = createPaymentData()

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

When you call `payWithPinpadBluetooth`, the SDK:
1. **Prompts** the customer to present their card (Insert, Swipe, or Tap)
2. **Reads** card data via the selected method
3. **Requests PIN** entry if required
4. **Encrypts** card data using hardware E2EE
5. **Submits** the authorization request to Get Mini gateway
6. **Returns** the result via delegate callbacks

### Step 3: Handle Transaction Results

The SDK delivers results through the `RedsysBTPinpadPaymentDelegate` callbacks.

**Success Handling**

```
func onPaymentFinished(_ result: RespuestaTransaccionDTO!, orError error: Error!) {
    if let transaction = result, error == nil {
        // Transaction successful - both authorized and captured
        print("Sale Successful!")
        print("Authorization Code: \(transaction.codigoAutorizacion ?? "N/A")")

        // Save transaction details
        saveTransaction(
            authCode: transaction.codigoAutorizacion ?? "",
            orderId: transaction.numeroOperacion ?? "",
            amount: transaction.importeTotal ?? ""
        )

        // Check if signature is required (no-PIN transactions)
        // Note: AutenticadoPorPin is a BOOL property from Objective-C
        if !transaction.autenticadoPorPin {
            captureCustomerSignature(for: transaction)
        }

        // Display success message
        showSuccessAlert()
    } else {
        // Transaction failed
        handlePaymentError(error)
    }
}
```

**Progress Updates**

```
func onPaymentProcess(_ result: Any!, orError error: Error!) {
    // Called during processing for UI updates
    print("Payment in progress...")
    updateProgressIndicator()
}
```

**Error Handling**

```
func handlePaymentError(_ error: Error?) {
    print("Payment failed: \(error?.localizedDescription ?? "Unknown error")")

    // Display user-friendly error message
    showErrorAlert(message: "Transaction declined. Please try again.")

    // Log error for support
    logTransactionError(error)
}
```

## Key Considerations

### Instant Settlement

Unlike pre-authorizations, single-step payment funds are immediately authorized and captured. These transactions settle automatically at the end of the business day without requiring a separate capture operation.

### Amount Formatting

Always convert decimal amounts to cents for the `PagoDTO.valor` field:

| Display Amount | valor (cents) | Calculation |
| :---- | :---- | :---- |
| €10.50 | 1050 | 10.50 × 100 |
| €100.00 | 10000 | 100.00 × 100 |
| \$25.99 | 2599 | 25.99 × 100 |

### Unique Order IDs

The `nFactura` field must be unique for each transaction. Generate IDs using timestamps, UUIDs, or sequential numbers to prevent duplicate order tracking issues.

### Signature Management

For transactions where `autenticadoPorPin == false`, capturing a digital signature is mandatory to meet legal requirements. The `autenticadoPorPin` BOOL property indicates whether PIN authentication was used. See the signature submission process in [Transaction Lifecycle](/en/get-mini/ios-sdk/core-concepts/ios-lifecycle#fase-4-finalización-y-firma).

## Best Practices

**Prevent Duplicate Transactions**

Disable payment buttons while `onPaymentProcess` is active to prevent multiple simultaneous payment attempts:

```
func executePayment() {
    payButton.isEnabled = false
    // Execute payment...
}

func onPaymentFinished(_ result: RespuestaTransaccionDTO!, orError error: Error!) {
    payButton.isEnabled = true  // Re-enable after completion
    // Handle result...
}
```

**Save Transaction Data**

Always save authorization codes immediately upon success. You'll need these for refunds and reconciliation.

**Provide Clear Feedback**

Update your UI during `onPaymentProcess` to show customers that processing is occurring. Display clear success or error messages based on the final result.

## Troubleshooting

**Transaction Timeout**

If payment times out waiting for card presentation, ensure the PIN pad is powered on and displaying the ready prompt. Check Bluetooth connection stability.

**Declined Transactions**

Card declines occur at the issuing bank level. Display the decline reason to customers and offer to retry with a different card or payment method.

**Signature Required but Not Captured**

If `autenticadoPorPin == false`, you must capture and submit a signature using `envioFirmaDigitalizada`. See [Security and Licensing](/en/get-mini/ios-sdk/core-concepts/security-pci#signature-as-a-security-fallback) for details.

## Next Steps

Explore additional payment features:

* [Creat a Pre-authorized Payment](/en/get-mini/ios-sdk/guides/preauth-payments-ios) - Reserve funds for later capture
* [Transaction Lifecycle](/en/get-mini/ios-sdk/core-concepts/ios-lifecycle) - Understand the complete payment flow
* [Security and Licensing](/en/get-mini/ios-sdk/core-concepts/security-pci) - Learn about payment security