# 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(RyftPaymentSessionRequiredAction.type, from: data) // fetch from your backend and decode let config = RyftRequiredActionComponent.Configuration( clientSecret: config.clientSecret ) // 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) } ``` Standalone Component - Platform Fee Payment ```swift Required Action Component - Platform Fee Payment private func initialiseRyftRequiredActionComponent() { let action = try JSONDecoder().decode(RyftPaymentSessionRequiredAction.type, from: data) // fetch from your backend and decode let config = RyftRequiredActionComponent.Configuration( clientSecret: config.clientSecret, 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) } ``` ## 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. The full process can be managed by implementing the `RyftRequiredActionComponentDelegate` 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 RyftRequiredActionComponentDelegate public func onRequiredActionInProgress() { /* * (optional) * the component is performing some asynchronous task * show your loading indicator/screen */ } public func onRequiredActionHandled(result: Result) { /* * The action has completed with either the updated PaymentSession, or an Error */ switch result: case success(let updatedPaymentSession): // inspect the status to determine the next step 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.