# Handling Client-Side Actions

## Overview

When processing payments using the Ryft iOS Drop-In SDK, there may be scenarios where additional **client-side actions** are required to complete the payment. These actions can include 3D Secure authentication, handling redirects, or other verification steps mandated by the card issuer or payment method.

Our Drop-In SDK is designed to handle these client-side actions seamlessly, providing a smooth user experience. However, you may want to handle any required client-side actions explicitly in your application code.

A common use case would be a [MIT](/documentation/overview/core_concepts/stored_payment_methods#merchant-initiated-transactions-mit) payment where the card issuer requires 3D Secure authentication to complete the transaction. In such cases, you will need to bring the customer back to your application after they complete the authentication process.

## Implementing Client-Side Actions

To handle client-side actions in your application, you can use our **RyftRequiredActionComponent** object.

Here's an example of how to initialise the Ryft Required Action Component in your view controller:

Standalone Component - Single Payment
```swift Required Action Component - Single Payment
private func initialiseRyftRequiredActionComponent() {
    let action = try JSONDecoder().decode(PaymentSessionRequiredAction.self, from: data) // fetch from your backend and decode
    let config = RyftRequiredActionComponent.Configuration(
        clientSecret: "{{the client secret of the payment-session}}"
    )
    // create a fresh instance each time
    let component = RyftRequiredActionComponent(
        config: config,
        apiClient: DefaultRyftApiClient(publicApiKey: "{{your public API key}}")
    )
    component.delegate = self
    component.handle(action: action, presentingViewController: self)
}
```

Standalone Component - Platform Fee Payment
```swift Required Action Component - Platform Fee Payment
private func initialiseRyftRequiredActionComponent() {
    let action = try JSONDecoder().decode(PaymentSessionRequiredAction.self, from: data) // fetch from your backend and decode
    let config = RyftRequiredActionComponent.Configuration(
        clientSecret: "{{the client secret of the payment-session}}",
        accountId: "{{the Id of the sub-account you are taking payments for}}"
    )
    // create a fresh instance each time
    let component = RyftRequiredActionComponent(
        config: config,
        apiClient: DefaultRyftApiClient(publicApiKey: "{{your public API key}}")
    )
    component.delegate = self
    component.handle(action: action, presentingViewController: self)
}
```

## Handling Required Action Results

In order to handle the required action, you can simply call the `handle()` method to trigger any necessary client-side actions, including the full 3D Secure identify and challenge flow.

The full process can be managed by implementing the `RyftRequiredActionDelegate` protocol in your view controller. This protocol provides methods to listen for the result of the required action.

Here's an example of how to implement it:

```swift Implementing RyftRequiredActionDelegate
public func onRequiredActionInProgress() {
    /*
    * (optional)
    * the component is performing some asynchronous task
    * show your loading indicator/screen
    */
}

public func onRequiredActionHandled(result: RyftRequiredActionResult) {
    /*
    * The action has completed with a success, cancellation, or failure
    */
    switch result {
    case .success(let updatedPaymentSession):
        // inspect the status to determine the next step
        break
    case .cancelled:
        // the customer cancelled the 3D Secure challenge
        break
    case .failure(let error):
        // handle the error (try again/show an alert)
        print("error handling required action \(error)")
    }
}
```

Once the payment has been processed successfully, you can proceed to show a confirmation screen to the user or handle any post-payment logic as needed.