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

# PrimerHeadlessUniversalCheckoutDelegate

## Overview

Set the `PrimerHeadlessUniversalCheckoutDelegate` in order to receive callbacks from Primer SDK.

Callbacks can be used for managing the customer journey and trigger actions after specific events throughout the payment journey. See below for a breakdown of all callbacks supported within the Primer SDK.

### primerHeadlessUniversalCheckoutDidCompleteCheckoutWithData

This method will be called with the when the payment has been completed, returning the payment's data.\
\

⚠️ This method won't be called when you are using manual payment handling, or the vault manager.

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidCompleteCheckoutWithData(_ data: PrimerCheckoutData)
```

#### Parameters

**Properties**

**additionalInfo** `PrimerCheckoutAdditionalInfo`

**direct subclasses**

**XenditCheckoutVoucherAdditionalInfo**

**Parameters**

**expiresAt** `String` *required*

**couponCode** `String` *required*

**retailerName** `String` *required*

**PromptPayCheckoutAdditionalInfo**

**Parameters**

**expiresAt** `String` *required*

**qrCodeUrl** `String`

**qrCodeBase64** `String` *required*

**MultibancoCheckoutAdditionalInfo**

**Parameters**

**expiresAt** `String`

**entity** `String`

**reference** `String`

**ACHAdditionalInfo**

**Subclasses**

**ACHBankAccountCollectorAdditionalInfo** `ACHAdditionalInfo`

**Properties**

**collectorViewController** `UIViewController`

Provides the bank account collector for ACH bank account
selection.

**ACHMandateAdditionalInfo** `ACHAdditionalInfo`

Provides an empty `ACHMandateAdditionalInfo` object to
prompt the merchant to display the mandate information.

#### Example

```swift SWIFT theme={"dark"}
// 👇 Add this
import PrimerSDK

// 👇 Conform to PrimerDelegate
class MyViewController: UIViewController, PrimerDelegate {

	// ...

    // 👇 Add this
	func primerDidCompleteCheckoutWithData(_ data: PrimerCheckoutData) {
        // Do something with the payment's data
    }
}
```

### primerHeadlessUniversalCheckoutDidLoadAvailablePaymentMethods

This method will return the payment methods that should be displayed based on the current client session data.

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidLoadAvailablePaymentMethods(_ paymentMethods: [PrimerHeadlessUniversalCheckout.PaymentMethod])
```

#### Parameters

**Properties**

**paymentMethodType** `String` *required*

**supportedPrimerSessionIntents** `[PrimerSessionIntent]` *required*

**enum cases**

**.checkout**

Use `checkout` when you want go through the checkout flow

**.vault**

Use `vault` when you want to vault a payment method, so you can use the token to pay another time.

**paymentMethodManagerCategories** `enum String` *required*

**enum cases**

**.nativeUI**

**.rawData**

**requiredInputDataClass** `PrimerRawData.Type`

### primerHeadlessUniversalCheckoutDidTokenizePaymentMethod

This method will be called with the when the payment method has been is tokenized, returning the payment method's tokenization data. Use the `token` to create a payment on your backend. Make sure that you call the `decisionHandler` once your operation has been completed.

⚠️ This method will be called when you are using manual payment handling, or the vault manager.

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidTokenizePaymentMethod(
    _ paymentMethodTokenData: PrimerPaymentMethodTokenData,
    decisionHandler: @escaping (PrimerHeadlessUniversalCheckoutResumeDecision) -> Void
)
```

#### Parameters

**Properties**

**paymentMethodTokenData** `PrimerPaymentMethodTokenData`

**Parameters**

**analyticsId** `String`

**id** `String`

**paymentInstrumentData** `PaymentInstrumentData`

**Parameters**

**paymentMethodConfigId** `String`

**paymentMethodType** `String`

**sessionInfo** `SessionInfo`

**first6Digits** `String`

**firstDigits** `String`

**last4Digits** `String`

**accountNumberLast4Digits** `String`

**expirationMonth** `String`

**expirationYear** `String`

**cardholderName** `String`

**network** `String`

**isNetworkTokenized** `String`

**binData** `BinData`

**threeDSecureAuthentication** `ThreeDS.AuthenticationDetails`

**paypalBillingAgreementId** `String`

**externalPayerInfo** `ExternalPayerInfo`

Additional PayPal data.

**Properties**

**email** `String`

The payer's email address.

**externalPayerId** `String?`

The payer's unique ID.

**firstName** `String?`

The payer's given name.

**lastName** `String?`

The payer's given surname.

**shippingAddress** `ShippingAddress`

**klarnaCustomerToken** `String`

**sessionData** `SessionData`

**bankName** `String`

**paymentInstrumentType** `PaymentInstrumentType`

**Cases**

**paymentCard**

**offSession**

**cardOffSession**

**payPalOrder**

**payPalBillingAgreement**

**applePay**

**googlePay**

**klarna**

**klarnaPaymentSession**

**klarnaCustomerToken**

**apayaToken**

**hoolah**

**unknown**

**threeDSecureAuthentication** `ThreeDS.AuthenticationDetails`

**token** `String` *required*

**tokenType** `TokenType`

**Cases**

**multiUse**

**singleUse**

**vaultData** `VaultData`

**decisionHandler** `enum PrimerResumeDecision` *required*

**cases**

**succeed()**

Call `.succeed` when you want to show the success screen, or finalize the flow successfully in case you have hidden the success screen.

**.continueWithNewClientToken(\_:)**

Call `.continueWithNewClientToken` when the payment has entered in a PENDING state and a required action client token has been provided.

#### Example

```swift SWIFT theme={"dark"}
// 👇 Add this
import PrimerSDK

// 👇 Conform to PrimerHeadlessUniversalCheckoutDelegate
class MyViewController: UIViewController, PrimerHeadlessUniversalCheckoutDelegate {

	// ...

    // 👇 Add this
	func primerHeadlessUniversalCheckoutDidTokenizePaymentMethod(
        _ paymentMethodTokenData: PrimerPaymentMethodTokenData,
        decisionHandler: @escaping (PrimerResumeDecision) -> Void
    ) {
        // Create your payment
        createPayment(with: paymentMethodTokenData.token) { res, err in
            if let err = err {
                // 👇 Call the decisionHandler to show the error screen with your custom error message
                decisionHandler(.fail(withErrorMessage: "Oh no, something went wrong creating the payment..."))

            } else if let res = res {
                if let newClientToken = res.requiredAction?.clientToken {
                    // 👇 Call the decisionHandler with the new client token to continue the flow
                    decisionHandler(.continueWithNewClientToken(requiredAction.clientToken))
                } else {
                    // 👇 Call the decisionHandler to show the success screen
                    decisionHandler(.succeed())
                }
            }
        }
    }
}
```

### primerHeadlessUniversalCheckoutDidResumeWith

This method will be called providing a `resumeToken` so you can [resume the payment](https://primer.io/docs/api-reference/v2.4/api-reference/payments-api/resume-a-payment.md).

> [!WARNING]
>
> This method **will** be called when you are using
> `PrimerPaymentHandling.MANUAL`
> [flow](https://primer.io/docs/sdk/ios/v2.x.x/common-objects/PrimerSettings.md#parameters) and when
> the payment is in a PENDING state.

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidResumeWith(
    _ resumeToken: String,
    decisionHandler: @escaping (PrimerHeadlessUniversalCheckoutResumeDecision) -> Void
)
```

#### Parameters

**Properties**

**resumeToken** `String` *required*

**decisionHandler** `enum PrimerResumeDecision` *required*

**cases**

**succeed()**

Call `.succeed` when you want to show the success screen, or finalize the flow successfully in case you have hidden the success screen.

**.continueWithNewClientToken(\_:)**

Call `.continueWithNewClientToken` when the payment has entered in a PENDING state and a required action client token has been provided.

#### Example

```swift SWIFT theme={"dark"}
// 👇 Add this
import PrimerSDK

// 👇 Conform to PrimerHeadlessUniversalCheckoutDelegate
class MyViewController: UIViewController, PrimerHeadlessUniversalCheckoutDelegate {

	// ...

    // 👇 Add this
	func primerHeadlessUniversalCheckoutDidResumeWith(
        _ resumeToken: String,
        decisionHandler: @escaping (PrimerResumeDecision) -> Void
    ) {
        // Resume your payment
        resumePayment(with: resumeToken) { res, err in
            if let err = err {
                // 👇 Call the decisionHandler to show the error screen with your custom error message
                decisionHandler(.fail(withErrorMessage: "Oh no, something went wrong creating the payment..."))

            } else if let res = res {
                if let newClientToken = res.requiredAction?.clientToken {
                    // 👇 Call the decisionHandler with the new client token to continue the flow
                    decisionHandler(.continueWithNewClientToken(requiredAction.clientToken))
                } else {
                    // 👇 Call the decisionHandler to show the success screen
                    decisionHandler(.succeed())
                }
            }
        }
    }
}
```

### primerHeadlessUniversalCheckoutDidEnterResumePendingWithPaymentAdditionalInfo

This callback is trigger when the payment is not authorized as it’s an asynchronous alternative payment method, such as a voucher payment method, but the payment has stayed in a pending state.

> [!WARNING]
>
> This method will be called only when using the `PrimerPaymentHandling.auto`
> [flow](https://primer.io/docs/sdk/ios/v2.x.x/common-objects/PrimerSettings.md#parameters).

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidEnterResumePendingWithPaymentAdditionalInfo(_ additionalInfo: PrimerCheckoutAdditionalInfo?)
```

#### Parameters

**Properties**

**additionalInfo** `PrimerCheckoutAdditionalInfo`

**direct subclasses**

**XenditCheckoutVoucherAdditionalInfo**

**Parameters**

**expiresAt** `String` *required*

**couponCode** `String` *required*

**retailerName** `String` *required*

**PromptPayCheckoutAdditionalInfo**

**Parameters**

**expiresAt** `String` *required*

**qrCodeUrl** `String`

**qrCodeBase64** `String` *required*

**MultibancoCheckoutAdditionalInfo**

**Parameters**

**expiresAt** `String`

**entity** `String`

**reference** `String`

**ACHAdditionalInfo**

**Subclasses**

**ACHBankAccountCollectorAdditionalInfo** `ACHAdditionalInfo`

**Properties**

**collectorViewController** `UIViewController`

Provides the bank account collector for ACH bank account
selection.

**ACHMandateAdditionalInfo** `ACHAdditionalInfo`

Provides an empty `ACHMandateAdditionalInfo` object to
prompt the merchant to display the mandate information.

### primerHeadlessUniversalCheckoutDidReceiveAdditionalInfo

This callback is trigger when the payment is not authorized as it’s an asynchronous alternative payment method, such as a voucher payment method.

> [!WARNING]
>
> This method will be called only when using the `PrimerPaymentHandling.auto`
> [flow](https://primer.io/docs/sdk/ios/v2.x.x/common-objects/PrimerSettings.md#parameters).

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidReceiveAdditionalInfo(_ additionalInfo: PrimerCheckoutAdditionalInfo?)
```

#### Parameters

**Properties**

**additionalInfo** `PrimerCheckoutAdditionalInfo`

**direct subclasses**

**XenditCheckoutVoucherAdditionalInfo**

**Parameters**

**expiresAt** `String` *required*

**couponCode** `String` *required*

**retailerName** `String` *required*

**PromptPayCheckoutAdditionalInfo**

**Parameters**

**expiresAt** `String` *required*

**qrCodeUrl** `String`

**qrCodeBase64** `String` *required*

**MultibancoCheckoutAdditionalInfo**

**Parameters**

**expiresAt** `String`

**entity** `String`

**reference** `String`

**ACHAdditionalInfo**

**Subclasses**

**ACHBankAccountCollectorAdditionalInfo** `ACHAdditionalInfo`

**Properties**

**collectorViewController** `UIViewController`

Provides the bank account collector for ACH bank account
selection.

**ACHMandateAdditionalInfo** `ACHAdditionalInfo`

Provides an empty `ACHMandateAdditionalInfo` object to
prompt the merchant to display the mandate information.

### primerHeadlessUniversalCheckoutDidFail

This method will be called when an error occurs. It may return `PrimerCheckoutData` if the error occurs after the payment creation.

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidFail(withError err: Error, checkoutData: PrimerCheckoutData?)
```

#### Parameters

**Properties**

**err** `Error` *required*

### primerHeadlessUniversalCheckoutWillUpdateClientSession

This method will be called to notify you that the client session will be updated, e.g.
a surcharge needs to be applied when a payment method has been chosen.

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutWillUpdateClientSession()
```

### primerHeadlessUniversalCheckoutDidUpdateClientSession

This method will be called to notify you that the client session has been updated, e.g.
surcharge has been applied when a payment method has been chosen.

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutDidUpdateClientSession(_ clientSession: PrimerClientSession)
```

#### Parameters

**Properties**

**clientSession** `PrimerClientSession` *required*

### primerHeadlessUniversalCheckoutWillCreatePaymentWithData

This method will be called with just before the payment gets created, and lets you decide whether you want to proceed
with the payment creation.

⚠️ This method will be called only when checking out using the `auto` [flow](https://primer.io/docs/sdk/ios/v2.x.x/common-objects/PrimerSettings.md).

```swift SWIFT theme={"dark"}
func primerHeadlessUniversalCheckoutWillCreatePaymentWithData(
    _ data: PrimerCheckoutPaymentMethodData,
    decisionHandler: @escaping (PrimerPaymentCreationDecision) -> Void
)
```

#### Parameters

**Properties**

**paymentMethodTokenData** `PrimerPaymentMethodTokenData`

**Parameters**

**analyticsId** `String`

**id** `String`

**paymentInstrumentData** `PaymentInstrumentData`

**Parameters**

**paymentMethodConfigId** `String`

**paymentMethodType** `String`

**sessionInfo** `SessionInfo`

**first6Digits** `String`

**firstDigits** `String`

**last4Digits** `String`

**accountNumberLast4Digits** `String`

**expirationMonth** `String`

**expirationYear** `String`

**cardholderName** `String`

**network** `String`

**isNetworkTokenized** `String`

**binData** `BinData`

**threeDSecureAuthentication** `ThreeDS.AuthenticationDetails`

**paypalBillingAgreementId** `String`

**externalPayerInfo** `ExternalPayerInfo`

Additional PayPal data.

**Properties**

**email** `String`

The payer's email address.

**externalPayerId** `String?`

The payer's unique ID.

**firstName** `String?`

The payer's given name.

**lastName** `String?`

The payer's given surname.

**shippingAddress** `ShippingAddress`

**klarnaCustomerToken** `String`

**sessionData** `SessionData`

**bankName** `String`

**paymentInstrumentType** `PaymentInstrumentType`

**Cases**

**paymentCard**

**offSession**

**cardOffSession**

**payPalOrder**

**payPalBillingAgreement**

**applePay**

**googlePay**

**klarna**

**klarnaPaymentSession**

**klarnaCustomerToken**

**apayaToken**

**hoolah**

**unknown**

**threeDSecureAuthentication** `ThreeDS.AuthenticationDetails`

**token** `String` *required*

**tokenType** `TokenType`

**Cases**

**multiUse**

**singleUse**

**vaultData** `VaultData`

**decisionHandler** `enum PrimerPaymentCreationDecision` *required*

**Cases**

**.continuePaymentCreation(withIdempotencyKey:)**

Call `.continuePaymentCreation` when you want to continue with the payment creation.
Optionally provide a `withIdempotencyKey` to prevent duplicate payments. The SDK attaches it as `X-Idempotency-Key` header on payment creation and resume requests. The same key is reused for the entire payment lifecycle and automatically cleared on completion or failure.

**.abortPaymentCreation(withErrorMessage:)**

Call `.abortPaymentCreation` when you want to abort the payment. Optionally you can provide an error message to get presented on the error screen.

#### Example

```swift SWIFT theme={"dark"}
// 👇 Add this
import PrimerSDK

// 👇 Conform to PrimerHeadlessUniversalCheckoutDelegate
class MyViewController: UIViewController, PrimerHeadlessUniversalCheckoutDelegate {

	// ...

    // 👇 Add this
	func primerHeadlessUniversalCheckoutWillCreatePaymentWithData(
        _ data: PrimerCheckoutPaymentMethodData,
        decisionHandler: @escaping (PrimerPaymentCreationDecision) -> Void
    ) {

    }
}
```

#### Example with Idempotency Key

```swift SWIFT theme={"dark"}
class MyViewController: UIViewController, PrimerHeadlessUniversalCheckoutDelegate {
    func primerHeadlessUniversalCheckoutWillCreatePaymentWithData(
        _ data: PrimerCheckoutPaymentMethodData,
        decisionHandler: @escaping (PrimerPaymentCreationDecision) -> Void
    ) {
        let idempotencyKey = UUID().uuidString
        decisionHandler(.continuePaymentCreation(withIdempotencyKey: idempotencyKey))
    }
}
```


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