# Quick Start: Your First Sale

This tutorial walks you through the essential steps to process your first payment transaction using the Get Mini SDK. You'll initialize the SDK environment, log in as a merchant, connect to a physical PIN pad device, and execute a sale transaction with delegate-based result handling.

## Requirements

Before you begin, ensure you have:

- **SDK integrated** into your Xcode project with the `-ObjC` and `-lsqlite3` linker flags set
- **External Accessory protocols** added to your Info.plist (e.g., `com.datecs.pinpad`)
- **Test credentials** provided by Get Mini: FUC (Merchant ID), Terminal ID, License Key, and login credentials
- **Physical iOS device** for testing (Simulator does not support Bluetooth PIN pad communication)
- **Bluetooth PIN pad device** powered on and within range

<Callout type="warning">

You must complete [Install the SDK](/en/get-mini/ios-sdk/first-steps/install-the-sdk) and [Configure iOS Permissions](/en/get-mini/ios-sdk/first-steps/configure-ios-permissions) before proceeding with this tutorial.

</Callout>

## Payment Process

This section guides you through the complete payment flow from initialization to transaction result handling.

### Step 1: Initialize the SDK Environment

The SDK must be initialized with your license key and target environment before any operations. This setup typically occurs in your `AppDelegate` or a dedicated payment manager class:

```
// Import via Bridging Header: CommonUtils.h
func initializeSDK() {
    // Set environment: "des" (Development), "int" (Integration), "ccal" (Pre-production), "real" (Production)
    CommonUtils.setEntorno("des")

    // Set your license key provided by Get Mini
    CommonUtils.setAppLicense("YOUR_LICENSE_KEY")
}
```

Call this initialization method in `application(_:didFinishLaunchingWithOptions:)` before any SDK operations. The environment setting determines which Get Mini gateway servers the SDK connects to for processing transactions.

<Callout type="warning">

Always use the test environment (`"des"`) during development. Only switch to production (`"real"`) when deploying to live environments with valid production credentials.

</Callout>

### Step 2: Perform Merchant Login

Before processing transactions, retrieve the merchant configuration from Get Mini. The login operation returns merchant data (FUC, Terminal, etc.) required for payment operations:

```
// Import via Bridging Header: DatosLoginDTO.h, RedsysConfigurationManager.h
func performMerchantLogin() {
    let loginDTO = DatosLoginDTO(user: "your_username", andPass: "your_password")

    RedsysConfigurationManager.obtenerDatosComercioLogin(loginDTO) { result, error in
        if let merchantData = result {
            print("Login successful for: \(merchantData.nombreComercio ?? "Merchant")")
            // Store merchantData for use in payment operations
            self.saveMerchantData(merchantData)
        } else {
            print("Login failed: \(error?.localizedDescription ?? "Unknown error")")
        }
    }
}
```

The `DatosLoginResponseDTO` object returned on success contains essential merchant configuration including FUC, Terminal ID, and other settings needed to create the `MerchanDTO` object for payment processing.

### Step 3: Implement Delegate Protocols

Your view controller must conform to the SDK delegate protocols to receive callbacks during initialization and payment processing. Add the required protocols to your class declaration:

```
// Import via Bridging Header: RedsysPinpadManager.h
class PaymentViewController: UIViewController,
                             RedsysDelegateGeneric,
                             RedsysBTPinpadInitDelegate,
                             RedsysBTPinpadPaymentDelegate {

    var pinpadManager: RedsysPinpadManager!
    var selectedDevice: Any?
    var pinpadConfig: PinpadConfig?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Manager initialization will happen when starting the payment flow
    }

    // MARK: - Init Delegate Methods

    func onInitFinished(_ result: Any!, orError error: Error!) {
        if let config = result as? PinpadConfig {
            print("PinPad initialized successfully")
            self.pinpadConfig = config
            // Proceed to payment
        } else {
            print("Initialization failed: \(error?.localizedDescription ?? "")")
        }
    }

    // MARK: - Payment Delegate Methods

    func onPaymentProcess(_ result: Any!, orError error: Error!) {
        // Called during payment processing to notify progress
        print("Payment in progress...")
    }

    func onPaymentFinished(_ result: RespuestaTransaccionDTO!, orError error: Error!) {
        if let transaction = result, error == nil {
            print("Sale Approved! Auth Code: \(transaction.codigoAutorizacion ?? "")")
        } else {
            print("Sale Failed: \(error?.localizedDescription ?? "")")
        }
    }
}
```

The delegate methods provide callbacks at different stages: `onInitFinished` confirms the PIN pad is ready, `onPaymentProcess` notifies of progress updates, and `onPaymentFinished` delivers the final transaction result.

### Step 4: Initialize PIN pad Manager

Create the PIN pad manager instance and initialize it for Bluetooth communication:

```
func startPaymentFlow() {
    // Initialize manager with Bluetooth technology
    pinpadManager = RedsysPinpadManager(bluetoothTech: "GENERAL")

    // Get available Bluetooth devices
    let availableDevices = pinpadManager.bluetoothDevicesList()

    guard let devices = availableDevices as? [Any], !devices.isEmpty else {
        print("No PinPad devices found")
        return
    }

    // Select first available device
    selectedDevice = devices[0]

    // Configure the selected device
    connectAndConfigureDevice()
}

func connectAndConfigureDevice() {
    // Create MerchanDTO from login response
    let merchantDTO = MerchanDTO()
    merchantDTO.fuc = "999008881"  // From DatosLoginResponseDTO
    merchantDTO.fucExtendido = "999008881"
    merchantDTO.terminal = "001"
    merchantDTO.password = "your_password"

    // Connect and configure the device
    pinpadManager.connectAndConfigureDevice(selectedDevice,
                                           merchan: merchantDTO,
                                           withDelegate: self)
}
```

The manager scans for paired Bluetooth devices and establishes a connection. The `onInitFinished` delegate method will be called when the device is ready for transactions.

### Step 5: Execute the Payment

Once the PIN pad is initialized (confirmed in `onInitFinished`), create the payment DTO and execute the transaction:

```
func executePayment() {
    guard let config = pinpadConfig else {
        print("PinPad not initialized")
        return
    }

    // Create payment DTO
    let amount: Float = 10.50  // Amount in currency units
    let pagoDTO = PagoDTO(
        valor: Int(amount * 100),  // Convert to cents
        mMoneda: 978,              // ISO 4217 code (978 = EUR)
        nFactura: "TEST\(Int.random(in: 1000...9999))",  // Unique invoice number
        email: "",
        tlfCliente: "",
        datosPropietarios: ""
    )

    // Create MerchanDTO (same as in Step 4)
    let merchantDTO = MerchanDTO()
    merchantDTO.fuc = "999008881"
    merchantDTO.fucExtendido = "999008881"
    merchantDTO.terminal = "001"
    merchantDTO.password = "your_password"

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

The SDK handles the complete transaction flow including prompting for card insertion, PIN entry, communication with the payment gateway, and returning the result through the `onPaymentFinished` delegate callback.

| Parameter | Type | Description |
| :---- | :---- | :---- |
| `valor` | Int | Transaction amount in cents (e.g., 1050 for €10.50) |
| `mMoneda` | Int | ISO 4217 currency code (978 = EUR, 840 = USD) |
| `nFactura` | String | Unique invoice/order number for tracking |

### Step 6: Handle Transaction Results

Process the transaction outcome in the `onPaymentFinished` delegate callback:

```
func onPaymentFinished(_ result: RespuestaTransaccionDTO!, orError error: Error!) {
    if let transaction = result, error == nil {
        // Transaction successful
        let authCode = transaction.codigoAutorizacion ?? ""
        let amount = transaction.importeTotal ?? ""

        print("Payment Approved")
        print("Auth Code: \(authCode)")
        print("Amount: \(amount)")

        // Save to database
        saveTransaction(authCode: authCode, amount: amount)

        // Show success message
        showSuccessAlert(authCode: authCode)
    } else {
        // Transaction failed
        print("Payment Failed: \(error?.localizedDescription ?? "")")
        showErrorAlert(message: error?.localizedDescription ?? "Transaction failed")
    }
}
```

Always save the authorization code (`codigoAutorizacion`) from successful transactions. This code is required for refunds and reconciliation.

## Troubleshooting

**Crash on RedsysPinpadManager Initialization**

Verify the `-ObjC` linker flag is added in **Other Linker Flags**. Missing this flag causes "Selector not recognized" crashes.

**No PIN pad Devices Found**

Ensure the `UISupportedExternalAccessoryProtocols` in Info.plist includes the correct protocol for your device (e.g., `com.datecs.pinpad` for Itos/Castles devices). Confirm the device is paired in iOS Settings > Bluetooth.

**Environment Error During Login**

If login fails with environment errors, verify `CommonUtils.setEntorno` is set to `"des"` for test credentials or `"real"` for production credentials. The environment must match your credentials.

## Next Steps

Now that you've successfully processed your first payment, explore additional SDK capabilities:

* [iOS SDK Overview](/en/get-mini/ios-sdk/ios-sdk-overview) - Learn about multi-vendor support and security features
* [Configure iOS Permissions](/en/get-mini/ios-sdk/first-steps/configure-ios-permissions) - Review all required protocols and permissions